Account for di_blocks allocations when IN_SPACECOUNTED is set in an
inode's i_flag. It's possible that after ufs_infactive() calls softdep_releasefile(), i_nlink stays >0 for a considerable amount of time (> 60 seconds here). During this period, any ffs allocation routines that alter di_blocks must also account for the blocks in the filesystem's fs_pendingblocks value. This change fixes an eventual df/du discrepency that will happen as the result of fs_pendingblocks being reduced to <0. The only manifestation of this that people may recognise is the following message on boot: /somefs: update error: blocks -N files M at which point the negative pending block count is adjusted to zero. Reviewed by: tegge MFC after: 3 weeks
This commit is contained in:
parent
baf2de77c9
commit
c3843b2cca
@ -143,6 +143,7 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp)
|
||||
int cg, reclaimed;
|
||||
static struct timeval lastfail;
|
||||
static int curfail;
|
||||
int64_t delta;
|
||||
#ifdef QUOTA
|
||||
int error;
|
||||
#endif
|
||||
@ -183,7 +184,13 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp)
|
||||
cg = dtog(fs, bpref);
|
||||
bno = ffs_hashalloc(ip, cg, bpref, size, ffs_alloccg);
|
||||
if (bno > 0) {
|
||||
DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + btodb(size));
|
||||
delta = btodb(size);
|
||||
if (ip->i_flag & IN_SPACECOUNTED) {
|
||||
UFS_LOCK(ump);
|
||||
fs->fs_pendingblocks += delta;
|
||||
UFS_UNLOCK(ump);
|
||||
}
|
||||
DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta);
|
||||
ip->i_flag |= IN_CHANGE | IN_UPDATE;
|
||||
*bnp = bno;
|
||||
return (0);
|
||||
@ -237,6 +244,7 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, cred, bpp)
|
||||
ufs2_daddr_t bno;
|
||||
static struct timeval lastfail;
|
||||
static int curfail;
|
||||
int64_t delta;
|
||||
|
||||
*bpp = 0;
|
||||
vp = ITOV(ip);
|
||||
@ -302,7 +310,13 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, cred, bpp)
|
||||
if (bno) {
|
||||
if (bp->b_blkno != fsbtodb(fs, bno))
|
||||
panic("ffs_realloccg: bad blockno");
|
||||
DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + btodb(nsize - osize));
|
||||
delta = btodb(nsize - osize);
|
||||
if (ip->i_flag & IN_SPACECOUNTED) {
|
||||
UFS_LOCK(ump);
|
||||
fs->fs_pendingblocks += delta;
|
||||
UFS_UNLOCK(ump);
|
||||
}
|
||||
DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta);
|
||||
ip->i_flag |= IN_CHANGE | IN_UPDATE;
|
||||
allocbuf(bp, nsize);
|
||||
bp->b_flags |= B_DONE;
|
||||
@ -371,7 +385,13 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, cred, bpp)
|
||||
ffs_blkfree(ump, fs, ip->i_devvp,
|
||||
bno + numfrags(fs, nsize),
|
||||
(long)(request - nsize), ip->i_number);
|
||||
DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + btodb(nsize - osize));
|
||||
delta = btodb(nsize - osize);
|
||||
if (ip->i_flag & IN_SPACECOUNTED) {
|
||||
UFS_LOCK(ump);
|
||||
fs->fs_pendingblocks += delta;
|
||||
UFS_UNLOCK(ump);
|
||||
}
|
||||
DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta);
|
||||
ip->i_flag |= IN_CHANGE | IN_UPDATE;
|
||||
allocbuf(bp, nsize);
|
||||
bp->b_flags |= B_DONE;
|
||||
@ -2431,6 +2451,11 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
|
||||
if ((error = ffs_vget(mp, (ino_t)cmd.value, LK_EXCLUSIVE, &vp)))
|
||||
break;
|
||||
ip = VTOI(vp);
|
||||
if (ip->i_flag & IN_SPACECOUNTED) {
|
||||
UFS_LOCK(ump);
|
||||
fs->fs_pendingblocks += cmd.size;
|
||||
UFS_UNLOCK(ump);
|
||||
}
|
||||
DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + cmd.size);
|
||||
ip->i_flag |= IN_CHANGE;
|
||||
vput(vp);
|
||||
|
@ -2229,7 +2229,7 @@ softdep_setup_freeblocks(ip, length, flags)
|
||||
}
|
||||
/*
|
||||
* If the file was removed, then the space being freed was
|
||||
* accounted for then (see softdep_filereleased()). If the
|
||||
* accounted for then (see softdep_releasefile()). If the
|
||||
* file is merely being truncated, then we account for it now.
|
||||
*/
|
||||
if ((ip->i_flag & IN_SPACECOUNTED) == 0) {
|
||||
@ -2747,7 +2747,7 @@ handle_workitem_freeblocks(freeblks, flags)
|
||||
if ((bn = freeblks->fb_iblks[level]) == 0)
|
||||
continue;
|
||||
if ((error = indir_trunc(freeblks, fsbtodb(fs, bn),
|
||||
level, baselbns[level], &blocksreleased)) == 0)
|
||||
level, baselbns[level], &blocksreleased)) != 0)
|
||||
allerror = error;
|
||||
ffs_blkfree(ump, fs, freeblks->fb_devvp, bn,
|
||||
fs->fs_bsize, freeblks->fb_previousinum);
|
||||
@ -3514,9 +3514,9 @@ softdep_releasefile(ip)
|
||||
int extblocks;
|
||||
|
||||
if (ip->i_effnlink > 0)
|
||||
panic("softdep_filerelease: file still referenced");
|
||||
panic("softdep_releasefile: file still referenced");
|
||||
/*
|
||||
* We may be called several times as the real reference count
|
||||
* We may be called several times as the on-disk link count
|
||||
* drops to zero. We only want to account for the space once.
|
||||
*/
|
||||
if (ip->i_flag & IN_SPACECOUNTED)
|
||||
|
Loading…
Reference in New Issue
Block a user