Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/tests/zfs-tests/cmd/clone_mmap_write.c
107278 views
1
// SPDX-License-Identifier: CDDL-1.0
2
/*
3
* CDDL HEADER START
4
*
5
* The contents of this file are subject to the terms of the
6
* Common Development and Distribution License (the "License").
7
* You may not use this file except in compliance with the License.
8
*
9
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
* or https://opensource.org/licenses/CDDL-1.0.
11
* See the License for the specific language governing permissions
12
* and limitations under the License.
13
*
14
* When distributing Covered Code, include this CDDL HEADER in each
15
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
* If applicable, add the following below this CDDL HEADER, with the
17
* fields enclosed by brackets "[]" replaced with your own identifying
18
* information: Portions Copyright [yyyy] [name of copyright owner]
19
*
20
* CDDL HEADER END
21
*/
22
23
/*
24
* This program clones the file, mmap it, and writes from the map into
25
* file. This scenario triggers a panic on Linux in dbuf_redirty(),
26
* which is fixed under PR#15656. On FreeBSD, the same test causes data
27
* corruption, which is fixed by PR#15665.
28
*
29
* It would be good to test for this scenario in ZTS. This program and
30
* issue was initially produced by @robn.
31
*/
32
#ifndef _GNU_SOURCE
33
#define _GNU_SOURCE
34
#endif
35
36
#include <fcntl.h>
37
#include <string.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <unistd.h>
41
#include <errno.h>
42
#include <sys/stat.h>
43
#include <sys/mman.h>
44
45
#if defined(_GNU_SOURCE) && defined(__linux__)
46
_Static_assert(sizeof (loff_t) == sizeof (off_t),
47
"loff_t and off_t must be the same size");
48
#endif
49
50
ssize_t
51
copy_file_range(int, off_t *, int, off_t *, size_t, unsigned int)
52
__attribute__((weak));
53
54
static int
55
open_file(const char *source)
56
{
57
int fd;
58
if ((fd = open(source, O_RDWR | O_APPEND)) < 0) {
59
(void) fprintf(stderr, "Error opening %s\n", source);
60
exit(1);
61
}
62
sync();
63
return (fd);
64
}
65
66
static int
67
clone_file(int sfd, long long size, const char *dest)
68
{
69
int dfd;
70
71
if ((dfd = open(dest, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
72
(void) fprintf(stderr, "Error opening %s\n", dest);
73
exit(1);
74
}
75
76
if (copy_file_range(sfd, 0, dfd, 0, size, 0) < 0) {
77
(void) fprintf(stderr, "copy_file_range failed\n");
78
exit(1);
79
}
80
81
return (dfd);
82
}
83
84
static void *
85
map_file(int fd, long long size)
86
{
87
void *p = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
88
if (p == MAP_FAILED) {
89
(void) fprintf(stderr, "mmap failed\n");
90
exit(1);
91
}
92
93
return (p);
94
}
95
96
static void
97
map_write(void *p, int fd)
98
{
99
if (pwrite(fd, p, 1024*128, 0) < 0) {
100
(void) fprintf(stderr, "write failed\n");
101
exit(1);
102
}
103
}
104
105
int
106
main(int argc, char **argv)
107
{
108
int sfd, dfd;
109
void *p;
110
struct stat sb;
111
if (argc != 3) {
112
(void) printf("usage: %s <input source file> "
113
"<clone destination file>\n", argv[0]);
114
exit(1);
115
}
116
sfd = open_file(argv[1]);
117
if (fstat(sfd, &sb) == -1) {
118
(void) fprintf(stderr, "fstat failed\n");
119
exit(1);
120
}
121
dfd = clone_file(sfd, sb.st_size, argv[2]);
122
p = map_file(dfd, sb.st_size);
123
map_write(p, dfd);
124
return (0);
125
}
126
127