Rather than copying all the indirect blocks of the snapshot,

simply mark them as BLK_NOCOPY. This trick cuts the initial
size of the snapshot in half and cuts the time to take a
snapshot by a third.
This commit is contained in:
Kirk McKusick 2001-04-26 00:50:53 +00:00
parent 71665b0add
commit c9509f5865
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=75993

View File

@ -83,7 +83,7 @@ ffs_snapshot(mp, snapfile)
char *snapfile;
{
ufs_daddr_t rlbn;
ufs_daddr_t lbn, blkno, copyblkno, inoblks[FSMAXSNAP];
ufs_daddr_t lbn, blkno, iblkno, inoblks[FSMAXSNAP];
int error, cg, snaploc, indiroff, numblks;
int i, size, base, len, loc, inoblkcnt;
int blksperindir, flag = mp->mnt_flag;
@ -180,21 +180,31 @@ ffs_snapshot(mp, snapfile)
* be filled in below once we are ready to go, but this upsets
* the soft update code, so we go ahead and write the new buffers.
*
* Allocate all indirect blocks. Also allocate shadow copies
* for each of the indirect blocks.
* Allocate all indirect blocks and mark all of them as not
* needing to be copied.
*/
for (blkno = NDADDR; blkno < numblks; blkno += NINDIR(fs)) {
error = VOP_BALLOC(vp, lblktosize(fs, (off_t)blkno),
fs->fs_bsize, p->p_ucred, B_METAONLY, &ibp);
if (error)
goto out;
copyblkno = fragstoblks(fs, dbtofsb(fs, ibp->b_blkno));
iblkno = fragstoblks(fs, dbtofsb(fs, ibp->b_blkno));
bdwrite(ibp);
error = VOP_BALLOC(vp, lblktosize(fs, (off_t)copyblkno),
fs->fs_bsize, p->p_ucred, 0, &nbp);
if (error)
goto out;
bawrite(nbp);
if (iblkno < NDADDR) {
if (ip->i_db[iblkno] != 0)
panic("ffs_snapshot: lost direct block");
ip->i_db[iblkno] = BLK_NOCOPY;
} else {
error = VOP_BALLOC(vp, lblktosize(fs, (off_t)iblkno),
fs->fs_bsize, KERNCRED, B_METAONLY, &ibp);
if (error)
goto out;
indiroff = (iblkno - NDADDR) % NINDIR(fs);
if (((ufs_daddr_t *)(ibp->b_data))[indiroff] != 0)
panic("ffs_snapshot: lost indirect block");
((ufs_daddr_t *)(ibp->b_data))[indiroff] = BLK_NOCOPY;
bdwrite(ibp);
}
}
/*
* Allocate shadow blocks to copy all of the other snapshot inodes
@ -429,32 +439,6 @@ ffs_snapshot(mp, snapfile)
nbp->b_flags |= B_VALIDSUSPWRT;
bdwrite(nbp);
}
/*
* Copy all indirect blocks to their shadows (allocated above)
* to avoid deadlock in ffs_copyonwrite.
*/
for (blkno = NDADDR; blkno < numblks; blkno += NINDIR(fs)) {
error = VOP_BALLOC(vp, lblktosize(fs, (off_t)blkno),
fs->fs_bsize, p->p_ucred, B_METAONLY, &ibp);
if (error)
goto out1;
copyblkno = fragstoblks(fs, dbtofsb(fs, ibp->b_blkno));
bqrelse(ibp);
error = VOP_BALLOC(vp, lblktosize(fs, (off_t)copyblkno),
fs->fs_bsize, p->p_ucred, 0, &nbp);
if (error)
goto out1;
error = VOP_BALLOC(vp, lblktosize(fs, (off_t)blkno),
fs->fs_bsize, p->p_ucred, B_METAONLY, &ibp);
if (error) {
brelse(nbp);
goto out1;
}
bcopy(ibp->b_data, nbp->b_data, fs->fs_bsize);
bqrelse(ibp);
nbp->b_flags |= B_VALIDSUSPWRT;
bawrite(nbp);
}
/*
* Record snapshot inode. Since this is the newest snapshot,
* it must be placed at the end of the list.