FBSD TryToSmush locking fixup
authorBen Kaduk <kaduk@mit.edu>
Wed, 30 Jun 2010 04:21:10 +0000 (00:21 -0400)
committerDerrick Brashear <shadow@dementia.org>
Wed, 30 Jun 2010 12:13:58 +0000 (05:13 -0700)
We need to hold the interlock when we check v_flags, so do so.

TryToSmush is sometimes called with the vnode already locked,
as the current code appears to hold the vnode lock for the
current working directory (which is probably a bug).  Check if
the lock is already held (panic if someone else has it!), and
unlock as appropriate when we're done.

Change-Id: Id09ef1e10632c7f63b590271a6339a069176deac
Reviewed-on: http://gerrit.openafs.org/2294
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

src/afs/FBSD/osi_vm.c

index f8807fc..7ad17c8 100644 (file)
@@ -185,15 +185,28 @@ osi_VM_TryToSmush(struct vcache *avc, afs_ucred_t *acred, int sync)
 {
     struct vnode *vp;
     int tries, code;
+    int islocked;
 
     SPLVAR;
 
     vp = AFSTOV(avc);
 
+    VI_LOCK(vp);
     if (vp->v_iflag & VI_DOOMED) {
+       VI_UNLOCK(vp);
        USERPRI;
        return;
     }
+    VI_UNLOCK(vp);
+
+    islocked = VOP_ISLOCKED(vp);
+    if (islocked == LK_EXCLOTHER)
+       panic("Trying to Smush over someone else's lock");
+    else if (islocked == LK_SHARED) {
+       afs_warn("Trying to Smush with a shared lock");
+       vn_lock(vp, LK_UPGRADE);
+    } else if (!islocked)
+       vn_lock(vp, LK_EXCLUSIVE);
 
     if (vp->v_bufobj.bo_object != NULL) {
        VM_OBJECT_LOCK(vp->v_bufobj.bo_object);
@@ -218,9 +231,14 @@ osi_VM_TryToSmush(struct vcache *avc, afs_ucred_t *acred, int sync)
     tries = 5;
     code = osi_vinvalbuf(vp, V_SAVE, PCATCH, 0);
     while (code && (tries > 0)) {
+       afs_warn("TryToSmush retrying vinvalbuf");
        code = osi_vinvalbuf(vp, V_SAVE, PCATCH, 0);
        --tries;
     }
+    if (islocked == LK_SHARED)
+       vn_lock(vp, LK_DOWNGRADE);
+    else if (!islocked)
+       VOP_UNLOCK(vp, 0);
     USERPRI;
 }