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