Date: Sat, 24 Sep 2016 08:13:15 +0000 (UTC) From: Andriy Gapon <avg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r306292 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs Message-ID: <201609240813.u8O8DF1k075054@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: avg Date: Sat Sep 24 08:13:15 2016 New Revision: 306292 URL: https://svnweb.freebsd.org/changeset/base/306292 Log: fix vnode lock assertion for extended attributes directory Background. In ZFS a file with extended attributes has a special directory associated with it where each extended attribute is a file. The attribute's name is a file name and its value is a file content. When the ownership of a file with extended attributes is changed, ZFS also changes ownership of the special directory. This is where the bug was hit. The bug was introduced in r209158. Nota bene. ZFS vnode locks are typically acquired before z_teardown_lock (i.e., before ZFS_ENTER). But this is not the case for the vnodes that represent the extended attribute directory and files. Those are always locked after ZFS_ENTER. This is confusing and fragile. PR: 212702 Reported by: Christian Fuss to FreeNAS Tested by: mav MFC after: 1 week Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 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 Sat Sep 24 07:59:54 2016 (r306291) +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Sat Sep 24 08:13:15 2016 (r306292) @@ -3197,6 +3197,11 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, i if (err == 0 && xattr_obj) { err = zfs_zget(zp->z_zfsvfs, xattr_obj, &attrzp); + if (err == 0) { + err = vn_lock(ZTOV(attrzp), LK_EXCLUSIVE); + if (err != 0) + vrele(ZTOV(attrzp)); + } if (err) goto out2; } @@ -3206,7 +3211,7 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, i if (new_uid != zp->z_uid && zfs_fuid_overquota(zfsvfs, B_FALSE, new_uid)) { if (attrzp) - vrele(ZTOV(attrzp)); + vput(ZTOV(attrzp)); err = SET_ERROR(EDQUOT); goto out2; } @@ -3218,7 +3223,7 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, i if (new_gid != zp->z_gid && zfs_fuid_overquota(zfsvfs, B_TRUE, new_gid)) { if (attrzp) - vrele(ZTOV(attrzp)); + vput(ZTOV(attrzp)); err = SET_ERROR(EDQUOT); goto out2; } @@ -3449,7 +3454,7 @@ out: } if (attrzp) - vrele(ZTOV(attrzp)); + vput(ZTOV(attrzp)); if (aclp) zfs_acl_free(aclp);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609240813.u8O8DF1k075054>