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
32 #include <sys/mount.h>
48 #if __FreeBSD_version >= 800028
51 #include <sys/cdefs.h>
61 make_file(const char *pathname, off_t sz)
64 const char *template = "/flocktempXXXXXX";
69 if (stat(pathname, &st) == 0) {
70 if (S_ISREG(st.st_mode)) {
71 fd = open(pathname, O_RDWR);
73 err(1, "open(%s)", pathname);
74 if (ftruncate(fd, sz) < 0)
80 len = strlen(pathname) + strlen(template) + 1;
81 filename = malloc(len);
82 strcpy(filename, pathname);
83 strcat(filename, template);
84 fd = mkstemp(filename);
87 if (ftruncate(fd, sz) < 0)
89 if (unlink(filename) < 0)
97 ignore_alarm(int __unused sig)
102 safe_waitpid(pid_t pid)
109 while (waitpid(pid, &status, 0) != pid) {
122 printf("FAIL (%s)\n", #test); \
128 do { printf("SUCCEED\n"); return 0; } while (0)
131 * Test 1 - F_GETLK on unlocked region
133 * If no lock is found that would prevent this lock from being
134 * created, the structure is left unchanged by this function call
135 * except for the lock type which is set to F_UNLCK.
138 test1(int fd, __unused int argc, const __unused char **argv)
140 struct flock fl1, fl2;
142 memset(&fl1, 1, sizeof(fl1));
143 fl1.l_type = F_WRLCK;
144 fl1.l_whence = SEEK_SET;
147 if (fcntl(fd, F_GETLK, &fl1) < 0)
150 printf("1 - F_GETLK on unlocked region: ");
151 FAIL(fl1.l_start != fl2.l_start);
152 FAIL(fl1.l_len != fl2.l_len);
153 FAIL(fl1.l_pid != fl2.l_pid);
154 FAIL(fl1.l_type != F_UNLCK);
155 FAIL(fl1.l_whence != fl2.l_whence);
157 FAIL(fl1.l_sysid != fl2.l_sysid);
164 * Test 2 - F_SETLK on locked region
166 * If a shared or exclusive lock cannot be set, fcntl returns
167 * immediately with EACCES or EAGAIN.
170 test2(int fd, __unused int argc, const __unused char **argv)
173 * We create a child process to hold the lock which we will
174 * test. We use a pipe to communicate with the child.
188 fl.l_whence = SEEK_SET;
196 * We are the child. We set a write lock and then
197 * write one byte back to the parent to tell it. The
198 * parent will kill us when its done.
200 if (fcntl(fd, F_SETLK, &fl) < 0)
201 err(1, "F_SETLK (child)");
202 if (write(pfd[1], "a", 1) < 0)
203 err(1, "writing to pipe (child)");
209 * Wait until the child has set its lock and then perform the
212 if (read(pfd[0], &ch, 1) != 1)
213 err(1, "reading from pipe (child)");
216 * fcntl should return -1 with errno set to either EACCES or
219 printf("2 - F_SETLK on locked region: ");
220 res = fcntl(fd, F_SETLK, &fl);
226 FAIL(errno != EACCES && errno != EAGAIN);
232 * Test 3 - F_SETLKW on locked region
234 * If a shared or exclusive lock is blocked by other locks, the
235 * process waits until the request can be satisfied.
237 * XXX this test hangs on FreeBSD NFS filesystems due to limitations
238 * in FreeBSD's client (and server) lockd implementation.
241 test3(int fd, __unused int argc, const __unused char **argv)
244 * We create a child process to hold the lock which we will
245 * test. We use a pipe to communicate with the child.
259 fl.l_whence = SEEK_SET;
267 * We are the child. We set a write lock and then
268 * write one byte back to the parent to tell it. The
269 * parent will kill us when its done.
271 if (fcntl(fd, F_SETLK, &fl) < 0)
272 err(1, "F_SETLK (child)");
273 if (write(pfd[1], "a", 1) < 0)
274 err(1, "writing to pipe (child)");
280 * Wait until the child has set its lock and then perform the
283 if (read(pfd[0], &ch, 1) != 1)
284 err(1, "reading from pipe (child)");
287 * fcntl should wait until the alarm and then return -1 with
288 * errno set to EINTR.
290 printf("3 - F_SETLKW on locked region: ");
294 res = fcntl(fd, F_SETLKW, &fl);
300 FAIL(errno != EINTR);
306 * Test 4 - F_GETLK on locked region
308 * Get the first lock that blocks the lock.
311 test4(int fd, __unused int argc, const __unused char **argv)
314 * We create a child process to hold the lock which we will
315 * test. We use a pipe to communicate with the child.
328 fl.l_whence = SEEK_SET;
336 * We are the child. We set a write lock and then
337 * write one byte back to the parent to tell it. The
338 * parent will kill us when its done.
340 if (fcntl(fd, F_SETLK, &fl) < 0)
341 err(1, "F_SETLK (child)");
342 if (write(pfd[1], "a", 1) < 0)
343 err(1, "writing to pipe (child)");
349 * Wait until the child has set its lock and then perform the
352 if (read(pfd[0], &ch, 1) != 1)
353 err(1, "reading from pipe (child)");
356 * fcntl should return a lock structure reflecting the lock we
357 * made in the child process.
359 if (fcntl(fd, F_GETLK, &fl) < 0)
362 printf("4 - F_GETLK on locked region: ");
363 FAIL(fl.l_start != 0);
364 FAIL(fl.l_len != 99);
365 FAIL(fl.l_type != F_WRLCK);
366 FAIL(fl.l_pid != pid);
368 FAIL(fl.l_sysid != 0);
380 * Test 5 - F_SETLKW simple deadlock
382 * If a blocking shared lock request would cause a deadlock (i.e. the
383 * lock request is blocked by a process which is itself blocked on a
384 * lock currently owned by the process making the new request),
385 * EDEADLK is returned.
388 test5(int fd, __unused int argc, const __unused char **argv)
391 * We create a child process to hold the lock which we will
392 * test. Because our test relies on the child process being
393 * blocked on the parent's lock, we can't easily use a pipe to
394 * synchronize so we just sleep in the parent to given the
395 * child a chance to setup.
397 * To create the deadlock condition, we arrange for the parent
398 * to lock the first byte of the file and the child to lock
399 * the second byte. After locking the second byte, the child
400 * will attempt to lock the first byte of the file, and
401 * block. The parent will then attempt to lock the second byte
402 * (owned by the child) which should cause deadlock.
409 * Lock the first byte in the parent.
414 fl.l_whence = SEEK_SET;
415 if (fcntl(fd, F_SETLK, &fl) < 0)
416 err(1, "F_SETLK 1 (parent)");
424 * Lock the second byte in the child and then block on
428 if (fcntl(fd, F_SETLK, &fl) < 0)
429 err(1, "F_SETLK (child)");
431 if (fcntl(fd, F_SETLKW, &fl) < 0)
432 err(1, "F_SETLKW (child)");
437 * Wait until the child has set its lock and then perform the
443 * fcntl should immediately return -1 with errno set to
444 * EDEADLK. If the alarm fires, we failed to detect the
448 printf("5 - F_SETLKW simple deadlock: ");
451 res = fcntl(fd, F_SETLKW, &fl);
456 FAIL(errno != EDEADLK);
461 if (fcntl(fd, F_SETLK, &fl) < 0)
465 * Cancel the alarm to avoid confusing later tests.
473 * Test 6 - F_SETLKW complex deadlock.
475 * This test involves three process, P, C1 and C2. We set things up so
476 * that P locks byte zero, C1 locks byte 1 and C2 locks byte 2. We
477 * also block C2 by attempting to lock byte zero. Lastly, P attempts
478 * to lock a range including byte 1 and 2. This represents a deadlock
479 * (due to C2's blocking attempt to lock byte zero).
482 test6(int fd, __unused int argc, const __unused char **argv)
485 * Because our test relies on the child process being blocked
486 * on the parent's lock, we can't easily use a pipe to
487 * synchronize so we just sleep in the parent to given the
488 * children a chance to setup.
495 * Lock the first byte in the parent.
500 fl.l_whence = SEEK_SET;
501 if (fcntl(fd, F_SETLK, &fl) < 0)
502 err(1, "F_SETLK 1 (parent)");
511 * Lock the second byte in the child and then sleep
514 if (fcntl(fd, F_SETLK, &fl) < 0)
515 err(1, "F_SETLK (child1)");
527 * Lock the third byte in the child and then block on
531 if (fcntl(fd, F_SETLK, &fl) < 0)
532 err(1, "F_SETLK (child2)");
534 if (fcntl(fd, F_SETLKW, &fl) < 0)
535 err(1, "F_SETLKW (child2)");
540 * Wait until the children have set their locks and then
546 * fcntl should immediately return -1 with errno set to
547 * EDEADLK. If the alarm fires, we failed to detect the
551 printf("6 - F_SETLKW complex deadlock: ");
555 res = fcntl(fd, F_SETLKW, &fl);
564 if (fcntl(fd, F_SETLK, &fl) < 0)
568 FAIL(errno != EDEADLK);
571 * Cancel the alarm to avoid confusing later tests.
579 * Test 7 - F_SETLK shared lock on exclusive locked region
581 * If a shared or exclusive lock cannot be set, fcntl returns
582 * immediately with EACCES or EAGAIN.
585 test7(int fd, __unused int argc, const __unused char **argv)
588 * We create a child process to hold the lock which we will
589 * test. We use a pipe to communicate with the child.
603 fl.l_whence = SEEK_SET;
611 * We are the child. We set a write lock and then
612 * write one byte back to the parent to tell it. The
613 * parent will kill us when its done.
615 if (fcntl(fd, F_SETLK, &fl) < 0)
616 err(1, "F_SETLK (child)");
617 if (write(pfd[1], "a", 1) < 0)
618 err(1, "writing to pipe (child)");
624 * Wait until the child has set its lock and then perform the
627 if (read(pfd[0], &ch, 1) != 1)
628 err(1, "reading from pipe (child)");
631 * fcntl should wait until the alarm and then return -1 with
632 * errno set to EINTR.
634 printf("7 - F_SETLK shared lock on exclusive locked region: ");
637 res = fcntl(fd, F_SETLK, &fl);
644 FAIL(errno != EACCES && errno != EAGAIN);
650 * Test 8 - F_SETLK shared lock on share locked region
652 * When a shared lock is set on a segment of a file, other processes
653 * shall be able to set shared locks on that segment or a portion of
657 test8(int fd, __unused int argc, const __unused char **argv)
660 * We create a child process to hold the lock which we will
661 * test. We use a pipe to communicate with the child.
675 fl.l_whence = SEEK_SET;
683 * We are the child. We set a write lock and then
684 * write one byte back to the parent to tell it. The
685 * parent will kill us when its done.
687 if (fcntl(fd, F_SETLK, &fl) < 0)
688 err(1, "F_SETLK (child)");
689 if (write(pfd[1], "a", 1) < 0)
690 err(1, "writing to pipe (child)");
696 * Wait until the child has set its lock and then perform the
699 if (read(pfd[0], &ch, 1) != 1)
700 err(1, "reading from pipe (child)");
703 * fcntl should wait until the alarm and then return -1 with
704 * errno set to EINTR.
706 printf("8 - F_SETLK shared lock on share locked region: ");
709 res = fcntl(fd, F_SETLK, &fl);
719 if (fcntl(fd, F_SETLK, &fl) < 0)
728 * Test 9 - F_SETLK exclusive lock on share locked region
730 * If a shared or exclusive lock cannot be set, fcntl returns
731 * immediately with EACCES or EAGAIN.
734 test9(int fd, __unused int argc, const __unused char **argv)
737 * We create a child process to hold the lock which we will
738 * test. We use a pipe to communicate with the child.
752 fl.l_whence = SEEK_SET;
760 * We are the child. We set a write lock and then
761 * write one byte back to the parent to tell it. The
762 * parent will kill us when its done.
764 if (fcntl(fd, F_SETLK, &fl) < 0)
765 err(1, "F_SETLK (child)");
766 if (write(pfd[1], "a", 1) < 0)
767 err(1, "writing to pipe (child)");
773 * Wait until the child has set its lock and then perform the
776 if (read(pfd[0], &ch, 1) != 1)
777 err(1, "reading from pipe (child)");
780 * fcntl should wait until the alarm and then return -1 with
781 * errno set to EINTR.
783 printf("9 - F_SETLK exclusive lock on share locked region: ");
786 res = fcntl(fd, F_SETLK, &fl);
793 FAIL(errno != EACCES && errno != EAGAIN);
799 * Test 10 - trying to set bogus pid or sysid values
801 * The l_pid and l_sysid fields are only used with F_GETLK to return
802 * the process ID of the process holding a blocking lock and the
803 * system ID of the system that owns that process
806 test10(int fd, __unused int argc, const __unused char **argv)
809 * We create a child process to hold the lock which we will
810 * test. We use a pipe to communicate with the child.
823 fl.l_whence = SEEK_SET;
835 * We are the child. We set a write lock and then
836 * write one byte back to the parent to tell it. The
837 * parent will kill us when its done.
839 if (fcntl(fd, F_SETLK, &fl) < 0)
840 err(1, "F_SETLK (child)");
841 if (write(pfd[1], "a", 1) < 0)
842 err(1, "writing to pipe (child)");
848 * Wait until the child has set its lock and then perform the
851 if (read(pfd[0], &ch, 1) != 1)
852 err(1, "reading from pipe (child)");
854 printf("10 - trying to set bogus pid or sysid values: ");
856 if (fcntl(fd, F_GETLK, &fl) < 0)
864 FAIL(fl.l_pid != pid);
866 FAIL(fl.l_sysid != 0);
873 * Test 11 - remote locks
875 * XXX temporary interface which will be removed when the kernel lockd
879 test11(int fd, __unused int argc, const __unused char **argv)
881 #ifdef F_SETLK_REMOTE
891 fl.l_whence = SEEK_SET;
895 printf("11 - remote locks: ");
897 res = fcntl(fd, F_SETLK_REMOTE, &fl);
901 res = fcntl(fd, F_SETLK_REMOTE, &fl);
903 FAIL(errno != EACCES && errno != EAGAIN);
905 res = fcntl(fd, F_GETLK, &fl);
907 FAIL(fl.l_pid != 9999);
908 FAIL(fl.l_sysid != 1001);
914 res = fcntl(fd, F_SETLK_REMOTE, &fl);
921 fl.l_whence = SEEK_SET;
923 res = fcntl(fd, F_SETLK_REMOTE, &fl);
927 res = fcntl(fd, F_SETLK_REMOTE, &fl);
930 fl.l_type = F_UNLCKSYS;
932 res = fcntl(fd, F_SETLK_REMOTE, &fl);
936 res = fcntl(fd, F_GETLK, &fl);
938 FAIL(fl.l_pid != 1234);
939 FAIL(fl.l_sysid != 1002);
941 fl.l_type = F_UNLCKSYS;
943 res = fcntl(fd, F_SETLK_REMOTE, &fl);
953 * Test 12 - F_SETLKW on locked region which is then unlocked
955 * If a shared or exclusive lock is blocked by other locks, the
956 * process waits until the request can be satisfied.
959 test12(int fd, __unused int argc, const __unused char **argv)
962 * We create a child process to hold the lock which we will
963 * test. We use a pipe to communicate with the child.
977 fl.l_whence = SEEK_SET;
985 * We are the child. We set a write lock and then
986 * write one byte back to the parent to tell it. The
987 * parent will kill us when its done.
989 if (fcntl(fd, F_SETLK, &fl) < 0)
990 err(1, "F_SETLK (child)");
991 if (write(pfd[1], "a", 1) < 0)
992 err(1, "writing to pipe (child)");
999 * Wait until the child has set its lock and then perform the
1002 if (read(pfd[0], &ch, 1) != 1)
1003 err(1, "reading from pipe (child)");
1006 * fcntl should wait until the alarm and then return -1 with
1007 * errno set to EINTR.
1009 printf("12 - F_SETLKW on locked region which is then unlocked: ");
1013 res = fcntl(fd, F_SETLKW, &fl);
1022 fl.l_type = F_UNLCK;
1023 if (fcntl(fd, F_SETLK, &fl) < 0)
1030 * Test 13 - F_SETLKW on locked region, race with owner
1032 * If a shared or exclusive lock is blocked by other locks, the
1033 * process waits until the request can be satisfied.
1036 test13(int fd, __unused int argc, const __unused char **argv)
1039 * We create a child process to hold the lock which we will
1040 * test. We use a pipe to communicate with the child.
1048 struct itimerval itv;
1050 printf("13 - F_SETLKW on locked region, race with owner: ");
1053 for (i = 0; i < 100; i++) {
1059 fl.l_type = F_WRLCK;
1060 fl.l_whence = SEEK_SET;
1068 * We are the child. We set a write lock and then
1069 * write one byte back to the parent to tell it. The
1070 * parent will kill us when its done.
1072 if (fcntl(fd, F_SETLK, &fl) < 0)
1073 err(1, "F_SETLK (child)");
1074 if (write(pfd[1], "a", 1) < 0)
1075 err(1, "writing to pipe (child)");
1082 * Wait until the child has set its lock and then perform the
1085 while (read(pfd[0], &ch, 1) != 1) {
1088 err(1, "reading from pipe (child)");
1092 * fcntl should wait until the alarm and then return -1 with
1093 * errno set to EINTR.
1095 itv.it_interval.tv_sec = 0;
1096 itv.it_interval.tv_usec = 0;
1097 itv.it_value.tv_sec = 0;
1098 itv.it_value.tv_usec = 2;
1099 setitimer(ITIMER_REAL, &itv, NULL);
1101 res = fcntl(fd, F_SETLKW, &fl);
1106 FAIL(!(res == 0 || (res == -1 && errno == EINTR)));
1110 fl.l_type = F_UNLCK;
1111 if (fcntl(fd, F_SETLK, &fl) < 0)
1118 * Test 14 - soak test
1121 test14(int fd, int argc, const char **argv)
1123 #define CHILD_COUNT 20
1125 * We create a set of child processes and let each one run
1126 * through a random sequence of locks and unlocks.
1128 int i, j, id, id_base;
1129 int pids[CHILD_COUNT], pid;
1135 struct itimerval itv;
1140 id_base = strtol(argv[1], NULL, 0);
1142 printf("14 - soak test: ");
1145 for (i = 0; i < 128; i++)
1148 for (i = 0; i < CHILD_COUNT; i++) {
1155 * Parent - record the pid and continue.
1162 * Child - do some work and exit.
1167 for (j = 0; j < 50; j++) {
1168 int start, end, len;
1172 start = random() & 127;
1173 end = random() & 127;
1174 } while (end <= start);
1177 wrlock = random() & 1;
1182 fl.l_whence = SEEK_SET;
1184 fl.l_type = wrlock ? F_WRLCK : F_RDLCK;
1186 fl.l_type = F_UNLCK;
1188 itv.it_interval.tv_sec = 0;
1189 itv.it_interval.tv_usec = 0;
1190 itv.it_value.tv_sec = 0;
1191 itv.it_value.tv_usec = 3000;
1192 setitimer(ITIMER_REAL, &itv, NULL);
1194 if (fcntl(fd, F_SETLKW, &fl) < 0) {
1195 if (errno == EDEADLK || errno == EINTR) {
1197 snprintf(outbuf, sizeof(outbuf),
1198 "%d[%d]: %s [%d .. %d] %s\n",
1200 set ? (wrlock ? "write lock"
1202 : "unlock", start, end,
1215 itv.it_interval.tv_sec = 0;
1216 itv.it_interval.tv_usec = 0;
1217 itv.it_value.tv_sec = 0;
1218 itv.it_value.tv_usec = 0;
1219 setitimer(ITIMER_REAL, &itv, NULL);
1222 snprintf(outbuf, sizeof(outbuf),
1223 "%d[%d]: %s [%d .. %d] succeeded\n",
1225 set ? (wrlock ? "write lock" : "read lock")
1226 : "unlock", start, end);
1227 write(1, outbuf, strlen(outbuf));
1233 * We got a write lock - write
1234 * our ID to each byte that we
1237 for (i = start; i < end; i++)
1239 memset(&buf[start], id, len);
1240 if (pwrite(fd, &buf[start], len,
1242 printf("%d: short write\n", id);
1247 * We got a read lock - read
1248 * the bytes which we claimed
1249 * so that we can check that
1253 for (i = start; i < end; i++)
1255 if (pread(fd, &buf[start], len,
1257 printf("%d: short read\n", id);
1262 for (i = start; i < end; i++)
1269 * Read back the whole region so that we can
1270 * check that all the bytes we have some kind
1271 * of claim to have the correct value.
1273 if (pread(fd, tbuf, sizeof(tbuf), 0) != sizeof(tbuf)) {
1274 printf("%d: short read\n", id);
1278 for (i = 0; i < 128; i++) {
1279 if (map[i] != F_UNLCK && buf[i] != tbuf[i]) {
1280 snprintf(outbuf, sizeof(outbuf),
1281 "%d: byte %d expected %d, "
1282 "got %d\n", id, i, buf[i], tbuf[i]);
1283 write(1, outbuf, strlen(outbuf));
1289 printf("%d[%d]: done\n", id, j);
1295 for (i = 0; i < CHILD_COUNT; i++) {
1296 status += safe_waitpid(pids[i]);
1305 * Test 15 - flock(2) semantcs
1307 * When a lock holder has a shared lock and attempts to upgrade that
1308 * shared lock to exclusive, it must drop the shared lock before
1309 * blocking on the exclusive lock.
1311 * To test this, we first arrange for two shared locks on the file,
1312 * and then attempt to upgrade one of them to exclusive. This should
1313 * drop one of the shared locks and block. We interrupt the blocking
1314 * lock request and examine the lock state of the file after dropping
1315 * the other shared lock - there should be no active locks at this
1319 test15(int fd, __unused int argc, const __unused char **argv)
1323 * We create a child process to hold the lock which we will
1324 * test. We use a pipe to communicate with the child.
1326 * Since we only have one file descriptors and lock ownership
1327 * for flock(2) goes with the file descriptor, we use fcntl to
1328 * set the child's shared lock.
1346 * We are the child. We set a shared lock and then
1347 * write one byte back to the parent to tell it. The
1348 * parent will kill us when its done.
1352 fl.l_type = F_RDLCK;
1353 fl.l_whence = SEEK_SET;
1354 if (fcntl(fd, F_SETLK, &fl) < 0)
1355 err(1, "fcntl(F_SETLK) (child)");
1356 if (write(pfd[1], "a", 1) < 0)
1357 err(1, "writing to pipe (child)");
1363 * Wait until the child has set its lock and then perform the
1366 if (read(pfd[0], &ch, 1) != 1)
1367 err(1, "reading from pipe (child)");
1370 if (flock(fd, LOCK_SH) < 0)
1371 err(1, "flock shared");
1374 * flock should wait until the alarm and then return -1 with
1375 * errno set to EINTR.
1377 printf("15 - flock(2) semantics: ");
1383 * Kill the child to force it to drop its locks.
1390 fl.l_type = F_WRLCK;
1391 fl.l_whence = SEEK_SET;
1392 res = fcntl(fd, F_GETLK, &fl);
1397 FAIL(fl.l_type != F_UNLCK);
1411 test16_func(void *tc_in)
1414 struct test_ctx *tc = tc_in;
1416 error = fcntl(tc->tc_fd, F_SETLKW, &tc->tc_fl);
1418 pthread_exit((void *)error);
1424 * Test 16 - F_SETLKW from two threads
1426 * If two threads within a process are blocked on a lock and the lock
1427 * is granted, make sure things are sane.
1430 test16(int fd, __unused int argc, const __unused char **argv)
1433 * We create a child process to hold the lock which we will
1434 * test. We use a pipe to communicate with the child.
1438 struct test_ctx tc = { .tc_fd = fd };
1442 pthread_t thr[THREADS];
1447 tc.tc_fl.l_start = 0;
1449 tc.tc_fl.l_type = F_WRLCK;
1450 tc.tc_fl.l_whence = SEEK_SET;
1458 * We are the child. We set a write lock and then
1459 * write one byte back to the parent to tell it. The
1460 * parent will kill us when its done.
1462 if (fcntl(fd, F_SETLK, &tc.tc_fl) < 0)
1463 err(1, "F_SETLK (child)");
1464 if (write(pfd[1], "a", 1) < 0)
1465 err(1, "writing to pipe (child)");
1471 * Wait until the child has set its lock and then perform the
1474 if (read(pfd[0], &ch, 1) != 1)
1475 err(1, "reading from pipe (child)");
1478 * fcntl should wait until the alarm and then return -1 with
1479 * errno set to EINTR.
1481 printf("16 - F_SETLKW on locked region by two threads: ");
1483 for (i = 0; i < THREADS; i++) {
1484 error = pthread_create(&thr[i], NULL, test16_func, &tc);
1486 err(1, "pthread_create");
1490 * Sleep, then kill the child. This makes me a little sad, but it's
1491 * tricky to tell whether the threads are all really blocked by this
1500 for (i = 0; i < THREADS; i++) {
1502 error = pthread_join(thr[i], &res);
1504 err(1, "pthread_join");
1505 FAIL((uintptr_t)res != 0);
1512 int (*testfn)(int, int, const char **); /* function to perform the test */
1513 int num; /* test number */
1514 int intr; /* non-zero if the test interrupts a lock */
1517 struct test tests[] = {
1535 int test_count = sizeof(tests) / sizeof(tests[0]);
1538 main(int argc, const char *argv[])
1544 struct sigaction sa;
1546 const char **test_argv;
1549 errx(1, "usage: flock <directory> [test number] ...");
1552 fd = make_file(argv[1], 1024);
1554 testnum = strtol(argv[2], NULL, 0);
1555 test_argc = argc - 2;
1556 test_argv = argv + 2;
1563 sa.sa_handler = ignore_alarm;
1564 sigemptyset(&sa.sa_mask);
1566 sigaction(SIGALRM, &sa, 0);
1569 #if defined(__FreeBSD__) && __FreeBSD_version < 800040
1572 * FreeBSD with userland NLM can't interrupt a blocked
1573 * lock request on an NFS mounted filesystem.
1577 nointr = !strcmp(st.f_fstypename, "nfs");
1581 for (i = 0; i < test_count; i++) {
1582 if (tests[i].intr && nointr)
1584 if (!testnum || tests[i].num == testnum)
1585 tests[i].testfn(fd, test_argc, test_argv);