Fix inode block accounting and free space accounting.
SCCS-vsn: sys/ufs/lfs/lfs_inode.c 7.78
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)lfs_inode.c 7.77 (Berkeley) %G%
+ * @(#)lfs_inode.c 7.78 (Berkeley) %G%
*/
#include <sys/param.h>
*/
#include <sys/param.h>
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (0);
ip = VTOI(vp);
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (0);
ip = VTOI(vp);
- if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0)
+ if ((ip->i_flag & (IUPD | IACC | ICHG | IMOD)) == 0)
ip->i_atime.ts_sec = ap->a_ta->tv_sec;
ip->i_atime.ts_sec = ap->a_ta->tv_sec;
+ if (ip->i_flag & IUPD) {
ip->i_mtime.ts_sec = ap->a_tm->tv_sec;
(ip)->i_modrev++;
}
ip->i_mtime.ts_sec = ap->a_tm->tv_sec;
(ip)->i_modrev++;
}
ip->i_ctime.ts_sec = time.tv_sec;
ip->i_ctime.ts_sec = time.tv_sec;
- ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD);
+ ip->i_flag &= ~(IUPD|IACC|ICHG);
- /* Push back the vnode and any dirty blocks it may have. */
+ if (!(ip->i_flag & IMOD))
+ ++(VFSTOUFS(vp->v_mount)->um_lfs->lfs_uinodes);
+ ip->i_flag |= IMOD;
+
+ /* If sync, push back the vnode and any dirty blocks it may have. */
return (ap->a_waitfor & LFS_SYNC ? lfs_vflush(vp) : 0);
}
return (ap->a_waitfor & LFS_SYNC ? lfs_vflush(vp) : 0);
}
panic("lfs_truncate: negative bytes in segment %d\n", \
lastseg); \
sup->su_nbytes -= num << fs->lfs_bshift; \
panic("lfs_truncate: negative bytes in segment %d\n", \
lastseg); \
sup->su_nbytes -= num << fs->lfs_bshift; \
+ e1 = VOP_BWRITE(sup_bp); \
blocksreleased += num; \
}
blocksreleased += num; \
}
(void)vnode_pager_uncache(vp);
bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));
allocbuf(bp, size);
(void)vnode_pager_uncache(vp);
bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));
allocbuf(bp, size);
+ if (e1 = VOP_BWRITE(bp))
+ return (e1);
}
/*
* Modify sup->su_nbyte counters for each deleted block; keep track
}
/*
* Modify sup->su_nbyte counters for each deleted block; keep track
bzero(bp->b_un.b_daddr + inp->in_off,
fs->lfs_bsize -
inp->in_off * sizeof(daddr_t));
bzero(bp->b_un.b_daddr + inp->in_off,
fs->lfs_bsize -
inp->in_off * sizeof(daddr_t));
+ if (e1 = VOP_BWRITE(bp))
+ return (e1);
}
}
if (depth == 0 && a[1].in_off == 0) {
}
}
if (depth == 0 && a[1].in_off == 0) {
if (length == 0) {
LFS_IENTRY(ifp, fs, ip->i_number, bp);
++ifp->if_version;
if (length == 0) {
LFS_IENTRY(ifp, fs, ip->i_number, bp);
++ifp->if_version;
- ip->i_blocks -= btodb(blocksreleased << fs->lfs_bshift);
- fs->lfs_bfree += btodb(blocksreleased << fs->lfs_bshift);
+ if (ip->i_blocks < fsbtodb(fs, blocksreleased))
panic("lfs_truncate: block count < 0");
#endif
panic("lfs_truncate: block count < 0");
#endif
+ ip->i_blocks -= fsbtodb(fs, blocksreleased);
+ fs->lfs_bfree += fsbtodb(fs, blocksreleased);
+ /*
+ * Traverse dirty block list counting number of dirty buffers
+ * that are being deleted out of the cache, so that the lfs_avail
+ * field can be updated.
+ */
+ for (bp = vp->v_dirtyblkhd; bp; bp = bp->b_blockf)
+ if (bp->b_flags & B_LOCKED)
+ fs->lfs_avail -= fsbtodb(fs, 1);
e1 = vinvalbuf(vp, length > 0, ap->a_cred, ap->a_p);
e2 = VOP_UPDATE(vp, &tv, &tv, 0);
return (e1 ? e1 : e2 ? e2 : 0);
e1 = vinvalbuf(vp, length > 0, ap->a_cred, ap->a_p);
e2 = VOP_UPDATE(vp, &tv, &tv, 0);
return (e1 ? e1 : e2 ? e2 : 0);