Path: blob/main/sys/contrib/openzfs/tests/zfs-tests/cmd/clone_mmap_write.c
48529 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* Common Development and Distribution License (the "License").6* You may not use this file except in compliance with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/2122/*23* This program clones the file, mmap it, and writes from the map into24* file. This scenario triggers a panic on Linux in dbuf_redirty(),25* which is fixed under PR#15656. On FreeBSD, the same test causes data26* corruption, which is fixed by PR#15665.27*28* It would be good to test for this scenario in ZTS. This program and29* issue was initially produced by @robn.30*/31#ifndef _GNU_SOURCE32#define _GNU_SOURCE33#endif3435#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>4344#ifdef __FreeBSD__45#define loff_t off_t46#endif4748ssize_t49copy_file_range(int, loff_t *, int, loff_t *, size_t, unsigned int)50__attribute__((weak));5152static int53open_file(const char *source)54{55int fd;56if ((fd = open(source, O_RDWR | O_APPEND)) < 0) {57(void) fprintf(stderr, "Error opening %s\n", source);58exit(1);59}60sync();61return (fd);62}6364static int65clone_file(int sfd, long long size, const char *dest)66{67int dfd;6869if ((dfd = open(dest, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {70(void) fprintf(stderr, "Error opening %s\n", dest);71exit(1);72}7374if (copy_file_range(sfd, 0, dfd, 0, size, 0) < 0) {75(void) fprintf(stderr, "copy_file_range failed\n");76exit(1);77}7879return (dfd);80}8182static void *83map_file(int fd, long long size)84{85void *p = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);86if (p == MAP_FAILED) {87(void) fprintf(stderr, "mmap failed\n");88exit(1);89}9091return (p);92}9394static void95map_write(void *p, int fd)96{97if (pwrite(fd, p, 1024*128, 0) < 0) {98(void) fprintf(stderr, "write failed\n");99exit(1);100}101}102103int104main(int argc, char **argv)105{106int sfd, dfd;107void *p;108struct stat sb;109if (argc != 3) {110(void) printf("usage: %s <input source file> "111"<clone destination file>\n", argv[0]);112exit(1);113}114sfd = open_file(argv[1]);115if (fstat(sfd, &sb) == -1) {116(void) fprintf(stderr, "fstat failed\n");117exit(1);118}119dfd = clone_file(sfd, sb.st_size, argv[2]);120p = map_file(dfd, sb.st_size);121map_write(p, dfd);122return (0);123}124125126