FBSD: Avoid holding AFS_GLOCK during vinvalbuf 70/13970/5
authorAndrew Deason <adeason@dson.org>
Wed, 27 Nov 2019 05:39:24 +0000 (23:39 -0600)
committerBenjamin Kaduk <kaduk@mit.edu>
Fri, 24 Apr 2020 03:18:58 +0000 (23:18 -0400)
Currently we call vinvalbuf(9) in a few places while holding
AFS_GLOCK, but AFS_GLOCK is a non-sleepable lock (struct mtx), and
vinvalbuf can sleep. This can trigger a panic in some rare conditions,
with the message:

    Sleeping thread (tid 100179, pid 95481) owns a non-sleepable lock

To avoid this, drop AFS_GLOCK around a few places that call
vinvalbuf().

Change-Id: I58acb144b6ffa007675402e7639b63ff3745dec5
Reviewed-on: https://gerrit.openafs.org/13970
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>

src/afs/FBSD/osi_vm.c
src/afs/afs_osi_vm.c
src/afs/afs_vcache.c

index 6dcd373..49bbe98 100644 (file)
@@ -173,6 +173,8 @@ osi_VM_TryToSmush(struct vcache *avc, afs_ucred_t *acred, int sync)
     }
     VI_UNLOCK(vp);
 
+    AFS_GUNLOCK();
+
     islocked = islocked_vnode(vp);
     if (islocked == LK_EXCLOTHER)
        panic("Trying to Smush over someone else's lock");
@@ -213,6 +215,8 @@ osi_VM_TryToSmush(struct vcache *avc, afs_ucred_t *acred, int sync)
        lock_vnode(vp, LK_DOWNGRADE);
     else if (!islocked)
        unlock_vnode(vp);
+
+    AFS_GLOCK();
 }
 
 /* Purge VM for a file when its callback is revoked.
index dc25df8..5c1c03a 100644 (file)
@@ -93,13 +93,9 @@ osi_FlushPages(struct vcache *avc, afs_ucred_t *credp)
               ICL_TYPE_INT32, origDV.low, ICL_TYPE_INT32, avc->f.m.Length);
 
     ReleaseWriteLock(&avc->lock);
-#ifndef AFS_FBSD_ENV
     AFS_GUNLOCK();
-#endif
     osi_VM_FlushPages(avc, credp);
-#ifndef AFS_FBSD_ENV
     AFS_GLOCK();
-#endif
     ObtainWriteLock(&avc->lock, 88);
 
     /* do this last, and to original version, since stores may occur
index c0749d2..23600c9 100644 (file)
@@ -1742,19 +1742,15 @@ afs_GetVCache(struct VenusFid *afid, struct vrequest *areq)
        if (!iheldthelock)
            VOP_UNLOCK(vp, LK_EXCLUSIVE, current_proc());
 #  elif defined(AFS_FBSD_ENV)
+       AFS_GUNLOCK();
        iheldthelock = VOP_ISLOCKED(vp);
        if (!iheldthelock) {
-           /* nosleep/sleep lock order reversal */
-           int glocked = ISAFS_GLOCK();
-           if (glocked)
-               AFS_GUNLOCK();
            vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-           if (glocked)
-               AFS_GLOCK();
        }
        vinvalbuf(vp, V_SAVE, PINOD, 0); /* changed late in 8.0-CURRENT */
        if (!iheldthelock)
            VOP_UNLOCK(vp, 0);
+       AFS_GLOCK();
 #  elif defined(AFS_OBSD_ENV)
        iheldthelock = VOP_ISLOCKED(vp, curproc);
        if (!iheldthelock)