summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_vnops.c
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2002-08-22 06:58:11 +0000
committerjeff <jeff@FreeBSD.org>2002-08-22 06:58:11 +0000
commit820f26ad86899f246ecf708829e33ae1eb8b0bf7 (patch)
treeeb99fb2547185035938ae7bdb4a87f96c795345b /sys/kern/vfs_vnops.c
parent1e39ba86206301d7f569b3f402577d596d55faa0 (diff)
downloadFreeBSD-src-820f26ad86899f246ecf708829e33ae1eb8b0bf7.zip
FreeBSD-src-820f26ad86899f246ecf708829e33ae1eb8b0bf7.tar.gz
- Fix interlock handling in vn_lock(). Previously, vn_lock() could return
with interlock held in error conditions when the caller did not specify LK_INTERLOCK. - Add several comments to vn_lock() describing the rational behind the code flow since it was not immediately obvious.
Diffstat (limited to 'sys/kern/vfs_vnops.c')
-rw-r--r--sys/kern/vfs_vnops.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 875e3f0..3f00fda 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -843,25 +843,27 @@ debug_vn_lock(vp, flags, td, filename, line)
vp->v_iflag |= VI_XWANT;
msleep(vp, VI_MTX(vp), PINOD | PDROP,
"vn_lock", 0);
- mp_fixme("interlock not released.");
+ /*
+ * Since we're just going to return, unlock interlock
+ * if the caller didn't call us with it held.
+ */
+ if ((flags & (LK_INTERLOCK|LK_RETRY)) == 0)
+ VI_UNLOCK(vp);
error = ENOENT;
} else {
-#if 0
- /* this can now occur in normal operation */
- if (vp->v_vxproc != NULL)
- log(LOG_INFO, "VXLOCK interlock avoided in vn_lock\n");
-#endif
#ifdef DEBUG_LOCKS
vp->filename = filename;
vp->line = line;
#endif
+ /*
+ * lockmgr drops interlock before it will return for
+ * any reason. So force the code above to relock it.
+ */
error = VOP_LOCK(vp,
flags | LK_NOPAUSE | LK_INTERLOCK, td);
- if (error == 0)
- return (error);
+ flags &= ~LK_INTERLOCK;
}
- flags &= ~LK_INTERLOCK;
- } while (flags & LK_RETRY);
+ } while (flags & LK_RETRY && error != 0);
return (error);
}
OpenPOWER on IntegriCloud