Whamcloud - gitweb
LU-2524 test: Modify tdir to be single directory
[fs/lustre-release.git] / lustre / tests / flocks_test.c
index fe2f045..ab38fa0 100644 (file)
@@ -1,6 +1,4 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
  * GPL HEADER START
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -28,6 +26,8 @@
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2011, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -42,6 +42,7 @@
 #include <unistd.h>
 #include <pthread.h>
 #include <sys/file.h>
+#include <sys/wait.h>
 #include <stdarg.h>
 
 #define MAX_PATH_LENGTH 4096
@@ -131,6 +132,7 @@ int t1(int argc, char *argv[])
         int fd;
         int mount_with_flock = 0;
         int error = 0;
+       int rc = 0;
 
         if (argc != 5) {
                 t1_usage();
@@ -166,13 +168,19 @@ int t1(int argc, char *argv[])
                 error = flock(fd, LOCK_EX);
         } else {
                 t1_usage();
-                return EXIT_FAILURE;
+               rc = EXIT_FAILURE;
+               goto out;
         }
 
         if (mount_with_flock)
-                return((error == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
+               rc = ((error == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
         else
-                return((error == 0) ? EXIT_FAILURE : EXIT_SUCCESS);
+               rc = ((error == 0) ? EXIT_FAILURE : EXIT_SUCCESS);
+
+out:
+       if (fd >= 0)
+               close(fd);
+       return rc;
 }
 
 /** ===============================================================
@@ -243,7 +251,8 @@ int t2(int argc, char* argv[])
         rc = t_fcntl(fd, F_GETFL);
         if ((rc & O_APPEND) == 0) {
                 fprintf(stderr, "error get flag: ret %x\n", rc);
-                return EXIT_FAILURE;
+               rc = EXIT_FAILURE;
+               goto out;
         }
 
         ta.lock = &lock;
@@ -268,6 +277,167 @@ out:
         return rc;
 }
 
+/** =================================================================
+ * test number 3
+ *
+ * Bug 24040: Two conflicting flocks from same process different fds should fail
+ *            two conflicting flocks from different processes but same fs
+ *            should succeed.
+ */
+int t3(int argc, char *argv[])
+{
+        int fd, fd2;
+        int pid;
+        int rc = EXIT_SUCCESS;
+
+        if (argc != 3) {
+                fprintf(stderr, "Usage: ./flocks_test 3 filename\n");
+                return EXIT_FAILURE;
+        }
+
+        if ((fd = open(argv[2], O_RDWR)) < 0) {
+                fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
+                return EXIT_FAILURE;
+        }
+        if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
+                perror("first flock failed");
+                rc = EXIT_FAILURE;
+                goto out;
+        }
+        if ((fd2 = open(argv[2], O_RDWR)) < 0) {
+                fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
+                rc = EXIT_FAILURE;
+                goto out;
+        }
+        if (flock(fd2, LOCK_EX | LOCK_NB) >= 0) {
+                fprintf(stderr, "Second flock succeeded - FAIL\n");
+                rc = EXIT_FAILURE;
+                close(fd2);
+                goto out;
+        }
+
+        close(fd2);
+
+        pid = fork();
+        if (pid == -1) {
+                perror("fork");
+                rc = EXIT_FAILURE;
+                goto out;
+        }
+
+        if (pid == 0) {
+                if ((fd2 = open(argv[2], O_RDWR)) < 0) {
+                        fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
+                        rc = EXIT_FAILURE;
+                        exit(rc);
+                }
+                if (flock(fd2, LOCK_EX | LOCK_NB) >= 0) {
+                        fprintf(stderr, "Second flock succeeded - FAIL\n");
+                        rc = EXIT_FAILURE;
+                        goto out_child;
+                }
+                if (flock(fd, LOCK_UN) == -1) {
+                        fprintf(stderr, "Child unlock on parent fd failed\n");
+                        rc = EXIT_FAILURE;
+                        goto out_child;
+                }
+                if (flock(fd2, LOCK_EX | LOCK_NB) == -1) {
+                        fprintf(stderr, "Relock after parent unlock failed!\n");
+                        rc = EXIT_FAILURE;
+                        goto out_child;
+                }
+        out_child:
+                close(fd2);
+                exit(rc);
+        }
+
+        waitpid(pid, &rc, 0);
+out:
+        close(fd);
+        return rc;
+}
+
+int t4(int argc, char *argv[])
+{
+       struct flock lock = {
+               .l_type = F_WRLCK,
+               .l_whence = SEEK_SET,
+               .l_start = 0,
+               .l_len = 10,
+       };
+
+       int fd, fd2;
+       int pid;
+       int rc = EXIT_SUCCESS;
+
+       if (argc != 4) {
+               fprintf(stderr, "Usage: ./flocks_test 4 file1 file2\n");
+               return EXIT_FAILURE;
+       }
+
+       if ((fd = open(argv[2], O_RDWR)) < 0) {
+               fprintf(stderr, "Couldn't open file: %s\n", argv[2]);
+               return EXIT_FAILURE;
+       }
+       if ((fd2 = open(argv[3], O_RDWR)) < 0) {
+               fprintf(stderr, "Couldn't open file: %s\n", argv[3]);
+               rc = EXIT_FAILURE;
+               goto out;
+       }
+
+       pid = fork();
+       if (pid == -1) {
+               perror("fork");
+               rc = EXIT_FAILURE;
+               goto out;
+       }
+
+       if (pid == 0) {
+               printf("%d: get lock1\n", getpid());
+               fflush(stdout);
+               if (t_fcntl(fd, F_SETLKW, &lock) < 0) {
+                       perror("first flock failed");
+                       rc = EXIT_FAILURE;
+                       goto out_child;
+               }
+               printf("%d: done\n", getpid());
+               sleep(3);
+               printf("%d: get lock2\n", getpid());
+               fflush(stdout);
+               if (t_fcntl(fd2, F_SETLKW, &lock) < 0) {
+                       perror("first flock failed");
+                       rc = EXIT_FAILURE;
+                       goto out_child;
+               }
+               printf("%d: done\n", getpid());
+out_child:
+               printf("%d: exit rc=%d\n", getpid(), rc);
+               exit(rc);
+       } else {
+               printf("%d: get lock2\n", getpid());
+               fflush(stdout);
+               if (t_fcntl(fd2, F_SETLKW, &lock) < 0) {
+                       perror("first flock failed");
+                       rc = EXIT_FAILURE;
+                       goto out;
+               }
+               printf("%d: done\n", getpid());
+               sleep(3);
+               printf("%d: get lock1\n", getpid());
+               fflush(stdout);
+               if (t_fcntl(fd, F_SETLKW, &lock) < 0) {
+                       perror("first flock failed");
+                       rc = EXIT_FAILURE;
+                       goto out;
+               }
+               printf("%d: done\n", getpid());
+       }
+
+out:
+       printf("%d: exit rc=%d\n", getpid(), rc);
+       return rc;
+}
+
 /** ==============================================================
  * program entry
  */
@@ -294,6 +464,12 @@ int main(int argc, char* argv[])
         case 2:
                 rc = t2(argc, argv);
                 break;
+        case 3:
+                rc = t3(argc, argv);
+                break;
+       case 4:
+               rc = t4(argc, argv);
+               break;
         default:
                 fprintf(stderr, "unknow test number %s\n", argv[1]);
                 break;