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
48529 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
#ifdef __FreeBSD__
46
#define loff_t off_t
47
#endif
48
49
ssize_t
50
copy_file_range(int, loff_t *, int, loff_t *, size_t, unsigned int)
51
__attribute__((weak));
52
53
static int
54
open_file(const char *source)
55
{
56
int fd;
57
if ((fd = open(source, O_RDWR | O_APPEND)) < 0) {
58
(void) fprintf(stderr, "Error opening %s\n", source);
59
exit(1);
60
}
61
sync();
62
return (fd);
63
}
64
65
static int
66
clone_file(int sfd, long long size, const char *dest)
67
{
68
int dfd;
69
70
if ((dfd = open(dest, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
71
(void) fprintf(stderr, "Error opening %s\n", dest);
72
exit(1);
73
}
74
75
if (copy_file_range(sfd, 0, dfd, 0, size, 0) < 0) {
76
(void) fprintf(stderr, "copy_file_range failed\n");
77
exit(1);
78
}
79
80
return (dfd);
81
}
82
83
static void *
84
map_file(int fd, long long size)
85
{
86
void *p = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
87
if (p == MAP_FAILED) {
88
(void) fprintf(stderr, "mmap failed\n");
89
exit(1);
90
}
91
92
return (p);
93
}
94
95
static void
96
map_write(void *p, int fd)
97
{
98
if (pwrite(fd, p, 1024*128, 0) < 0) {
99
(void) fprintf(stderr, "write failed\n");
100
exit(1);
101
}
102
}
103
104
int
105
main(int argc, char **argv)
106
{
107
int sfd, dfd;
108
void *p;
109
struct stat sb;
110
if (argc != 3) {
111
(void) printf("usage: %s <input source file> "
112
"<clone destination file>\n", argv[0]);
113
exit(1);
114
}
115
sfd = open_file(argv[1]);
116
if (fstat(sfd, &sb) == -1) {
117
(void) fprintf(stderr, "fstat failed\n");
118
exit(1);
119
}
120
dfd = clone_file(sfd, sb.st_size, argv[2]);
121
p = map_file(dfd, sb.st_size);
122
map_write(p, dfd);
123
return (0);
124
}
125
126