From owner-svn-src-all@FreeBSD.ORG Tue May 5 11:01:07 2015 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 4B515EDB; Tue, 5 May 2015 11:01:07 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 3952B10EB; Tue, 5 May 2015 11:01:07 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t45B17mV012282; Tue, 5 May 2015 11:01:07 GMT (envelope-from avg@FreeBSD.org) Received: (from avg@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t45B16eD012277; Tue, 5 May 2015 11:01:06 GMT (envelope-from avg@FreeBSD.org) Message-Id: <201505051101.t45B16eD012277@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: avg set sender to avg@FreeBSD.org using -f From: Andriy Gapon Date: Tue, 5 May 2015 11:01:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r282475 - in head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs: . sys X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 05 May 2015 11:01:07 -0000 Author: avg Date: Tue May 5 11:01:06 2015 New Revision: 282475 URL: https://svnweb.freebsd.org/changeset/base/282475 Log: zfs: do not hold an extra reference on a root vnode while a filesystem is mounted At present zfs_domount() acquires a reference on the filesystem's root vnode and that reference is kept until zfs_umount. The latter calls vflush(rootrefs = 1) to dispose of the extra reference. There is no explanation of why that reference is kept - what problem it solves or what behavior it improves. Also, that logic is FreeBSD specific. There is one real problem with that reference, though. zfs recv -F may receive a full, non-incremental stream to a mounted filesystem. In that case the received root object is likely to have a different z_gen attribute value. Because of that, zfs_rezget will leave the previous root znode and vnode disassociated from the actual object (z_sa_hdl == NULL). Thus, future calls to VFS_ROOT() -> zfs_root() will produce a new vnode-znode pair, while the old one will be kept alive by the outstanding reference. So, the outstanding reference will not actually be for the new root vnode (or, more precisely, vnodes - because a root vnode may be recycled and a newer one can be created). As a result, when vflush(rootrefs = 1) s called there will be two problems: - a leaked reference on the old root vnode preventing a graceful unmount - insufficient references on the actual root vnode leading to a crash upon access to the vnode after it is destroyed by vgone() + vdrop() The second issue will actually override the first one. Differential Revision: https://reviews.freebsd.org/D2353 Reviewed by: delphij, kib, smh MFC after: 17 days Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h ============================================================================== --- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h Tue May 5 11:00:50 2015 (r282474) +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h Tue May 5 11:01:06 2015 (r282475) @@ -261,10 +261,6 @@ VTOZ(vnode_t *vp) } \ } -/* Called on entry to each ZFS vnode and vfs operation that can not return EIO */ -#define ZFS_ENTER_NOERROR(zfsvfs) \ - rrm_enter(&(zfsvfs)->z_teardown_lock, RW_READER, FTAG) - /* Must be called before exiting the vop */ #define ZFS_EXIT(zfsvfs) rrm_exit(&(zfsvfs)->z_teardown_lock, FTAG) 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 Tue May 5 11:00:50 2015 (r282474) +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c Tue May 5 11:01:06 2015 (r282475) @@ -1239,9 +1239,6 @@ zfs_domount(vfs_t *vfsp, char *osname) } vfs_mountedfrom(vfsp, osname); - /* Grab extra reference. */ - VERIFY(VFS_ROOT(vfsp, LK_EXCLUSIVE, &vp) == 0); - VOP_UNLOCK(vp, 0); if (!zfsvfs->z_issnap) zfsctl_create(zfsvfs); @@ -1819,7 +1816,7 @@ zfs_root(vfs_t *vfsp, int flags, vnode_t znode_t *rootzp; int error; - ZFS_ENTER_NOERROR(zfsvfs); + ZFS_ENTER(zfsvfs); error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp); if (error == 0) @@ -1994,7 +1991,7 @@ zfs_umount(vfs_t *vfsp, int fflag) /* * Flush all the files. */ - ret = vflush(vfsp, 1, (fflag & MS_FORCE) ? FORCECLOSE : 0, td); + ret = vflush(vfsp, 0, (fflag & MS_FORCE) ? FORCECLOSE : 0, td); if (ret != 0) { if (!zfsvfs->z_issnap) { zfsctl_create(zfsvfs);