From c9509f5865da39aadf70260aa8efca0da156b0c4 Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Thu, 26 Apr 2001 00:50:53 +0000 Subject: [PATCH] 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. --- sys/ufs/ffs/ffs_snapshot.c | 54 ++++++++++++++------------------------ 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index 0e1e68fc7de4..b92d179f708f 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 @@ 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.