+
+ /* If truncating the file to 0, update the version number. */
+ if (length == 0) {
+ LFS_IENTRY(ifp, fs, ip->i_number, bp);
+ ++ifp->if_version;
+ (void) VOP_BWRITE(bp);
+ }
+
+#ifdef DIAGNOSTIC
+ if (ip->i_blocks < fsbtodb(fs, blocksreleased)) {
+ printf("lfs_truncate: block count < 0\n");
+ blocksreleased = ip->i_blocks;
+ }
+#endif
+ ip->i_blocks -= fsbtodb(fs, blocksreleased);
+ fs->lfs_bfree += fsbtodb(fs, blocksreleased);
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ /*
+ * 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.
+ */
+ a_released = 0;
+ i_released = 0;
+ for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = bp->b_vnbufs.le_next)
+ if (bp->b_flags & B_LOCKED) {
+ ++a_released;
+ /*
+ * XXX
+ * When buffers are created in the cache, their block
+ * number is set equal to their logical block number.
+ * If that is still true, we are assuming that the
+ * blocks are new (not yet on disk) and weren't
+ * counted above. However, there is a slight chance
+ * that a block's disk address is equal to its logical
+ * block number in which case, we'll get an overcounting
+ * here.
+ */
+ if (bp->b_blkno == bp->b_lblkno)
+ ++i_released;
+ }
+ blocksreleased = fsbtodb(fs, i_released);
+#ifdef DIAGNOSTIC
+ if (blocksreleased > ip->i_blocks) {
+ printf("lfs_inode: Warning! %s\n",
+ "more blocks released from inode than are in inode");
+ blocksreleased = ip->i_blocks;
+ }
+#endif
+ fs->lfs_bfree += blocksreleased;
+ ip->i_blocks -= blocksreleased;