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_cached.c
109057 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
* Copyright (c) 2024 by Pawel Jakub Dawidek
25
*/
26
27
#include <sys/mman.h>
28
#include <sys/stat.h>
29
30
#include <assert.h>
31
#include <errno.h>
32
#include <fcntl.h>
33
#include <stdbool.h>
34
#include <stdio.h>
35
#include <stdlib.h>
36
#include <string.h>
37
#include <unistd.h>
38
39
#if defined(_GNU_SOURCE) && defined(__linux__)
40
_Static_assert(sizeof (loff_t) == sizeof (off_t),
41
"loff_t and off_t must be the same size");
42
#endif
43
44
ssize_t
45
copy_file_range(int, off_t *, int, off_t *, size_t, unsigned int)
46
__attribute__((weak));
47
48
static void *
49
mmap_file(int fd, size_t size)
50
{
51
void *p;
52
53
p = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
54
if (p == MAP_FAILED) {
55
(void) fprintf(stderr, "mmap failed: %s\n", strerror(errno));
56
exit(2);
57
}
58
59
return (p);
60
}
61
62
static void
63
usage(const char *progname)
64
{
65
66
/*
67
* -i cache input before copy_file_range(2).
68
* -o cache input before copy_file_range(2).
69
*/
70
(void) fprintf(stderr, "usage: %s [-io] <input> <output>\n", progname);
71
exit(3);
72
}
73
74
int
75
main(int argc, char *argv[])
76
{
77
int dfd, sfd;
78
size_t dsize, ssize;
79
void *dmem, *smem, *ptr;
80
off_t doff, soff;
81
struct stat sb;
82
bool cache_input, cache_output;
83
const char *progname;
84
int c;
85
86
progname = argv[0];
87
cache_input = cache_output = false;
88
89
while ((c = getopt(argc, argv, "io")) != -1) {
90
switch (c) {
91
case 'i':
92
cache_input = true;
93
break;
94
case 'o':
95
cache_output = true;
96
break;
97
default:
98
usage(progname);
99
}
100
}
101
argc -= optind;
102
argv += optind;
103
104
if (argc != 2) {
105
usage(progname);
106
}
107
108
sfd = open(argv[0], O_RDONLY);
109
if (fstat(sfd, &sb) == -1) {
110
(void) fprintf(stderr, "fstat failed: %s\n", strerror(errno));
111
exit(2);
112
}
113
ssize = sb.st_size;
114
smem = mmap_file(sfd, ssize);
115
116
dfd = open(argv[1], O_RDWR);
117
if (fstat(dfd, &sb) == -1) {
118
(void) fprintf(stderr, "fstat failed: %s\n", strerror(errno));
119
exit(2);
120
}
121
dsize = sb.st_size;
122
dmem = mmap_file(dfd, dsize);
123
124
/*
125
* Hopefully it won't be compiled out.
126
*/
127
if (cache_input) {
128
ptr = malloc(ssize);
129
assert(ptr != NULL);
130
memcpy(ptr, smem, ssize);
131
free(ptr);
132
}
133
if (cache_output) {
134
ptr = malloc(ssize);
135
assert(ptr != NULL);
136
memcpy(ptr, dmem, dsize);
137
free(ptr);
138
}
139
140
soff = doff = 0;
141
if (copy_file_range(sfd, &soff, dfd, &doff, ssize, 0) < 0) {
142
(void) fprintf(stderr, "copy_file_range failed: %s\n",
143
strerror(errno));
144
exit(2);
145
}
146
147
exit(memcmp(smem, dmem, ssize) == 0 ? 0 : 1);
148
}
149
150