- Use an empty snap block list to set the initial file size. Snapshot is

now valid from the beginning.  No need to copy the last fs block two times.
- No need to allocate the cylinder group blocks twice.
- cgbuf -> sbbuf
This commit is contained in:
hannken 2005-05-25 11:07:13 +00:00
parent bf77c4e4b3
commit a69fbd6a18

View File

@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.15 2005/05/22 08:35:28 hannken Exp $");
__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.16 2005/05/25 11:07:13 hannken Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@ -150,7 +150,7 @@ ffs_snapshot(mp, vp, ctime)
long redo = 0;
int32_t *lp;
void *space;
caddr_t cgbuf;
caddr_t sbbuf = NULL;
struct ufsmount *ump = VFSTOUFS(mp);
struct fs *copy_fs = NULL, *fs = ump->um_fs;
struct proc *p = curproc;
@ -200,15 +200,14 @@ ffs_snapshot(mp, vp, ctime)
ip = VTOI(vp);
devvp = ip->i_devvp;
/*
* Allocate and copy the last block contents so as to be able
* to set size to that of the filesystem.
* Write an empty list of preallocated blocks to the end of
* the snapshot to set size to at least that of the filesystem.
*/
numblks = howmany(fs->fs_size, fs->fs_frag);
cgbuf = malloc(fs->fs_bsize, M_UFSMNT, M_WAITOK);
if ((error = readfsblk(vp, cgbuf, numblks - 1)) != 0)
goto out;
blkno = 1;
blkno = ufs_rw64(blkno, ns);
error = vn_rdwr(UIO_WRITE, vp,
cgbuf, fs->fs_bsize, lblktosize(fs, (off_t)(numblks - 1)),
(caddr_t)&blkno, sizeof(blkno), lblktosize(fs, (off_t)numblks),
UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, p->p_ucred, NULL, NULL);
if (error)
goto out;
@ -247,16 +246,6 @@ ffs_snapshot(mp, vp, ctime)
goto out;
bawrite(nbp);
}
/*
* Allocate all cylinder group blocks.
*/
for (cg = 0; cg < fs->fs_ncg; cg++) {
error = VOP_BALLOC(vp, lfragtosize(fs, cgtod(fs, cg)),
fs->fs_bsize, KERNCRED, 0, &nbp);
if (error)
goto out;
bawrite(nbp);
}
/*
* Copy all the cylinder group maps. Although the
* filesystem is still active, we hope that only a few
@ -301,13 +290,6 @@ ffs_snapshot(mp, vp, ctime)
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
microtime(&starttime);
/*
* The last block saved before may have changed so update it now.
*/
if ((error = readfsblk(vp, cgbuf, numblks - 1)) != 0)
goto out1;
if ((error = writevnblk(vp, cgbuf, numblks - 1)) != 0)
goto out1;
/*
* First, copy all the cylinder group maps that have changed.
*/
@ -327,14 +309,15 @@ ffs_snapshot(mp, vp, ctime)
* Grab a copy of the superblock and its summary information.
* We delay writing it until the suspension is released below.
*/
sbbuf = malloc(fs->fs_bsize, M_UFSMNT, M_WAITOK);
loc = blkoff(fs, fs->fs_sblockloc);
if (loc > 0)
bzero(&cgbuf[0], loc);
copy_fs = (struct fs *)(cgbuf + loc);
bzero(&sbbuf[0], loc);
copy_fs = (struct fs *)(sbbuf + loc);
bcopy(fs, copy_fs, fs->fs_sbsize);
size = fs->fs_bsize < SBLOCKSIZE ? fs->fs_bsize : SBLOCKSIZE;
if (fs->fs_sbsize < size)
bzero(&cgbuf[loc + fs->fs_sbsize], size - fs->fs_sbsize);
bzero(&sbbuf[loc + fs->fs_sbsize], size - fs->fs_sbsize);
size = blkroundup(fs, fs->fs_cssize);
if (fs->fs_contigsumsize > 0)
size += fs->fs_ncg * sizeof(int32_t);
@ -593,8 +576,8 @@ out1:
*/
for (i = 0; i < snaplistsize; i++)
snapblklist[i] = ufs_rw64(snapblklist[i], ns);
error = vn_rdwr(UIO_WRITE, vp,
(caddr_t)snapblklist, snaplistsize*sizeof(ufs2_daddr_t), ip->i_size,
error = vn_rdwr(UIO_WRITE, vp, (caddr_t)snapblklist,
snaplistsize*sizeof(ufs2_daddr_t), lblktosize(fs, (off_t)numblks),
UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, p->p_ucred, NULL, NULL);
for (i = 0; i < snaplistsize; i++)
snapblklist[i] = ufs_rw64(snapblklist[i], ns);
@ -648,7 +631,7 @@ done:
brelse(nbp);
fs->fs_snapinum[snaploc] = 0;
}
bcopy(cgbuf, nbp->b_data, fs->fs_bsize);
bcopy(sbbuf, nbp->b_data, fs->fs_bsize);
bawrite(nbp);
}
out:
@ -687,8 +670,8 @@ out:
simple_unlock(&global_v_numoutput_slock);
splx(s);
}
if (cgbuf)
free(cgbuf, M_UFSMNT);
if (sbbuf)
free(sbbuf, M_UFSMNT);
if (fs->fs_active != 0) {
FREE(fs->fs_active, M_DEVBUF);
fs->fs_active = 0;