Index: src/sys/kern/vfs_bio.c =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/kern/vfs_bio.c,v retrieving revision 1.296 diff -u -p -r1.296 vfs_bio.c --- src/sys/kern/vfs_bio.c 11 Jun 2020 19:20:46 -0000 1.296 +++ src/sys/kern/vfs_bio.c 30 Jul 2020 17:34:08 -0000 @@ -1516,6 +1516,36 @@ getnewbuf(int slpflag, int slptimeo, int } /* + * Invalidate the specified buffer if it exists. + */ +void +binvalbuf(struct vnode *vp, daddr_t blkno) +{ + buf_t *bp; + int err; + + mutex_enter(&bufcache_lock); + + loop: + bp = incore(vp, blkno); + if (bp != NULL) { + err = bbusy(bp, 0, 0, NULL); + if (err == EPASSTHROUGH) + goto loop; + bremfree(bp); + if (ISSET(bp->b_oflags, BO_DELWRI)) { + SET(bp->b_cflags, BC_NOCACHE); + mutex_exit(&bufcache_lock); + bwrite(bp); + } else { + brelsel(bp, BC_INVAL); + mutex_exit(&bufcache_lock); + } + } else + mutex_exit(&bufcache_lock); +} + +/* * Attempt to free an aged buffer off the queues. * Called with queue lock held. * Returns the amount of buffer memory freed. Index: src/sys/sys/buf.h =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/sys/buf.h,v retrieving revision 1.133 diff -u -p -r1.133 buf.h --- src/sys/sys/buf.h 20 Apr 2020 21:39:05 -0000 1.133 +++ src/sys/sys/buf.h 30 Jul 2020 16:01:48 -0000 @@ -287,6 +287,7 @@ buf_t *incore(struct vnode *, daddr_t); int allocbuf(buf_t *, int, int); void brelsel(buf_t *, int); void brelse(buf_t *, int); +void binvalbuf(struct vnode *, daddr_t); /* * So-far indeterminate ops that might belong to either Index: src/sys/ufs/ffs/ffs_inode.c =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/ufs/ffs/ffs_inode.c,v retrieving revision 1.130 diff -u -p -r1.130 ffs_inode.c --- src/sys/ufs/ffs/ffs_inode.c 26 Jul 2020 00:21:24 -0000 1.130 +++ src/sys/ufs/ffs/ffs_inode.c 30 Jul 2020 17:33:26 -0000 @@ -208,6 +208,7 @@ ffs_truncate(struct vnode *ovp, off_t le { daddr_t lastblock; struct inode *oip = VTOI(ovp); + struct mount *omp = ovp->v_mount; daddr_t bn, lastiblock[UFS_NIADDR], indir_lbn[UFS_NIADDR]; daddr_t blks[UFS_NDADDR + UFS_NIADDR], oldblks[UFS_NDADDR + UFS_NIADDR]; struct fs *fs; @@ -220,6 +221,8 @@ ffs_truncate(struct vnode *ovp, off_t le int sync; struct ufsmount *ump = oip->i_ump; void *dcookie; + long bsize; + bool wapbl = omp->mnt_wapbl != NULL; UFS_WAPBL_JLOCK_ASSERT(ump->um_mountp); @@ -255,11 +258,11 @@ ffs_truncate(struct vnode *ovp, off_t le #ifdef QUOTA (void) chkdq(oip, -extblocks, NOCRED, FORCE); #endif - vinvalbuf(ovp, 0, cred, curlwp, 0, 0); osize = oip->i_din2->di_extsize; oip->i_din2->di_blocks -= extblocks; oip->i_din2->di_extsize = 0; for (i = 0; i < UFS_NXADDR; i++) { + binvalbuf(ovp, -1 - i); oldblks[i] = oip->i_din2->di_extb[i]; oip->i_din2->di_extb[i] = 0; } @@ -269,8 +272,15 @@ ffs_truncate(struct vnode *ovp, off_t le for (i = 0; i < UFS_NXADDR; i++) { if (oldblks[i] == 0) continue; - ffs_blkfree(fs, oip->i_devvp, oldblks[i], - ffs_sblksize(fs, osize, i), oip->i_number); + bsize = ffs_sblksize(fs, osize, i); + if (wapbl) { + error = UFS_WAPBL_REGISTER_DEALLOCATION(omp, + FFS_FSBTODB(fs, oldblks[i]), bsize, NULL); + if (error) + return error; + } else + ffs_blkfree(fs, oip->i_devvp, oldblks[i], + bsize, oip->i_number); } extblocks = 0; } @@ -501,8 +511,6 @@ ffs_truncate(struct vnode *ovp, off_t le * All whole direct blocks or frags. */ for (i = UFS_NDADDR - 1; i > lastblock; i--) { - long bsize; - bn = ffs_getdb(fs, oip, i); if (bn == 0) continue;