]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
STABLE14-linux-and-locks-cleanup-20070202
authorChaskiel M Grundman <cg2v@andrew.cmu.edu>
Sat, 3 Feb 2007 03:25:15 +0000 (03:25 +0000)
committerDerrick Brashear <shadow@dementia.org>
Sat, 3 Feb 2007 03:25:15 +0000 (03:25 +0000)
fix linux flock, remove a bogus lock assert, and fix pid tracking to avoid useless panic

(cherry picked from commit fd1c37ebe7f5fb2ed52371705aaf1efc7764c7eb)

acinclude.m4
src/afs/LINUX/osi_vnodeops.c
src/afs/afs_callback.c
src/afs/lock.h
src/cf/linux-test4.m4

index 54bdb1c0de428dabd0e2d063004efd4fc5933ef6..ee55603c571460faa418012fc5938bbd4b2e4af9 100644 (file)
@@ -606,6 +606,7 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
                 LINUX_IOP_I_PERMISSION_TAKES_NAMEIDATA
                 LINUX_DOP_D_REVALIDATE_TAKES_NAMEIDATA
                 LINUX_AOP_WRITEBACK_CONTROL
+                LINUX_FS_STRUCT_FOP_HAS_FLOCK
                 LINUX_KERNEL_LINUX_SYSCALL_H
                 LINUX_KERNEL_LINUX_SEQ_FILE_H
                 LINUX_KERNEL_SELINUX
@@ -830,6 +831,9 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
                 if test "x$ac_cv_linux_init_work_has_data" = "xyes" ; then
                  AC_DEFINE(INIT_WORK_HAS_DATA, 1, [define if INIT_WORK takes a data (3rd) argument])
                 fi
+                if test "x$ac_cv_linux_fs_struct_fop_has_flock" = "xyes" ; then
+                 AC_DEFINE(STRUCT_FILE_OPERATIONS_HAS_FLOCK, 1, [define if your struct file_operations has flock])
+                fi
                 :
                fi
 esac
index 60a087c10f7d04d6762b84d14c45de6fbf352b28..ecdcd7e94709af67213d6072ace2e8b2b9c986d4 100644 (file)
@@ -472,7 +472,8 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
     AFS_GUNLOCK();
 
 #ifdef AFS_LINUX24_ENV
-    if (code == 0 && (cmd == F_SETLK || cmd == F_SETLKW)) {
+    if ((code == 0 || flp->fl_type == F_UNLCK) && 
+        (cmd == F_SETLK || cmd == F_SETLKW)) {
 #ifdef AFS_LINUX26_ENV
        struct file_lock flp2;
        flp2 = *flp;
@@ -481,8 +482,7 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
 #else
        code = posix_lock_file(fp, flp, 0);
 #endif 
-       osi_Assert(code != -EAGAIN); /* there should be no conflicts */
-       if (code) {
+       if (code && flp->fl_type != F_UNLCK) {
            struct AFS_FLOCK flock2;
            flock2 = flock;
            flock2.l_type = F_UNLCK;
@@ -503,6 +503,59 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
 
 }
 
+#ifdef STRUCT_FILE_OPERATIONS_HAS_FLOCK
+static int
+afs_linux_flock(struct file *fp, int cmd, struct file_lock *flp) {
+    int code = 0;
+    struct vcache *vcp = VTOAFS(FILE_INODE(fp));
+    cred_t *credp = crref();
+    struct AFS_FLOCK flock;
+    /* 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 = 0;
+    flock.l_len = OFFSET_MAX;
+
+    /* Safe because there are no large files, yet */
+#if defined(F_GETLK64) && (F_GETLK != F_GETLK64)
+    if (cmd == F_GETLK64)
+       cmd = F_GETLK;
+    else if (cmd == F_SETLK64)
+       cmd = F_SETLK;
+    else if (cmd == F_SETLKW64)
+       cmd = F_SETLKW;
+#endif /* F_GETLK64 && F_GETLK != F_GETLK64 */
+
+    AFS_GLOCK();
+    code = afs_lockctl(vcp, &flock, cmd, credp);
+    AFS_GUNLOCK();
+
+    if ((code == 0 || flp->fl_type == F_UNLCK) && 
+        (cmd == F_SETLK || cmd == F_SETLKW)) {
+       struct file_lock flp2;
+       flp2 = *flp;
+       flp2.fl_flags &=~ FL_SLEEP;
+       code = flock_lock_file_wait(fp, &flp2);
+       if (code && flp->fl_type != F_UNLCK) {
+           struct AFS_FLOCK flock2;
+           flock2 = flock;
+           flock2.l_type = F_UNLCK;
+           AFS_GLOCK();
+           afs_lockctl(vcp, &flock2, F_SETLK, credp);
+           AFS_GUNLOCK();
+       }
+    }
+    /* Convert flock back to Linux's file_lock */
+    flp->fl_type = flock.l_type;
+    flp->fl_pid = flock.l_pid;
+
+    crfree(credp);
+    return -code;
+}
+#endif
+
 /* afs_linux_flush
  * essentially the same as afs_fsync() but we need to get the return
  * code for the sys_close() here, not afs_linux_release(), so call
@@ -594,6 +647,9 @@ struct file_operations afs_file_fops = {
   .release =   afs_linux_release,
   .fsync =     afs_linux_fsync,
   .lock =      afs_linux_lock,
+#ifdef STRUCT_FILE_OPERATIONS_HAS_FLOCK
+  .flock =     afs_linux_flock,
+#endif
 };
 
 
index 4e791d0ec35ec0b9f431d6a4dd561f1682023487..5e8c1c0a7c8177c78a3b0ae048b6fc97ac0207a4 100644 (file)
@@ -136,8 +136,8 @@ SRXAFSCB_GetCE(struct rx_call *a_call, afs_int32 a_index,
     a_result->lock.readersReading = tvc->lock.readers_reading;
     a_result->lock.numWaiting = tvc->lock.num_waiting;
 #if defined(INSTRUMENT_LOCKS)
-    a_result->lock.pid_last_reader = tvc->lock.pid_last_reader;
-    a_result->lock.pid_writer = tvc->lock.pid_writer;
+    a_result->lock.pid_last_reader = MyPidxx2Pid(tvc->lock.pid_last_reader);
+    a_result->lock.pid_writer = MyPidxx2Pid(tvc->lock.pid_writer);
     a_result->lock.src_indicator = tvc->lock.src_indicator;
 #else
     /* On osf20 , the vcache does not maintain these three fields */
@@ -222,8 +222,8 @@ SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
     a_result->lock.readersReading = tvc->lock.readers_reading;
     a_result->lock.numWaiting = tvc->lock.num_waiting;
 #if defined(INSTRUMENT_LOCKS)
-    a_result->lock.pid_last_reader = tvc->lock.pid_last_reader;
-    a_result->lock.pid_writer = tvc->lock.pid_writer;
+    a_result->lock.pid_last_reader = MyPidxx2Pid(tvc->lock.pid_last_reader);
+    a_result->lock.pid_writer = MyPidxx2Pid(tvc->lock.pid_writer);
     a_result->lock.src_indicator = tvc->lock.src_indicator;
 #else
     /* On osf20 , the vcache does not maintain these three fields */
index 27e4f2a1d9815914383e863bde73165a9ab5f2bc..852babc38a6655a9b78ab723d942f7152c280d3b 100644 (file)
@@ -89,7 +89,7 @@ typedef struct afs_bozoLock afs_bozoLock_t;
 #if defined(AFS_SUN57_ENV)
 typedef kthread_t * afs_lock_tracker_t;
 #define MyPidxx (curthread)
-#define MyPidxx2Pid(x) (ttoproc(x)->p_pid)
+#define MyPidxx2Pid(x) (x ? ttoproc(x)->p_pid : 0)
 #elif defined(AFS_SUN5_ENV) || defined(AFS_OBSD_ENV)
 typedef unsigned int afs_lock_tracker_t;
 #define MyPidxx (curproc->p_pid)
@@ -104,7 +104,7 @@ extern tid_t thread_self();
 #if defined(AFS_HPUX101_ENV)
 typedef struct proc * afs_lock_tracker_t;
 #define MyPidxx (u.u_procp)
-#define MyPidxx2Pid(x) ((afs_int32)p_pid(x))
+#define MyPidxx2Pid(x) (x ? (afs_int32)p_pid(x) : 0)
 #else
 #if defined(AFS_SGI64_ENV)
 #if defined(AFS_SGI65_ENV)
@@ -120,7 +120,7 @@ typedef unsigned int afs_lock_tracker_t;
 #ifdef AFS_LINUX20_ENV
 typedef struct task_struct * afs_lock_tracker_t;
 #define MyPidxx (current)
-#define MyPidxx2Pid(x) ((x)->pid)
+#define MyPidxx2Pid(x) (x? (x)->pid : 0)
 #else
 #if defined(AFS_DARWIN_ENV)
 #if defined(AFS_DARWIN80_ENV)
index 61b92c881483c1586967e247042bb4523ed7b3d5..6beb68c554d1ded1a5ccee8cb7dd4e3637af7af6 100644 (file)
@@ -761,3 +761,14 @@ INIT_WORK(w,f,i);],
       ac_cv_linux_init_work_has_data=no)])
   AC_MSG_RESULT($ac_cv_linux_init_work_has_data)])
 
+
+AC_DEFUN([LINUX_FS_STRUCT_FOP_HAS_FLOCK], [
+  AC_MSG_CHECKING([for flock in struct file_operations])
+  AC_CACHE_VAL([ac_cv_linux_fs_struct_fop_has_flock], [
+    AC_TRY_KBUILD(
+[#include <linux/fs.h>],
+[struct file_operations _fop;
+_fop.flock(NULL, 0, NULL);],
+      ac_cv_linux_fs_struct_fop_has_flock=yes,
+      ac_cv_linux_fs_struct_fop_has_flock=no)])
+  AC_MSG_RESULT($ac_cv_linux_fs_struct_fop_has_flock)])