diff options
author | mckusick <mckusick@FreeBSD.org> | 2001-04-26 00:50:53 +0000 |
---|---|---|
committer | mckusick <mckusick@FreeBSD.org> | 2001-04-26 00:50:53 +0000 |
commit | ed86738068071ce04462b238c4419c4dc1bd5e00 (patch) | |
tree | ccf86011d8a7762c9383eedb3dfc380791dbd863 /sys/ufs | |
parent | fff873d9fc1285bbd9c190558272aeece4196af9 (diff) | |
download | FreeBSD-src-ed86738068071ce04462b238c4419c4dc1bd5e00.zip FreeBSD-src-ed86738068071ce04462b238c4419c4dc1bd5e00.tar.gz |
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.
Diffstat (limited to 'sys/ufs')
-rw-r--r-- | sys/ufs/ffs/ffs_snapshot.c | 54 |
1 files changed, 19 insertions, 35 deletions
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index 0e1e68f..b92d179 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -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 @@ restart: * 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 @@ -430,32 +440,6 @@ restart: 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. */ |