Fix readonly check for vdev user properties
[zfs.git] / tests / zfs-tests / cmd / clone_mmap_write.c
blob6a5cd8721c57add3edebce25d05f8f53391c992c
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * This program clones the file, mmap it, and writes from the map into
24 * file. This scenario triggers a panic on Linux in dbuf_redirty(),
25 * which is fixed under PR#15656. On FreeBSD, the same test causes data
26 * corruption, which is fixed by PR#15665.
28 * It would be good to test for this scenario in ZTS. This program and
29 * issue was initially produced by @robn.
31 #ifndef _GNU_SOURCE
32 #define _GNU_SOURCE
33 #endif
35 #include <fcntl.h>
36 #include <string.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <errno.h>
41 #include <sys/stat.h>
42 #include <sys/mman.h>
44 #ifdef __FreeBSD__
45 #define loff_t off_t
46 #endif
48 ssize_t
49 copy_file_range(int, loff_t *, int, loff_t *, size_t, unsigned int)
50 __attribute__((weak));
52 static int
53 open_file(const char *source)
55 int fd;
56 if ((fd = open(source, O_RDWR | O_APPEND)) < 0) {
57 (void) fprintf(stderr, "Error opening %s\n", source);
58 exit(1);
60 sync();
61 return (fd);
64 static int
65 clone_file(int sfd, long long size, const char *dest)
67 int dfd;
69 if ((dfd = open(dest, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
70 (void) fprintf(stderr, "Error opening %s\n", dest);
71 exit(1);
74 if (copy_file_range(sfd, 0, dfd, 0, size, 0) < 0) {
75 (void) fprintf(stderr, "copy_file_range failed\n");
76 exit(1);
79 return (dfd);
82 static void *
83 map_file(int fd, long long size)
85 void *p = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
86 if (p == MAP_FAILED) {
87 (void) fprintf(stderr, "mmap failed\n");
88 exit(1);
91 return (p);
94 static void
95 map_write(void *p, int fd)
97 if (pwrite(fd, p, 1024*128, 0) < 0) {
98 (void) fprintf(stderr, "write failed\n");
99 exit(1);
104 main(int argc, char **argv)
106 int sfd, dfd;
107 void *p;
108 struct stat sb;
109 if (argc != 3) {
110 (void) printf("usage: %s <input source file> "
111 "<clone destination file>\n", argv[0]);
112 exit(1);
114 sfd = open_file(argv[1]);
115 if (fstat(sfd, &sb) == -1) {
116 (void) fprintf(stderr, "fstat failed\n");
117 exit(1);
119 dfd = clone_file(sfd, sb.st_size, argv[2]);
120 p = map_file(dfd, sb.st_size);
121 map_write(p, dfd);
122 return (0);