4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
48 #define MAX_PATH_LENGTH 4096
52 int t_fcntl(int fd, int cmd, ...)
66 fprintf(stderr, "fcntl GETFL failed: %s\n",
72 arg = va_arg(ap, long);
74 rc = fcntl(fd, cmd, arg);
77 fprintf(stderr, "fcntl SETFL %ld failed: %s\n",
78 arg, strerror(errno));
85 lock = va_arg(ap, struct flock *);
87 rc = fcntl(fd, cmd, lock);
90 fprintf(stderr, "fcntl cmd %d failed: %s\n",
91 cmd, strerror(errno));
96 arg = va_arg(ap, long);
98 rc = fcntl(fd, cmd, arg);
101 fprintf(stderr, "fcntl F_DUPFD %d failed: %s\n",
102 (int)arg, strerror(errno));
108 fprintf(stderr, "fcntl cmd %d not supported\n", cmd);
114 int t_unlink(const char *path)
120 fprintf(stderr, "unlink(%s) error: %s\n", path, strerror(errno));
124 /** =================================================================
131 fprintf(stderr, "usage: ./flocks_test 1 on|off -c|-f|-l /path/to/file\n");
134 int t1(int argc, char *argv[])
137 int mount_with_flock = 0;
146 if (!strncmp(argv[2], "on", 3)) {
147 mount_with_flock = 1;
148 } else if (!strncmp(argv[2], "off", 4)) {
149 mount_with_flock = 0;
155 if ((fd = open(argv[4], O_RDWR)) < 0) {
156 fprintf(stderr, "Couldn't open file: %s\n", argv[4]);
160 if (!strncmp(argv[3], "-c", 3)) {
164 fl.l_whence = SEEK_SET;
168 error = fcntl(fd, F_SETLK, &fl);
169 } else if (!strncmp(argv[3], "-l", 3)) {
170 error = lockf(fd, F_LOCK, 1);
171 } else if (!strncmp(argv[3], "-f", 3)) {
172 error = flock(fd, LOCK_EX);
179 if (mount_with_flock)
180 rc = ((error == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
182 rc = ((error == 0) ? EXIT_FAILURE : EXIT_SUCCESS);
190 /** ===============================================================
193 * 2 threads flock ops interweave
200 void* t2_thread1(void *arg)
202 struct flock *lock = ((th_data *)arg)->lock;
203 int fd = ((th_data *)arg)->fd;
205 printf("thread 1: set write lock (blocking)\n");
206 lock->l_type = F_WRLCK;
207 t_fcntl(fd, F_SETLKW, lock);
208 printf("thread 1: set write lock done\n");
209 t_fcntl(fd, F_GETLK, lock);
210 printf("thread 1: unlock\n");
211 lock->l_type = F_UNLCK;
212 t_fcntl(fd, F_SETLK, lock);
213 printf("thread 1: unlock done\n");
217 void* t2_thread2(void *arg)
219 struct flock *lock = ((th_data *)arg)->lock;
220 int fd = ((th_data *)arg)->fd;
223 printf("thread 2: unlock\n");
224 lock->l_type = F_UNLCK;
225 t_fcntl(fd, F_SETLK, lock);
226 printf("thread 2: unlock done\n");
227 printf("thread 2: set write lock (non-blocking)\n");
228 lock->l_type = F_WRLCK;
229 t_fcntl(fd, F_SETLK, lock);
230 printf("thread 2: set write lock done\n");
231 t_fcntl(fd, F_GETLK, lock);
235 int t2(int argc, char* argv[])
237 struct flock lock = {
239 .l_whence = SEEK_SET,
241 char file[MAX_PATH_LENGTH] = "";
246 snprintf(file, MAX_PATH_LENGTH, "%s/test_t2_file", argv[2]);
248 fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
250 fprintf(stderr, "error open file: %s\n", file);
254 t_fcntl(fd, F_SETFL, O_APPEND);
255 rc = t_fcntl(fd, F_GETFL);
256 if ((rc < 0) || (rc & O_APPEND) == 0) {
257 fprintf(stderr, "error get flag: ret %x\n", rc);
264 rc = pthread_create(&th1, NULL, t2_thread1, &ta);
266 fprintf(stderr, "error create thread 1\n");
270 rc = pthread_create(&th2, NULL, t2_thread2, &ta);
272 fprintf(stderr, "error create thread 2\n");
276 (void)pthread_join(th1, NULL);
277 (void)pthread_join(th2, NULL);
284 /** =================================================================
287 * Bug 24040: Two conflicting flocks from same process different fds should fail
288 * two conflicting flocks from different processes but same fs
291 int t3(int argc, char *argv[])
295 int rc = EXIT_SUCCESS;
298 fprintf(stderr, "Usage: ./flocks_test 3 filename\n");
302 if ((fd = open(argv[2], O_RDWR)) < 0) {
303 fprintf(stderr, "Couldn't open file: %s\n", argv[2]);
306 if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
307 perror("first flock failed");
311 if ((fd2 = open(argv[2], O_RDWR)) < 0) {
312 fprintf(stderr, "Couldn't open file: %s\n", argv[2]);
316 if (flock(fd2, LOCK_EX | LOCK_NB) >= 0) {
317 fprintf(stderr, "Second flock succeeded - FAIL\n");
333 if ((fd2 = open(argv[2], O_RDWR)) < 0) {
334 fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
338 if (flock(fd2, LOCK_EX | LOCK_NB) >= 0) {
339 fprintf(stderr, "Second flock succeeded - FAIL\n");
343 if (flock(fd, LOCK_UN) == -1) {
344 fprintf(stderr, "Child unlock on parent fd failed\n");
348 if (flock(fd2, LOCK_EX | LOCK_NB) == -1) {
349 fprintf(stderr, "Relock after parent unlock failed!\n");
358 waitpid(pid, &rc, 0);
364 int t4(int argc, char *argv[])
366 struct flock lock = {
368 .l_whence = SEEK_SET,
376 int rc = EXIT_SUCCESS;
379 fprintf(stderr, "Usage: ./flocks_test 4 file1 file2\n");
383 if ((fd = open(argv[2], O_RDWR)) < 0) {
384 fprintf(stderr, "Couldn't open file: %s\n", argv[2]);
387 if ((fd2 = open(argv[3], O_RDWR)) < 0) {
388 fprintf(stderr, "Couldn't open file: %s\n", argv[3]);
400 if (child_pid == 0) {
401 printf("%d: get lock1\n", getpid());
403 if (t_fcntl(fd, F_SETLKW, &lock) < 0) {
404 fprintf(stderr, "%d: cannot get lock1: %s\n",
405 getpid(), strerror(errno));
409 printf("%d: done\n", getpid());
411 printf("%d: get lock2\n", getpid());
413 if (t_fcntl(fd2, F_SETLKW, &lock) < 0) {
414 fprintf(stderr, "%d: cannot get lock2: %s\n",
415 getpid(), strerror(errno));
417 if (errno == EDEADLK)
424 printf("%d: done\n", getpid());
426 printf("%d: exit rc=%d\n", getpid(), rc);
429 printf("%d: get lock2\n", getpid());
431 if (t_fcntl(fd2, F_SETLKW, &lock) < 0) {
432 fprintf(stderr, "%d: cannot get lock2: %s\n",
433 getpid(), strerror(errno));
437 printf("%d: done\n", getpid());
439 printf("%d: get lock1\n", getpid());
441 if (t_fcntl(fd, F_SETLKW, &lock) < 0) {
442 fprintf(stderr, "%d: cannot get lock1: %s\n",
443 getpid(), strerror(errno));
445 if (errno != EDEADLK) {
450 printf("%d: done\n", getpid());
456 fprintf(stderr, "%d: error closing file1: %s\n",
457 getpid(), strerror(errno));
461 if (close(fd2) < 0) {
462 fprintf(stderr, "%d: error closing file2: %s\n",
463 getpid(), strerror(errno));
467 if (waitpid(child_pid, &child_status, 0) < 0) {
468 fprintf(stderr, "%d: cannot get termination status of %d: %s\n",
469 getpid(), child_pid, strerror(errno));
471 } else if (!WIFEXITED(child_status)) {
472 fprintf(stderr, "%d: child %d terminated with status %d\n",
473 getpid(), child_pid, child_status);
476 rc = WEXITSTATUS(child_status);
480 printf("%d: exit rc=%d\n", getpid(), rc);
485 "Usage: ./flocks_test 5 set|get|unlock [read|write] [sleep N] file1\n"\
486 " set: F_SETLKW F_WRLCK\n" \
487 " get: F_GETLK F_WRLCK (conflict)\n" \
488 " unlock: F_SETLKW F_UNLCK\n" \
489 " read|write: lock mode, write by default\n" \
490 " sleep N: sleep for N secs after fcntl\n" \
491 " file1: fcntl is called for this file\n"
493 int t5(int argc, char *argv[])
495 struct flock lock = {
497 .l_whence = SEEK_SET,
500 int setlk = 0, getlk = 0, unlk = 0, secs = 0;
505 if (argc < 4 || argc > 7) {
506 fprintf(stderr, T5_USAGE);
510 if (!strncmp(argv[2], "set", 4))
512 else if (!strncmp(argv[2], "get", 4))
514 else if (!strncmp(argv[2], "unlock", 7))
517 fprintf(stderr, "Wrong 2nd argument: %s\n", argv[2]);
523 if (!strncmp(argv[pos], "read", 5)) {
524 lock.l_type = F_RDLCK;
526 } else if (!strncmp(argv[pos], "write", 6)) {
527 lock.l_type = F_WRLCK;
531 if (!strncmp(argv[pos], "sleep", 6)) {
532 secs = atoi(argv[pos + 1]);
533 if (secs < 0 || secs > 10) {
534 fprintf(stderr, "Sleep argument is wrong: %s\n",
541 fd = open(argv[pos], O_RDWR);
543 fprintf(stderr, "Couldn't open file: %s\n", argv[pos]);
547 fprintf(stderr, "\nFLOCKS_TEST 5: %s %s flock\n",
548 setlk ? "SET" : getlk ? "GET" : "UNLOCK",
549 lock.l_type == F_WRLCK ? "write" : "read");
552 rc = t_fcntl(fd, F_SETLKW, &lock);
554 rc = t_fcntl(fd, F_GETLK, &lock);
556 lock.l_type = F_UNLCK;
557 rc = t_fcntl(fd, F_SETLKW, &lock);
564 return rc < 0 ? -rc : 0;
568 /** ==============================================================
573 fprintf(stderr, "usage: ./flocks_test test# [corresponding arguments]\n");
576 int main(int argc, char* argv[])
579 int rc = EXIT_SUCCESS;
585 test_no = atoi(argv[1]);
604 fprintf(stderr, "unknow test number %s\n", argv[1]);