diff options
author | mckusick <mckusick@FreeBSD.org> | 2001-05-08 07:29:03 +0000 |
---|---|---|
committer | mckusick <mckusick@FreeBSD.org> | 2001-05-08 07:29:03 +0000 |
commit | 1be6156a3d0e1361a8aded14931c71b619cd3968 (patch) | |
tree | ae4c1748f1e4f0e1072f970a9217717449282f92 /sys/ufs | |
parent | 9b0de0da1c26163969ed800f7c9cc2f47e11fd07 (diff) | |
download | FreeBSD-src-1be6156a3d0e1361a8aded14931c71b619cd3968.zip FreeBSD-src-1be6156a3d0e1361a8aded14931c71b619cd3968.tar.gz |
Several fixes for units errors:
1) Do not assume that the superblock will be of size fs->fs_bsize.
This fixes a panic when taking a snapshot on a filesystem with
a block size bigger than 8K.
2) Properly calculate the number of fragments that follow the
superblock summary information. This fixes a bug with inconsistent
snapshots.
3) When cleaning up a snapshot that is about to be removed, properly
calculate the number of blocks that need to be checked. This fixes
a bug that created partially allocated inodes.
4) When moving blocks from a snapshot that is about to be removed
to another snapshot, properly account for the reduced number of
blocks in the snapshot from which they are taken. This fixes a
bug in which the number of blocks released from a snapshot did not
match the number that it claimed to have.
Diffstat (limited to 'sys/ufs')
-rw-r--r-- | sys/ufs/ffs/ffs_snapshot.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index d377adc..ce6e904 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -229,7 +229,7 @@ restart: /* * Allocate copies for the superblock and its summary information. */ - error = UFS_BALLOC(vp, (off_t)(SBOFF), fs->fs_bsize, KERNCRED, 0, &nbp); + error = UFS_BALLOC(vp, (off_t)(SBOFF), SBSIZE, KERNCRED, 0, &nbp); if (error) goto out; bawrite(nbp); @@ -379,7 +379,9 @@ restart: bcopy(fs->fs_csp, copy_fs->fs_csp, fs->fs_cssize); (char *)space += fs->fs_cssize; loc = howmany(fs->fs_cssize, fs->fs_fsize); - if ((len = fragnum(fs, loc) * fs->fs_fsize) > 0) { + i = fs->fs_frag - loc % fs->fs_frag; + len = (i == fs->fs_frag) ? 0 : i * fs->fs_fsize; + if (len > 0) { if ((error = bread(ip->i_devvp, fsbtodb(fs, fs->fs_csaddr + loc), len, KERNCRED, &bp)) != 0) { @@ -741,7 +743,7 @@ ffs_snapremove(vp) struct buf *ibp; struct fs *fs; ufs_daddr_t blkno, dblk; - int error, loc, last; + int error, numblks, loc, last; ip = VTOI(vp); fs = ip->i_fs; @@ -767,12 +769,16 @@ ffs_snapremove(vp) */ for (blkno = 1; blkno < NDADDR; blkno++) { dblk = ip->i_db[blkno]; - if (dblk == BLK_NOCOPY || dblk == BLK_SNAP || - (dblk == blkstofrags(fs, blkno) && - ffs_snapblkfree(ip, dblk, fs->fs_bsize))) + if (dblk == BLK_NOCOPY || dblk == BLK_SNAP) ip->i_db[blkno] = 0; + else if ((dblk == blkstofrags(fs, blkno) && + ffs_snapblkfree(ip, dblk, fs->fs_bsize))) { + ip->i_blocks -= btodb(fs->fs_bsize); + ip->i_db[blkno] = 0; + } } - for (blkno = NDADDR; blkno < fs->fs_size; blkno += NINDIR(fs)) { + numblks = howmany(ip->i_size, fs->fs_bsize); + for (blkno = NDADDR; blkno < numblks; blkno += NINDIR(fs)) { error = UFS_BALLOC(vp, lblktosize(fs, (off_t)blkno), fs->fs_bsize, KERNCRED, B_METAONLY, &ibp); if (error) @@ -781,10 +787,13 @@ ffs_snapremove(vp) last = NINDIR(fs); for (loc = 0; loc < last; loc++) { dblk = ((ufs_daddr_t *)(ibp->b_data))[loc]; - if (dblk == BLK_NOCOPY || dblk == BLK_SNAP || - (dblk == blkstofrags(fs, blkno) && - ffs_snapblkfree(ip, dblk, fs->fs_bsize))) + if (dblk == BLK_NOCOPY || dblk == BLK_SNAP) ((ufs_daddr_t *)(ibp->b_data))[loc] = 0; + else if ((dblk == blkstofrags(fs, blkno) && + ffs_snapblkfree(ip, dblk, fs->fs_bsize))) { + ip->i_blocks -= btodb(fs->fs_bsize); + ((ufs_daddr_t *)(ibp->b_data))[loc] = 0; + } } bawrite(ibp); } |