summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs/ffs_snapshot.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ufs/ffs/ffs_snapshot.c')
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c66
1 files changed, 49 insertions, 17 deletions
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index b36cb58..11362cf 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -142,7 +142,7 @@ MTX_SYSINIT(ffs_snapfree, &snapfree_lock, "snapdata free list", MTX_DEF);
static int cgaccount(int, struct vnode *, struct buf *, int);
static int expunge_ufs1(struct vnode *, struct inode *, struct fs *,
int (*)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *, struct fs *,
- ufs_lbn_t, int), int);
+ ufs_lbn_t, int), int, int);
static int indiracct_ufs1(struct vnode *, struct vnode *, int,
ufs1_daddr_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, struct fs *,
int (*)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *, struct fs *,
@@ -155,7 +155,7 @@ static int mapacct_ufs1(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,
struct fs *, ufs_lbn_t, int);
static int expunge_ufs2(struct vnode *, struct inode *, struct fs *,
int (*)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *, struct fs *,
- ufs_lbn_t, int), int);
+ ufs_lbn_t, int), int, int);
static int indiracct_ufs2(struct vnode *, struct vnode *, int,
ufs2_daddr_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, struct fs *,
int (*)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *, struct fs *,
@@ -582,7 +582,8 @@ loop:
len = fragroundup(fs, blkoff(fs, xp->i_size));
if (len != 0 && len < fs->fs_bsize) {
ffs_blkfree(ump, copy_fs, vp,
- DIP(xp, i_db[loc]), len, xp->i_number);
+ DIP(xp, i_db[loc]), len, xp->i_number,
+ NULL);
blkno = DIP(xp, i_db[loc]);
DIP_SET(xp, i_db[loc], 0);
}
@@ -590,15 +591,15 @@ loop:
snaplistsize += 1;
if (xp->i_ump->um_fstype == UFS1)
error = expunge_ufs1(vp, xp, copy_fs, fullacct_ufs1,
- BLK_NOCOPY);
+ BLK_NOCOPY, 1);
else
error = expunge_ufs2(vp, xp, copy_fs, fullacct_ufs2,
- BLK_NOCOPY);
+ BLK_NOCOPY, 1);
if (blkno)
DIP_SET(xp, i_db[loc], blkno);
if (!error)
error = ffs_freefile(ump, copy_fs, vp, xp->i_number,
- xp->i_mode);
+ xp->i_mode, NULL);
VOP_UNLOCK(xvp, 0);
vdrop(xvp);
if (error) {
@@ -612,6 +613,26 @@ loop:
}
MNT_IUNLOCK(mp);
/*
+ * Erase the journal file from the snapshot.
+ */
+ if (fs->fs_flags & FS_SUJ) {
+ error = softdep_journal_lookup(mp, &xvp);
+ if (error) {
+ free(copy_fs->fs_csp, M_UFSMNT);
+ bawrite(sbp);
+ sbp = NULL;
+ goto out1;
+ }
+ xp = VTOI(xvp);
+ if (xp->i_ump->um_fstype == UFS1)
+ error = expunge_ufs1(vp, xp, copy_fs, fullacct_ufs1,
+ BLK_NOCOPY, 0);
+ else
+ error = expunge_ufs2(vp, xp, copy_fs, fullacct_ufs2,
+ BLK_NOCOPY, 0);
+ vput(xvp);
+ }
+ /*
* Acquire a lock on the snapdata structure, creating it if necessary.
*/
sn = ffs_snapdata_acquire(devvp);
@@ -691,16 +712,16 @@ out1:
break;
if (xp->i_ump->um_fstype == UFS1)
error = expunge_ufs1(vp, xp, fs, snapacct_ufs1,
- BLK_SNAP);
+ BLK_SNAP, 0);
else
error = expunge_ufs2(vp, xp, fs, snapacct_ufs2,
- BLK_SNAP);
+ BLK_SNAP, 0);
if (error == 0 && xp->i_effnlink == 0) {
error = ffs_freefile(ump,
copy_fs,
vp,
xp->i_number,
- xp->i_mode);
+ xp->i_mode, NULL);
}
if (error) {
fs->fs_snapinum[snaploc] = 0;
@@ -719,9 +740,11 @@ out1:
* the list of allocated blocks in i_snapblklist.
*/
if (ip->i_ump->um_fstype == UFS1)
- error = expunge_ufs1(vp, ip, copy_fs, mapacct_ufs1, BLK_SNAP);
+ error = expunge_ufs1(vp, ip, copy_fs, mapacct_ufs1,
+ BLK_SNAP, 0);
else
- error = expunge_ufs2(vp, ip, copy_fs, mapacct_ufs2, BLK_SNAP);
+ error = expunge_ufs2(vp, ip, copy_fs, mapacct_ufs2,
+ BLK_SNAP, 0);
if (error) {
fs->fs_snapinum[snaploc] = 0;
free(snapblklist, M_UFSMNT);
@@ -954,13 +977,14 @@ cgaccount(cg, vp, nbp, passno)
* is reproduced once each for UFS1 and UFS2.
*/
static int
-expunge_ufs1(snapvp, cancelip, fs, acctfunc, expungetype)
+expunge_ufs1(snapvp, cancelip, fs, acctfunc, expungetype, clearmode)
struct vnode *snapvp;
struct inode *cancelip;
struct fs *fs;
int (*acctfunc)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,
struct fs *, ufs_lbn_t, int);
int expungetype;
+ int clearmode;
{
int i, error, indiroff;
ufs_lbn_t lbn, rlbn;
@@ -1005,7 +1029,7 @@ expunge_ufs1(snapvp, cancelip, fs, acctfunc, expungetype)
*/
dip = (struct ufs1_dinode *)bp->b_data +
ino_to_fsbo(fs, cancelip->i_number);
- if (expungetype == BLK_NOCOPY || cancelip->i_effnlink == 0)
+ if (clearmode || cancelip->i_effnlink == 0)
dip->di_mode = 0;
dip->di_size = 0;
dip->di_blocks = 0;
@@ -1220,7 +1244,7 @@ mapacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
*ip->i_snapblklist++ = lblkno;
if (blkno == BLK_SNAP)
blkno = blkstofrags(fs, lblkno);
- ffs_blkfree(ip->i_ump, fs, vp, blkno, fs->fs_bsize, inum);
+ ffs_blkfree(ip->i_ump, fs, vp, blkno, fs->fs_bsize, inum, NULL);
}
return (0);
}
@@ -1234,13 +1258,14 @@ mapacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
* is reproduced once each for UFS1 and UFS2.
*/
static int
-expunge_ufs2(snapvp, cancelip, fs, acctfunc, expungetype)
+expunge_ufs2(snapvp, cancelip, fs, acctfunc, expungetype, clearmode)
struct vnode *snapvp;
struct inode *cancelip;
struct fs *fs;
int (*acctfunc)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
struct fs *, ufs_lbn_t, int);
int expungetype;
+ int clearmode;
{
int i, error, indiroff;
ufs_lbn_t lbn, rlbn;
@@ -1285,7 +1310,7 @@ expunge_ufs2(snapvp, cancelip, fs, acctfunc, expungetype)
*/
dip = (struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, cancelip->i_number);
- if (expungetype == BLK_NOCOPY)
+ if (clearmode || cancelip->i_effnlink == 0)
dip->di_mode = 0;
dip->di_size = 0;
dip->di_blocks = 0;
@@ -1500,7 +1525,7 @@ mapacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
*ip->i_snapblklist++ = lblkno;
if (blkno == BLK_SNAP)
blkno = blkstofrags(fs, lblkno);
- ffs_blkfree(ip->i_ump, fs, vp, blkno, fs->fs_bsize, inum);
+ ffs_blkfree(ip->i_ump, fs, vp, blkno, fs->fs_bsize, inum, NULL);
}
return (0);
}
@@ -1657,6 +1682,13 @@ ffs_snapremove(vp)
ip->i_flags &= ~SF_SNAPSHOT;
DIP_SET(ip, i_flags, ip->i_flags);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ /*
+ * The dirtied indirects must be written out before
+ * softdep_setup_freeblocks() is called. Otherwise indir_trunc()
+ * may find indirect pointers using the magic BLK_* values.
+ */
+ if (DOINGSOFTDEP(vp))
+ ffs_syncvnode(vp, MNT_WAIT);
#ifdef QUOTA
/*
* Reenable disk quotas for ex-snapshot file.
OpenPOWER on IntegriCloud