From fd1c37ebe7f5fb2ed52371705aaf1efc7764c7eb Mon Sep 17 00:00:00 2001 From: Chaskiel M Grundman Date: Sat, 3 Feb 2007 03:23:16 +0000 Subject: [PATCH] linux-and-locks-cleanup-20070202 fix linux flock, remove a bogus lock assert, and fix pid tracking to avoid useless panic --- acinclude.m4 | 4 +++ src/afs/LINUX/osi_vnodeops.c | 62 ++++++++++++++++++++++++++++++++++-- src/afs/afs_callback.c | 8 ++--- src/afs/lock.h | 6 ++-- src/cf/linux-test4.m4 | 11 +++++++ 5 files changed, 81 insertions(+), 10 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index c5bb1a9b06..db38569b0e 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -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 diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 29bee80277..5aefdcde77 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -490,7 +490,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; @@ -499,8 +500,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; @@ -521,6 +521,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 @@ -612,6 +665,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 }; diff --git a/src/afs/afs_callback.c b/src/afs/afs_callback.c index 3b2c9cf361..7b1f276476 100644 --- a/src/afs/afs_callback.c +++ b/src/afs/afs_callback.c @@ -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 */ diff --git a/src/afs/lock.h b/src/afs/lock.h index 27e4f2a1d9..852babc38a 100644 --- a/src/afs/lock.h +++ b/src/afs/lock.h @@ -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) diff --git a/src/cf/linux-test4.m4 b/src/cf/linux-test4.m4 index 61b92c8814..6beb68c554 100644 --- a/src/cf/linux-test4.m4 +++ b/src/cf/linux-test4.m4 @@ -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 ], +[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)])