svn commit: r206667 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs

Pawel Jakub Dawidek pjd at FreeBSD.org
Thu Apr 15 16:40:55 UTC 2010


Author: pjd
Date: Thu Apr 15 16:40:54 2010
New Revision: 206667
URL: http://svn.freebsd.org/changeset/base/206667

Log:
  Fix 3-way deadlock that can happen because of ZFS and vnode lock
  order reversal.
  
  thread0 (vfs_fhtovp)	thread1 (vop_getattr)	thread2 (zfs_recv)
  --------------------	---------------------	------------------
  			vn_lock
  rrw_enter_read
  						rrw_enter_write (hangs)
  			rrw_enter_read (hangs)
  vn_lock (hangs)
  
  Submitted by:	Attila Nagy <bra at fsn.hu>
  MFC after:	3 days

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	Thu Apr 15 16:35:34 2010	(r206666)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	Thu Apr 15 16:40:54 2010	(r206667)
@@ -868,13 +868,15 @@ zfs_root(vfs_t *vfsp, int flags, vnode_t
 	ZFS_ENTER_NOERROR(zfsvfs);
 
 	error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp);
+
+	ZFS_EXIT(zfsvfs);
+
 	if (error == 0) {
 		*vpp = ZTOV(rootzp);
 		error = vn_lock(*vpp, flags);
 		(*vpp)->v_vflag |= VV_ROOT;
 	}
 
-	ZFS_EXIT(zfsvfs);
 	return (error);
 }
 
@@ -1143,13 +1145,13 @@ zfs_vget(vfs_t *vfsp, ino_t ino, int fla
 		VN_RELE(ZTOV(zp));
 		err = EINVAL;
 	}
+	ZFS_EXIT(zfsvfs);
 	if (err != 0)
 		*vpp = NULL;
 	else {
 		*vpp = ZTOV(zp);
 		vn_lock(*vpp, flags);
 	}
-	ZFS_EXIT(zfsvfs);
 	return (err);
 }
 
@@ -1237,8 +1239,8 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vno
 		} else {
 			VN_HOLD(*vpp);
 		}
-		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
 		ZFS_EXIT(zfsvfs);
+		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
 		return (0);
 	}
 
@@ -1259,10 +1261,11 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vno
 		return (EINVAL);
 	}
 
+	ZFS_EXIT(zfsvfs);
+
 	*vpp = ZTOV(zp);
 	vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
 	vnode_create_vobject(*vpp, zp->z_phys->zp_size, curthread);
-	ZFS_EXIT(zfsvfs);
 	return (0);
 }
 

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Thu Apr 15 16:35:34 2010	(r206666)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Thu Apr 15 16:40:54 2010	(r206667)
@@ -1209,15 +1209,17 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode
 			ltype = VOP_ISLOCKED(dvp);
 			VOP_UNLOCK(dvp, 0);
 		}
+		ZFS_EXIT(zfsvfs);
 		error = vn_lock(*vpp, cnp->cn_lkflags);
 		if (cnp->cn_flags & ISDOTDOT)
 			vn_lock(dvp, ltype | LK_RETRY);
 		if (error != 0) {
 			VN_RELE(*vpp);
 			*vpp = NULL;
-			ZFS_EXIT(zfsvfs);
 			return (error);
 		}
+	} else {
+		ZFS_EXIT(zfsvfs);
 	}
 
 #ifdef FREEBSD_NAMECACHE
@@ -1237,8 +1239,6 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode
 	}
 #endif
 
-	ZFS_EXIT(zfsvfs);
-
 	return (error);
 }
 


More information about the svn-src-head mailing list