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>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
30 #include <sys/param.h>
34 #include <sys/mount.h>
51 #if __FreeBSD_version >= 800028
54 #include <sys/cdefs.h>
57 #define nitems(x) (sizeof((x)) / sizeof((x)[0]))
62 #define __unused __attribute__((__unused__))
69 static int verbose = 0;
72 make_file(const char *pathname, off_t sz)
75 const char *template = "/flocktempXXXXXX";
80 if (stat(pathname, &st) == 0) {
81 if (S_ISREG(st.st_mode)) {
82 fd = open(pathname, O_RDWR);
84 err(1, "open(%s)", pathname);
85 if (ftruncate(fd, sz) < 0)
91 len = strlen(pathname) + strlen(template) + 1;
92 filename = malloc(len);
93 strcpy(filename, pathname);
94 strcat(filename, template);
95 fd = mkstemp(filename);
98 if (ftruncate(fd, sz) < 0)
100 if (unlink(filename) < 0)
108 ignore_alarm(int __unused sig)
113 safe_waitpid(pid_t pid)
120 while (waitpid(pid, &status, 0) != pid) {
133 printf("FAIL (%s)\n", #test); \
139 do { printf("SUCCEED\n"); return 0; } while (0)
142 * Test 1 - F_GETLK on unlocked region
144 * If no lock is found that would prevent this lock from being
145 * created, the structure is left unchanged by this function call
146 * except for the lock type which is set to F_UNLCK.
149 test1(int fd, __unused int argc, const __unused char **argv)
151 struct flock fl1, fl2;
153 memset(&fl1, 1, sizeof(fl1));
154 fl1.l_type = F_WRLCK;
155 fl1.l_whence = SEEK_SET;
158 if (fcntl(fd, F_GETLK, &fl1) < 0)
161 printf("1 - F_GETLK on unlocked region: ");
162 FAIL(fl1.l_start != fl2.l_start);
163 FAIL(fl1.l_len != fl2.l_len);
164 FAIL(fl1.l_pid != fl2.l_pid);
165 FAIL(fl1.l_type != F_UNLCK);
166 FAIL(fl1.l_whence != fl2.l_whence);
168 FAIL(fl1.l_sysid != fl2.l_sysid);
175 * Test 2 - F_SETLK on locked region
177 * If a shared or exclusive lock cannot be set, fcntl returns
178 * immediately with EACCES or EAGAIN.
181 test2(int fd, __unused int argc, const __unused char **argv)
184 * We create a child process to hold the lock which we will
185 * test. We use a pipe to communicate with the child.
199 fl.l_whence = SEEK_SET;
207 * We are the child. We set a write lock and then
208 * write one byte back to the parent to tell it. The
209 * parent will kill us when its done.
211 if (fcntl(fd, F_SETLK, &fl) < 0)
212 err(1, "F_SETLK (child)");
213 if (write(pfd[1], "a", 1) < 0)
214 err(1, "writing to pipe (child)");
220 * Wait until the child has set its lock and then perform the
223 if (read(pfd[0], &ch, 1) != 1)
224 err(1, "reading from pipe (child)");
227 * fcntl should return -1 with errno set to either EACCES or
230 printf("2 - F_SETLK on locked region: ");
231 res = fcntl(fd, F_SETLK, &fl);
237 FAIL(errno != EACCES && errno != EAGAIN);
243 * Test 3 - F_SETLKW on locked region
245 * If a shared or exclusive lock is blocked by other locks, the
246 * process waits until the request can be satisfied.
248 * XXX this test hangs on FreeBSD NFS filesystems due to limitations
249 * in FreeBSD's client (and server) lockd implementation.
252 test3(int fd, __unused int argc, const __unused char **argv)
255 * We create a child process to hold the lock which we will
256 * test. We use a pipe to communicate with the child.
270 fl.l_whence = SEEK_SET;
278 * We are the child. We set a write lock and then
279 * write one byte back to the parent to tell it. The
280 * parent will kill us when its done.
282 if (fcntl(fd, F_SETLK, &fl) < 0)
283 err(1, "F_SETLK (child)");
284 if (write(pfd[1], "a", 1) < 0)
285 err(1, "writing to pipe (child)");
291 * Wait until the child has set its lock and then perform the
294 if (read(pfd[0], &ch, 1) != 1)
295 err(1, "reading from pipe (child)");
298 * fcntl should wait until the alarm and then return -1 with
299 * errno set to EINTR.
301 printf("3 - F_SETLKW on locked region: ");
305 res = fcntl(fd, F_SETLKW, &fl);
311 FAIL(errno != EINTR);
317 * Test 4 - F_GETLK on locked region
319 * Get the first lock that blocks the lock.
322 test4(int fd, __unused int argc, const __unused char **argv)
325 * We create a child process to hold the lock which we will
326 * test. We use a pipe to communicate with the child.
339 fl.l_whence = SEEK_SET;
347 * We are the child. We set a write lock and then
348 * write one byte back to the parent to tell it. The
349 * parent will kill us when its done.
351 if (fcntl(fd, F_SETLK, &fl) < 0)
352 err(1, "F_SETLK (child)");
353 if (write(pfd[1], "a", 1) < 0)
354 err(1, "writing to pipe (child)");
360 * Wait until the child has set its lock and then perform the
363 if (read(pfd[0], &ch, 1) != 1)
364 err(1, "reading from pipe (child)");
367 * fcntl should return a lock structure reflecting the lock we
368 * made in the child process.
370 if (fcntl(fd, F_GETLK, &fl) < 0)
373 printf("4 - F_GETLK on locked region: ");
374 FAIL(fl.l_start != 0);
375 FAIL(fl.l_len != 99);
376 FAIL(fl.l_type != F_WRLCK);
377 FAIL(fl.l_pid != pid);
379 FAIL(fl.l_sysid != 0);
391 * Test 5 - F_SETLKW simple deadlock
393 * If a blocking shared lock request would cause a deadlock (i.e. the
394 * lock request is blocked by a process which is itself blocked on a
395 * lock currently owned by the process making the new request),
396 * EDEADLK is returned.
399 test5(int fd, __unused int argc, const __unused char **argv)
402 * We create a child process to hold the lock which we will
403 * test. Because our test relies on the child process being
404 * blocked on the parent's lock, we can't easily use a pipe to
405 * synchronize so we just sleep in the parent to given the
406 * child a chance to setup.
408 * To create the deadlock condition, we arrange for the parent
409 * to lock the first byte of the file and the child to lock
410 * the second byte. After locking the second byte, the child
411 * will attempt to lock the first byte of the file, and
412 * block. The parent will then attempt to lock the second byte
413 * (owned by the child) which should cause deadlock.
420 * Lock the first byte in the parent.
425 fl.l_whence = SEEK_SET;
426 if (fcntl(fd, F_SETLK, &fl) < 0)
427 err(1, "F_SETLK 1 (parent)");
435 * Lock the second byte in the child and then block on
439 if (fcntl(fd, F_SETLK, &fl) < 0)
440 err(1, "F_SETLK (child)");
442 if (fcntl(fd, F_SETLKW, &fl) < 0)
443 err(1, "F_SETLKW (child)");
448 * Wait until the child has set its lock and then perform the
454 * fcntl should immediately return -1 with errno set to
455 * EDEADLK. If the alarm fires, we failed to detect the
459 printf("5 - F_SETLKW simple deadlock: ");
462 res = fcntl(fd, F_SETLKW, &fl);
467 FAIL(errno != EDEADLK);
472 if (fcntl(fd, F_SETLK, &fl) < 0)
476 * Cancel the alarm to avoid confusing later tests.
484 * Test 6 - F_SETLKW complex deadlock.
486 * This test involves three process, P, C1 and C2. We set things up so
487 * that P locks byte zero, C1 locks byte 1 and C2 locks byte 2. We
488 * also block C2 by attempting to lock byte zero. Lastly, P attempts
489 * to lock a range including byte 1 and 2. This represents a deadlock
490 * (due to C2's blocking attempt to lock byte zero).
493 test6(int fd, __unused int argc, const __unused char **argv)
496 * Because our test relies on the child process being blocked
497 * on the parent's lock, we can't easily use a pipe to
498 * synchronize so we just sleep in the parent to given the
499 * children a chance to setup.
506 * Lock the first byte in the parent.
511 fl.l_whence = SEEK_SET;
512 if (fcntl(fd, F_SETLK, &fl) < 0)
513 err(1, "F_SETLK 1 (parent)");
522 * Lock the second byte in the child and then sleep
525 if (fcntl(fd, F_SETLK, &fl) < 0)
526 err(1, "F_SETLK (child1)");
538 * Lock the third byte in the child and then block on
542 if (fcntl(fd, F_SETLK, &fl) < 0)
543 err(1, "F_SETLK (child2)");
545 if (fcntl(fd, F_SETLKW, &fl) < 0)
546 err(1, "F_SETLKW (child2)");
551 * Wait until the children have set their locks and then
557 * fcntl should immediately return -1 with errno set to
558 * EDEADLK. If the alarm fires, we failed to detect the
562 printf("6 - F_SETLKW complex deadlock: ");
566 res = fcntl(fd, F_SETLKW, &fl);
575 if (fcntl(fd, F_SETLK, &fl) < 0)
579 FAIL(errno != EDEADLK);
582 * Cancel the alarm to avoid confusing later tests.
590 * Test 7 - F_SETLK shared lock on exclusive locked region
592 * If a shared or exclusive lock cannot be set, fcntl returns
593 * immediately with EACCES or EAGAIN.
596 test7(int fd, __unused int argc, const __unused char **argv)
599 * We create a child process to hold the lock which we will
600 * test. We use a pipe to communicate with the child.
614 fl.l_whence = SEEK_SET;
622 * We are the child. We set a write lock and then
623 * write one byte back to the parent to tell it. The
624 * parent will kill us when its done.
626 if (fcntl(fd, F_SETLK, &fl) < 0)
627 err(1, "F_SETLK (child)");
628 if (write(pfd[1], "a", 1) < 0)
629 err(1, "writing to pipe (child)");
635 * Wait until the child has set its lock and then perform the
638 if (read(pfd[0], &ch, 1) != 1)
639 err(1, "reading from pipe (child)");
642 * fcntl should wait until the alarm and then return -1 with
643 * errno set to EINTR.
645 printf("7 - F_SETLK shared lock on exclusive locked region: ");
648 res = fcntl(fd, F_SETLK, &fl);
655 FAIL(errno != EACCES && errno != EAGAIN);
661 * Test 8 - F_SETLK shared lock on share locked region
663 * When a shared lock is set on a segment of a file, other processes
664 * shall be able to set shared locks on that segment or a portion of
668 test8(int fd, __unused int argc, const __unused char **argv)
671 * We create a child process to hold the lock which we will
672 * test. We use a pipe to communicate with the child.
686 fl.l_whence = SEEK_SET;
694 * We are the child. We set a write lock and then
695 * write one byte back to the parent to tell it. The
696 * parent will kill us when its done.
698 if (fcntl(fd, F_SETLK, &fl) < 0)
699 err(1, "F_SETLK (child)");
700 if (write(pfd[1], "a", 1) < 0)
701 err(1, "writing to pipe (child)");
707 * Wait until the child has set its lock and then perform the
710 if (read(pfd[0], &ch, 1) != 1)
711 err(1, "reading from pipe (child)");
714 * fcntl should wait until the alarm and then return -1 with
715 * errno set to EINTR.
717 printf("8 - F_SETLK shared lock on share locked region: ");
720 res = fcntl(fd, F_SETLK, &fl);
730 if (fcntl(fd, F_SETLK, &fl) < 0)
739 * Test 9 - F_SETLK exclusive lock on share locked region
741 * If a shared or exclusive lock cannot be set, fcntl returns
742 * immediately with EACCES or EAGAIN.
745 test9(int fd, __unused int argc, const __unused char **argv)
748 * We create a child process to hold the lock which we will
749 * test. We use a pipe to communicate with the child.
763 fl.l_whence = SEEK_SET;
771 * We are the child. We set a write lock and then
772 * write one byte back to the parent to tell it. The
773 * parent will kill us when its done.
775 if (fcntl(fd, F_SETLK, &fl) < 0)
776 err(1, "F_SETLK (child)");
777 if (write(pfd[1], "a", 1) < 0)
778 err(1, "writing to pipe (child)");
784 * Wait until the child has set its lock and then perform the
787 if (read(pfd[0], &ch, 1) != 1)
788 err(1, "reading from pipe (child)");
791 * fcntl should wait until the alarm and then return -1 with
792 * errno set to EINTR.
794 printf("9 - F_SETLK exclusive lock on share locked region: ");
797 res = fcntl(fd, F_SETLK, &fl);
804 FAIL(errno != EACCES && errno != EAGAIN);
810 * Test 10 - trying to set bogus pid or sysid values
812 * The l_pid and l_sysid fields are only used with F_GETLK to return
813 * the process ID of the process holding a blocking lock and the
814 * system ID of the system that owns that process
817 test10(int fd, __unused int argc, const __unused char **argv)
820 * We create a child process to hold the lock which we will
821 * test. We use a pipe to communicate with the child.
834 fl.l_whence = SEEK_SET;
846 * We are the child. We set a write lock and then
847 * write one byte back to the parent to tell it. The
848 * parent will kill us when its done.
850 if (fcntl(fd, F_SETLK, &fl) < 0)
851 err(1, "F_SETLK (child)");
852 if (write(pfd[1], "a", 1) < 0)
853 err(1, "writing to pipe (child)");
859 * Wait until the child has set its lock and then perform the
862 if (read(pfd[0], &ch, 1) != 1)
863 err(1, "reading from pipe (child)");
865 printf("10 - trying to set bogus pid or sysid values: ");
867 if (fcntl(fd, F_GETLK, &fl) < 0)
875 FAIL(fl.l_pid != pid);
877 FAIL(fl.l_sysid != 0);
884 * Test 11 - remote locks
886 * XXX temporary interface which will be removed when the kernel lockd
890 test11(int fd, __unused int argc, const __unused char **argv)
892 #ifdef F_SETLK_REMOTE
902 fl.l_whence = SEEK_SET;
906 printf("11 - remote locks: ");
908 res = fcntl(fd, F_SETLK_REMOTE, &fl);
912 res = fcntl(fd, F_SETLK_REMOTE, &fl);
914 FAIL(errno != EACCES && errno != EAGAIN);
916 res = fcntl(fd, F_GETLK, &fl);
918 FAIL(fl.l_pid != 9999);
919 FAIL(fl.l_sysid != 1001);
925 res = fcntl(fd, F_SETLK_REMOTE, &fl);
932 fl.l_whence = SEEK_SET;
934 res = fcntl(fd, F_SETLK_REMOTE, &fl);
938 res = fcntl(fd, F_SETLK_REMOTE, &fl);
941 fl.l_type = F_UNLCKSYS;
943 res = fcntl(fd, F_SETLK_REMOTE, &fl);
947 res = fcntl(fd, F_GETLK, &fl);
949 FAIL(fl.l_pid != 1234);
950 FAIL(fl.l_sysid != 1002);
952 fl.l_type = F_UNLCKSYS;
954 res = fcntl(fd, F_SETLK_REMOTE, &fl);
964 * Test 12 - F_SETLKW on locked region which is then unlocked
966 * If a shared or exclusive lock is blocked by other locks, the
967 * process waits until the request can be satisfied.
970 test12(int fd, __unused int argc, const __unused char **argv)
973 * We create a child process to hold the lock which we will
974 * test. We use a pipe to communicate with the child.
988 fl.l_whence = SEEK_SET;
996 * We are the child. We set a write lock and then
997 * write one byte back to the parent to tell it. The
998 * parent will kill us when its done.
1000 if (fcntl(fd, F_SETLK, &fl) < 0)
1001 err(1, "F_SETLK (child)");
1002 if (write(pfd[1], "a", 1) < 0)
1003 err(1, "writing to pipe (child)");
1010 * Wait until the child has set its lock and then perform the
1013 if (read(pfd[0], &ch, 1) != 1)
1014 err(1, "reading from pipe (child)");
1017 * fcntl should wait until the alarm and then return -1 with
1018 * errno set to EINTR.
1020 printf("12 - F_SETLKW on locked region which is then unlocked: ");
1024 res = fcntl(fd, F_SETLKW, &fl);
1033 fl.l_type = F_UNLCK;
1034 if (fcntl(fd, F_SETLK, &fl) < 0)
1041 * Test 13 - F_SETLKW on locked region, race with owner
1043 * If a shared or exclusive lock is blocked by other locks, the
1044 * process waits until the request can be satisfied.
1047 test13(int fd, __unused int argc, const __unused char **argv)
1050 * We create a child process to hold the lock which we will
1051 * test. We use a pipe to communicate with the child.
1059 struct itimerval itv;
1061 printf("13 - F_SETLKW on locked region, race with owner: ");
1064 for (i = 0; i < 100; i++) {
1070 fl.l_type = F_WRLCK;
1071 fl.l_whence = SEEK_SET;
1079 * We are the child. We set a write lock and then
1080 * write one byte back to the parent to tell it. The
1081 * parent will kill us when its done.
1083 if (fcntl(fd, F_SETLK, &fl) < 0)
1084 err(1, "F_SETLK (child)");
1085 if (write(pfd[1], "a", 1) < 0)
1086 err(1, "writing to pipe (child)");
1093 * Wait until the child has set its lock and then perform the
1096 while (read(pfd[0], &ch, 1) != 1) {
1099 err(1, "reading from pipe (child)");
1103 * fcntl should wait until the alarm and then return -1 with
1104 * errno set to EINTR.
1106 itv.it_interval.tv_sec = 0;
1107 itv.it_interval.tv_usec = 0;
1108 itv.it_value.tv_sec = 0;
1109 itv.it_value.tv_usec = 2;
1110 setitimer(ITIMER_REAL, &itv, NULL);
1112 res = fcntl(fd, F_SETLKW, &fl);
1117 FAIL(!(res == 0 || (res == -1 && errno == EINTR)));
1121 fl.l_type = F_UNLCK;
1122 if (fcntl(fd, F_SETLK, &fl) < 0)
1129 * Test 14 - soak test
1132 test14(int fd, int argc, const char **argv)
1134 #define CHILD_COUNT 20
1136 * We create a set of child processes and let each one run
1137 * through a random sequence of locks and unlocks.
1139 int i, j, id, id_base;
1140 int pids[CHILD_COUNT], pid;
1146 struct itimerval itv;
1151 id_base = strtol(argv[1], NULL, 0);
1153 printf("14 - soak test: ");
1156 for (i = 0; i < 128; i++)
1159 for (i = 0; i < CHILD_COUNT; i++) {
1166 * Parent - record the pid and continue.
1173 * Child - do some work and exit.
1178 for (j = 0; j < 50; j++) {
1179 int start, end, len;
1183 start = random() & 127;
1184 end = random() & 127;
1185 } while (end <= start);
1188 wrlock = random() & 1;
1193 fl.l_whence = SEEK_SET;
1195 fl.l_type = wrlock ? F_WRLCK : F_RDLCK;
1197 fl.l_type = F_UNLCK;
1199 itv.it_interval.tv_sec = 0;
1200 itv.it_interval.tv_usec = 0;
1201 itv.it_value.tv_sec = 0;
1202 itv.it_value.tv_usec = 3000;
1203 setitimer(ITIMER_REAL, &itv, NULL);
1205 if (fcntl(fd, F_SETLKW, &fl) < 0) {
1206 if (errno == EDEADLK || errno == EINTR) {
1208 snprintf(outbuf, sizeof(outbuf),
1209 "%d[%d]: %s [%d .. %d] %s\n",
1211 set ? (wrlock ? "write lock"
1213 : "unlock", start, end,
1226 itv.it_interval.tv_sec = 0;
1227 itv.it_interval.tv_usec = 0;
1228 itv.it_value.tv_sec = 0;
1229 itv.it_value.tv_usec = 0;
1230 setitimer(ITIMER_REAL, &itv, NULL);
1233 snprintf(outbuf, sizeof(outbuf),
1234 "%d[%d]: %s [%d .. %d] succeeded\n",
1236 set ? (wrlock ? "write lock" : "read lock")
1237 : "unlock", start, end);
1238 write(1, outbuf, strlen(outbuf));
1244 * We got a write lock - write
1245 * our ID to each byte that we
1248 for (i = start; i < end; i++)
1250 memset(&buf[start], id, len);
1251 if (pwrite(fd, &buf[start], len,
1253 printf("%d: short write\n", id);
1258 * We got a read lock - read
1259 * the bytes which we claimed
1260 * so that we can check that
1264 for (i = start; i < end; i++)
1266 if (pread(fd, &buf[start], len,
1268 printf("%d: short read\n", id);
1273 for (i = start; i < end; i++)
1280 * Read back the whole region so that we can
1281 * check that all the bytes we have some kind
1282 * of claim to have the correct value.
1284 if (pread(fd, tbuf, sizeof(tbuf), 0) != sizeof(tbuf)) {
1285 printf("%d: short read\n", id);
1289 for (i = 0; i < 128; i++) {
1290 if (map[i] != F_UNLCK && buf[i] != tbuf[i]) {
1291 snprintf(outbuf, sizeof(outbuf),
1292 "%d: byte %d expected %d, "
1293 "got %d\n", id, i, buf[i], tbuf[i]);
1294 write(1, outbuf, strlen(outbuf));
1300 printf("%d[%d]: done\n", id, j);
1306 for (i = 0; i < CHILD_COUNT; i++) {
1307 status += safe_waitpid(pids[i]);
1316 * Test 15 - flock(2) semantcs
1318 * When a lock holder has a shared lock and attempts to upgrade that
1319 * shared lock to exclusive, it must drop the shared lock before
1320 * blocking on the exclusive lock.
1322 * To test this, we first arrange for two shared locks on the file,
1323 * and then attempt to upgrade one of them to exclusive. This should
1324 * drop one of the shared locks and block. We interrupt the blocking
1325 * lock request and examine the lock state of the file after dropping
1326 * the other shared lock - there should be no active locks at this
1330 test15(int fd, __unused int argc, const __unused char **argv)
1334 * We create a child process to hold the lock which we will
1335 * test. We use a pipe to communicate with the child.
1337 * Since we only have one file descriptors and lock ownership
1338 * for flock(2) goes with the file descriptor, we use fcntl to
1339 * set the child's shared lock.
1356 * We are the child. We set a shared lock and then
1357 * write one byte back to the parent to tell it. The
1358 * parent will kill us when its done.
1362 fl.l_type = F_RDLCK;
1363 fl.l_whence = SEEK_SET;
1364 if (fcntl(fd, F_SETLK, &fl) < 0)
1365 err(1, "fcntl(F_SETLK) (child)");
1366 if (write(pfd[1], "a", 1) < 0)
1367 err(1, "writing to pipe (child)");
1373 * Wait until the child has set its lock and then perform the
1376 if (read(pfd[0], &ch, 1) != 1)
1377 err(1, "reading from pipe (child)");
1380 if (flock(fd, LOCK_SH) < 0)
1381 err(1, "flock shared");
1384 * flock should wait until the alarm and then return -1 with
1385 * errno set to EINTR.
1387 printf("15 - flock(2) semantics: ");
1393 * Kill the child to force it to drop its locks.
1400 fl.l_type = F_WRLCK;
1401 fl.l_whence = SEEK_SET;
1402 res = fcntl(fd, F_GETLK, &fl);
1407 FAIL(fl.l_type != F_UNLCK);
1421 test16_func(void *tc_in)
1424 struct test_ctx *tc = tc_in;
1426 error = fcntl(tc->tc_fd, F_SETLKW, &tc->tc_fl);
1428 pthread_exit((void *)error);
1434 * Test 16 - F_SETLKW from two threads
1436 * If two threads within a process are blocked on a lock and the lock
1437 * is granted, make sure things are sane.
1440 test16(int fd, __unused int argc, const __unused char **argv)
1443 * We create a child process to hold the lock which we will
1444 * test. We use a pipe to communicate with the child.
1448 struct test_ctx tc = { .tc_fd = fd };
1452 pthread_t thr[THREADS];
1457 tc.tc_fl.l_start = 0;
1459 tc.tc_fl.l_type = F_WRLCK;
1460 tc.tc_fl.l_whence = SEEK_SET;
1468 * We are the child. We set a write lock and then
1469 * write one byte back to the parent to tell it. The
1470 * parent will kill us when its done.
1472 if (fcntl(fd, F_SETLK, &tc.tc_fl) < 0)
1473 err(1, "F_SETLK (child)");
1474 if (write(pfd[1], "a", 1) < 0)
1475 err(1, "writing to pipe (child)");
1481 * Wait until the child has set its lock and then perform the
1484 if (read(pfd[0], &ch, 1) != 1)
1485 err(1, "reading from pipe (child)");
1488 * fcntl should wait until the alarm and then return -1 with
1489 * errno set to EINTR.
1491 printf("16 - F_SETLKW on locked region by two threads: ");
1493 for (i = 0; i < THREADS; i++) {
1494 error = pthread_create(&thr[i], NULL, test16_func, &tc);
1496 err(1, "pthread_create");
1500 * Sleep, then kill the child. This makes me a little sad, but it's
1501 * tricky to tell whether the threads are all really blocked by this
1510 for (i = 0; i < THREADS; i++) {
1512 error = pthread_join(thr[i], &res);
1514 err(1, "pthread_join");
1515 FAIL((uintptr_t)res != 0);
1522 int (*testfn)(int, int, const char **); /* function to perform the test */
1523 int num; /* test number */
1524 int intr; /* non-zero if the test interrupts a lock */
1527 static struct test tests[] = {
1547 main(int argc, const char *argv[])
1553 struct sigaction sa;
1555 const char **test_argv;
1558 errx(1, "usage: flock <directory> [test number] ...");
1561 fd = make_file(argv[1], 1024);
1563 testnum = strtol(argv[2], NULL, 0);
1564 test_argc = argc - 2;
1565 test_argv = argv + 2;
1572 sa.sa_handler = ignore_alarm;
1573 sigemptyset(&sa.sa_mask);
1575 sigaction(SIGALRM, &sa, 0);
1578 #if defined(__FreeBSD__) && __FreeBSD_version < 800040
1581 * FreeBSD with userland NLM can't interrupt a blocked
1582 * lock request on an NFS mounted filesystem.
1586 nointr = !strcmp(st.f_fstypename, "nfs");
1590 for (i = 0; i < nitems(tests); i++) {
1591 if (tests[i].intr && nointr)
1593 if (!testnum || tests[i].num == testnum)
1594 tests[i].testfn(fd, test_argc, test_argv);