]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
linux-byte-range-locks-sensibility-20090526
authorSimon Wilkinson <sxw@inf.ed.ac.uk>
Wed, 27 May 2009 01:47:40 +0000 (01:47 +0000)
committerDerrick Brashear <shadow|account-1000005@unknown>
Thu, 17 Dec 2009 06:28:56 +0000 (22:28 -0800)
LICENSE IPL10
FIXES 124766

make our locks work correctly with the linux connectathon lock testing

Change-Id: Ic632c30f597881ae40a8b412a3a1fd99f35ef025
Reviewed-on: http://gerrit.openafs.org/928
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
acinclude.m4
src/afs/LINUX/osi_vnodeops.c
src/afs/VNOPS/afs_vnop_flock.c
src/cf/linux-test4.m4

index 56c65d69f4c087b88235abd8a88bb8680f190467..31cd1a30e28d432ba3f5136594a993a8df6dbf72 100644 (file)
@@ -774,6 +774,8 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
                 LINUX_KERNEL_LINUX_SYSCALL_H
                 LINUX_KERNEL_LINUX_SEQ_FILE_H
                 LINUX_KERNEL_POSIX_LOCK_FILE_WAIT_ARG
+                LINUX_POSIX_TEST_LOCK_RETURNS_CONFLICT
+                LINUX_POSIX_TEST_LOCK_CONFLICT_ARG
                 LINUX_KERNEL_SELINUX
                 LINUX_KERNEL_SOCK_CREATE
                 LINUX_KERNEL_PAGE_FOLLOW_LINK
index 1d8354909c3c44234eb7b769eed8b4800d1c0cdc..7d8daeb38c2b18e81e9c6c968f11793b3991ff39 100644 (file)
@@ -476,13 +476,19 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
     struct vcache *vcp = VTOAFS(FILE_INODE(fp));
     cred_t *credp = crref();
     struct AFS_FLOCK flock;
+#if defined(POSIX_TEST_LOCK_CONFLICT_ARG)
+    struct file_lock conflict;
+#elif defined(POSIX_TEST_LOCK_RETURNS_CONFLICT)
+    struct file_lock *conflict;
+#endif
+    
     /* Convert to a lock format afs_lockctl understands. */
     memset((char *)&flock, 0, sizeof(flock));
     flock.l_type = flp->fl_type;
     flock.l_pid = flp->fl_pid;
     flock.l_whence = 0;
     flock.l_start = flp->fl_start;
-    flock.l_len = flp->fl_end - flp->fl_start;
+    flock.l_len = flp->fl_end - flp->fl_start + 1;
 
     /* Safe because there are no large files, yet */
 #if defined(F_GETLK64) && (F_GETLK != F_GETLK64)
@@ -501,12 +507,12 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
 #ifdef AFS_LINUX24_ENV
     if ((code == 0 || flp->fl_type == F_UNLCK) && 
         (cmd == F_SETLK || cmd == F_SETLKW)) {
-#ifdef POSIX_LOCK_FILE_WAIT_ARG
+# ifdef POSIX_LOCK_FILE_WAIT_ARG
        code = posix_lock_file(fp, flp, 0);
-#else
+# else
        flp->fl_flags &=~ FL_SLEEP;
        code = posix_lock_file(fp, flp);
-#endif 
+# endif 
        if (code && flp->fl_type != F_UNLCK) {
            struct AFS_FLOCK flock2;
            flock2 = flock;
@@ -516,12 +522,40 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
            AFS_GUNLOCK();
        }
     }
+    /* If lockctl says there are no conflicting locks, then also check with the
+     * kernel, as lockctl knows nothing about byte range locks
+     */
+    if (code == 0 && cmd == F_GETLK && flock.l_type == F_UNLCK) {
+# if defined(POSIX_TEST_LOCK_CONFLICT_ARG)
+        if (posix_test_lock(fp, flp, &conflict)) {
+            locks_copy_lock(flp, &conflict);
+            flp->fl_type = F_UNLCK;
+            crfree(credp);
+            return 0;
+        }
+# elif defined(POSIX_TEST_LOCK_RETURNS_CONFLICT)
+       if ((conflict = posix_test_lock(fp, flp))) {
+           locks_copy_lock(flp, conflict);
+           flp->fl_type = F_UNLCK;
+           crfee(credp);
+           return 0;
+       }
+# else
+        posix_test_lock(fp, flp);
+        /* If we found a lock in the kernel's structure, return it */
+        if (flp->fl_type != F_UNLCK) {
+            crfree(credp);
+            return 0;
+        }
+    }
+# endif
+    
 #endif
     /* Convert flock back to Linux's file_lock */
     flp->fl_type = flock.l_type;
     flp->fl_pid = flock.l_pid;
     flp->fl_start = flock.l_start;
-    flp->fl_end = flock.l_start + flock.l_len;
+    flp->fl_end = flock.l_start + flock.l_len - 1;
 
     crfree(credp);
     return afs_convert_code(code);
index 72192586f5cfb40d5a5ee4bbba0ef086f4a44c86..f3d33e7a1c4359ac5edbca8b5b0cbcc248d57a91 100644 (file)
@@ -467,8 +467,13 @@ DoLockWarning(void)
 
     /* otherwise, it is time to nag the user */
     lastWarnTime = now;
+#ifdef AFS_LINUX26_ENV
+    afs_warn
+       ("afs: byte-range locks only enforced for processes on this machine.\n");
+#else
     afs_warn
        ("afs: byte-range lock/unlock ignored; make sure no one else is running this program.\n");
+#endif
 }
 
 
index fa7143e96a416b8994e9230cf3fb950b5d341395..b2ec0c85b1c6ac4a0f79d9eca9a1d6586f1baec6 100644 (file)
@@ -477,7 +477,6 @@ AC_DEFUN([LINUX_KERNEL_POSIX_LOCK_FILE_WAIT_ARG], [
       ac_cv_linux_kernel_posix_lock_file_wait_arg=no)])
   AC_MSG_RESULT($ac_cv_linux_kernel_posix_lock_file_wait_arg)])
 
-
 AC_DEFUN([LINUX_KERNEL_SOCK_CREATE], [
   AC_MSG_CHECKING([for 5th argument in sock_create found in some SELinux kernels])
   AC_CACHE_VAL([ac_cv_linux_kernel_sock_create_v], [
@@ -1186,3 +1185,33 @@ _sb.s_bdi= NULL;],
   if test "x$ac_cv_linux_struct_super_block_has_s_bdi" = "xyes"; then
     AC_DEFINE([STRUCT_SUPER_BLOCK_HAS_S_BDI], 1, [define if struct super_block has an s_bdi member])
   fi])
+
+AC_DEFUN([LINUX_POSIX_TEST_LOCK_RETURNS_CONFLICT], [
+  AC_MSG_CHECKING([if posix_test_lock returns a struct file_lock])
+  AC_CACHE_VAL([ac_cv_linux_posix_test_lock_returns_conflict], [
+    AC_TRY_KBUILD(
+[#include <linux/fs.h>],
+[struct file_lock *lock;
+ struct file * file;
+lock = posix_test_lock(file, lock);],
+      ac_cv_linux_posix_test_lock_returns_conflict=yes,
+      ac_cv_linux_posix_test_lock_returns_conflict=no)])
+  AC_MSG_RESULT($ac_cv_linux_posix_test_lock_returns_conflict)
+  if test "x$ac_cv_linux_posix_test_lock_returns_conflict" = "xyes"; then
+    AC_DEFINE([POSIX_TEST_LOCK_RETURNS_CONFLICT], 1, [define if posix_test_lock returns the conflicting lock])
+  fi])
+
+AC_DEFUN([LINUX_POSIX_TEST_LOCK_CONFLICT_ARG], [
+  AC_MSG_CHECKING([if posix_test_lock takes a conflict argument])
+  AC_CACHE_VAL([ac_cv_linux_posix_test_lock_conflict_arg], [
+    AC_TRY_KBUILD(
+[#include <linux/fs.h>],
+[ struct file_lock *lock;
+  struct file *file;
+  posix_test_lock(file, lock, lock);],
+      ac_cv_linux_posix_test_lock_conflict_arg=yes,
+      ac_cv_lonuc_posix_test_lock_conflict_arg=no)])
+  AC_MSG_RESULT($ac_cv_linux_posix_test_lock_conflict_arg)
+  if test "x$ac_cv_linux_posix_test_lock_conflict_arg" = "xyes"; then
+    AC_DEFINE([POSIX_TEST_LOCK_CONFLICT_ARG], 1, [define if posix_test_lock takes a conflict argument])
+  fi])