flock_helper.c revision 268385
1/*-
2 * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
3 * Authors: Doug Rabson <dfr@rabson.org>
4 * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: head/tools/regression/file/flock/flock.c 268385 2014-07-08 08:11:52Z kib $
28 */
29
30#include <sys/file.h>
31#include <sys/time.h>
32#ifdef __FreeBSD__
33#include <sys/mount.h>
34#endif
35#include <sys/stat.h>
36#include <sys/wait.h>
37
38#include <err.h>
39#include <errno.h>
40#include <fcntl.h>
41#include <pthread.h>
42#include <signal.h>
43#include <stdint.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <unistd.h>
48
49#ifdef __FreeBSD__
50#if __FreeBSD_version >= 800028
51#define HAVE_SYSID
52#endif
53#include <sys/cdefs.h>
54#else
55#ifndef __unused
56#ifdef __GNUC__
57#define	__unused	__attribute__((__unused__))
58#else
59#define __unused
60#endif
61#endif
62#endif
63
64int verbose = 0;
65
66static int
67make_file(const char *pathname, off_t sz)
68{
69	struct stat st;
70	const char *template = "/flocktempXXXXXX";
71	size_t len;
72	char *filename;
73	int fd;
74
75	if (stat(pathname, &st) == 0) {
76		if (S_ISREG(st.st_mode)) {
77			fd = open(pathname, O_RDWR);
78			if (fd < 0)
79				err(1, "open(%s)", pathname);
80			if (ftruncate(fd, sz) < 0)
81				err(1, "ftruncate");
82			return (fd);
83		}
84	}
85
86	len = strlen(pathname) + strlen(template) + 1;
87	filename = malloc(len);
88	strcpy(filename, pathname);
89	strcat(filename, template);
90	fd = mkstemp(filename);
91	if (fd < 0)
92		err(1, "mkstemp");
93	if (ftruncate(fd, sz) < 0)
94		err(1, "ftruncate");
95	if (unlink(filename) < 0)
96		err(1, "unlink");
97	free(filename);
98
99	return (fd);
100}
101
102static void
103ignore_alarm(int __unused sig)
104{
105}
106
107static int
108safe_waitpid(pid_t pid)
109{
110	int save_errno;
111	int status;
112
113	save_errno = errno;
114	errno = 0;
115	while (waitpid(pid, &status, 0) != pid) {
116		if (errno == EINTR)
117			continue;
118		err(1, "waitpid");
119	}
120	errno = save_errno;
121
122	return (status);
123}
124
125#define FAIL(test)					\
126	do {						\
127		if (test) {				\
128			printf("FAIL (%s)\n", #test);	\
129			return -1;			\
130		}					\
131	} while (0)
132
133#define SUCCEED \
134	do { printf("SUCCEED\n"); return 0; } while (0)
135
136/*
137 * Test 1 - F_GETLK on unlocked region
138 *
139 * If no lock is found that would prevent this lock from being
140 * created, the structure is left unchanged by this function call
141 * except for the lock type which is set to F_UNLCK.
142 */
143static int
144test1(int fd, __unused int argc, const __unused char **argv)
145{
146	struct flock fl1, fl2;
147
148	memset(&fl1, 1, sizeof(fl1));
149	fl1.l_type = F_WRLCK;
150	fl1.l_whence = SEEK_SET;
151	fl2 = fl1;
152
153	if (fcntl(fd, F_GETLK, &fl1) < 0)
154		err(1, "F_GETLK");
155
156	printf("1 - F_GETLK on unlocked region: ");
157	FAIL(fl1.l_start != fl2.l_start);
158	FAIL(fl1.l_len != fl2.l_len);
159	FAIL(fl1.l_pid != fl2.l_pid);
160	FAIL(fl1.l_type != F_UNLCK);
161	FAIL(fl1.l_whence != fl2.l_whence);
162#ifdef HAVE_SYSID
163	FAIL(fl1.l_sysid != fl2.l_sysid);
164#endif
165
166	SUCCEED;
167}
168
169/*
170 * Test 2 - F_SETLK on locked region
171 *
172 * If a shared or exclusive lock cannot be set, fcntl returns
173 * immediately with EACCES or EAGAIN.
174 */
175static int
176test2(int fd, __unused int argc, const __unused char **argv)
177{
178	/*
179	 * We create a child process to hold the lock which we will
180	 * test. We use a pipe to communicate with the child.
181	 */
182	int pid;
183	int pfd[2];
184	struct flock fl;
185	char ch;
186	int res;
187
188	if (pipe(pfd) < 0)
189		err(1, "pipe");
190
191	fl.l_start = 0;
192	fl.l_len = 0;
193	fl.l_type = F_WRLCK;
194	fl.l_whence = SEEK_SET;
195
196	pid = fork();
197	if (pid < 0)
198		err(1, "fork");
199
200	if (pid == 0) {
201		/*
202		 * We are the child. We set a write lock and then
203		 * write one byte back to the parent to tell it. The
204		 * parent will kill us when its done.
205		 */
206		if (fcntl(fd, F_SETLK, &fl) < 0)
207			err(1, "F_SETLK (child)");
208		if (write(pfd[1], "a", 1) < 0)
209			err(1, "writing to pipe (child)");
210		pause();
211		exit(0);
212	}
213
214	/*
215	 * Wait until the child has set its lock and then perform the
216	 * test.
217	 */
218	if (read(pfd[0], &ch, 1) != 1)
219		err(1, "reading from pipe (child)");
220
221	/*
222	 * fcntl should return -1 with errno set to either EACCES or
223	 * EAGAIN.
224	 */
225	printf("2 - F_SETLK on locked region: ");
226	res = fcntl(fd, F_SETLK, &fl);
227	kill(pid, SIGTERM);
228	safe_waitpid(pid);
229	close(pfd[0]);
230	close(pfd[1]);
231	FAIL(res == 0);
232	FAIL(errno != EACCES && errno != EAGAIN);
233
234	SUCCEED;
235}
236
237/*
238 * Test 3 - F_SETLKW on locked region
239 *
240 * If a shared or exclusive lock is blocked by other locks, the
241 * process waits until the request can be satisfied.
242 *
243 * XXX this test hangs on FreeBSD NFS filesystems due to limitations
244 * in FreeBSD's client (and server) lockd implementation.
245 */
246static int
247test3(int fd, __unused int argc, const __unused char **argv)
248{
249	/*
250	 * We create a child process to hold the lock which we will
251	 * test. We use a pipe to communicate with the child.
252	 */
253	int pid;
254	int pfd[2];
255	struct flock fl;
256	char ch;
257	int res;
258
259	if (pipe(pfd) < 0)
260		err(1, "pipe");
261
262	fl.l_start = 0;
263	fl.l_len = 0;
264	fl.l_type = F_WRLCK;
265	fl.l_whence = SEEK_SET;
266
267	pid = fork();
268	if (pid < 0)
269		err(1, "fork");
270
271	if (pid == 0) {
272		/*
273		 * We are the child. We set a write lock and then
274		 * write one byte back to the parent to tell it. The
275		 * parent will kill us when its done.
276		 */
277		if (fcntl(fd, F_SETLK, &fl) < 0)
278			err(1, "F_SETLK (child)");
279		if (write(pfd[1], "a", 1) < 0)
280			err(1, "writing to pipe (child)");
281		pause();
282		exit(0);
283	}
284
285	/*
286	 * Wait until the child has set its lock and then perform the
287	 * test.
288	 */
289	if (read(pfd[0], &ch, 1) != 1)
290		err(1, "reading from pipe (child)");
291
292	/*
293	 * fcntl should wait until the alarm and then return -1 with
294	 * errno set to EINTR.
295	 */
296	printf("3 - F_SETLKW on locked region: ");
297
298	alarm(1);
299
300	res = fcntl(fd, F_SETLKW, &fl);
301	kill(pid, SIGTERM);
302	safe_waitpid(pid);
303	close(pfd[0]);
304	close(pfd[1]);
305	FAIL(res == 0);
306	FAIL(errno != EINTR);
307
308	SUCCEED;
309}
310
311/*
312 * Test 4 - F_GETLK on locked region
313 *
314 * Get the first lock that blocks the lock.
315 */
316static int
317test4(int fd, __unused int argc, const __unused char **argv)
318{
319	/*
320	 * We create a child process to hold the lock which we will
321	 * test. We use a pipe to communicate with the child.
322	 */
323	int pid;
324	int pfd[2];
325	struct flock fl;
326	char ch;
327
328	if (pipe(pfd) < 0)
329		err(1, "pipe");
330
331	fl.l_start = 0;
332	fl.l_len = 99;
333	fl.l_type = F_WRLCK;
334	fl.l_whence = SEEK_SET;
335
336	pid = fork();
337	if (pid < 0)
338		err(1, "fork");
339
340	if (pid == 0) {
341		/*
342		 * We are the child. We set a write lock and then
343		 * write one byte back to the parent to tell it. The
344		 * parent will kill us when its done.
345		 */
346		if (fcntl(fd, F_SETLK, &fl) < 0)
347			err(1, "F_SETLK (child)");
348		if (write(pfd[1], "a", 1) < 0)
349			err(1, "writing to pipe (child)");
350		pause();
351		exit(0);
352	}
353
354	/*
355	 * Wait until the child has set its lock and then perform the
356	 * test.
357	 */
358	if (read(pfd[0], &ch, 1) != 1)
359		err(1, "reading from pipe (child)");
360
361	/*
362	 * fcntl should return a lock structure reflecting the lock we
363	 * made in the child process.
364	 */
365	if (fcntl(fd, F_GETLK, &fl) < 0)
366		err(1, "F_GETLK");
367
368	printf("4 - F_GETLK on locked region: ");
369	FAIL(fl.l_start != 0);
370	FAIL(fl.l_len != 99);
371	FAIL(fl.l_type != F_WRLCK);
372	FAIL(fl.l_pid != pid);
373#ifdef HAVE_SYSID
374	FAIL(fl.l_sysid != 0);
375#endif
376
377	kill(pid, SIGTERM);
378	safe_waitpid(pid);
379	close(pfd[0]);
380	close(pfd[1]);
381
382	SUCCEED;
383}
384
385/*
386 * Test 5 - F_SETLKW simple deadlock
387 *
388 * If a blocking shared lock request would cause a deadlock (i.e. the
389 * lock request is blocked by a process which is itself blocked on a
390 * lock currently owned by the process making the new request),
391 * EDEADLK is returned.
392 */
393static int
394test5(int fd, __unused int argc, const __unused char **argv)
395{
396	/*
397	 * We create a child process to hold the lock which we will
398	 * test. Because our test relies on the child process being
399	 * blocked on the parent's lock, we can't easily use a pipe to
400	 * synchronize so we just sleep in the parent to given the
401	 * child a chance to setup.
402	 *
403	 * To create the deadlock condition, we arrange for the parent
404	 * to lock the first byte of the file and the child to lock
405	 * the second byte.  After locking the second byte, the child
406	 * will attempt to lock the first byte of the file, and
407	 * block. The parent will then attempt to lock the second byte
408	 * (owned by the child) which should cause deadlock.
409	 */
410	int pid;
411	struct flock fl;
412	int res;
413
414	/*
415	 * Lock the first byte in the parent.
416	 */
417	fl.l_start = 0;
418	fl.l_len = 1;
419	fl.l_type = F_WRLCK;
420	fl.l_whence = SEEK_SET;
421	if (fcntl(fd, F_SETLK, &fl) < 0)
422		err(1, "F_SETLK 1 (parent)");
423
424	pid = fork();
425	if (pid < 0)
426		err(1, "fork");
427
428	if (pid == 0) {
429		/*
430		 * Lock the second byte in the child and then block on
431		 * the parent's lock.
432		 */
433		fl.l_start = 1;
434		if (fcntl(fd, F_SETLK, &fl) < 0)
435			err(1, "F_SETLK (child)");
436		fl.l_start = 0;
437		if (fcntl(fd, F_SETLKW, &fl) < 0)
438			err(1, "F_SETLKW (child)");
439		exit(0);
440	}
441
442	/*
443	 * Wait until the child has set its lock and then perform the
444	 * test.
445	 */
446	sleep(1);
447
448	/*
449	 * fcntl should immediately return -1 with errno set to
450	 * EDEADLK. If the alarm fires, we failed to detect the
451	 * deadlock.
452	 */
453	alarm(1);
454	printf("5 - F_SETLKW simple deadlock: ");
455
456	fl.l_start = 1;
457	res = fcntl(fd, F_SETLKW, &fl);
458	kill(pid, SIGTERM);
459	safe_waitpid(pid);
460
461	FAIL(res == 0);
462	FAIL(errno != EDEADLK);
463
464	fl.l_start = 0;
465	fl.l_len = 0;
466	fl.l_type = F_UNLCK;
467	if (fcntl(fd, F_SETLK, &fl) < 0)
468		err(1, "F_UNLCK");
469
470	/*
471	 * Cancel the alarm to avoid confusing later tests.
472	 */
473	alarm(0);
474
475	SUCCEED;
476}
477
478/*
479 * Test 6 - F_SETLKW complex deadlock.
480 *
481 * This test involves three process, P, C1 and C2. We set things up so
482 * that P locks byte zero, C1 locks byte 1 and C2 locks byte 2. We
483 * also block C2 by attempting to lock byte zero. Lastly, P attempts
484 * to lock a range including byte 1 and 2. This represents a deadlock
485 * (due to C2's blocking attempt to lock byte zero).
486 */
487static int
488test6(int fd, __unused int argc, const __unused char **argv)
489{
490	/*
491	 * Because our test relies on the child process being blocked
492	 * on the parent's lock, we can't easily use a pipe to
493	 * synchronize so we just sleep in the parent to given the
494	 * children a chance to setup.
495	 */
496	int pid1, pid2;
497	struct flock fl;
498	int res;
499
500	/*
501	 * Lock the first byte in the parent.
502	 */
503	fl.l_start = 0;
504	fl.l_len = 1;
505	fl.l_type = F_WRLCK;
506	fl.l_whence = SEEK_SET;
507	if (fcntl(fd, F_SETLK, &fl) < 0)
508		err(1, "F_SETLK 1 (parent)");
509
510	pid1 = fork();
511	if (pid1 < 0)
512		err(1, "fork");
513
514	if (pid1 == 0) {
515		/*
516		 * C1
517		 * Lock the second byte in the child and then sleep
518		 */
519		fl.l_start = 1;
520		if (fcntl(fd, F_SETLK, &fl) < 0)
521			err(1, "F_SETLK (child1)");
522		pause();
523		exit(0);
524	}
525
526	pid2 = fork();
527	if (pid2 < 0)
528		err(1, "fork");
529
530	if (pid2 == 0) {
531		/*
532		 * C2
533		 * Lock the third byte in the child and then block on
534		 * the parent's lock.
535		 */
536		fl.l_start = 2;
537		if (fcntl(fd, F_SETLK, &fl) < 0)
538			err(1, "F_SETLK (child2)");
539		fl.l_start = 0;
540		if (fcntl(fd, F_SETLKW, &fl) < 0)
541			err(1, "F_SETLKW (child2)");
542		exit(0);
543	}
544
545	/*
546	 * Wait until the children have set their locks and then
547	 * perform the test.
548	 */
549	sleep(1);
550
551	/*
552	 * fcntl should immediately return -1 with errno set to
553	 * EDEADLK. If the alarm fires, we failed to detect the
554	 * deadlock.
555	 */
556	alarm(1);
557	printf("6 - F_SETLKW complex deadlock: ");
558
559	fl.l_start = 1;
560	fl.l_len = 2;
561	res = fcntl(fd, F_SETLKW, &fl);
562	kill(pid1, SIGTERM);
563	safe_waitpid(pid1);
564	kill(pid2, SIGTERM);
565	safe_waitpid(pid2);
566
567	fl.l_start = 0;
568	fl.l_len = 0;
569	fl.l_type = F_UNLCK;
570	if (fcntl(fd, F_SETLK, &fl) < 0)
571		err(1, "F_UNLCK");
572
573	FAIL(res == 0);
574	FAIL(errno != EDEADLK);
575
576	/*
577	 * Cancel the alarm to avoid confusing later tests.
578	 */
579	alarm(0);
580
581	SUCCEED;
582}
583
584/*
585 * Test 7 - F_SETLK shared lock on exclusive locked region
586 *
587 * If a shared or exclusive lock cannot be set, fcntl returns
588 * immediately with EACCES or EAGAIN.
589 */
590static int
591test7(int fd, __unused int argc, const __unused char **argv)
592{
593	/*
594	 * We create a child process to hold the lock which we will
595	 * test. We use a pipe to communicate with the child.
596	 */
597	int pid;
598	int pfd[2];
599	struct flock fl;
600	char ch;
601	int res;
602
603	if (pipe(pfd) < 0)
604		err(1, "pipe");
605
606	fl.l_start = 0;
607	fl.l_len = 0;
608	fl.l_type = F_WRLCK;
609	fl.l_whence = SEEK_SET;
610
611	pid = fork();
612	if (pid < 0)
613		err(1, "fork");
614
615	if (pid == 0) {
616		/*
617		 * We are the child. We set a write lock and then
618		 * write one byte back to the parent to tell it. The
619		 * parent will kill us when its done.
620		 */
621		if (fcntl(fd, F_SETLK, &fl) < 0)
622			err(1, "F_SETLK (child)");
623		if (write(pfd[1], "a", 1) < 0)
624			err(1, "writing to pipe (child)");
625		pause();
626		exit(0);
627	}
628
629	/*
630	 * Wait until the child has set its lock and then perform the
631	 * test.
632	 */
633	if (read(pfd[0], &ch, 1) != 1)
634		err(1, "reading from pipe (child)");
635
636	/*
637	 * fcntl should wait until the alarm and then return -1 with
638	 * errno set to EINTR.
639	 */
640	printf("7 - F_SETLK shared lock on exclusive locked region: ");
641
642	fl.l_type = F_RDLCK;
643	res = fcntl(fd, F_SETLK, &fl);
644	kill(pid, SIGTERM);
645	safe_waitpid(pid);
646	close(pfd[0]);
647	close(pfd[1]);
648
649	FAIL(res == 0);
650	FAIL(errno != EACCES && errno != EAGAIN);
651
652	SUCCEED;
653}
654
655/*
656 * Test 8 - F_SETLK shared lock on share locked region
657 *
658 * When a shared lock is set on a segment of a file, other processes
659 * shall be able to set shared locks on that segment or a portion of
660 * it.
661 */
662static int
663test8(int fd, __unused int argc, const __unused char **argv)
664{
665	/*
666	 * We create a child process to hold the lock which we will
667	 * test. We use a pipe to communicate with the child.
668	 */
669	int pid;
670	int pfd[2];
671	struct flock fl;
672	char ch;
673	int res;
674
675	if (pipe(pfd) < 0)
676		err(1, "pipe");
677
678	fl.l_start = 0;
679	fl.l_len = 0;
680	fl.l_type = F_RDLCK;
681	fl.l_whence = SEEK_SET;
682
683	pid = fork();
684	if (pid < 0)
685		err(1, "fork");
686
687	if (pid == 0) {
688		/*
689		 * We are the child. We set a write lock and then
690		 * write one byte back to the parent to tell it. The
691		 * parent will kill us when its done.
692		 */
693		if (fcntl(fd, F_SETLK, &fl) < 0)
694			err(1, "F_SETLK (child)");
695		if (write(pfd[1], "a", 1) < 0)
696			err(1, "writing to pipe (child)");
697		pause();
698		exit(0);
699	}
700
701	/*
702	 * Wait until the child has set its lock and then perform the
703	 * test.
704	 */
705	if (read(pfd[0], &ch, 1) != 1)
706		err(1, "reading from pipe (child)");
707
708	/*
709	 * fcntl should wait until the alarm and then return -1 with
710	 * errno set to EINTR.
711	 */
712	printf("8 - F_SETLK shared lock on share locked region: ");
713
714	fl.l_type = F_RDLCK;
715	res = fcntl(fd, F_SETLK, &fl);
716
717	kill(pid, SIGTERM);
718	safe_waitpid(pid);
719	close(pfd[0]);
720	close(pfd[1]);
721
722	fl.l_start = 0;
723	fl.l_len = 0;
724	fl.l_type = F_UNLCK;
725	if (fcntl(fd, F_SETLK, &fl) < 0)
726		err(1, "F_UNLCK");
727
728	FAIL(res != 0);
729
730	SUCCEED;
731}
732
733/*
734 * Test 9 - F_SETLK exclusive lock on share locked region
735 *
736 * If a shared or exclusive lock cannot be set, fcntl returns
737 * immediately with EACCES or EAGAIN.
738 */
739static int
740test9(int fd, __unused int argc, const __unused char **argv)
741{
742	/*
743	 * We create a child process to hold the lock which we will
744	 * test. We use a pipe to communicate with the child.
745	 */
746	int pid;
747	int pfd[2];
748	struct flock fl;
749	char ch;
750	int res;
751
752	if (pipe(pfd) < 0)
753		err(1, "pipe");
754
755	fl.l_start = 0;
756	fl.l_len = 0;
757	fl.l_type = F_RDLCK;
758	fl.l_whence = SEEK_SET;
759
760	pid = fork();
761	if (pid < 0)
762		err(1, "fork");
763
764	if (pid == 0) {
765		/*
766		 * We are the child. We set a write lock and then
767		 * write one byte back to the parent to tell it. The
768		 * parent will kill us when its done.
769		 */
770		if (fcntl(fd, F_SETLK, &fl) < 0)
771			err(1, "F_SETLK (child)");
772		if (write(pfd[1], "a", 1) < 0)
773			err(1, "writing to pipe (child)");
774		pause();
775		exit(0);
776	}
777
778	/*
779	 * Wait until the child has set its lock and then perform the
780	 * test.
781	 */
782	if (read(pfd[0], &ch, 1) != 1)
783		err(1, "reading from pipe (child)");
784
785	/*
786	 * fcntl should wait until the alarm and then return -1 with
787	 * errno set to EINTR.
788	 */
789	printf("9 - F_SETLK exclusive lock on share locked region: ");
790
791	fl.l_type = F_WRLCK;
792	res = fcntl(fd, F_SETLK, &fl);
793	kill(pid, SIGTERM);
794	safe_waitpid(pid);
795	close(pfd[0]);
796	close(pfd[1]);
797
798	FAIL(res == 0);
799	FAIL(errno != EACCES && errno != EAGAIN);
800
801	SUCCEED;
802}
803
804/*
805 * Test 10 - trying to set bogus pid or sysid values
806 *
807 * The l_pid and l_sysid fields are only used with F_GETLK to return
808 * the process ID of the process holding a blocking lock and the
809 * system ID of the system that owns that process
810 */
811static int
812test10(int fd, __unused int argc, const __unused char **argv)
813{
814	/*
815	 * We create a child process to hold the lock which we will
816	 * test. We use a pipe to communicate with the child.
817	 */
818	int pid;
819	int pfd[2];
820	struct flock fl;
821	char ch;
822
823	if (pipe(pfd) < 0)
824		err(1, "pipe");
825
826	fl.l_start = 0;
827	fl.l_len = 0;
828	fl.l_type = F_WRLCK;
829	fl.l_whence = SEEK_SET;
830	fl.l_pid = 9999;
831#ifdef HAVE_SYSID
832	fl.l_sysid = 9999;
833#endif
834
835	pid = fork();
836	if (pid < 0)
837		err(1, "fork");
838
839	if (pid == 0) {
840		/*
841		 * We are the child. We set a write lock and then
842		 * write one byte back to the parent to tell it. The
843		 * parent will kill us when its done.
844		 */
845		if (fcntl(fd, F_SETLK, &fl) < 0)
846			err(1, "F_SETLK (child)");
847		if (write(pfd[1], "a", 1) < 0)
848			err(1, "writing to pipe (child)");
849		pause();
850		exit(0);
851	}
852
853	/*
854	 * Wait until the child has set its lock and then perform the
855	 * test.
856	 */
857	if (read(pfd[0], &ch, 1) != 1)
858		err(1, "reading from pipe (child)");
859
860	printf("10 - trying to set bogus pid or sysid values: ");
861
862	if (fcntl(fd, F_GETLK, &fl) < 0)
863		err(1, "F_GETLK");
864
865	kill(pid, SIGTERM);
866	safe_waitpid(pid);
867	close(pfd[0]);
868	close(pfd[1]);
869
870	FAIL(fl.l_pid != pid);
871#ifdef HAVE_SYSID
872	FAIL(fl.l_sysid != 0);
873#endif
874
875	SUCCEED;
876}
877
878/*
879 * Test 11 - remote locks
880 *
881 * XXX temporary interface which will be removed when the kernel lockd
882 * is added.
883 */
884static int
885test11(int fd, __unused int argc, const __unused char **argv)
886{
887#ifdef F_SETLK_REMOTE
888	struct flock fl;
889	int res;
890
891	if (geteuid() != 0)
892		return 0;
893
894	fl.l_start = 0;
895	fl.l_len = 0;
896	fl.l_type = F_WRLCK;
897	fl.l_whence = SEEK_SET;
898	fl.l_pid = 9999;
899	fl.l_sysid = 1001;
900
901	printf("11 - remote locks: ");
902
903	res = fcntl(fd, F_SETLK_REMOTE, &fl);
904	FAIL(res != 0);
905
906	fl.l_sysid = 1002;
907	res = fcntl(fd, F_SETLK_REMOTE, &fl);
908	FAIL(res == 0);
909	FAIL(errno != EACCES && errno != EAGAIN);
910
911	res = fcntl(fd, F_GETLK, &fl);
912	FAIL(res != 0);
913	FAIL(fl.l_pid != 9999);
914	FAIL(fl.l_sysid != 1001);
915
916	fl.l_type = F_UNLCK;
917	fl.l_sysid = 1001;
918	fl.l_start = 0;
919	fl.l_len = 0;
920	res = fcntl(fd, F_SETLK_REMOTE, &fl);
921	FAIL(res != 0);
922
923	fl.l_pid = 1234;
924	fl.l_sysid = 1001;
925	fl.l_start = 0;
926	fl.l_len = 1;
927	fl.l_whence = SEEK_SET;
928	fl.l_type = F_RDLCK;
929	res = fcntl(fd, F_SETLK_REMOTE, &fl);
930	FAIL(res != 0);
931
932	fl.l_sysid = 1002;
933	res = fcntl(fd, F_SETLK_REMOTE, &fl);
934	FAIL(res != 0);
935
936	fl.l_type = F_UNLCKSYS;
937	fl.l_sysid = 1001;
938	res = fcntl(fd, F_SETLK_REMOTE, &fl);
939	FAIL(res != 0);
940
941	fl.l_type = F_WRLCK;
942	res = fcntl(fd, F_GETLK, &fl);
943	FAIL(res != 0);
944	FAIL(fl.l_pid != 1234);
945	FAIL(fl.l_sysid != 1002);
946
947	fl.l_type = F_UNLCKSYS;
948	fl.l_sysid = 1002;
949	res = fcntl(fd, F_SETLK_REMOTE, &fl);
950	FAIL(res != 0);
951
952	SUCCEED;
953#else
954	return 0;
955#endif
956}
957
958/*
959 * Test 12 - F_SETLKW on locked region which is then unlocked
960 *
961 * If a shared or exclusive lock is blocked by other locks, the
962 * process waits until the request can be satisfied.
963 */
964static int
965test12(int fd, __unused int argc, const __unused char **argv)
966{
967	/*
968	 * We create a child process to hold the lock which we will
969	 * test. We use a pipe to communicate with the child.
970	 */
971	int pid;
972	int pfd[2];
973	struct flock fl;
974	char ch;
975	int res;
976
977	if (pipe(pfd) < 0)
978		err(1, "pipe");
979
980	fl.l_start = 0;
981	fl.l_len = 0;
982	fl.l_type = F_WRLCK;
983	fl.l_whence = SEEK_SET;
984
985	pid = fork();
986	if (pid < 0)
987		err(1, "fork");
988
989	if (pid == 0) {
990		/*
991		 * We are the child. We set a write lock and then
992		 * write one byte back to the parent to tell it. The
993		 * parent will kill us when its done.
994		 */
995		if (fcntl(fd, F_SETLK, &fl) < 0)
996			err(1, "F_SETLK (child)");
997		if (write(pfd[1], "a", 1) < 0)
998			err(1, "writing to pipe (child)");
999
1000		sleep(1);
1001		exit(0);
1002	}
1003
1004	/*
1005	 * Wait until the child has set its lock and then perform the
1006	 * test.
1007	 */
1008	if (read(pfd[0], &ch, 1) != 1)
1009		err(1, "reading from pipe (child)");
1010
1011	/*
1012	 * fcntl should wait until the alarm and then return -1 with
1013	 * errno set to EINTR.
1014	 */
1015	printf("12 - F_SETLKW on locked region which is then unlocked: ");
1016
1017	//alarm(1);
1018
1019	res = fcntl(fd, F_SETLKW, &fl);
1020	kill(pid, SIGTERM);
1021	safe_waitpid(pid);
1022	close(pfd[0]);
1023	close(pfd[1]);
1024	FAIL(res != 0);
1025
1026	fl.l_start = 0;
1027	fl.l_len = 0;
1028	fl.l_type = F_UNLCK;
1029	if (fcntl(fd, F_SETLK, &fl) < 0)
1030		err(1, "F_UNLCK");
1031
1032	SUCCEED;
1033}
1034
1035/*
1036 * Test 13 - F_SETLKW on locked region, race with owner
1037 *
1038 * If a shared or exclusive lock is blocked by other locks, the
1039 * process waits until the request can be satisfied.
1040 */
1041static int
1042test13(int fd, __unused int argc, const __unused char **argv)
1043{
1044	/*
1045	 * We create a child process to hold the lock which we will
1046	 * test. We use a pipe to communicate with the child.
1047	 */
1048	int i;
1049	int pid;
1050	int pfd[2];
1051	struct flock fl;
1052	char ch;
1053	int res;
1054	struct itimerval itv;
1055
1056	printf("13 - F_SETLKW on locked region, race with owner: ");
1057	fflush(stdout);
1058
1059	for (i = 0; i < 100; i++) {
1060		if (pipe(pfd) < 0)
1061			err(1, "pipe");
1062
1063		fl.l_start = 0;
1064		fl.l_len = 0;
1065		fl.l_type = F_WRLCK;
1066		fl.l_whence = SEEK_SET;
1067
1068		pid = fork();
1069		if (pid < 0)
1070			err(1, "fork");
1071
1072		if (pid == 0) {
1073			/*
1074			 * We are the child. We set a write lock and then
1075			 * write one byte back to the parent to tell it. The
1076			 * parent will kill us when its done.
1077			 */
1078			if (fcntl(fd, F_SETLK, &fl) < 0)
1079				err(1, "F_SETLK (child)");
1080			if (write(pfd[1], "a", 1) < 0)
1081				err(1, "writing to pipe (child)");
1082
1083			usleep(1);
1084			exit(0);
1085		}
1086
1087		/*
1088		 * Wait until the child has set its lock and then perform the
1089		 * test.
1090		 */
1091		while (read(pfd[0], &ch, 1) != 1) {
1092			if (errno == EINTR)
1093				continue;
1094			err(1, "reading from pipe (child)");
1095		}
1096
1097		/*
1098		 * fcntl should wait until the alarm and then return -1 with
1099		 * errno set to EINTR.
1100		 */
1101		itv.it_interval.tv_sec = 0;
1102		itv.it_interval.tv_usec = 0;
1103		itv.it_value.tv_sec = 0;
1104		itv.it_value.tv_usec = 2;
1105		setitimer(ITIMER_REAL, &itv, NULL);
1106
1107		res = fcntl(fd, F_SETLKW, &fl);
1108		kill(pid, SIGTERM);
1109		safe_waitpid(pid);
1110		close(pfd[0]);
1111		close(pfd[1]);
1112		FAIL(!(res == 0 || (res == -1 && errno == EINTR)));
1113
1114		fl.l_start = 0;
1115		fl.l_len = 0;
1116		fl.l_type = F_UNLCK;
1117		if (fcntl(fd, F_SETLK, &fl) < 0)
1118			err(1, "F_UNLCK");
1119	}
1120	SUCCEED;
1121}
1122
1123/*
1124 * Test 14 - soak test
1125 */
1126static int
1127test14(int fd, int argc, const char **argv)
1128{
1129#define CHILD_COUNT 20
1130	/*
1131	 * We create a set of child processes and let each one run
1132	 * through a random sequence of locks and unlocks.
1133	 */
1134	int i, j, id, id_base;
1135	int pids[CHILD_COUNT], pid;
1136	char buf[128];
1137	char tbuf[128];
1138	int map[128];
1139	char outbuf[512];
1140	struct flock fl;
1141	struct itimerval itv;
1142	int status;
1143
1144	id_base = 0;
1145	if (argc >= 2)
1146		id_base = strtol(argv[1], NULL, 0);
1147
1148	printf("14 - soak test: ");
1149	fflush(stdout);
1150
1151	for (i = 0; i < 128; i++)
1152		map[i] = F_UNLCK;
1153
1154	for (i = 0; i < CHILD_COUNT; i++) {
1155
1156		pid = fork();
1157		if (pid < 0)
1158			err(1, "fork");
1159		if (pid) {
1160			/*
1161			 * Parent - record the pid and continue.
1162			 */
1163			pids[i] = pid;
1164			continue;
1165		}
1166
1167		/*
1168		 * Child - do some work and exit.
1169		 */
1170		id = id_base + i;
1171		srandom(getpid());
1172
1173		for (j = 0; j < 50; j++) {
1174			int start, end, len;
1175			int set, wrlock;
1176
1177			do {
1178				start = random() & 127;
1179				end = random() & 127;
1180			} while (end <= start);
1181
1182			set = random() & 1;
1183			wrlock = random() & 1;
1184
1185			len = end - start;
1186			fl.l_start = start;
1187			fl.l_len = len;
1188			fl.l_whence = SEEK_SET;
1189			if (set)
1190				fl.l_type = wrlock ? F_WRLCK : F_RDLCK;
1191			else
1192				fl.l_type = F_UNLCK;
1193
1194			itv.it_interval.tv_sec = 0;
1195			itv.it_interval.tv_usec = 0;
1196			itv.it_value.tv_sec = 0;
1197			itv.it_value.tv_usec = 3000;
1198			setitimer(ITIMER_REAL, &itv, NULL);
1199
1200			if (fcntl(fd, F_SETLKW, &fl) < 0) {
1201				if (errno == EDEADLK || errno == EINTR) {
1202					if (verbose) {
1203						snprintf(outbuf, sizeof(outbuf),
1204						    "%d[%d]: %s [%d .. %d] %s\n",
1205						    id, j,
1206						    set ? (wrlock ? "write lock"
1207							: "read lock")
1208						    : "unlock", start, end,
1209						    errno == EDEADLK
1210						    ? "deadlock"
1211						    : "interrupted");
1212						write(1, outbuf,
1213						    strlen(outbuf));
1214					}
1215					continue;
1216				} else {
1217					perror("fcntl");
1218				}
1219			}
1220
1221			itv.it_interval.tv_sec = 0;
1222			itv.it_interval.tv_usec = 0;
1223			itv.it_value.tv_sec = 0;
1224			itv.it_value.tv_usec = 0;
1225			setitimer(ITIMER_REAL, &itv, NULL);
1226
1227			if (verbose) {
1228				snprintf(outbuf, sizeof(outbuf),
1229				    "%d[%d]: %s [%d .. %d] succeeded\n",
1230				    id, j,
1231				    set ? (wrlock ? "write lock" : "read lock")
1232				    : "unlock", start, end);
1233				write(1, outbuf, strlen(outbuf));
1234			}
1235
1236			if (set) {
1237				if (wrlock) {
1238					/*
1239					 * We got a write lock - write
1240					 * our ID to each byte that we
1241					 * managed to claim.
1242					 */
1243					for (i = start; i < end; i++)
1244						map[i] = F_WRLCK;
1245					memset(&buf[start], id, len);
1246					if (pwrite(fd, &buf[start], len,
1247						start) != len) {
1248						printf("%d: short write\n", id);
1249						exit(1);
1250					}
1251				} else {
1252					/*
1253					 * We got a read lock - read
1254					 * the bytes which we claimed
1255					 * so that we can check that
1256					 * they don't change
1257					 * unexpectedly.
1258					 */
1259					for (i = start; i < end; i++)
1260						map[i] = F_RDLCK;
1261					if (pread(fd, &buf[start], len,
1262						start) != len) {
1263						printf("%d: short read\n", id);
1264						exit(1);
1265					}
1266				}
1267			} else {
1268				for (i = start; i < end; i++)
1269					map[i] = F_UNLCK;
1270			}
1271
1272			usleep(1000);
1273
1274			/*
1275			 * Read back the whole region so that we can
1276			 * check that all the bytes we have some kind
1277			 * of claim to have the correct value.
1278			 */
1279			if (pread(fd, tbuf, sizeof(tbuf), 0) != sizeof(tbuf)) {
1280				printf("%d: short read\n", id);
1281				exit(1);
1282			}
1283
1284			for (i = 0; i < 128; i++) {
1285				if (map[i] != F_UNLCK && buf[i] != tbuf[i]) {
1286					snprintf(outbuf, sizeof(outbuf),
1287					    "%d: byte %d expected %d, "
1288					    "got %d\n", id, i, buf[i], tbuf[i]);
1289					write(1, outbuf, strlen(outbuf));
1290					exit(1);
1291				}
1292			}
1293		}
1294		if (verbose)
1295			printf("%d[%d]: done\n", id, j);
1296
1297		exit(0);
1298	}
1299
1300	status = 0;
1301	for (i = 0; i < CHILD_COUNT; i++) {
1302		status += safe_waitpid(pids[i]);
1303	}
1304	if (status)
1305		FAIL(status != 0);
1306
1307	SUCCEED;
1308}
1309
1310/*
1311 * Test 15 - flock(2) semantcs
1312 *
1313 * When a lock holder has a shared lock and attempts to upgrade that
1314 * shared lock to exclusive, it must drop the shared lock before
1315 * blocking on the exclusive lock.
1316 *
1317 * To test this, we first arrange for two shared locks on the file,
1318 * and then attempt to upgrade one of them to exclusive. This should
1319 * drop one of the shared locks and block. We interrupt the blocking
1320 * lock request and examine the lock state of the file after dropping
1321 * the other shared lock - there should be no active locks at this
1322 * point.
1323 */
1324static int
1325test15(int fd, __unused int argc, const __unused char **argv)
1326{
1327#ifdef LOCK_EX
1328	/*
1329	 * We create a child process to hold the lock which we will
1330	 * test. We use a pipe to communicate with the child.
1331	 *
1332	 * Since we only have one file descriptors and lock ownership
1333	 * for flock(2) goes with the file descriptor, we use fcntl to
1334	 * set the child's shared lock.
1335	 */
1336	int pid;
1337	int pfd[2];
1338	struct flock fl;
1339	char ch;
1340	int res;
1341
1342	if (pipe(pfd) < 0)
1343		err(1, "pipe");
1344
1345	pid = fork();
1346	if (pid < 0)
1347		err(1, "fork");
1348
1349	if (pid == 0) {
1350		/*
1351		 * We are the child. We set a shared lock and then
1352		 * write one byte back to the parent to tell it. The
1353		 * parent will kill us when its done.
1354		 */
1355		fl.l_start = 0;
1356		fl.l_len = 0;
1357		fl.l_type = F_RDLCK;
1358		fl.l_whence = SEEK_SET;
1359		if (fcntl(fd, F_SETLK, &fl) < 0)
1360			err(1, "fcntl(F_SETLK) (child)");
1361		if (write(pfd[1], "a", 1) < 0)
1362			err(1, "writing to pipe (child)");
1363		pause();
1364		exit(0);
1365	}
1366
1367	/*
1368	 * Wait until the child has set its lock and then perform the
1369	 * test.
1370	 */
1371	if (read(pfd[0], &ch, 1) != 1)
1372		err(1, "reading from pipe (child)");
1373
1374	(void)dup(fd);
1375	if (flock(fd, LOCK_SH) < 0)
1376		err(1, "flock shared");
1377
1378	/*
1379	 * flock should wait until the alarm and then return -1 with
1380	 * errno set to EINTR.
1381	 */
1382	printf("15 - flock(2) semantics: ");
1383
1384	alarm(1);
1385	flock(fd, LOCK_EX);
1386
1387	/*
1388	 * Kill the child to force it to drop its locks.
1389	 */
1390	kill(pid, SIGTERM);
1391	safe_waitpid(pid);
1392
1393	fl.l_start = 0;
1394	fl.l_len = 0;
1395	fl.l_type = F_WRLCK;
1396	fl.l_whence = SEEK_SET;
1397	res = fcntl(fd, F_GETLK, &fl);
1398
1399	close(pfd[0]);
1400	close(pfd[1]);
1401	FAIL(res != 0);
1402	FAIL(fl.l_type != F_UNLCK);
1403
1404	SUCCEED;
1405#else
1406	return 0;
1407#endif
1408}
1409
1410struct test_ctx {
1411	struct flock tc_fl;
1412	int tc_fd;
1413};
1414
1415static void *
1416test16_func(void *tc_in)
1417{
1418	uintptr_t error;
1419	struct test_ctx *tc = tc_in;
1420
1421	error = fcntl(tc->tc_fd, F_SETLKW, &tc->tc_fl);
1422
1423	pthread_exit((void *)error);
1424}
1425
1426#define THREADS 10
1427
1428/*
1429 * Test 16 - F_SETLKW from two threads
1430 *
1431 * If two threads within a process are blocked on a lock and the lock
1432 * is granted, make sure things are sane.
1433 */
1434static int
1435test16(int fd, __unused int argc, const __unused char **argv)
1436{
1437	/*
1438	 * We create a child process to hold the lock which we will
1439	 * test. We use a pipe to communicate with the child.
1440	 */
1441	int pid;
1442	int pfd[2];
1443	struct test_ctx tc = { .tc_fd = fd };
1444	char ch;
1445	int i;
1446	int error;
1447	pthread_t thr[THREADS];
1448
1449	if (pipe(pfd) < 0)
1450		err(1, "pipe");
1451
1452	tc.tc_fl.l_start = 0;
1453	tc.tc_fl.l_len = 0;
1454	tc.tc_fl.l_type = F_WRLCK;
1455	tc.tc_fl.l_whence = SEEK_SET;
1456
1457	pid = fork();
1458	if (pid < 0)
1459		err(1, "fork");
1460
1461	if (pid == 0) {
1462		/*
1463		 * We are the child. We set a write lock and then
1464		 * write one byte back to the parent to tell it. The
1465		 * parent will kill us when its done.
1466		 */
1467		if (fcntl(fd, F_SETLK, &tc.tc_fl) < 0)
1468			err(1, "F_SETLK (child)");
1469		if (write(pfd[1], "a", 1) < 0)
1470			err(1, "writing to pipe (child)");
1471		pause();
1472		exit(0);
1473	}
1474
1475	/*
1476	 * Wait until the child has set its lock and then perform the
1477	 * test.
1478	 */
1479	if (read(pfd[0], &ch, 1) != 1)
1480		err(1, "reading from pipe (child)");
1481
1482	/*
1483	 * fcntl should wait until the alarm and then return -1 with
1484	 * errno set to EINTR.
1485	 */
1486	printf("16 - F_SETLKW on locked region by two threads: ");
1487
1488	for (i = 0; i < THREADS; i++) {
1489		error = pthread_create(&thr[i], NULL, test16_func, &tc);
1490		if (error)
1491			err(1, "pthread_create");
1492	}
1493
1494	/*
1495	 * Sleep, then kill the child. This makes me a little sad, but it's
1496	 * tricky to tell whether the threads are all really blocked by this
1497	 * point.
1498	 */
1499	sleep(1);
1500	kill(pid, SIGTERM);
1501	safe_waitpid(pid);
1502	close(pfd[0]);
1503	close(pfd[1]);
1504
1505	for (i = 0; i < THREADS; i++) {
1506		void *res;
1507		error = pthread_join(thr[i], &res);
1508		if (error)
1509			err(1, "pthread_join");
1510		FAIL((uintptr_t)res != 0);
1511	}
1512
1513	SUCCEED;
1514}
1515
1516struct test {
1517	int (*testfn)(int, int, const char **);	/* function to perform the test */
1518	int num;		/* test number */
1519	int intr;		/* non-zero if the test interrupts a lock */
1520};
1521
1522struct test tests[] = {
1523	{	test1,		1,	0	},
1524	{	test2,		2,	0	},
1525	{	test3,		3,	1	},
1526	{	test4,		4,	0	},
1527	{	test5,		5,	1	},
1528	{	test6,		6,	1	},
1529	{	test7,		7,	0	},
1530	{	test8,		8,	0	},
1531	{	test9,		9,	0	},
1532	{	test10,		10,	0	},
1533	{	test11,		11,	1	},
1534	{	test12,		12,	0	},
1535	{	test13,		13,	1	},
1536	{	test14,		14,	0	},
1537	{	test15,		15,	1	},
1538	{	test16,		16,	1	},
1539};
1540int test_count = sizeof(tests) / sizeof(tests[0]);
1541
1542int
1543main(int argc, const char *argv[])
1544{
1545	int testnum;
1546	int fd;
1547	int nointr;
1548	int i;
1549	struct sigaction sa;
1550	int test_argc;
1551	const char **test_argv;
1552
1553	if (argc < 2) {
1554		errx(1, "usage: flock <directory> [test number] ...");
1555	}
1556
1557	fd = make_file(argv[1], 1024);
1558	if (argc >= 3) {
1559		testnum = strtol(argv[2], NULL, 0);
1560		test_argc = argc - 2;
1561		test_argv = argv + 2;
1562	} else {
1563		testnum = 0;
1564		test_argc = 0;
1565		test_argv = 0;
1566	}
1567
1568	sa.sa_handler = ignore_alarm;
1569	sigemptyset(&sa.sa_mask);
1570	sa.sa_flags = 0;
1571	sigaction(SIGALRM, &sa, 0);
1572
1573	nointr = 0;
1574#if defined(__FreeBSD__) && __FreeBSD_version < 800040
1575	{
1576		/*
1577		 * FreeBSD with userland NLM can't interrupt a blocked
1578		 * lock request on an NFS mounted filesystem.
1579		 */
1580		struct statfs st;
1581		fstatfs(fd, &st);
1582		nointr = !strcmp(st.f_fstypename, "nfs");
1583	}
1584#endif
1585
1586	for (i = 0; i < test_count; i++) {
1587		if (tests[i].intr && nointr)
1588			continue;
1589		if (!testnum || tests[i].num == testnum)
1590			tests[i].testfn(fd, test_argc, test_argv);
1591	}
1592
1593	return 0;
1594}
1595