1*5e3eaea3SApple OSS Distributions /* compile: xcrun -sdk macosx.internal clang -ldarwintest -o test_file_leases file_leases.c -g -Weverything */
2*5e3eaea3SApple OSS Distributions
3*5e3eaea3SApple OSS Distributions #include <darwintest.h>
4*5e3eaea3SApple OSS Distributions #include <darwintest_utils.h>
5*5e3eaea3SApple OSS Distributions #include <darwintest_multiprocess.h>
6*5e3eaea3SApple OSS Distributions #include <copyfile.h>
7*5e3eaea3SApple OSS Distributions #include <errno.h>
8*5e3eaea3SApple OSS Distributions #include <fcntl.h>
9*5e3eaea3SApple OSS Distributions #include <stdint.h>
10*5e3eaea3SApple OSS Distributions #include <stdlib.h>
11*5e3eaea3SApple OSS Distributions #include <unistd.h>
12*5e3eaea3SApple OSS Distributions #include <sys/clonefile.h>
13*5e3eaea3SApple OSS Distributions #include <sys/event.h>
14*5e3eaea3SApple OSS Distributions #include <sys/resource.h>
15*5e3eaea3SApple OSS Distributions #include <sys/sysctl.h>
16*5e3eaea3SApple OSS Distributions #include <sys/xattr.h>
17*5e3eaea3SApple OSS Distributions
18*5e3eaea3SApple OSS Distributions #include "test_utils.h"
19*5e3eaea3SApple OSS Distributions
20*5e3eaea3SApple OSS Distributions
21*5e3eaea3SApple OSS Distributions T_GLOBAL_META(
22*5e3eaea3SApple OSS Distributions T_META_NAMESPACE("xnu.vfs.lease"),
23*5e3eaea3SApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
24*5e3eaea3SApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("vfs"),
25*5e3eaea3SApple OSS Distributions T_META_CHECK_LEAKS(false));
26*5e3eaea3SApple OSS Distributions
27*5e3eaea3SApple OSS Distributions #define TEST_LEASE_DIR "lease_dir"
28*5e3eaea3SApple OSS Distributions #define TEST_LEASE_FILE "lease_file"
29*5e3eaea3SApple OSS Distributions
30*5e3eaea3SApple OSS Distributions static char g_testfile[MAXPATHLEN];
31*5e3eaea3SApple OSS Distributions static char g_testdir[MAXPATHLEN];
32*5e3eaea3SApple OSS Distributions
33*5e3eaea3SApple OSS Distributions /*
34*5e3eaea3SApple OSS Distributions * This unit-test validates the behavior of file leasing (read and write leases)
35*5e3eaea3SApple OSS Distributions * by utilizing the file leasing API (fcntl's F_SETLEASE and F_GETLEASE
36*5e3eaea3SApple OSS Distributions * commands) provided by VFS.
37*5e3eaea3SApple OSS Distributions */
38*5e3eaea3SApple OSS Distributions
39*5e3eaea3SApple OSS Distributions
40*5e3eaea3SApple OSS Distributions static void
exit_cleanup(void)41*5e3eaea3SApple OSS Distributions exit_cleanup(void)
42*5e3eaea3SApple OSS Distributions {
43*5e3eaea3SApple OSS Distributions uint32_t val, new_val;
44*5e3eaea3SApple OSS Distributions size_t val_len, new_val_len;
45*5e3eaea3SApple OSS Distributions
46*5e3eaea3SApple OSS Distributions (void)remove(g_testfile);
47*5e3eaea3SApple OSS Distributions (void)rmdir(g_testdir);
48*5e3eaea3SApple OSS Distributions
49*5e3eaea3SApple OSS Distributions new_val = 60;
50*5e3eaea3SApple OSS Distributions new_val_len = val_len = sizeof(uint32_t);
51*5e3eaea3SApple OSS Distributions (void)sysctlbyname("vfs.lease.break_timeout", &val, &val_len,
52*5e3eaea3SApple OSS Distributions (void *)&new_val, new_val_len);
53*5e3eaea3SApple OSS Distributions }
54*5e3eaea3SApple OSS Distributions
55*5e3eaea3SApple OSS Distributions
56*5e3eaea3SApple OSS Distributions static void
create_test_file(void)57*5e3eaea3SApple OSS Distributions create_test_file(void)
58*5e3eaea3SApple OSS Distributions {
59*5e3eaea3SApple OSS Distributions const char *tmpdir = dt_tmpdir();
60*5e3eaea3SApple OSS Distributions int fd;
61*5e3eaea3SApple OSS Distributions
62*5e3eaea3SApple OSS Distributions T_SETUPBEGIN;
63*5e3eaea3SApple OSS Distributions
64*5e3eaea3SApple OSS Distributions /*
65*5e3eaea3SApple OSS Distributions * Make sure dataless file manipulation is enabled for this
66*5e3eaea3SApple OSS Distributions * process (children will inherit).
67*5e3eaea3SApple OSS Distributions *
68*5e3eaea3SApple OSS Distributions * See kpi_vfs.c:vfs_context_can_break_leases().
69*5e3eaea3SApple OSS Distributions */
70*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(
71*5e3eaea3SApple OSS Distributions setiopolicy_np(IOPOL_TYPE_VFS_MATERIALIZE_DATALESS_FILES,
72*5e3eaea3SApple OSS Distributions IOPOL_SCOPE_PROCESS, IOPOL_MATERIALIZE_DATALESS_FILES_ON),
73*5e3eaea3SApple OSS Distributions "Setup: ensuring dataless file materialization is enabled");
74*5e3eaea3SApple OSS Distributions
75*5e3eaea3SApple OSS Distributions atexit(exit_cleanup);
76*5e3eaea3SApple OSS Distributions
77*5e3eaea3SApple OSS Distributions snprintf(g_testdir, MAXPATHLEN, "%s/%s", tmpdir, TEST_LEASE_DIR);
78*5e3eaea3SApple OSS Distributions
79*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(mkdir(g_testdir, 0777),
80*5e3eaea3SApple OSS Distributions "Setup: creating test dir: %s", g_testdir);
81*5e3eaea3SApple OSS Distributions
82*5e3eaea3SApple OSS Distributions snprintf(g_testfile, MAXPATHLEN, "%s/%s", g_testdir, TEST_LEASE_FILE);
83*5e3eaea3SApple OSS Distributions
84*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
85*5e3eaea3SApple OSS Distributions fd = open(g_testfile, O_CREAT | O_RDWR, 0666);
86*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Create test fi1e: %s", g_testfile);
87*5e3eaea3SApple OSS Distributions
88*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(fd), "Close test file: %s", TEST_LEASE_FILE);
89*5e3eaea3SApple OSS Distributions
90*5e3eaea3SApple OSS Distributions T_SETUPEND;
91*5e3eaea3SApple OSS Distributions }
92*5e3eaea3SApple OSS Distributions
93*5e3eaea3SApple OSS Distributions #define HELPER_TIMEOUT_SECS 60
94*5e3eaea3SApple OSS Distributions #define MAX_HELPERS 10
95*5e3eaea3SApple OSS Distributions
96*5e3eaea3SApple OSS Distributions static void __attribute__((noreturn))
run_helpers(const char ** helper_test_names,int num_helpers)97*5e3eaea3SApple OSS Distributions run_helpers(const char **helper_test_names, int num_helpers)
98*5e3eaea3SApple OSS Distributions {
99*5e3eaea3SApple OSS Distributions dt_helper_t helpers[MAX_HELPERS];
100*5e3eaea3SApple OSS Distributions char *args[] = {g_testfile, g_testdir, NULL};
101*5e3eaea3SApple OSS Distributions int i;
102*5e3eaea3SApple OSS Distributions
103*5e3eaea3SApple OSS Distributions T_QUIET;
104*5e3eaea3SApple OSS Distributions T_ASSERT_LE(num_helpers, MAX_HELPERS, "too many helpers");
105*5e3eaea3SApple OSS Distributions
106*5e3eaea3SApple OSS Distributions for (i = 0; i < num_helpers; i++) {
107*5e3eaea3SApple OSS Distributions helpers[i] = dt_child_helper_args(helper_test_names[i], args);
108*5e3eaea3SApple OSS Distributions }
109*5e3eaea3SApple OSS Distributions dt_run_helpers(helpers, (size_t)num_helpers, HELPER_TIMEOUT_SECS);
110*5e3eaea3SApple OSS Distributions }
111*5e3eaea3SApple OSS Distributions
112*5e3eaea3SApple OSS Distributions T_HELPER_DECL(open_rdonly_acquire_read_lease_succeed, "Open file in O_RDONLY mode and acquire read lease succeeded")
113*5e3eaea3SApple OSS Distributions {
114*5e3eaea3SApple OSS Distributions char *testfile = argv[0];
115*5e3eaea3SApple OSS Distributions int err, fd;
116*5e3eaea3SApple OSS Distributions
117*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
118*5e3eaea3SApple OSS Distributions fd = open(testfile, O_RDONLY, 0666);
119*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDONLY: %s", testfile);
120*5e3eaea3SApple OSS Distributions
121*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
122*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_RDLCK);
123*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Acquire read lease: %s", testfile);
124*5e3eaea3SApple OSS Distributions
125*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
126*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_GETLEASE);
127*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_RDLCK, "Retrieve lease: %s", testfile);
128*5e3eaea3SApple OSS Distributions
129*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(fd), "Close test file: %s", testfile);
130*5e3eaea3SApple OSS Distributions }
131*5e3eaea3SApple OSS Distributions
132*5e3eaea3SApple OSS Distributions T_HELPER_DECL(open_rdonly_acquire_read_lease_EAGAIN, "Open file in O_RDONLY mode and acquire read lease failed with EAGAIN")
133*5e3eaea3SApple OSS Distributions {
134*5e3eaea3SApple OSS Distributions char *testfile = argv[0];
135*5e3eaea3SApple OSS Distributions int err, fd;
136*5e3eaea3SApple OSS Distributions
137*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
138*5e3eaea3SApple OSS Distributions fd = open(testfile, O_RDONLY, 0666);
139*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDONLY: %s", testfile);
140*5e3eaea3SApple OSS Distributions
141*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
142*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_RDLCK);
143*5e3eaea3SApple OSS Distributions T_ASSERT_TRUE((err == -1) && (errno == EAGAIN), "Acquire read lease: %s",
144*5e3eaea3SApple OSS Distributions testfile);
145*5e3eaea3SApple OSS Distributions
146*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(fd), "Close test file: %s", testfile);
147*5e3eaea3SApple OSS Distributions }
148*5e3eaea3SApple OSS Distributions
149*5e3eaea3SApple OSS Distributions T_HELPER_DECL(open_rdwr_acquire_write_lease_EAGAIN, "Open file in O_RDWR mode and acquire write lease failed with EAGAIN")
150*5e3eaea3SApple OSS Distributions {
151*5e3eaea3SApple OSS Distributions char *testfile = argv[0];
152*5e3eaea3SApple OSS Distributions int err, fd;
153*5e3eaea3SApple OSS Distributions
154*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
155*5e3eaea3SApple OSS Distributions fd = open(testfile, O_RDWR, 0666);
156*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDWR: %s", testfile);
157*5e3eaea3SApple OSS Distributions
158*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
159*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_WRLCK);
160*5e3eaea3SApple OSS Distributions T_ASSERT_TRUE((err == -1) && (errno == EAGAIN), "Acquire write lease: %s",
161*5e3eaea3SApple OSS Distributions testfile);
162*5e3eaea3SApple OSS Distributions
163*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(fd), "Close test file: %s", testfile);
164*5e3eaea3SApple OSS Distributions }
165*5e3eaea3SApple OSS Distributions
166*5e3eaea3SApple OSS Distributions T_HELPER_DECL(open_rdonly_read_lease_release, "Open file in O_RDONLY mode, acquire read lease, and release lease upon NOTE_LEASE_RELEASE event")
167*5e3eaea3SApple OSS Distributions {
168*5e3eaea3SApple OSS Distributions struct kevent lease_kevent;
169*5e3eaea3SApple OSS Distributions struct timespec kevent_timeout;
170*5e3eaea3SApple OSS Distributions char *testfile = argv[0];
171*5e3eaea3SApple OSS Distributions int err, fd, kq;
172*5e3eaea3SApple OSS Distributions
173*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
174*5e3eaea3SApple OSS Distributions fd = open(testfile, O_RDONLY, 0666);
175*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDONLY: %s", testfile);
176*5e3eaea3SApple OSS Distributions
177*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
178*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_RDLCK);
179*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Acquire read lease: %s", testfile);
180*5e3eaea3SApple OSS Distributions
181*5e3eaea3SApple OSS Distributions kq = kqueue();
182*5e3eaea3SApple OSS Distributions T_ASSERT_NE(kq, -1, "Create kqueue");
183*5e3eaea3SApple OSS Distributions
184*5e3eaea3SApple OSS Distributions kevent_timeout.tv_sec = kevent_timeout.tv_nsec = 0;
185*5e3eaea3SApple OSS Distributions EV_SET(&lease_kevent, fd, EVFILT_VNODE, (EV_ADD | EV_ENABLE | EV_CLEAR),
186*5e3eaea3SApple OSS Distributions (NOTE_LEASE_DOWNGRADE | NOTE_LEASE_RELEASE), 0, (void *)testfile);
187*5e3eaea3SApple OSS Distributions err = kevent(kq, &lease_kevent, 1, NULL, 0, &kevent_timeout);
188*5e3eaea3SApple OSS Distributions T_ASSERT_GE(err, 0, "Register lease event on kq: %d", kq);
189*5e3eaea3SApple OSS Distributions
190*5e3eaea3SApple OSS Distributions kevent_timeout.tv_sec = 60;
191*5e3eaea3SApple OSS Distributions kevent_timeout.tv_nsec = 0;
192*5e3eaea3SApple OSS Distributions EV_SET(&lease_kevent, fd, EVFILT_VNODE, EV_CLEAR, 0, 0, 0);
193*5e3eaea3SApple OSS Distributions
194*5e3eaea3SApple OSS Distributions err = kevent(kq, NULL, 0, &lease_kevent, 1, &kevent_timeout);
195*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Listen for lease event on kq: %d", kq);
196*5e3eaea3SApple OSS Distributions
197*5e3eaea3SApple OSS Distributions if (err > 0) {
198*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(lease_kevent.fflags, NOTE_LEASE_RELEASE,
199*5e3eaea3SApple OSS Distributions "Got lease event 0x%x", lease_kevent.fflags);
200*5e3eaea3SApple OSS Distributions
201*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
202*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_UNLCK);
203*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Release lease: %s", testfile);
204*5e3eaea3SApple OSS Distributions } else {
205*5e3eaea3SApple OSS Distributions T_FAIL("Timedout listening for lease event on kq: %d", kq);
206*5e3eaea3SApple OSS Distributions }
207*5e3eaea3SApple OSS Distributions }
208*5e3eaea3SApple OSS Distributions
209*5e3eaea3SApple OSS Distributions T_HELPER_DECL(open_rdonly_write_lease_downgrade, "Open file in O_RDONLY mode, acquire a write lease, and downgrade lease upon NOTE_LEASE_DOWNGRADE event")
210*5e3eaea3SApple OSS Distributions {
211*5e3eaea3SApple OSS Distributions struct kevent lease_kevent;
212*5e3eaea3SApple OSS Distributions struct timespec kevent_timeout;
213*5e3eaea3SApple OSS Distributions char *testfile = argv[0];
214*5e3eaea3SApple OSS Distributions int err, fd, kq;
215*5e3eaea3SApple OSS Distributions
216*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
217*5e3eaea3SApple OSS Distributions fd = open(testfile, O_RDONLY, 0666);
218*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDONLY: %s", testfile);
219*5e3eaea3SApple OSS Distributions
220*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
221*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_WRLCK);
222*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Acquire write lease: %s", testfile);
223*5e3eaea3SApple OSS Distributions
224*5e3eaea3SApple OSS Distributions kq = kqueue();
225*5e3eaea3SApple OSS Distributions T_ASSERT_NE(kq, -1, "Create kqueue");
226*5e3eaea3SApple OSS Distributions
227*5e3eaea3SApple OSS Distributions kevent_timeout.tv_sec = kevent_timeout.tv_nsec = 0;
228*5e3eaea3SApple OSS Distributions EV_SET(&lease_kevent, fd, EVFILT_VNODE, (EV_ADD | EV_ENABLE | EV_CLEAR),
229*5e3eaea3SApple OSS Distributions (NOTE_LEASE_DOWNGRADE | NOTE_LEASE_RELEASE), 0, (void *)testfile);
230*5e3eaea3SApple OSS Distributions err = kevent(kq, &lease_kevent, 1, NULL, 0, &kevent_timeout);
231*5e3eaea3SApple OSS Distributions T_ASSERT_GE(err, 0, "Register lease event on kq: %d", kq);
232*5e3eaea3SApple OSS Distributions
233*5e3eaea3SApple OSS Distributions kevent_timeout.tv_sec = 60;
234*5e3eaea3SApple OSS Distributions kevent_timeout.tv_nsec = 0;
235*5e3eaea3SApple OSS Distributions EV_SET(&lease_kevent, fd, EVFILT_VNODE, EV_CLEAR, 0, 0, 0);
236*5e3eaea3SApple OSS Distributions
237*5e3eaea3SApple OSS Distributions err = kevent(kq, NULL, 0, &lease_kevent, 1, &kevent_timeout);
238*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Listen for lease event on kq: %d", kq);
239*5e3eaea3SApple OSS Distributions
240*5e3eaea3SApple OSS Distributions if (err > 0) {
241*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(lease_kevent.fflags, NOTE_LEASE_DOWNGRADE,
242*5e3eaea3SApple OSS Distributions "Got lease event 0x%x", lease_kevent.fflags);
243*5e3eaea3SApple OSS Distributions
244*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
245*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_RDLCK);
246*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Downgrade to read lease: %s", testfile);
247*5e3eaea3SApple OSS Distributions } else {
248*5e3eaea3SApple OSS Distributions T_FAIL("Timedout listening for lease event on kq: %d", kq);
249*5e3eaea3SApple OSS Distributions }
250*5e3eaea3SApple OSS Distributions }
251*5e3eaea3SApple OSS Distributions
252*5e3eaea3SApple OSS Distributions T_HELPER_DECL(open_rw_write_lease_downgrade, "Open file multiple times in O_RDWR mode, acquire a write lease, and downgrade lease upon NOTE_LEASE_DOWNGRADE event")
253*5e3eaea3SApple OSS Distributions {
254*5e3eaea3SApple OSS Distributions struct kevent lease_kevent;
255*5e3eaea3SApple OSS Distributions struct timespec kevent_timeout;
256*5e3eaea3SApple OSS Distributions char *testfile = argv[0];
257*5e3eaea3SApple OSS Distributions int err, rw_fd1, rw_fd2, fd, kq;
258*5e3eaea3SApple OSS Distributions
259*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
260*5e3eaea3SApple OSS Distributions rw_fd1 = open(testfile, O_RDWR, 0666);
261*5e3eaea3SApple OSS Distributions T_ASSERT_NE(rw_fd1, -1, "Open test fi1e in O_RDWR: %s", testfile);
262*5e3eaea3SApple OSS Distributions
263*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
264*5e3eaea3SApple OSS Distributions rw_fd2 = open(testfile, O_RDWR, 0666);
265*5e3eaea3SApple OSS Distributions T_ASSERT_NE(rw_fd2, -1, "Open test fi1e in O_RDWR: %s", testfile);
266*5e3eaea3SApple OSS Distributions
267*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
268*5e3eaea3SApple OSS Distributions fd = open(testfile, O_EVTONLY, 0666);
269*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_EVTONLY: %s", testfile);
270*5e3eaea3SApple OSS Distributions
271*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
272*5e3eaea3SApple OSS Distributions /* Pass in the expected open counts when placing a write lease. */
273*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_SETLEASE_ARG(F_WRLCK, 3));
274*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Acquire write lease: %s", testfile);
275*5e3eaea3SApple OSS Distributions
276*5e3eaea3SApple OSS Distributions kq = kqueue();
277*5e3eaea3SApple OSS Distributions T_ASSERT_NE(kq, -1, "Create kqueue");
278*5e3eaea3SApple OSS Distributions
279*5e3eaea3SApple OSS Distributions kevent_timeout.tv_sec = kevent_timeout.tv_nsec = 0;
280*5e3eaea3SApple OSS Distributions EV_SET(&lease_kevent, fd, EVFILT_VNODE, (EV_ADD | EV_ENABLE | EV_CLEAR),
281*5e3eaea3SApple OSS Distributions (NOTE_LEASE_DOWNGRADE | NOTE_LEASE_RELEASE), 0, (void *)testfile);
282*5e3eaea3SApple OSS Distributions err = kevent(kq, &lease_kevent, 1, NULL, 0, &kevent_timeout);
283*5e3eaea3SApple OSS Distributions T_ASSERT_GE(err, 0, "Register lease event on kq: %d", kq);
284*5e3eaea3SApple OSS Distributions
285*5e3eaea3SApple OSS Distributions kevent_timeout.tv_sec = 60;
286*5e3eaea3SApple OSS Distributions kevent_timeout.tv_nsec = 0;
287*5e3eaea3SApple OSS Distributions EV_SET(&lease_kevent, fd, EVFILT_VNODE, EV_CLEAR, 0, 0, 0);
288*5e3eaea3SApple OSS Distributions
289*5e3eaea3SApple OSS Distributions err = kevent(kq, NULL, 0, &lease_kevent, 1, &kevent_timeout);
290*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Listen for lease event on kq: %d", kq);
291*5e3eaea3SApple OSS Distributions
292*5e3eaea3SApple OSS Distributions if (err > 0) {
293*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(lease_kevent.fflags, NOTE_LEASE_DOWNGRADE,
294*5e3eaea3SApple OSS Distributions "Got lease event 0x%x", lease_kevent.fflags);
295*5e3eaea3SApple OSS Distributions
296*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
297*5e3eaea3SApple OSS Distributions /* Pass in the expected write counts when placing a read lease. */
298*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_SETLEASE_ARG(F_RDLCK, 2));
299*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Downgrade to read lease: %s", testfile);
300*5e3eaea3SApple OSS Distributions } else {
301*5e3eaea3SApple OSS Distributions T_FAIL("Timedout listening for lease event on kq: %d", kq);
302*5e3eaea3SApple OSS Distributions }
303*5e3eaea3SApple OSS Distributions }
304*5e3eaea3SApple OSS Distributions
305*5e3eaea3SApple OSS Distributions T_HELPER_DECL(open_rdonly_read_lease_timedout, "Open file in O_RDONLY mode, acquire read lease, and hold lease beyond lease break timeout upon NOTE_LEASE_RELEASE event", T_META_ASROOT(true))
306*5e3eaea3SApple OSS Distributions {
307*5e3eaea3SApple OSS Distributions struct kevent lease_kevent;
308*5e3eaea3SApple OSS Distributions struct timespec kevent_timeout;
309*5e3eaea3SApple OSS Distributions uint32_t val, new_val;
310*5e3eaea3SApple OSS Distributions size_t val_len, new_val_len;
311*5e3eaea3SApple OSS Distributions char *testfile = argv[0];
312*5e3eaea3SApple OSS Distributions int err, fd, kq;
313*5e3eaea3SApple OSS Distributions
314*5e3eaea3SApple OSS Distributions if (!is_development_kernel()) {
315*5e3eaea3SApple OSS Distributions T_SKIP("Skipping test on release kernel");
316*5e3eaea3SApple OSS Distributions }
317*5e3eaea3SApple OSS Distributions
318*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
319*5e3eaea3SApple OSS Distributions fd = open(testfile, O_RDONLY, 0666);
320*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDONLY: %s", testfile);
321*5e3eaea3SApple OSS Distributions
322*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
323*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_RDLCK);
324*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Acquire read lease: %s", testfile);
325*5e3eaea3SApple OSS Distributions
326*5e3eaea3SApple OSS Distributions new_val = 10;
327*5e3eaea3SApple OSS Distributions new_val_len = val_len = sizeof(uint32_t);
328*5e3eaea3SApple OSS Distributions err = sysctlbyname("vfs.lease.break_timeout", (void *)&val, &val_len,
329*5e3eaea3SApple OSS Distributions (void *)&new_val, new_val_len);
330*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Change vfs.lease.break_timeout to %d secs", new_val);
331*5e3eaea3SApple OSS Distributions
332*5e3eaea3SApple OSS Distributions kq = kqueue();
333*5e3eaea3SApple OSS Distributions T_ASSERT_NE(kq, -1, "Create kqueue");
334*5e3eaea3SApple OSS Distributions
335*5e3eaea3SApple OSS Distributions kevent_timeout.tv_sec = kevent_timeout.tv_nsec = 0;
336*5e3eaea3SApple OSS Distributions EV_SET(&lease_kevent, fd, EVFILT_VNODE, (EV_ADD | EV_ENABLE | EV_CLEAR),
337*5e3eaea3SApple OSS Distributions (NOTE_LEASE_DOWNGRADE | NOTE_LEASE_RELEASE), 0, (void *)testfile);
338*5e3eaea3SApple OSS Distributions err = kevent(kq, &lease_kevent, 1, NULL, 0, &kevent_timeout);
339*5e3eaea3SApple OSS Distributions T_ASSERT_GE(err, 0, "Register lease event on kq: %d", kq);
340*5e3eaea3SApple OSS Distributions
341*5e3eaea3SApple OSS Distributions kevent_timeout.tv_sec = 30;
342*5e3eaea3SApple OSS Distributions kevent_timeout.tv_nsec = 0;
343*5e3eaea3SApple OSS Distributions EV_SET(&lease_kevent, fd, EVFILT_VNODE, EV_CLEAR, 0, 0, 0);
344*5e3eaea3SApple OSS Distributions
345*5e3eaea3SApple OSS Distributions err = kevent(kq, NULL, 0, &lease_kevent, 1, &kevent_timeout);
346*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Listen for lease event on kq: %d", kq);
347*5e3eaea3SApple OSS Distributions
348*5e3eaea3SApple OSS Distributions if (err > 0) {
349*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(lease_kevent.fflags, NOTE_LEASE_RELEASE,
350*5e3eaea3SApple OSS Distributions "Got lease event 0x%x", lease_kevent.fflags);
351*5e3eaea3SApple OSS Distributions
352*5e3eaea3SApple OSS Distributions /* Sleep to force lease break timedout. */
353*5e3eaea3SApple OSS Distributions T_LOG("Sleep for %d secs to force lease break timedout", new_val + 5);
354*5e3eaea3SApple OSS Distributions sleep(new_val + 5);
355*5e3eaea3SApple OSS Distributions } else {
356*5e3eaea3SApple OSS Distributions T_FAIL("Timedout listening for lease event on kq: %d", kq);
357*5e3eaea3SApple OSS Distributions }
358*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Change vfs.lease.break_timeout to %d secs", new_val);
359*5e3eaea3SApple OSS Distributions }
360*5e3eaea3SApple OSS Distributions
361*5e3eaea3SApple OSS Distributions T_HELPER_DECL(open_rdonly_dir_read_lease, "Open directory in O_RDONLY mode, acquire read lease, and release lease upon NOTE_LEASE_RELEASE event")
362*5e3eaea3SApple OSS Distributions {
363*5e3eaea3SApple OSS Distributions struct kevent lease_kevent;
364*5e3eaea3SApple OSS Distributions struct timespec kevent_timeout;
365*5e3eaea3SApple OSS Distributions char *testdir = argv[1];
366*5e3eaea3SApple OSS Distributions int err, dir_fd, kq;
367*5e3eaea3SApple OSS Distributions
368*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
369*5e3eaea3SApple OSS Distributions dir_fd = open(testdir, O_RDONLY);
370*5e3eaea3SApple OSS Distributions T_ASSERT_NE(dir_fd, -1, "Open test dir in O_RDONLY: %s", testdir);
371*5e3eaea3SApple OSS Distributions
372*5e3eaea3SApple OSS Distributions kq = kqueue();
373*5e3eaea3SApple OSS Distributions T_ASSERT_NE(kq, -1, "Create kqueue");
374*5e3eaea3SApple OSS Distributions
375*5e3eaea3SApple OSS Distributions retry:
376*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
377*5e3eaea3SApple OSS Distributions err = fcntl(dir_fd, F_SETLEASE, F_RDLCK);
378*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Acquire read lease: %s", testdir);
379*5e3eaea3SApple OSS Distributions
380*5e3eaea3SApple OSS Distributions kevent_timeout.tv_sec = kevent_timeout.tv_nsec = 0;
381*5e3eaea3SApple OSS Distributions EV_SET(&lease_kevent, dir_fd, EVFILT_VNODE, (EV_ADD | EV_ENABLE | EV_CLEAR),
382*5e3eaea3SApple OSS Distributions (NOTE_LEASE_DOWNGRADE | NOTE_LEASE_RELEASE), 0, (void *)testdir);
383*5e3eaea3SApple OSS Distributions err = kevent(kq, &lease_kevent, 1, NULL, 0, &kevent_timeout);
384*5e3eaea3SApple OSS Distributions T_ASSERT_GE(err, 0, "Register lease event on kq: %d", kq);
385*5e3eaea3SApple OSS Distributions
386*5e3eaea3SApple OSS Distributions kevent_timeout.tv_sec = 30;
387*5e3eaea3SApple OSS Distributions kevent_timeout.tv_nsec = 0;
388*5e3eaea3SApple OSS Distributions EV_SET(&lease_kevent, dir_fd, EVFILT_VNODE, EV_CLEAR, 0, 0, 0);
389*5e3eaea3SApple OSS Distributions
390*5e3eaea3SApple OSS Distributions err = kevent(kq, NULL, 0, &lease_kevent, 1, &kevent_timeout);
391*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Listen for lease event on kq: %d", kq);
392*5e3eaea3SApple OSS Distributions
393*5e3eaea3SApple OSS Distributions if (err > 0) {
394*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(lease_kevent.fflags, NOTE_LEASE_RELEASE,
395*5e3eaea3SApple OSS Distributions "Got lease event 0x%x", lease_kevent.fflags);
396*5e3eaea3SApple OSS Distributions
397*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
398*5e3eaea3SApple OSS Distributions err = fcntl(dir_fd, F_SETLEASE, F_UNLCK);
399*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Release lease: %s", testdir);
400*5e3eaea3SApple OSS Distributions
401*5e3eaea3SApple OSS Distributions /*
402*5e3eaea3SApple OSS Distributions * Retry until we got no more events (kevent timedout) which means
403*5e3eaea3SApple OSS Distributions * the other helper is done with all the tests.
404*5e3eaea3SApple OSS Distributions */
405*5e3eaea3SApple OSS Distributions goto retry;
406*5e3eaea3SApple OSS Distributions } else {
407*5e3eaea3SApple OSS Distributions T_FAIL("Timedout listening for lease event on kq: %d", kq);
408*5e3eaea3SApple OSS Distributions }
409*5e3eaea3SApple OSS Distributions }
410*5e3eaea3SApple OSS Distributions
411*5e3eaea3SApple OSS Distributions T_HELPER_DECL(open_rdwr, "Open file in O_RDWR mode")
412*5e3eaea3SApple OSS Distributions {
413*5e3eaea3SApple OSS Distributions char *testfile = argv[0];
414*5e3eaea3SApple OSS Distributions int fd;
415*5e3eaea3SApple OSS Distributions
416*5e3eaea3SApple OSS Distributions /* wait for the other helper to be in ready state */
417*5e3eaea3SApple OSS Distributions sleep(1);
418*5e3eaea3SApple OSS Distributions
419*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
420*5e3eaea3SApple OSS Distributions fd = open(testfile, O_RDWR, 0666);
421*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDWR: %s", testfile);
422*5e3eaea3SApple OSS Distributions }
423*5e3eaea3SApple OSS Distributions
424*5e3eaea3SApple OSS Distributions T_HELPER_DECL(open_rdonly, "Open file in O_RDONLY mode")
425*5e3eaea3SApple OSS Distributions {
426*5e3eaea3SApple OSS Distributions char *testfile = argv[0];
427*5e3eaea3SApple OSS Distributions int fd;
428*5e3eaea3SApple OSS Distributions
429*5e3eaea3SApple OSS Distributions /* wait for the other helper to be in ready state */
430*5e3eaea3SApple OSS Distributions sleep(1);
431*5e3eaea3SApple OSS Distributions
432*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
433*5e3eaea3SApple OSS Distributions fd = open(testfile, O_RDONLY, 0666);
434*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDONLY: %s", testfile);
435*5e3eaea3SApple OSS Distributions }
436*5e3eaea3SApple OSS Distributions
437*5e3eaea3SApple OSS Distributions T_HELPER_DECL(truncate, "Truncate file")
438*5e3eaea3SApple OSS Distributions {
439*5e3eaea3SApple OSS Distributions char *testfile = argv[0];
440*5e3eaea3SApple OSS Distributions int err;
441*5e3eaea3SApple OSS Distributions
442*5e3eaea3SApple OSS Distributions /* wait for the other helper to be in ready state */
443*5e3eaea3SApple OSS Distributions sleep(1);
444*5e3eaea3SApple OSS Distributions
445*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
446*5e3eaea3SApple OSS Distributions err = truncate(testfile, 0);
447*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Truncate test fi1e: %s", testfile);
448*5e3eaea3SApple OSS Distributions }
449*5e3eaea3SApple OSS Distributions
450*5e3eaea3SApple OSS Distributions T_HELPER_DECL(open_rdonly_request_read_range_lock, "Open file in O_RDONLY mode and request byte range lock")
451*5e3eaea3SApple OSS Distributions {
452*5e3eaea3SApple OSS Distributions struct flock lreq;
453*5e3eaea3SApple OSS Distributions char *testfile = argv[0];
454*5e3eaea3SApple OSS Distributions int err, fd;
455*5e3eaea3SApple OSS Distributions
456*5e3eaea3SApple OSS Distributions /* wait for the other helper to be in ready state */
457*5e3eaea3SApple OSS Distributions sleep(1);
458*5e3eaea3SApple OSS Distributions
459*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
460*5e3eaea3SApple OSS Distributions fd = open(testfile, O_RDONLY, 0666);
461*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDONLY: %s", testfile);
462*5e3eaea3SApple OSS Distributions
463*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
464*5e3eaea3SApple OSS Distributions lreq.l_start = 0;
465*5e3eaea3SApple OSS Distributions lreq.l_len = 0;
466*5e3eaea3SApple OSS Distributions lreq.l_type = F_RDLCK;
467*5e3eaea3SApple OSS Distributions lreq.l_whence = 0;
468*5e3eaea3SApple OSS Distributions
469*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLK, &lreq);
470*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Acquire read range lock on test fi1e: %s", testfile);
471*5e3eaea3SApple OSS Distributions
472*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
473*5e3eaea3SApple OSS Distributions lreq.l_start = 0;
474*5e3eaea3SApple OSS Distributions lreq.l_len = 0;
475*5e3eaea3SApple OSS Distributions lreq.l_type = F_UNLCK;
476*5e3eaea3SApple OSS Distributions lreq.l_whence = 0;
477*5e3eaea3SApple OSS Distributions
478*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLK, &lreq);
479*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Release read range lock on test fi1e: %s", testfile);
480*5e3eaea3SApple OSS Distributions }
481*5e3eaea3SApple OSS Distributions
482*5e3eaea3SApple OSS Distributions T_HELPER_DECL(file_syscalls, "Call file syscalls")
483*5e3eaea3SApple OSS Distributions {
484*5e3eaea3SApple OSS Distributions char destfile[MAXPATHLEN];
485*5e3eaea3SApple OSS Distributions struct attrlist attrlist;
486*5e3eaea3SApple OSS Distributions char *xattr_key = "com.apple.xattr_test";
487*5e3eaea3SApple OSS Distributions char xattr_val[] = "xattr_foo";
488*5e3eaea3SApple OSS Distributions char *testfile = argv[0];
489*5e3eaea3SApple OSS Distributions uint32_t flags;
490*5e3eaea3SApple OSS Distributions int err, fd;
491*5e3eaea3SApple OSS Distributions
492*5e3eaea3SApple OSS Distributions /* wait for the other helper to be in ready state */
493*5e3eaea3SApple OSS Distributions sleep(1);
494*5e3eaea3SApple OSS Distributions
495*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
496*5e3eaea3SApple OSS Distributions fd = open(testfile, O_RDWR | O_CREAT, 0666);
497*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDWR|O_CREAT: %s", testfile);
498*5e3eaea3SApple OSS Distributions sleep(1);
499*5e3eaea3SApple OSS Distributions
500*5e3eaea3SApple OSS Distributions /* Test ftruncate (fd needs to be opened with write mode) */
501*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
502*5e3eaea3SApple OSS Distributions err = ftruncate(fd, 0);
503*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "fdtruncate: %s", testfile);
504*5e3eaea3SApple OSS Distributions sleep(1);
505*5e3eaea3SApple OSS Distributions
506*5e3eaea3SApple OSS Distributions /* Test (p)write. */
507*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
508*5e3eaea3SApple OSS Distributions err = (int)write(fd, destfile, sizeof(destfile));
509*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "write: %s", testfile);
510*5e3eaea3SApple OSS Distributions sleep(1);
511*5e3eaea3SApple OSS Distributions
512*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
513*5e3eaea3SApple OSS Distributions err = (int)pwrite(fd, destfile, sizeof(destfile), sizeof(destfile));
514*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "write: %s", testfile);
515*5e3eaea3SApple OSS Distributions sleep(1);
516*5e3eaea3SApple OSS Distributions
517*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(fd), "Close test file: %s", testfile);
518*5e3eaea3SApple OSS Distributions
519*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
520*5e3eaea3SApple OSS Distributions fd = open(testfile, O_RDONLY, 0666);
521*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDONLY: %s", testfile);
522*5e3eaea3SApple OSS Distributions
523*5e3eaea3SApple OSS Distributions /* Test (f)chflags syscall */
524*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
525*5e3eaea3SApple OSS Distributions err = chflags(testfile, 0);
526*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "chflags: %s", testfile);
527*5e3eaea3SApple OSS Distributions sleep(1);
528*5e3eaea3SApple OSS Distributions
529*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
530*5e3eaea3SApple OSS Distributions err = fchflags(fd, 0);
531*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "fchflags: %s", testfile);
532*5e3eaea3SApple OSS Distributions sleep(1);
533*5e3eaea3SApple OSS Distributions
534*5e3eaea3SApple OSS Distributions /* Test (f)chmod syscall */
535*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
536*5e3eaea3SApple OSS Distributions err = chmod(testfile, S_IRWXU);
537*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "chmod: %s", testfile);
538*5e3eaea3SApple OSS Distributions sleep(1);
539*5e3eaea3SApple OSS Distributions
540*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
541*5e3eaea3SApple OSS Distributions err = fchmod(fd, S_IRWXU);
542*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "fchmod: %s", testfile);
543*5e3eaea3SApple OSS Distributions sleep(1);
544*5e3eaea3SApple OSS Distributions
545*5e3eaea3SApple OSS Distributions /* Test clonefile */
546*5e3eaea3SApple OSS Distributions snprintf(destfile, sizeof(destfile), "%s.%d", testfile, rand());
547*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
548*5e3eaea3SApple OSS Distributions err = clonefile(testfile, destfile, CLONE_NOFOLLOW);
549*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "clonefile src: %s dest: %s", testfile, destfile);
550*5e3eaea3SApple OSS Distributions sleep(1);
551*5e3eaea3SApple OSS Distributions
552*5e3eaea3SApple OSS Distributions /* Test copyfile */
553*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
554*5e3eaea3SApple OSS Distributions err = copyfile(testfile, destfile, NULL, COPYFILE_DATA | COPYFILE_STAT);
555*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "copyfile src: %s dest: %s", testfile, destfile);
556*5e3eaea3SApple OSS Distributions sleep(1);
557*5e3eaea3SApple OSS Distributions
558*5e3eaea3SApple OSS Distributions /* Test unlink */
559*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
560*5e3eaea3SApple OSS Distributions err = unlink(destfile);
561*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "unlink: %s", destfile);
562*5e3eaea3SApple OSS Distributions sleep(1);
563*5e3eaea3SApple OSS Distributions
564*5e3eaea3SApple OSS Distributions /* Test (f)setxattr and (f)removexattr */
565*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
566*5e3eaea3SApple OSS Distributions err = setxattr(testfile, xattr_key, &xattr_val[0], sizeof(xattr_val), 0, 0);
567*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "setxattr: %s", testfile);
568*5e3eaea3SApple OSS Distributions sleep(1);
569*5e3eaea3SApple OSS Distributions
570*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
571*5e3eaea3SApple OSS Distributions err = removexattr(testfile, xattr_key, 0);
572*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "removexattr: %s", testfile);
573*5e3eaea3SApple OSS Distributions sleep(1);
574*5e3eaea3SApple OSS Distributions
575*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
576*5e3eaea3SApple OSS Distributions err = fsetxattr(fd, xattr_key, &xattr_val[0], sizeof(xattr_val), 0, 0);
577*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "fsetxattr: %s", testfile);
578*5e3eaea3SApple OSS Distributions sleep(1);
579*5e3eaea3SApple OSS Distributions
580*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
581*5e3eaea3SApple OSS Distributions err = fremovexattr(fd, xattr_key, 0);
582*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "fremovexattr: %s", testfile);
583*5e3eaea3SApple OSS Distributions sleep(1);
584*5e3eaea3SApple OSS Distributions
585*5e3eaea3SApple OSS Distributions /* Test (f)setattrlist */
586*5e3eaea3SApple OSS Distributions flags = 0;
587*5e3eaea3SApple OSS Distributions memset(&attrlist, 0, sizeof(attrlist));
588*5e3eaea3SApple OSS Distributions attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
589*5e3eaea3SApple OSS Distributions attrlist.commonattr = (ATTR_CMN_FLAGS);
590*5e3eaea3SApple OSS Distributions
591*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
592*5e3eaea3SApple OSS Distributions err = setattrlist(testfile, &attrlist, &flags, sizeof(flags), 0);
593*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "setattrlist: %s", testfile);
594*5e3eaea3SApple OSS Distributions sleep(1);
595*5e3eaea3SApple OSS Distributions
596*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
597*5e3eaea3SApple OSS Distributions err = fsetattrlist(fd, &attrlist, &flags, sizeof(flags), 0);
598*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "fsetattrlist: %s", testfile);
599*5e3eaea3SApple OSS Distributions sleep(1);
600*5e3eaea3SApple OSS Distributions
601*5e3eaea3SApple OSS Distributions /* Test truncate */
602*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
603*5e3eaea3SApple OSS Distributions err = truncate(testfile, 0);
604*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "truncate: %s", testfile);
605*5e3eaea3SApple OSS Distributions sleep(1);
606*5e3eaea3SApple OSS Distributions
607*5e3eaea3SApple OSS Distributions /* Test (f)utimes */
608*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
609*5e3eaea3SApple OSS Distributions err = utimes(testfile, NULL);
610*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "utimes: %s", testfile);
611*5e3eaea3SApple OSS Distributions sleep(1);
612*5e3eaea3SApple OSS Distributions
613*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
614*5e3eaea3SApple OSS Distributions err = futimes(fd, NULL);
615*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "futimes: %s", testfile);
616*5e3eaea3SApple OSS Distributions
617*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(fd), "Close test file: %s", testfile);
618*5e3eaea3SApple OSS Distributions }
619*5e3eaea3SApple OSS Distributions
620*5e3eaea3SApple OSS Distributions T_HELPER_DECL(file_syscalls_2, "Call file syscalls (mknod)", T_META_ASROOT(true))
621*5e3eaea3SApple OSS Distributions {
622*5e3eaea3SApple OSS Distributions char destfile[MAXPATHLEN];
623*5e3eaea3SApple OSS Distributions char *testfile = argv[0];
624*5e3eaea3SApple OSS Distributions int err;
625*5e3eaea3SApple OSS Distributions
626*5e3eaea3SApple OSS Distributions snprintf(destfile, sizeof(destfile), "%s.%d", testfile, rand());
627*5e3eaea3SApple OSS Distributions
628*5e3eaea3SApple OSS Distributions /* wait for the other helper to be in ready state */
629*5e3eaea3SApple OSS Distributions sleep(1);
630*5e3eaea3SApple OSS Distributions
631*5e3eaea3SApple OSS Distributions /* Test mknod */
632*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
633*5e3eaea3SApple OSS Distributions err = mknod(destfile, (S_IFCHR | S_IRWXU), 0);
634*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "mknod: %s", destfile);
635*5e3eaea3SApple OSS Distributions sleep(1);
636*5e3eaea3SApple OSS Distributions
637*5e3eaea3SApple OSS Distributions /* Test unlink */
638*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
639*5e3eaea3SApple OSS Distributions err = unlink(destfile);
640*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "unlink: %s", destfile);
641*5e3eaea3SApple OSS Distributions }
642*5e3eaea3SApple OSS Distributions
643*5e3eaea3SApple OSS Distributions /*
644*5e3eaea3SApple OSS Distributions * Test acquire, downgrade, and release lease.
645*5e3eaea3SApple OSS Distributions * a. Process A opens the file in O_RDONLY mode
646*5e3eaea3SApple OSS Distributions * b. Process A acquires write lease
647*5e3eaea3SApple OSS Distributions * c. Process A downgrade from write to read lease
648*5e3eaea3SApple OSS Distributions * d. Process A release lease
649*5e3eaea3SApple OSS Distributions *
650*5e3eaea3SApple OSS Distributions * Result: Lease operations should succeed as expected.
651*5e3eaea3SApple OSS Distributions */
652*5e3eaea3SApple OSS Distributions T_DECL(acquire_downgrade_release, "Test acquire, downgrade and release lease", T_META_ENABLED(TARGET_OS_OSX))
653*5e3eaea3SApple OSS Distributions {
654*5e3eaea3SApple OSS Distributions int err, fd;
655*5e3eaea3SApple OSS Distributions
656*5e3eaea3SApple OSS Distributions create_test_file();
657*5e3eaea3SApple OSS Distributions
658*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
659*5e3eaea3SApple OSS Distributions fd = open(g_testfile, O_RDONLY, 0666);
660*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDONLY: %s", g_testfile);
661*5e3eaea3SApple OSS Distributions
662*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
663*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_WRLCK);
664*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Acquire write lease: %s", g_testfile);
665*5e3eaea3SApple OSS Distributions
666*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
667*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_GETLEASE);
668*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_WRLCK, "Retrieve lease: %s", g_testfile);
669*5e3eaea3SApple OSS Distributions
670*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
671*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_RDLCK);
672*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Downgrade to read lease: %s", g_testfile);
673*5e3eaea3SApple OSS Distributions
674*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
675*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_GETLEASE);
676*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_RDLCK, "Retrieve lease: %s", g_testfile);
677*5e3eaea3SApple OSS Distributions
678*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
679*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_UNLCK);
680*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Release lease: %s", g_testfile);
681*5e3eaea3SApple OSS Distributions
682*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
683*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_GETLEASE);
684*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_UNLCK, "Retrieve lease: %s", g_testfile);
685*5e3eaea3SApple OSS Distributions
686*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(fd), "Close test file: %s", g_testfile);
687*5e3eaea3SApple OSS Distributions }
688*5e3eaea3SApple OSS Distributions
689*5e3eaea3SApple OSS Distributions /*
690*5e3eaea3SApple OSS Distributions * Test acquire lease failure due to open conflicts.
691*5e3eaea3SApple OSS Distributions * a. Process A opens the file in O_RDWR mode
692*5e3eaea3SApple OSS Distributions * b. Process B opens the file in O_RDONLY mode
693*5e3eaea3SApple OSS Distributions * c. Process B tries to acquire read lease
694*5e3eaea3SApple OSS Distributions *
695*5e3eaea3SApple OSS Distributions * Result: Process B should fail to acquire read lease with EAGAIN due to the
696*5e3eaea3SApple OSS Distributions * file has been opened with write mode (O_RDWR).
697*5e3eaea3SApple OSS Distributions */
698*5e3eaea3SApple OSS Distributions T_DECL(open_conflict_1, "Test acquire read lease failure due to open conflicts", T_META_ENABLED(TARGET_OS_OSX))
699*5e3eaea3SApple OSS Distributions {
700*5e3eaea3SApple OSS Distributions const char *helper_test_names[] = {"open_rdonly_acquire_read_lease_EAGAIN"};
701*5e3eaea3SApple OSS Distributions int fd;
702*5e3eaea3SApple OSS Distributions
703*5e3eaea3SApple OSS Distributions create_test_file();
704*5e3eaea3SApple OSS Distributions
705*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
706*5e3eaea3SApple OSS Distributions fd = open(g_testfile, O_RDWR, 0666);
707*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDWR: %s", g_testfile);
708*5e3eaea3SApple OSS Distributions
709*5e3eaea3SApple OSS Distributions run_helpers(helper_test_names, 1);
710*5e3eaea3SApple OSS Distributions
711*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(fd), "Close test file: %s", g_testfile);
712*5e3eaea3SApple OSS Distributions }
713*5e3eaea3SApple OSS Distributions
714*5e3eaea3SApple OSS Distributions /*
715*5e3eaea3SApple OSS Distributions * Test acquire lease failure due to open conflicts.
716*5e3eaea3SApple OSS Distributions * a. Process A opens the file in O_RDONLY mode
717*5e3eaea3SApple OSS Distributions * b. Process B opens the file in O_RDWR mode
718*5e3eaea3SApple OSS Distributions * c. Process B tries to acquire write lease
719*5e3eaea3SApple OSS Distributions *
720*5e3eaea3SApple OSS Distributions * Result: Process B should fail to acquire write lease with EAGAIN due to the
721*5e3eaea3SApple OSS Distributions * file has been opened elsewhere.
722*5e3eaea3SApple OSS Distributions */
723*5e3eaea3SApple OSS Distributions T_DECL(open_conflict_2, "Test acquire write lease failure due to open conflicts", T_META_ENABLED(TARGET_OS_OSX))
724*5e3eaea3SApple OSS Distributions {
725*5e3eaea3SApple OSS Distributions const char *helper_test_names[] = {"open_rdwr_acquire_write_lease_EAGAIN"};
726*5e3eaea3SApple OSS Distributions int fd;
727*5e3eaea3SApple OSS Distributions
728*5e3eaea3SApple OSS Distributions create_test_file();
729*5e3eaea3SApple OSS Distributions
730*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
731*5e3eaea3SApple OSS Distributions fd = open(g_testfile, O_RDONLY, 0666);
732*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDONLY: %s", g_testfile);
733*5e3eaea3SApple OSS Distributions
734*5e3eaea3SApple OSS Distributions run_helpers(helper_test_names, 1);
735*5e3eaea3SApple OSS Distributions
736*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(fd), "Close test file: %s", g_testfile);
737*5e3eaea3SApple OSS Distributions }
738*5e3eaea3SApple OSS Distributions
739*5e3eaea3SApple OSS Distributions /*
740*5e3eaea3SApple OSS Distributions * Test multiple processes put a read lease on the file.
741*5e3eaea3SApple OSS Distributions * a. Process A opens the file with O_RDONLY mode and place a read lease
742*5e3eaea3SApple OSS Distributions * b. Process B opens the file with O_RDONLY mode and place a read lease
743*5e3eaea3SApple OSS Distributions *
744*5e3eaea3SApple OSS Distributions * Result: Both processes should succeed in placing read lease on the file.
745*5e3eaea3SApple OSS Distributions */
746*5e3eaea3SApple OSS Distributions T_DECL(multiple_read_leases, "Test multiple processes put a read lease on the file", T_META_ENABLED(TARGET_OS_OSX))
747*5e3eaea3SApple OSS Distributions {
748*5e3eaea3SApple OSS Distributions const char *helper_test_names[] = {"open_rdonly_acquire_read_lease_succeed",
749*5e3eaea3SApple OSS Distributions "open_rdonly_acquire_read_lease_succeed"};
750*5e3eaea3SApple OSS Distributions
751*5e3eaea3SApple OSS Distributions create_test_file();
752*5e3eaea3SApple OSS Distributions run_helpers(helper_test_names, 2);
753*5e3eaea3SApple OSS Distributions }
754*5e3eaea3SApple OSS Distributions
755*5e3eaea3SApple OSS Distributions /*
756*5e3eaea3SApple OSS Distributions * Test acquire and release lease when there is no lease is in place.
757*5e3eaea3SApple OSS Distributions *
758*5e3eaea3SApple OSS Distributions * Result: Acquire lease should succeed with F_UNLCK (no lease).
759*5e3eaea3SApple OSS Distributions * Release lease should fail with ENOLCK.
760*5e3eaea3SApple OSS Distributions */
761*5e3eaea3SApple OSS Distributions T_DECL(acquire_release_no_lease, "Test acquire and release lease when there is no lease is in place", T_META_ENABLED(TARGET_OS_OSX))
762*5e3eaea3SApple OSS Distributions {
763*5e3eaea3SApple OSS Distributions int err, fd;
764*5e3eaea3SApple OSS Distributions
765*5e3eaea3SApple OSS Distributions create_test_file();
766*5e3eaea3SApple OSS Distributions
767*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
768*5e3eaea3SApple OSS Distributions fd = open(g_testfile, O_RDWR, 0666);
769*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDWR: %s", g_testfile);
770*5e3eaea3SApple OSS Distributions
771*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
772*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_GETLEASE);
773*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_UNLCK, "Retrieve lease: %s", g_testfile);
774*5e3eaea3SApple OSS Distributions
775*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
776*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_UNLCK);
777*5e3eaea3SApple OSS Distributions T_ASSERT_TRUE((err == -1) && (errno == ENOLCK), "Release lease: %s",
778*5e3eaea3SApple OSS Distributions g_testfile);
779*5e3eaea3SApple OSS Distributions }
780*5e3eaea3SApple OSS Distributions
781*5e3eaea3SApple OSS Distributions /*
782*5e3eaea3SApple OSS Distributions * Test acquire, release and retrieve lease on non-regular file.
783*5e3eaea3SApple OSS Distributions *
784*5e3eaea3SApple OSS Distributions * Result: Acquire, release and retrieve lease should fail with EBADF.
785*5e3eaea3SApple OSS Distributions */
786*5e3eaea3SApple OSS Distributions T_DECL(acquire_release_retrieve_non_file, "Test acquire, release and retrieve lease on non-regular file", T_META_ENABLED(TARGET_OS_OSX))
787*5e3eaea3SApple OSS Distributions {
788*5e3eaea3SApple OSS Distributions int err, fd;
789*5e3eaea3SApple OSS Distributions
790*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
791*5e3eaea3SApple OSS Distributions fd = socket(AF_UNIX, SOCK_STREAM, 0);
792*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open socket");
793*5e3eaea3SApple OSS Distributions
794*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
795*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_RDLCK);
796*5e3eaea3SApple OSS Distributions T_ASSERT_TRUE((err == -1) && (errno == EBADF), "Acquire read lease on socket");
797*5e3eaea3SApple OSS Distributions
798*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
799*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_WRLCK);
800*5e3eaea3SApple OSS Distributions T_ASSERT_TRUE((err == -1) && (errno == EBADF), "Acquire write lease on socket");
801*5e3eaea3SApple OSS Distributions
802*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
803*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_UNLCK);
804*5e3eaea3SApple OSS Distributions T_ASSERT_TRUE((err == -1) && (errno == EBADF), "Release lease on socket");
805*5e3eaea3SApple OSS Distributions
806*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
807*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_GETLEASE);
808*5e3eaea3SApple OSS Distributions T_ASSERT_TRUE((err == -1) && (errno == EBADF), "Retrieve lease on socket");
809*5e3eaea3SApple OSS Distributions
810*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(fd), "Close socket");
811*5e3eaea3SApple OSS Distributions }
812*5e3eaea3SApple OSS Distributions
813*5e3eaea3SApple OSS Distributions /*
814*5e3eaea3SApple OSS Distributions * Test retrieve and downgrade lease with duplicated fd created with dup(2).
815*5e3eaea3SApple OSS Distributions * a. Process A opens the file with O_RDONLY mode and place a write lease
816*5e3eaea3SApple OSS Distributions * b. Process A duplicates the existing file descriptor
817*5e3eaea3SApple OSS Distributions * c. Process A retrieves and downgrade lease with duplicated fd
818*5e3eaea3SApple OSS Distributions * d. Process A closes the original and duplicated fds to release lease.
819*5e3eaea3SApple OSS Distributions *
820*5e3eaea3SApple OSS Distributions * Result: Retrieve and downgrade with duplicated fd should succeed.
821*5e3eaea3SApple OSS Distributions * When all fds are closed, lease should be released implicity.
822*5e3eaea3SApple OSS Distributions */
823*5e3eaea3SApple OSS Distributions T_DECL(retrieve_downgrade_dup_fd, "Test retrieve and downgrade lease with duplicated fd created with dup()", T_META_ENABLED(TARGET_OS_OSX))
824*5e3eaea3SApple OSS Distributions {
825*5e3eaea3SApple OSS Distributions int err, dup_fd, fd;
826*5e3eaea3SApple OSS Distributions
827*5e3eaea3SApple OSS Distributions create_test_file();
828*5e3eaea3SApple OSS Distributions
829*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
830*5e3eaea3SApple OSS Distributions fd = open(g_testfile, O_RDONLY, 0666);
831*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDONLY: %s", g_testfile);
832*5e3eaea3SApple OSS Distributions
833*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
834*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_GETLEASE);
835*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_UNLCK, "Retrieve lease: %s", g_testfile);
836*5e3eaea3SApple OSS Distributions
837*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
838*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_WRLCK);
839*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Acquire write lease: %s", g_testfile);
840*5e3eaea3SApple OSS Distributions
841*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
842*5e3eaea3SApple OSS Distributions dup_fd = dup(fd);
843*5e3eaea3SApple OSS Distributions T_ASSERT_NE(dup_fd, -1, "Duplicate existing fd: %d", fd);
844*5e3eaea3SApple OSS Distributions
845*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
846*5e3eaea3SApple OSS Distributions err = fcntl(dup_fd, F_GETLEASE);
847*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_WRLCK, "Retrieve lease with dup fd: %d", dup_fd);
848*5e3eaea3SApple OSS Distributions
849*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
850*5e3eaea3SApple OSS Distributions err = fcntl(dup_fd, F_SETLEASE, F_RDLCK);
851*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Downgrade to read lease with dup fd: %d", dup_fd);
852*5e3eaea3SApple OSS Distributions
853*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
854*5e3eaea3SApple OSS Distributions err = fcntl(dup_fd, F_GETLEASE);
855*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_RDLCK, "Retrieve lease with dup fd: %d", dup_fd);
856*5e3eaea3SApple OSS Distributions
857*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(fd), "Close original fd");
858*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(dup_fd), "Close duplicated fd");
859*5e3eaea3SApple OSS Distributions
860*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
861*5e3eaea3SApple OSS Distributions fd = open(g_testfile, O_RDONLY, 0666);
862*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDONLY: %s", g_testfile);
863*5e3eaea3SApple OSS Distributions
864*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
865*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_GETLEASE);
866*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_UNLCK, "Retrieve lease: %s", g_testfile);
867*5e3eaea3SApple OSS Distributions
868*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(fd), "Close fd");
869*5e3eaea3SApple OSS Distributions }
870*5e3eaea3SApple OSS Distributions
871*5e3eaea3SApple OSS Distributions /*
872*5e3eaea3SApple OSS Distributions * Test retrieve and release lease with duplicated fd created with fork(2).
873*5e3eaea3SApple OSS Distributions * a. Process A opens the file with O_RDONLY mode and place a write lease
874*5e3eaea3SApple OSS Distributions * b. Process A forks to create a child process
875*5e3eaea3SApple OSS Distributions * c. Child process retrieves and releases lease with duplicated fd
876*5e3eaea3SApple OSS Distributions * d. Child process exits
877*5e3eaea3SApple OSS Distributions * e. Process A verifies the lease has been released
878*5e3eaea3SApple OSS Distributions *
879*5e3eaea3SApple OSS Distributions * Result: Retrieve and release with duplicated fd should succeed.
880*5e3eaea3SApple OSS Distributions * Child process should be able to release the leased placed by the
881*5e3eaea3SApple OSS Distributions * parent process.
882*5e3eaea3SApple OSS Distributions */
883*5e3eaea3SApple OSS Distributions T_DECL(retrieve_release_fork_fd, "Test retrieve and release lease with duplicated fd created with fork()", T_META_ENABLED(TARGET_OS_OSX))
884*5e3eaea3SApple OSS Distributions {
885*5e3eaea3SApple OSS Distributions pid_t child_pid;
886*5e3eaea3SApple OSS Distributions int err, fd;
887*5e3eaea3SApple OSS Distributions
888*5e3eaea3SApple OSS Distributions create_test_file();
889*5e3eaea3SApple OSS Distributions
890*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
891*5e3eaea3SApple OSS Distributions fd = open(g_testfile, O_RDONLY, 0666);
892*5e3eaea3SApple OSS Distributions T_ASSERT_NE(fd, -1, "Open test fi1e in O_RDONLY: %s", g_testfile);
893*5e3eaea3SApple OSS Distributions
894*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
895*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_GETLEASE);
896*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_UNLCK, "Retrieve lease: %s", g_testfile);
897*5e3eaea3SApple OSS Distributions
898*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
899*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_WRLCK);
900*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Acquire write lease: %s", g_testfile);
901*5e3eaea3SApple OSS Distributions
902*5e3eaea3SApple OSS Distributions child_pid = fork();
903*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(child_pid, "Fork process");
904*5e3eaea3SApple OSS Distributions
905*5e3eaea3SApple OSS Distributions if (child_pid == 0) {
906*5e3eaea3SApple OSS Distributions /* child process */
907*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_GETLEASE);
908*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_WRLCK, "Retrieve lease with fork fd: %d", fd);
909*5e3eaea3SApple OSS Distributions
910*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
911*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_SETLEASE, F_UNLCK);
912*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Release lease with fork fd: %d", fd);
913*5e3eaea3SApple OSS Distributions
914*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
915*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_GETLEASE);
916*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_UNLCK, "Retrieve lease with fork fd: %d", fd);
917*5e3eaea3SApple OSS Distributions
918*5e3eaea3SApple OSS Distributions exit(0);
919*5e3eaea3SApple OSS Distributions } else {
920*5e3eaea3SApple OSS Distributions /* wait for child process to exit */
921*5e3eaea3SApple OSS Distributions if (dt_waitpid(child_pid, &err, NULL, 30) == false) {
922*5e3eaea3SApple OSS Distributions T_FAIL("dt_waitpid() failed on child pid %d", child_pid);
923*5e3eaea3SApple OSS Distributions }
924*5e3eaea3SApple OSS Distributions
925*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
926*5e3eaea3SApple OSS Distributions err = fcntl(fd, F_GETLEASE);
927*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_UNLCK, "Retrieve lease with parent fd: %d", fd);
928*5e3eaea3SApple OSS Distributions
929*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(fd), "Close fd");
930*5e3eaea3SApple OSS Distributions }
931*5e3eaea3SApple OSS Distributions }
932*5e3eaea3SApple OSS Distributions
933*5e3eaea3SApple OSS Distributions /*
934*5e3eaea3SApple OSS Distributions * Test lease break release event.
935*5e3eaea3SApple OSS Distributions * a. Process A opens the file in O_RDONLY mode and place a read lease
936*5e3eaea3SApple OSS Distributions * b. Process B opens the file in O_RDWR mode and open syscall is blocked
937*5e3eaea3SApple OSS Distributions * c. Lease break release event is sent to Process A
938*5e3eaea3SApple OSS Distributions *
939*5e3eaea3SApple OSS Distributions * Result: Process A releases the lease and process B's open is unblocked
940*5e3eaea3SApple OSS Distributions */
941*5e3eaea3SApple OSS Distributions T_DECL(lease_break_release_1, "Test lease break release event when file is opened in O_RDWR mode", T_META_ENABLED(TARGET_OS_OSX))
942*5e3eaea3SApple OSS Distributions {
943*5e3eaea3SApple OSS Distributions const char *helper_test_names[] = {"open_rdonly_read_lease_release", "open_rdwr"};
944*5e3eaea3SApple OSS Distributions
945*5e3eaea3SApple OSS Distributions create_test_file();
946*5e3eaea3SApple OSS Distributions
947*5e3eaea3SApple OSS Distributions run_helpers(helper_test_names, 2);
948*5e3eaea3SApple OSS Distributions }
949*5e3eaea3SApple OSS Distributions
950*5e3eaea3SApple OSS Distributions /*
951*5e3eaea3SApple OSS Distributions * Test lease break release event.
952*5e3eaea3SApple OSS Distributions * a. Process A opens the file in O_RDONLY mode and place a read lease
953*5e3eaea3SApple OSS Distributions * b. Process B truncates the file and truncate syscall is blocked
954*5e3eaea3SApple OSS Distributions * c. Lease break release event is sent to Process A
955*5e3eaea3SApple OSS Distributions *
956*5e3eaea3SApple OSS Distributions * Result: Process A releases the lease and process B's truncate is unblocked.
957*5e3eaea3SApple OSS Distributions */
958*5e3eaea3SApple OSS Distributions T_DECL(lease_break_release_2, "Test lease break release event when file is truncated", T_META_ENABLED(TARGET_OS_OSX))
959*5e3eaea3SApple OSS Distributions {
960*5e3eaea3SApple OSS Distributions const char *helper_test_names[] = {"open_rdonly_read_lease_release", "truncate"};
961*5e3eaea3SApple OSS Distributions
962*5e3eaea3SApple OSS Distributions create_test_file();
963*5e3eaea3SApple OSS Distributions
964*5e3eaea3SApple OSS Distributions run_helpers(helper_test_names, 2);
965*5e3eaea3SApple OSS Distributions }
966*5e3eaea3SApple OSS Distributions
967*5e3eaea3SApple OSS Distributions /*
968*5e3eaea3SApple OSS Distributions * Test lease break release event.
969*5e3eaea3SApple OSS Distributions * a. Process A opens the file in O_RDONLY mode and place a read lease
970*5e3eaea3SApple OSS Distributions * b. Process B opens the file in O_RDONLY mode and requests byte range lock
971*5e3eaea3SApple OSS Distributions * via fcntl(F_SETLK or F_OFD_SETLK)
972*5e3eaea3SApple OSS Distributions * c. Lease break release event is sent to Process A
973*5e3eaea3SApple OSS Distributions *
974*5e3eaea3SApple OSS Distributions * Result: Process A releases the lease and process B's fcntl call is unblocked.
975*5e3eaea3SApple OSS Distributions */
976*5e3eaea3SApple OSS Distributions T_DECL(lease_break_release_3, "Test lease break release event when byte range lock is requested", T_META_ENABLED(TARGET_OS_OSX))
977*5e3eaea3SApple OSS Distributions {
978*5e3eaea3SApple OSS Distributions const char *helper_test_names[] = {"open_rdonly_read_lease_release", "open_rdonly_request_read_range_lock"};
979*5e3eaea3SApple OSS Distributions
980*5e3eaea3SApple OSS Distributions create_test_file();
981*5e3eaea3SApple OSS Distributions
982*5e3eaea3SApple OSS Distributions run_helpers(helper_test_names, 2);
983*5e3eaea3SApple OSS Distributions }
984*5e3eaea3SApple OSS Distributions
985*5e3eaea3SApple OSS Distributions /*
986*5e3eaea3SApple OSS Distributions * Test lease break release event.
987*5e3eaea3SApple OSS Distributions * a. Process A opens the file in O_RDONLY mode and place a read lease
988*5e3eaea3SApple OSS Distributions * a. Process B opens the file in O_RDONLY mode and place a read lease
989*5e3eaea3SApple OSS Distributions * b. Process C opens the file in O_RDWR mode and open syscall is blocked
990*5e3eaea3SApple OSS Distributions * c. Lease break release events are sent to Process A and B
991*5e3eaea3SApple OSS Distributions *
992*5e3eaea3SApple OSS Distributions * Result: Process A and B release the lease and process C's open is unblocked
993*5e3eaea3SApple OSS Distributions */
994*5e3eaea3SApple OSS Distributions T_DECL(lease_break_release_4, "Test multiple lease break release events", T_META_ENABLED(TARGET_OS_OSX))
995*5e3eaea3SApple OSS Distributions {
996*5e3eaea3SApple OSS Distributions const char *helper_test_names[] = {"open_rdonly_read_lease_release",
997*5e3eaea3SApple OSS Distributions "open_rdonly_read_lease_release", "open_rdwr"};
998*5e3eaea3SApple OSS Distributions
999*5e3eaea3SApple OSS Distributions create_test_file();
1000*5e3eaea3SApple OSS Distributions
1001*5e3eaea3SApple OSS Distributions run_helpers(helper_test_names, 3);
1002*5e3eaea3SApple OSS Distributions }
1003*5e3eaea3SApple OSS Distributions
1004*5e3eaea3SApple OSS Distributions /*
1005*5e3eaea3SApple OSS Distributions * Test lease break downgrade event.
1006*5e3eaea3SApple OSS Distributions * a. Process A opens the file in O_RDONLY mode and place a write lease
1007*5e3eaea3SApple OSS Distributions * b. Process B opens the file in O_RDONLY mode and open syscall is blocked
1008*5e3eaea3SApple OSS Distributions * c. Lease break downgrade event is sent to Process A
1009*5e3eaea3SApple OSS Distributions *
1010*5e3eaea3SApple OSS Distributions * Result: Process A downgrades the lease and process B's open is unblocked.
1011*5e3eaea3SApple OSS Distributions */
1012*5e3eaea3SApple OSS Distributions T_DECL(lease_break_downgrade_1, "Test lease break downgrade event with read-only opens", T_META_ENABLED(TARGET_OS_OSX))
1013*5e3eaea3SApple OSS Distributions {
1014*5e3eaea3SApple OSS Distributions const char *helper_test_names[] = {"open_rdonly_write_lease_downgrade", "open_rdonly"};
1015*5e3eaea3SApple OSS Distributions
1016*5e3eaea3SApple OSS Distributions create_test_file();
1017*5e3eaea3SApple OSS Distributions
1018*5e3eaea3SApple OSS Distributions run_helpers(helper_test_names, 2);
1019*5e3eaea3SApple OSS Distributions }
1020*5e3eaea3SApple OSS Distributions
1021*5e3eaea3SApple OSS Distributions /*
1022*5e3eaea3SApple OSS Distributions * Test lease break downgrade event.
1023*5e3eaea3SApple OSS Distributions * a. Process A opens the file multiple times in O_RDWR mode and place a
1024*5e3eaea3SApple OSS Distributions * write lease
1025*5e3eaea3SApple OSS Distributions * b. Process B opens the file in O_RDONLY mode and open syscall is blocked
1026*5e3eaea3SApple OSS Distributions * c. Lease break downgrade event is sent to Process A
1027*5e3eaea3SApple OSS Distributions *
1028*5e3eaea3SApple OSS Distributions * Result: Process A downgrades the lease and process B's open is unblocked.
1029*5e3eaea3SApple OSS Distributions */
1030*5e3eaea3SApple OSS Distributions T_DECL(lease_break_downgrade_2, "Test lease break downgrade event with multiple read-write opens", T_META_ENABLED(TARGET_OS_OSX))
1031*5e3eaea3SApple OSS Distributions {
1032*5e3eaea3SApple OSS Distributions const char *helper_test_names[] = {"open_rw_write_lease_downgrade", "open_rdonly"};
1033*5e3eaea3SApple OSS Distributions
1034*5e3eaea3SApple OSS Distributions create_test_file();
1035*5e3eaea3SApple OSS Distributions
1036*5e3eaea3SApple OSS Distributions run_helpers(helper_test_names, 2);
1037*5e3eaea3SApple OSS Distributions }
1038*5e3eaea3SApple OSS Distributions
1039*5e3eaea3SApple OSS Distributions /*
1040*5e3eaea3SApple OSS Distributions * Test lease break timedout
1041*5e3eaea3SApple OSS Distributions * a. Process A opens the file in O_RDONLY mode and place a read lease
1042*5e3eaea3SApple OSS Distributions * b. Process B opens the file in O_RDWR mode and open syscall is blocked
1043*5e3eaea3SApple OSS Distributions * c. Lease break release event is sent to Process A
1044*5e3eaea3SApple OSS Distributions * d. Lease is not release within sysctl's 'vfs.lease.break_timeout'
1045*5e3eaea3SApple OSS Distributions *
1046*5e3eaea3SApple OSS Distributions * Result: Kernel forcibly breaks the lease and process B's open is unblocked.
1047*5e3eaea3SApple OSS Distributions */
1048*5e3eaea3SApple OSS Distributions T_DECL(lease_break_timedout, "Test lease break timedout", T_META_ENABLED(TARGET_OS_OSX))
1049*5e3eaea3SApple OSS Distributions {
1050*5e3eaea3SApple OSS Distributions const char *helper_test_names[] = {"open_rdonly_read_lease_timedout", "open_rdwr"};
1051*5e3eaea3SApple OSS Distributions
1052*5e3eaea3SApple OSS Distributions create_test_file();
1053*5e3eaea3SApple OSS Distributions
1054*5e3eaea3SApple OSS Distributions run_helpers(helper_test_names, 2);
1055*5e3eaea3SApple OSS Distributions }
1056*5e3eaea3SApple OSS Distributions
1057*5e3eaea3SApple OSS Distributions /*
1058*5e3eaea3SApple OSS Distributions * Test acquire and release lease on directory.
1059*5e3eaea3SApple OSS Distributions * a. Process A opens the directory in O_RDONLY mode
1060*5e3eaea3SApple OSS Distributions * b. Process A acquires read lease
1061*5e3eaea3SApple OSS Distributions * d. Process A release lease
1062*5e3eaea3SApple OSS Distributions *
1063*5e3eaea3SApple OSS Distributions * Result: Lease operations should succeed as expected.
1064*5e3eaea3SApple OSS Distributions */
1065*5e3eaea3SApple OSS Distributions T_DECL(acquire_release_read_lease_dir, "Test acquire and release read lease", T_META_ENABLED(TARGET_OS_OSX))
1066*5e3eaea3SApple OSS Distributions {
1067*5e3eaea3SApple OSS Distributions int err, dir_fd;
1068*5e3eaea3SApple OSS Distributions
1069*5e3eaea3SApple OSS Distributions create_test_file();
1070*5e3eaea3SApple OSS Distributions
1071*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
1072*5e3eaea3SApple OSS Distributions dir_fd = open(g_testdir, O_RDONLY);
1073*5e3eaea3SApple OSS Distributions T_ASSERT_NE(dir_fd, -1, "Open test dir in O_RDONLY: %s", g_testdir);
1074*5e3eaea3SApple OSS Distributions
1075*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
1076*5e3eaea3SApple OSS Distributions err = fcntl(dir_fd, F_SETLEASE, F_RDLCK);
1077*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Acquire read lease: %s", g_testdir);
1078*5e3eaea3SApple OSS Distributions
1079*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
1080*5e3eaea3SApple OSS Distributions err = fcntl(dir_fd, F_GETLEASE);
1081*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_RDLCK, "Retrieve lease: %s", g_testdir);
1082*5e3eaea3SApple OSS Distributions
1083*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
1084*5e3eaea3SApple OSS Distributions err = fcntl(dir_fd, F_SETLEASE, F_UNLCK);
1085*5e3eaea3SApple OSS Distributions T_ASSERT_NE(err, -1, "Release lease: %s", g_testdir);
1086*5e3eaea3SApple OSS Distributions
1087*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
1088*5e3eaea3SApple OSS Distributions err = fcntl(dir_fd, F_GETLEASE);
1089*5e3eaea3SApple OSS Distributions T_ASSERT_EQ(err, F_UNLCK, "Retrieve lease: %s", g_testdir);
1090*5e3eaea3SApple OSS Distributions
1091*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(dir_fd), "Close test dir: %s", g_testdir);
1092*5e3eaea3SApple OSS Distributions }
1093*5e3eaea3SApple OSS Distributions
1094*5e3eaea3SApple OSS Distributions /*
1095*5e3eaea3SApple OSS Distributions * Test acquire write lease on directory.
1096*5e3eaea3SApple OSS Distributions *
1097*5e3eaea3SApple OSS Distributions * Result: Acquire write lease should fail with EBADF.
1098*5e3eaea3SApple OSS Distributions */
1099*5e3eaea3SApple OSS Distributions T_DECL(acquire_write_lease_dir, "Test acquire write lease on directory", T_META_ENABLED(TARGET_OS_OSX))
1100*5e3eaea3SApple OSS Distributions {
1101*5e3eaea3SApple OSS Distributions int err, dir_fd;
1102*5e3eaea3SApple OSS Distributions
1103*5e3eaea3SApple OSS Distributions create_test_file();
1104*5e3eaea3SApple OSS Distributions
1105*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
1106*5e3eaea3SApple OSS Distributions dir_fd = open(g_testdir, O_RDONLY);
1107*5e3eaea3SApple OSS Distributions T_ASSERT_NE(dir_fd, -1, "Open test dir in O_RDONLY: %s", g_testdir);
1108*5e3eaea3SApple OSS Distributions
1109*5e3eaea3SApple OSS Distributions T_WITH_ERRNO;
1110*5e3eaea3SApple OSS Distributions err = fcntl(dir_fd, F_SETLEASE, F_WRLCK);
1111*5e3eaea3SApple OSS Distributions T_ASSERT_TRUE((err == -1) && (errno == ENOTSUP), "Acquire write lease on directory: %s", g_testdir);
1112*5e3eaea3SApple OSS Distributions
1113*5e3eaea3SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(close(dir_fd), "Close test dir");
1114*5e3eaea3SApple OSS Distributions }
1115*5e3eaea3SApple OSS Distributions
1116*5e3eaea3SApple OSS Distributions /*
1117*5e3eaea3SApple OSS Distributions * Test lease break release event for directory read leasing.
1118*5e3eaea3SApple OSS Distributions * a. Process A opens the directory in O_RDONLY mode and place a read lease
1119*5e3eaea3SApple OSS Distributions * b. Process B performs various syscalls that can cause its directory contents
1120*5e3eaea3SApple OSS Distributions * (namespace) to change, modify contents or change attributes on the
1121*5e3eaea3SApple OSS Distributions * immediate files.
1122*5e3eaea3SApple OSS Distributions *
1123*5e3eaea3SApple OSS Distributions * Result: Process A releases the lease and process B's syscall is unblocked.
1124*5e3eaea3SApple OSS Distributions */
1125*5e3eaea3SApple OSS Distributions T_DECL(read_lease_dir_1, "Test directory read leasing and lease break events", T_META_ENABLED(TARGET_OS_OSX))
1126*5e3eaea3SApple OSS Distributions {
1127*5e3eaea3SApple OSS Distributions const char *helper_test_names[] = {"open_rdonly_dir_read_lease", "file_syscalls"};
1128*5e3eaea3SApple OSS Distributions
1129*5e3eaea3SApple OSS Distributions create_test_file();
1130*5e3eaea3SApple OSS Distributions
1131*5e3eaea3SApple OSS Distributions run_helpers(helper_test_names, 2);
1132*5e3eaea3SApple OSS Distributions }
1133*5e3eaea3SApple OSS Distributions
1134*5e3eaea3SApple OSS Distributions T_DECL(read_lease_dir_2, "Test directory read leasing and lease break events", T_META_ENABLED(TARGET_OS_OSX))
1135*5e3eaea3SApple OSS Distributions {
1136*5e3eaea3SApple OSS Distributions const char *helper_test_names[] = {"open_rdonly_dir_read_lease", "file_syscalls_2"};
1137*5e3eaea3SApple OSS Distributions
1138*5e3eaea3SApple OSS Distributions create_test_file();
1139*5e3eaea3SApple OSS Distributions
1140*5e3eaea3SApple OSS Distributions run_helpers(helper_test_names, 2);
1141*5e3eaea3SApple OSS Distributions }
1142