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