Author: avg
Date: Wed Jul 13 10:16:45 2016
New Revision: 302752
URL: https://svnweb.freebsd.org/changeset/base/302752

Log:
  MFC r299947: fix locking in zfsctl_root_lookup

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

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c       
Wed Jul 13 10:14:36 2016        (r302751)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c       
Wed Jul 13 10:16:45 2016        (r302752)
@@ -551,9 +551,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);
@@ -626,10 +637,10 @@ 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;
-       int ltype;
 
        if ((flags & ISLASTCN) && (nameiop == RENAME || nameiop == CREATE))
                return (EOPNOTSUPP);
@@ -638,16 +649,15 @@ 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')) {
-               ltype = VOP_ISLOCKED(dvp);
-               if (flags & ISDOTDOT) {
-                       VN_HOLD(*vpp);
+               if (flags & ISDOTDOT)
                        VOP_UNLOCK(dvp, 0);
+               err = vn_lock(*vpp, lkflags);
+               if (err != 0) {
+                       vrele(*vpp);
+                       *vpp = NULL;
                }
-               vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
-               if (flags & ISDOTDOT) {
-                       VN_RELE(*vpp);
-                       vn_lock(dvp, ltype| LK_RETRY);
-               }
+               if (flags & ISDOTDOT)
+                       vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
        }
 
        return (err);
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "[email protected]"

Reply via email to