From 25f70ef12791187253fa6ece9dd9586b12d5a890 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 10 Apr 2014 15:04:37 +0000 Subject: [PATCH 06/14] Fix locking in ffs snapshot_expunge. --- sys/ufs/ffs/ffs_snapshot.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index 98b092c..cf0410d 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -626,16 +626,10 @@ snapshot_expunge(struct mount *mp, struct vnode *vp, struct fs *copy_fs, */ if ((fs->fs_flags & FS_DOWAPBL) && fs->fs_journal_location == UFS_WAPBL_JOURNALLOC_IN_FILESYSTEM) { - error = VFS_VGET(mp, - fs->fs_journallocs[UFS_WAPBL_INFS_INO], 0, &logvp); + error = VFS_VGET(mp, fs->fs_journallocs[UFS_WAPBL_INFS_INO], 0, + &logvp); if (error) goto out; - error = vn_lock(logvp, LK_EXCLUSIVE); - if (error) { - vrele(logvp); - logvp = NULL; - goto out; - } } /* * We also calculate the needed size for the snapshot list. @@ -654,14 +648,21 @@ snapshot_expunge(struct mount *mp, struct vnode *vp, struct fs *copy_fs, if (snapdebug) vprint("ffs_snapshot: busy vnode", xvp); #endif + error = vn_lock(xvp, LK_EXCLUSIVE); + if (error) { + vrele(xvp); + continue; + } xp = VTOI(xvp); if (xvp != logvp) { if (VOP_GETATTR(xvp, &vat, l->l_cred) == 0 && vat.va_nlink > 0) { + VOP_UNLOCK(xvp); vrele(xvp); continue; } if (ffs_checkfreefile(copy_fs, vp, xp->i_number)) { + VOP_UNLOCK(xvp); vrele(xvp); continue; } @@ -676,9 +677,9 @@ snapshot_expunge(struct mount *mp, struct vnode *vp, struct fs *copy_fs, if (len > 0 && len < fs->fs_bsize) { error = UFS_WAPBL_BEGIN(mp); if (error) { + VOP_UNLOCK(xvp); vrele(xvp); - vfs_vnode_iterator_destroy(marker); - goto out; + break; } ffs_blkfree_snap(copy_fs, vp, db_get(xp, loc), len, xp->i_number); @@ -699,13 +700,14 @@ snapshot_expunge(struct mount *mp, struct vnode *vp, struct fs *copy_fs, UFS_WAPBL_END(mp); } } + VOP_UNLOCK(xvp); vrele(xvp); - if (error) { - vfs_vnode_iterator_destroy(marker); - goto out; - } + if (error) + break; } vfs_vnode_iterator_destroy(marker); + if (error) + goto out; /* * Create a preliminary list of preallocated snapshot blocks. @@ -728,7 +730,7 @@ snapshot_expunge(struct mount *mp, struct vnode *vp, struct fs *copy_fs, out: if (logvp != NULL) - vput(logvp); + vrele(logvp); if (error && *snaplist != NULL) { free(*snaplist, M_UFSMNT); *snaplist = NULL; -- 1.8.3.1