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