summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2005-03-13 12:04:12 +0000
committerjeff <jeff@FreeBSD.org>2005-03-13 12:04:12 +0000
commit6d607052330e66dc1e260e8f180de926262e8041 (patch)
tree46902fafd3cddf062e4a953287a3aef7082658b8 /sys/ufs
parentcebf929bc833e9802f4f5142935c8f5355502a26 (diff)
downloadFreeBSD-src-6d607052330e66dc1e260e8f180de926262e8041.zip
FreeBSD-src-6d607052330e66dc1e260e8f180de926262e8041.tar.gz
- It is not legal to access v_data without the vnode lock or interlock
held. Grab the vnode interlock if LK_INTERLOCK has not been passed in so that we can inspect v_data in ffs_lock(). Sponsored by: Isilon Systems, Inc.
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ffs/ffs_vnops.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 9b3a440..0362876 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -343,7 +343,17 @@ ffs_lock(ap)
{
struct vnode *vp = ap->a_vp;
- if ((VTOI(vp)->i_flags & SF_SNAPSHOT) &&
+ /*
+ * v_data could be NULL if a thread attempts to lock a
+ * vnode that is being recycled. Just hit the normal
+ * vnode lock in this case. Grab the interlock so we may
+ * safely inspect the vnode.
+ */
+ if ((ap->a_flags & LK_INTERLOCK) == 0) {
+ VI_LOCK(vp);
+ ap->a_flags |= LK_INTERLOCK;
+ }
+ if (vp->v_data && (VTOI(vp)->i_flags & SF_SNAPSHOT) &&
((ap->a_flags & LK_TYPE_MASK) == LK_SHARED)) {
ap->a_flags &= ~LK_TYPE_MASK;
ap->a_flags |= LK_EXCLUSIVE;
OpenPOWER on IntegriCloud