]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - tools/regression/file/flock/flock.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / tools / regression / file / flock / flock.c
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$
28  */
29
30 #include <sys/time.h>
31 #ifdef __FreeBSD__
32 #include <sys/param.h>
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 <signal.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46
47 #ifdef __FreeBSD__
48 #if __FreeBSD_version >= 800028
49 #define HAVE_SYSID
50 #endif
51 #if __FreeBSD_version < 800000 && __FreeBSD_version >= 700103
52 #define HAVE_SYSID
53 #endif
54 #if __FreeBSD_version < 700000 && __FreeBSD_version >= 603102
55 #define HAVE_SYSID
56 #endif
57 #include <sys/cdefs.h>
58 #else
59 #ifndef __unused
60 #define __unused
61 #endif
62 #endif
63
64 int verbose = 0;
65
66 static int
67 make_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
102 static void
103 ignore_alarm(int __unused sig)
104 {
105 }
106
107 static int
108 safe_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  */
143 static int
144 test1(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  */
175 static int
176 test2(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  */
246 static int
247 test3(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  */
316 static int
317 test4(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  */
393 static int
394 test5(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  */
487 static int
488 test6(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  */
590 static int
591 test7(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  */
662 static int
663 test8(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  */
739 static int
740 test9(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  */
811 static int
812 test10(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  */
884 static int
885 test11(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  */
964 static int
965 test12(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  */
1041 static int
1042 test13(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  */
1126 static int
1127 test14(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  */
1324 static int
1325 test15(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         int fd2;
1339         struct flock fl;
1340         char ch;
1341         int res;
1342
1343         if (pipe(pfd) < 0)
1344                 err(1, "pipe");
1345
1346         pid = fork();
1347         if (pid < 0)
1348                 err(1, "fork");
1349
1350         if (pid == 0) {
1351                 /*
1352                  * We are the child. We set a shared lock and then
1353                  * write one byte back to the parent to tell it. The
1354                  * parent will kill us when its done.
1355                  */
1356                 fl.l_start = 0;
1357                 fl.l_len = 0;
1358                 fl.l_type = F_RDLCK;
1359                 fl.l_whence = SEEK_SET;
1360                 if (fcntl(fd, F_SETLK, &fl) < 0)
1361                         err(1, "fcntl(F_SETLK) (child)");
1362                 if (write(pfd[1], "a", 1) < 0)
1363                         err(1, "writing to pipe (child)");
1364                 pause();
1365                 exit(0);
1366         }
1367
1368         /*
1369          * Wait until the child has set its lock and then perform the
1370          * test.
1371          */
1372         if (read(pfd[0], &ch, 1) != 1)
1373                 err(1, "reading from pipe (child)");
1374
1375         fd2 = dup(fd);
1376         if (flock(fd, LOCK_SH) < 0)
1377                 err(1, "flock shared");
1378
1379         /*
1380          * flock should wait until the alarm and then return -1 with
1381          * errno set to EINTR.
1382          */
1383         printf("15 - flock(2) semantics: ");
1384
1385         alarm(1);
1386         flock(fd, LOCK_EX);
1387
1388         /*
1389          * Kill the child to force it to drop its locks.
1390          */
1391         kill(pid, SIGTERM);
1392         safe_waitpid(pid);
1393
1394         fl.l_start = 0;
1395         fl.l_len = 0;
1396         fl.l_type = F_WRLCK;
1397         fl.l_whence = SEEK_SET;
1398         res = fcntl(fd, F_GETLK, &fl);
1399
1400         close(pfd[0]);
1401         close(pfd[1]);
1402         FAIL(res != 0);
1403         FAIL(fl.l_type != F_UNLCK);
1404
1405         SUCCEED;
1406 #else
1407         return 0;
1408 #endif
1409 }
1410
1411 struct test {
1412         int (*testfn)(int, int, const char **); /* function to perform the test */
1413         int num;                /* test number */
1414         int intr;               /* non-zero if the test interrupts a lock */
1415 };
1416
1417 struct test tests[] = {
1418         {       test1,          1,      0       },
1419         {       test2,          2,      0       },
1420         {       test3,          3,      1       },
1421         {       test4,          4,      0       },
1422         {       test5,          5,      1       },
1423         {       test6,          6,      1       },
1424         {       test7,          7,      0       },
1425         {       test8,          8,      0       },
1426         {       test9,          9,      0       },
1427         {       test10,         10,     0       },
1428         {       test11,         11,     1       },
1429         {       test12,         12,     0       },
1430         {       test13,         13,     1       },
1431         {       test14,         14,     0       },
1432         {       test15,         15,     1       },
1433 };
1434 int test_count = sizeof(tests) / sizeof(tests[0]);
1435
1436 int
1437 main(int argc, const char *argv[])
1438 {
1439         int testnum;
1440         int fd;
1441         int nointr;
1442         int i;
1443         struct sigaction sa;
1444         int test_argc;
1445         const char **test_argv;
1446
1447         if (argc < 2) {
1448                 errx(1, "usage: flock <directory> [test number] ...");
1449         }
1450
1451         fd = make_file(argv[1], 1024);
1452         if (argc >= 3) {
1453                 testnum = strtol(argv[2], NULL, 0);
1454                 test_argc = argc - 2;
1455                 test_argv = argv + 2;
1456         } else {
1457                 testnum = 0;
1458                 test_argc = 0;
1459                 test_argv = 0;
1460         }
1461
1462         sa.sa_handler = ignore_alarm;
1463         sigemptyset(&sa.sa_mask);
1464         sa.sa_flags = 0;
1465         sigaction(SIGALRM, &sa, 0);
1466
1467         nointr = 0;
1468 #if defined(__FreeBSD__) && __FreeBSD_version < 700110
1469         {
1470                 /*
1471                  * FreeBSD with userland NLM can't interrupt a blocked
1472                  * lock request on an NFS mounted filesystem.
1473                  */
1474                 struct statfs st;
1475                 fstatfs(fd, &st);
1476                 nointr = !strcmp(st.f_fstypename, "nfs");
1477         }
1478 #endif
1479
1480         for (i = 0; i < test_count; i++) {
1481                 if (tests[i].intr && nointr)
1482                         continue;
1483                 if (!testnum || tests[i].num == testnum)
1484                         tests[i].testfn(fd, test_argc, test_argv);
1485         }
1486
1487         return 0;
1488 }