Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 10 Jan 2015 01:01:13 +0000 (UTC)
From:      Xin LI <delphij@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r276899 - stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201501100101.t0A11Drf096490@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: delphij
Date: Sat Jan 10 01:01:12 2015
New Revision: 276899
URL: https://svnweb.freebsd.org/changeset/base/276899

Log:
  MFC r264392 (davide):
  
  Fix a panic in zfs_rename().
  this is due to a wrong dereference of a vnode when it's not locked and
  can be (potentially) recycled. 'sdvp' cannot be locked on zfs_rename()
  entry point because the VFS can't be sure that this scenario is
  LOR-free (it might violate the parent->child lock acquisition rule).
  Dereference 'tdvp' instead, which is already locked on entry, and access
  'sdvp' fields only when it's safe, i.e. under ZFS_ENTER scope.
  
  While at it, remove the usage of VOP_REALVP, as long as this is a NOP
  on FreeBSD.

Modified:
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Sat Jan 10 00:11:10 2015	(r276898)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Sat Jan 10 01:01:12 2015	(r276899)
@@ -3730,9 +3730,8 @@ static int
 zfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr,
     caller_context_t *ct, int flags)
 {
-	znode_t		*tdzp, *szp, *tzp;
-	znode_t		*sdzp = VTOZ(sdvp);
-	zfsvfs_t	*zfsvfs = sdzp->z_zfsvfs;
+	znode_t		*tdzp, *sdzp, *szp, *tzp;
+	zfsvfs_t 	*zfsvfs;
 	zilog_t		*zilog;
 	vnode_t		*realvp;
 	zfs_dirlock_t	*sdl, *tdl;
@@ -3743,24 +3742,27 @@ zfs_rename(vnode_t *sdvp, char *snm, vno
 	int		zflg = 0;
 	boolean_t	waited = B_FALSE;
 
+	tdzp = VTOZ(tdvp);
+	ZFS_VERIFY_ZP(tdzp);
+	zfsvfs = tdzp->z_zfsvfs;
 	ZFS_ENTER(zfsvfs);
-	ZFS_VERIFY_ZP(sdzp);
 	zilog = zfsvfs->z_log;
+	sdzp = VTOZ(sdvp);
 
 	/*
-	 * Make sure we have the real vp for the target directory.
+	 * In case sdzp is not valid, let's be sure to exit from the right
+	 * zfsvfs_t.
 	 */
-	if (VOP_REALVP(tdvp, &realvp, ct) == 0)
-		tdvp = realvp;
-
-	tdzp = VTOZ(tdvp);
-	ZFS_VERIFY_ZP(tdzp);
+	if (sdzp->z_sa_hdl == NULL) {
+		ZFS_EXIT(zfsvfs);
+		return (SET_ERROR(EIO));
+	}
 
 	/*
 	 * We check z_zfsvfs rather than v_vfsp here, because snapshots and the
 	 * ctldir appear to have the same v_vfsp.
 	 */
-	if (tdzp->z_zfsvfs != zfsvfs || zfsctl_is_node(tdvp)) {
+	if (sdzp->z_zfsvfs != zfsvfs || zfsctl_is_node(tdvp)) {
 		ZFS_EXIT(zfsvfs);
 		return (SET_ERROR(EXDEV));
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201501100101.t0A11Drf096490>