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