From owner-svn-src-all@FreeBSD.ORG Wed Mar 28 21:21:20 2012 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 1FF5F106564A; Wed, 28 Mar 2012 21:21:20 +0000 (UTC) (envelope-from mckusick@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E5B398FC08; Wed, 28 Mar 2012 21:21:19 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q2SLLJhf054697; Wed, 28 Mar 2012 21:21:19 GMT (envelope-from mckusick@svn.freebsd.org) Received: (from mckusick@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q2SLLJIu054695; Wed, 28 Mar 2012 21:21:19 GMT (envelope-from mckusick@svn.freebsd.org) Message-Id: <201203282121.q2SLLJIu054695@svn.freebsd.org> From: Kirk McKusick Date: Wed, 28 Mar 2012 21:21:19 +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: r233629 - head/sys/ufs/ffs 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: Wed, 28 Mar 2012 21:21:20 -0000 Author: mckusick Date: Wed Mar 28 21:21:19 2012 New Revision: 233629 URL: http://svn.freebsd.org/changeset/base/233629 Log: A refinement of change 232351 to avoid a race with a forcible unmount. While we have a snapshot vnode unlocked to avoid a deadlock with another inode in the same inode block being updated, the filesystem containing it may be forcibly unmounted. When that happens the snapshot vnode is revoked. We need to check for that condition and fail appropriately. This change will be included along with 232351 when it is MFC'ed to 9. Spotted by: kib Reviewed by: kib Modified: head/sys/ufs/ffs/ffs_inode.c Modified: head/sys/ufs/ffs/ffs_inode.c ============================================================================== --- head/sys/ufs/ffs/ffs_inode.c Wed Mar 28 20:58:30 2012 (r233628) +++ head/sys/ufs/ffs/ffs_inode.c Wed Mar 28 21:21:19 2012 (r233629) @@ -106,6 +106,7 @@ ffs_update(vp, waitfor) flags = 0; if (IS_SNAPSHOT(ip)) flags = GB_LOCK_NOWAIT; +loop: error = breadn_flags(ip->i_devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), (int) fs->fs_bsize, 0, 0, 0, NOCRED, flags, &bp); @@ -115,13 +116,27 @@ ffs_update(vp, waitfor) return (error); } KASSERT((IS_SNAPSHOT(ip)), ("EBUSY from non-snapshot")); - vref(vp); /* Protect against ffs_snapgone() */ + /* + * Wait for our inode block to become available. + * + * Hold a reference to the vnode to protect against + * ffs_snapgone(). Since we hold a reference, it can only + * get reclaimed (VI_DOOMED flag) in a forcible downgrade + * or unmount. For an unmount, the entire filesystem will be + * gone, so we cannot attempt to touch anything associated + * with it while the vnode is unlocked; all we can do is + * pause briefly and try again. If when we relock the vnode + * we discover that it has been reclaimed, updating it is no + * longer necessary and we can just return an error. + */ + vref(vp); VOP_UNLOCK(vp, 0); - (void) bread(ip->i_devvp, - fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), - (int) fs->fs_bsize, NOCRED, &bp); + pause("ffsupd", 1); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); vrele(vp); + if ((vp->v_iflag & VI_DOOMED) != 0) + return (ENOENT); + goto loop; } if (DOINGSOFTDEP(vp)) softdep_update_inodeblock(ip, bp, waitfor);