From owner-svn-src-all@FreeBSD.ORG Thu Sep 24 15:56:26 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id BCF67106566B; Thu, 24 Sep 2009 15:56:26 +0000 (UTC) (envelope-from pjd@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id A1D258FC1C; Thu, 24 Sep 2009 15:56:26 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n8OFuQa8001089; Thu, 24 Sep 2009 15:56:26 GMT (envelope-from pjd@svn.freebsd.org) Received: (from pjd@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n8OFuQjD001086; Thu, 24 Sep 2009 15:56:26 GMT (envelope-from pjd@svn.freebsd.org) Message-Id: <200909241556.n8OFuQjD001086@svn.freebsd.org> From: Pawel Jakub Dawidek Date: Thu, 24 Sep 2009 15:56:26 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r197459 - in head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs: . sys X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 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: Thu, 24 Sep 2009 15:56:26 -0000 Author: pjd Date: Thu Sep 24 15:56:26 2009 New Revision: 197459 URL: http://svn.freebsd.org/changeset/base/197459 Log: Before calling vflush(FORCECLOSE) mark file system as unmounted so the following vnops will fail. This is very important, because without this change vnode could be reclaimed at any point, even if we increased usecount. The only way to ensure that vnode won't be reclaimed was to lock it, which would be very hard to do in ZFS without changing a lot of code. With this change simply increasing usecount is enough to be sure vnode won't be reclaimed from under us. To be precise it can still be reclaimed but we won't be able to see it, because every try to enter ZFS through VFS will result in EIO. The only function that cannot return EIO, because it is needed for vflush() is zfs_root(). Introduce ZFS_ENTER_NOERROR() macro that only locks z_teardown_lock and never returns EIO. MFC after: 3 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 Thu Sep 24 15:49:15 2009 (r197458) +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h Thu Sep 24 15:56:26 2009 (r197459) @@ -255,6 +255,7 @@ VTOZ(vnode_t *vp) /* * ZFS_ENTER() is called on entry to each ZFS vnode and vfs operation. + * ZFS_ENTER_NOERROR() is called when we can't return EIO. * ZFS_EXIT() must be called before exitting the vop. * ZFS_VERIFY_ZP() verifies the znode is valid. */ @@ -267,6 +268,9 @@ VTOZ(vnode_t *vp) } \ } +#define ZFS_ENTER_NOERROR(zfsvfs) \ + rrw_enter(&(zfsvfs)->z_teardown_lock, RW_READER, FTAG) + #define ZFS_EXIT(zfsvfs) rrw_exit(&(zfsvfs)->z_teardown_lock, FTAG) #define ZFS_VERIFY_ZP(zp) \ 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 Thu Sep 24 15:49:15 2009 (r197458) +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c Thu Sep 24 15:56:26 2009 (r197459) @@ -864,7 +864,7 @@ zfs_root(vfs_t *vfsp, int flags, vnode_t znode_t *rootzp; int error; - ZFS_ENTER(zfsvfs); + ZFS_ENTER_NOERROR(zfsvfs); error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp); if (error == 0) { @@ -1030,6 +1030,17 @@ zfs_umount(vfs_t *vfsp, int fflag) ASSERT(zfsvfs->z_ctldir == NULL); } + if (fflag & MS_FORCE) { + /* + * Mark file system as unmounted before calling + * vflush(FORCECLOSE). This way we ensure no future vnops + * will be called and risk operating on DOOMED vnodes. + */ + rrw_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG); + zfsvfs->z_unmounted = B_TRUE; + rrw_exit(&zfsvfs->z_teardown_lock, FTAG); + } + /* * Flush all the files. */