Module Name: src Committed By: hannken Date: Sun Dec 12 10:29:25 UTC 2010
Modified Files: src/sys/ufs/ffs: ffs_snapshot.c Log Message: Keep a reference to the snapshot vnode until it gets removed from the snapshot list. To generate a diff of this commit: cvs rdiff -u -r1.100 -r1.101 src/sys/ufs/ffs/ffs_snapshot.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/ufs/ffs/ffs_snapshot.c diff -u src/sys/ufs/ffs/ffs_snapshot.c:1.100 src/sys/ufs/ffs/ffs_snapshot.c:1.101 --- src/sys/ufs/ffs/ffs_snapshot.c:1.100 Sun Dec 12 10:28:22 2010 +++ src/sys/ufs/ffs/ffs_snapshot.c Sun Dec 12 10:29:25 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_snapshot.c,v 1.100 2010/12/12 10:28:22 hannken Exp $ */ +/* $NetBSD: ffs_snapshot.c,v 1.101 2010/12/12 10:29:25 hannken Exp $ */ /* * Copyright 2000 Marshall Kirk McKusick. All Rights Reserved. @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.100 2010/12/12 10:28:22 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.101 2010/12/12 10:29:25 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_ffs.h" @@ -278,6 +278,7 @@ fs->fs_snapinum[snaploc] = ip->i_number; mutex_enter(&si->si_lock); + vref(vp); if (is_active_snapshot(si, ip)) panic("ffs_snapshot: %"PRIu64" already on list", ip->i_number); TAILQ_INSERT_TAIL(&si->si_snapshots, ip, i_nextsnap); @@ -391,8 +392,7 @@ (void) ffs_truncate(vp, (off_t)0, 0, NOCRED); UFS_WAPBL_END(mp); } - } else - vref(vp); + } return (error); } @@ -1269,10 +1269,8 @@ if (xp == ip) break; mutex_exit(&si->si_lock); - if (xp != NULL) - vrele(ITOV(ip)); #ifdef DEBUG - else if (snapdebug) + if (snapdebug && xp == NULL) printf("ffs_snapgone: lost snapshot vnode %llu\n", (unsigned long long)ip->i_number); #endif @@ -1339,6 +1337,7 @@ free(ip->i_snapblklist, M_UFSMNT); ip->i_snapblklist = NULL; } + vrele(vp); } else mutex_exit(&si->si_lock); /* @@ -1713,28 +1712,25 @@ ffs_snapshot_unmount(struct mount *mp) { struct vnode *devvp = VFSTOUFS(mp)->um_devvp; - struct inode *xp; - struct vnode *vp = NULL; + struct inode *ip; struct snap_info *si; + bool list_empty = true; si = VFSTOUFS(mp)->um_snapinfo; mutex_enter(&si->si_lock); - while ((xp = TAILQ_FIRST(&si->si_snapshots)) != 0) { - vp = ITOV(xp); - TAILQ_REMOVE(&si->si_snapshots, xp, i_nextsnap); - if (xp->i_snapblklist == si->si_snapblklist) + while ((ip = TAILQ_FIRST(&si->si_snapshots)) != 0) { + list_empty = false; + TAILQ_REMOVE(&si->si_snapshots, ip, i_nextsnap); + if (ip->i_snapblklist == si->si_snapblklist) si->si_snapblklist = NULL; - free(xp->i_snapblklist, M_UFSMNT); - if (xp->i_nlink > 0) { - si->si_gen++; - mutex_exit(&si->si_lock); - vrele(vp); - mutex_enter(&si->si_lock); - } + free(ip->i_snapblklist, M_UFSMNT); + si->si_gen++; + mutex_exit(&si->si_lock); + vrele(ITOV(ip)); + mutex_enter(&si->si_lock); } - si->si_gen++; mutex_exit(&si->si_lock); - if (vp) + if (! list_empty) fscow_disestablish(mp, ffs_copyonwrite, devvp); }