diff options
author | mckusick <mckusick@FreeBSD.org> | 2002-12-03 18:19:27 +0000 |
---|---|---|
committer | mckusick <mckusick@FreeBSD.org> | 2002-12-03 18:19:27 +0000 |
commit | 6822be5fe2bf90a5a45f1d01377d882248fde1f3 (patch) | |
tree | c989e179634dc249918209236b5aa2dfefeb4cc8 /sys | |
parent | c62f378dea65ed7eddda7cb57c4409372d695f01 (diff) | |
download | FreeBSD-src-6822be5fe2bf90a5a45f1d01377d882248fde1f3.zip FreeBSD-src-6822be5fe2bf90a5a45f1d01377d882248fde1f3.tar.gz |
Have to use bread() rather than UFS_BALLOC() when obtaining a
previously allocated block as the previous use of the block may
have fallen out of the cache. Failure to reread its contents cause
zeroed results to be written instead of the proper contents.
Conversely, when the block is going to be entirely filled in, it
is not necessary reread the old contents.
Sponsored by: DARPA & NAI Labs.
Approved by: re
Diffstat (limited to 'sys')
-rw-r--r-- | sys/ufs/ffs/ffs_snapshot.c | 54 |
1 files changed, 30 insertions, 24 deletions
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index 2eedf82..ff7947b 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -272,12 +272,10 @@ restart: MALLOC(fs->fs_active, int *, len, M_DEVBUF, M_WAITOK); bzero(fs->fs_active, len); for (cg = 0; cg < fs->fs_ncg; cg++) { - error = bread(vp, fragstoblks(fs, cgtod(fs, cg)), fs->fs_bsize, - KERNCRED, &nbp); - if (error) { - brelse(nbp); + error = UFS_BALLOC(vp, (off_t)(cgtod(fs, cg)) << fs->fs_fshift, + fs->fs_bsize, KERNCRED, 0, &nbp); + if (error) goto out; - } error = cgaccount(cg, vp, nbp, 1); bawrite(nbp); if (error) @@ -330,12 +328,10 @@ restart: if ((ACTIVECGNUM(fs, cg) & ACTIVECGOFF(cg)) != 0) continue; redo++; - error = bread(vp, fragstoblks(fs, cgtod(fs, cg)), fs->fs_bsize, - KERNCRED, &nbp); - if (error) { - brelse(nbp); + error = UFS_BALLOC(vp, (off_t)(cgtod(fs, cg)) << fs->fs_fshift, + fs->fs_bsize, KERNCRED, 0, &nbp); + if (error) goto out1; - } error = cgaccount(cg, vp, nbp, 2); bawrite(nbp); if (error) @@ -777,7 +773,7 @@ expunge_ufs1(snapvp, cancelip, fs, acctfunc, expungetype) lbn = fragstoblks(fs, ino_to_fsba(fs, cancelip->i_number)); blkno = 0; if (lbn < NDADDR) { - blkno = cancelip->i_din1->di_db[lbn]; + blkno = VTOI(snapvp)->i_din1->di_db[lbn]; } else { td->td_proc->p_flag |= P_COWINPROGRESS; error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn), @@ -789,12 +785,17 @@ expunge_ufs1(snapvp, cancelip, fs, acctfunc, expungetype) blkno = ((ufs1_daddr_t *)(bp->b_data))[indiroff]; bqrelse(bp); } - error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn), - fs->fs_bsize, KERNCRED, 0, &bp); - if (error) - return (error); - if (blkno == 0 && (error = readblock(bp, lbn))) - return (error); + if (blkno != 0) { + if ((error = bread(snapvp, lbn, fs->fs_bsize, KERNCRED, &bp))) + return (error); + } else { + error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn), + fs->fs_bsize, KERNCRED, 0, &bp); + if (error) + return (error); + if ((error = readblock(bp, lbn)) != 0) + return (error); + } /* * Set a snapshot inode to be a zero length file, regular files * to be completely unallocated. @@ -1034,7 +1035,7 @@ expunge_ufs2(snapvp, cancelip, fs, acctfunc, expungetype) lbn = fragstoblks(fs, ino_to_fsba(fs, cancelip->i_number)); blkno = 0; if (lbn < NDADDR) { - blkno = cancelip->i_din2->di_db[lbn]; + blkno = VTOI(snapvp)->i_din2->di_db[lbn]; } else { td->td_proc->p_flag |= P_COWINPROGRESS; error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn), @@ -1046,12 +1047,17 @@ expunge_ufs2(snapvp, cancelip, fs, acctfunc, expungetype) blkno = ((ufs2_daddr_t *)(bp->b_data))[indiroff]; bqrelse(bp); } - error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn), - fs->fs_bsize, KERNCRED, 0, &bp); - if (error) - return (error); - if (blkno == 0 && (error = readblock(bp, lbn))) - return (error); + if (blkno != 0) { + if ((error = bread(snapvp, lbn, fs->fs_bsize, KERNCRED, &bp))) + return (error); + } else { + error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn), + fs->fs_bsize, KERNCRED, 0, &bp); + if (error) + return (error); + if ((error = readblock(bp, lbn)) != 0) + return (error); + } /* * Set a snapshot inode to be a zero length file, regular files * to be completely unallocated. |