Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Jul 2016 10:30:32 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r302755 - stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201607131030.u6DAUWwO014314@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Wed Jul 13 10:30:32 2016
New Revision: 302755
URL: https://svnweb.freebsd.org/changeset/base/302755

Log:
  MFC r299947: fix locking in zfsctl_root_lookup

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

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	Wed Jul 13 10:26:38 2016	(r302754)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	Wed Jul 13 10:30:32 2016	(r302755)
@@ -534,9 +534,20 @@ zfsctl_root_lookup(vnode_t *dvp, char *n
 	ZFS_ENTER(zfsvfs);
 
 	if (strcmp(nm, "..") == 0) {
+#ifdef illumos
 		err = VFS_ROOT(dvp->v_vfsp, LK_EXCLUSIVE, vpp);
+#else
+		/*
+		 * NB: can not use VFS_ROOT here as it would acquire
+		 * the vnode lock of the parent (root) vnode while
+		 * holding the child's (.zfs) lock.
+		 */
+		znode_t *rootzp;
+
+		err = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp);
 		if (err == 0)
-			VOP_UNLOCK(*vpp, 0);
+			*vpp = ZTOV(rootzp);
+#endif
 	} else {
 		err = gfs_vop_lookup(dvp, nm, vpp, pnp, flags, rdir,
 		    cr, ct, direntflags, realpnp);
@@ -598,6 +609,7 @@ zfsctl_freebsd_root_lookup(ap)
 	vnode_t **vpp = ap->a_vpp;
 	cred_t *cr = ap->a_cnp->cn_cred;
 	int flags = ap->a_cnp->cn_flags;
+	int lkflags = ap->a_cnp->cn_lkflags;
 	int nameiop = ap->a_cnp->cn_nameiop;
 	char nm[NAME_MAX + 1];
 	int err;
@@ -609,8 +621,18 @@ zfsctl_freebsd_root_lookup(ap)
 	strlcpy(nm, ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen + 1);
 
 	err = zfsctl_root_lookup(dvp, nm, vpp, NULL, 0, NULL, cr, NULL, NULL, NULL);
-	if (err == 0 && (nm[0] != '.' || nm[1] != '\0'))
-		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
+	if (err == 0 && (nm[0] != '.' || nm[1] != '\0')) {
+		if (flags & ISDOTDOT)
+			VOP_UNLOCK(dvp, 0);
+		err = vn_lock(*vpp, lkflags);
+		if (err != 0) {
+			vrele(*vpp);
+			*vpp = NULL;
+		}
+		if (flags & ISDOTDOT)
+			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
+	}
+
 	return (err);
 }
 



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