1 /* $NetBSD: ffs_inode.c,v 1.132 2026/07/22 14:44:49 hannken Exp $ */ 2 3 /*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1982, 1986, 1989, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)ffs_inode.c 8.13 (Berkeley) 4/21/95 61 */ 62 63 #include <sys/cdefs.h> 64 __KERNEL_RCSID(0, "$NetBSD: ffs_inode.c,v 1.132 2026/07/22 14:44:49 hannken Exp $"); 65 66 #if defined(_KERNEL_OPT) 67 #include "opt_ffs.h" 68 #include "opt_quota.h" 69 #endif 70 71 #include <sys/param.h> 72 #include <sys/systm.h> 73 #include <sys/buf.h> 74 #include <sys/file.h> 75 #include <sys/fstrans.h> 76 #include <sys/kauth.h> 77 #include <sys/kernel.h> 78 #include <sys/kmem.h> 79 #include <sys/mount.h> 80 #include <sys/proc.h> 81 #include <sys/resourcevar.h> 82 #include <sys/trace.h> 83 #include <sys/vnode.h> 84 #include <sys/wapbl.h> 85 86 #include <ufs/ufs/quota.h> 87 #include <ufs/ufs/inode.h> 88 #include <ufs/ufs/ufsmount.h> 89 #include <ufs/ufs/ufs_extern.h> 90 #include <ufs/ufs/ufs_bswap.h> 91 #include <ufs/ufs/ufs_wapbl.h> 92 93 #include <ufs/ffs/fs.h> 94 #include <ufs/ffs/ffs_extern.h> 95 96 static int ffs_indirtrunc(struct inode *, daddr_t, daddr_t, daddr_t, int, 97 int64_t *); 98 99 /* 100 * Update the access, modified, and inode change times as specified 101 * by the IN_ACCESS, IN_UPDATE, and IN_CHANGE flags respectively. 102 * The IN_MODIFIED flag is used to specify that the inode needs to be 103 * updated but that the times have already been set. The access 104 * and modified times are taken from the second and third parameters; 105 * the inode change time is always taken from the current time. If 106 * UPDATE_WAIT flag is set, or UPDATE_DIROP is set then wait for the 107 * disk write of the inode to complete. 108 */ 109 110 int 111 ffs_update(struct vnode *vp, const struct timespec *acc, 112 const struct timespec *mod, int updflags) 113 { 114 struct fs *fs; 115 struct buf *bp; 116 struct inode *ip; 117 int error; 118 void *cp; 119 int waitfor, flags; 120 121 if (vp->v_mount->mnt_flag & MNT_RDONLY) 122 return (0); 123 ip = VTOI(vp); 124 FFS_ITIMES(ip, acc, mod, NULL); 125 if (updflags & UPDATE_CLOSE) 126 flags = ip->i_flag & (IN_MODIFIED | IN_ACCESSED); 127 else 128 flags = ip->i_flag & IN_MODIFIED; 129 if (flags == 0) 130 return (0); 131 fs = ip->i_fs; 132 133 if ((flags & IN_MODIFIED) != 0 && 134 (vp->v_mount->mnt_flag & MNT_ASYNC) == 0) { 135 waitfor = updflags & UPDATE_WAIT; 136 if ((updflags & UPDATE_DIROP) != 0) 137 waitfor |= UPDATE_WAIT; 138 } else 139 waitfor = 0; 140 141 /* 142 * Ensure that uid and gid are correct. This is a temporary 143 * fix until fsck has been changed to do the update. 144 */ 145 if (fs->fs_magic == FS_UFS1_MAGIC && /* XXX */ 146 fs->fs_old_inodefmt < FS_44INODEFMT) { /* XXX */ 147 ip->i_ffs1_ouid = ip->i_uid; /* XXX */ 148 ip->i_ffs1_ogid = ip->i_gid; /* XXX */ 149 } /* XXX */ 150 error = bread(ip->i_devvp, 151 FFS_FSBTODB(fs, ino_to_fsba(fs, ip->i_number)), 152 (int)fs->fs_bsize, B_MODIFY, &bp); 153 if (error) { 154 return (error); 155 } 156 ip->i_flag &= ~(IN_MODIFIED | IN_ACCESSED); 157 /* Keep unlinked inode list up to date */ 158 KDASSERTMSG(DIP(ip, nlink) == ip->i_nlink, 159 "DIP(ip, nlink) [%d] == ip->i_nlink [%d]", 160 DIP(ip, nlink), ip->i_nlink); 161 if (ip->i_mode) { 162 if (ip->i_nlink > 0) { 163 UFS_WAPBL_UNREGISTER_INODE(ip->i_ump->um_mountp, 164 ip->i_number, ip->i_mode); 165 } else { 166 UFS_WAPBL_REGISTER_INODE(ip->i_ump->um_mountp, 167 ip->i_number, ip->i_mode); 168 } 169 } 170 if (fs->fs_magic == FS_UFS1_MAGIC) { 171 cp = (char *)bp->b_data + 172 (ino_to_fsbo(fs, ip->i_number) * DINODE1_SIZE); 173 #ifdef FFS_EI 174 if (UFS_FSNEEDSWAP(fs)) 175 ffs_dinode1_swap(ip->i_din.ffs1_din, 176 (struct ufs1_dinode *)cp); 177 else 178 #endif 179 memcpy(cp, ip->i_din.ffs1_din, DINODE1_SIZE); 180 } else { 181 cp = (char *)bp->b_data + 182 (ino_to_fsbo(fs, ip->i_number) * DINODE2_SIZE); 183 #ifdef FFS_EI 184 if (UFS_FSNEEDSWAP(fs)) 185 ffs_dinode2_swap(ip->i_din.ffs2_din, 186 (struct ufs2_dinode *)cp); 187 else 188 #endif 189 memcpy(cp, ip->i_din.ffs2_din, DINODE2_SIZE); 190 } 191 if (waitfor) { 192 return (bwrite(bp)); 193 } else { 194 bdwrite(bp); 195 return (0); 196 } 197 } 198 199 #define SINGLE 0 /* index of single indirect block */ 200 #define DOUBLE 1 /* index of double indirect block */ 201 #define TRIPLE 2 /* index of triple indirect block */ 202 /* 203 * Truncate the inode oip to at most length size, freeing the 204 * disk blocks. 205 */ 206 int 207 ffs_truncate(struct vnode *ovp, off_t length, int ioflag, kauth_cred_t cred) 208 { 209 daddr_t lastblock; 210 struct inode *oip = VTOI(ovp); 211 struct mount *omp = ovp->v_mount; 212 daddr_t bn, lastiblock[UFS_NIADDR], indir_lbn[UFS_NIADDR]; 213 daddr_t blks[UFS_NDADDR + UFS_NIADDR], oldblks[UFS_NDADDR + UFS_NIADDR]; 214 struct fs *fs; 215 int extblocks; 216 int offset, pgoffset, level; 217 int64_t blocksreleased = 0, datablocks; 218 int i, aflag, nblocks; 219 int error, allerror = 0; 220 off_t osize; 221 int sync; 222 struct ufsmount *ump = oip->i_ump; 223 void *dcookie; 224 long bsize; 225 bool wapbl = omp->mnt_wapbl != NULL; 226 227 UFS_WAPBL_JLOCK_ASSERT(ump->um_mountp); 228 229 if (ovp->v_type == VCHR || ovp->v_type == VBLK || 230 ovp->v_type == VFIFO || ovp->v_type == VSOCK) { 231 KASSERT(oip->i_size == 0); 232 return 0; 233 } 234 235 if (length < 0) 236 return (EINVAL); 237 238 /* 239 * Historically clients did not have to specify which data 240 * they were truncating. So, if not specified, we assume 241 * traditional behavior, e.g., just the normal data. 242 */ 243 if ((ioflag & (IO_EXT | IO_NORMAL)) == 0) 244 ioflag |= IO_NORMAL; 245 246 fs = oip->i_fs; 247 #define i_din2 i_din.ffs2_din 248 extblocks = 0; 249 datablocks = DIP(oip, blocks); 250 if (fs->fs_magic == FS_UFS2_MAGIC && oip->i_din2->di_extsize > 0) { 251 extblocks = btodb(ffs_fragroundup(fs, oip->i_din2->di_extsize)); 252 datablocks -= extblocks; 253 } 254 if ((ioflag & IO_EXT) && extblocks > 0) { 255 if (length != 0) 256 panic("ffs_truncate: partial trunc of extdata"); 257 { 258 #ifdef QUOTA 259 (void) chkdq(oip, -extblocks, NOCRED, FORCE); 260 #endif 261 osize = oip->i_din2->di_extsize; 262 oip->i_din2->di_blocks -= extblocks; 263 oip->i_din2->di_extsize = 0; 264 for (i = 0; i < UFS_NXADDR; i++) { 265 binvalbuf(ovp, -1 - i); 266 oldblks[i] = oip->i_din2->di_extb[i]; 267 oip->i_din2->di_extb[i] = 0; 268 } 269 oip->i_flag |= IN_CHANGE; 270 if ((error = ffs_update(ovp, NULL, NULL, 0))) 271 return (error); 272 for (i = 0; i < UFS_NXADDR; i++) { 273 if (oldblks[i] == 0) 274 continue; 275 bsize = ffs_sblksize(fs, osize, i); 276 if (wapbl) { 277 error = UFS_WAPBL_REGISTER_DEALLOCATION(omp, 278 FFS_FSBTODB(fs, oldblks[i]), bsize, NULL); 279 if (error) 280 return error; 281 } else 282 ffs_blkfree(fs, oip->i_devvp, oldblks[i], 283 bsize, oip->i_number); 284 } 285 extblocks = 0; 286 } 287 } 288 if ((ioflag & IO_NORMAL) == 0) 289 return (0); 290 if (ovp->v_type == VLNK && 291 (oip->i_size < ump->um_maxsymlinklen || 292 (ump->um_maxsymlinklen == 0 && datablocks == 0))) { 293 KDASSERT(length == 0); 294 memset(SHORTLINK(oip), 0, (size_t)oip->i_size); 295 oip->i_size = 0; 296 DIP_ASSIGN(oip, size, 0); 297 oip->i_flag |= IN_CHANGE | IN_UPDATE; 298 return (ffs_update(ovp, NULL, NULL, 0)); 299 } 300 if (oip->i_size == length) { 301 /* still do a uvm_vnp_setsize() as writesize may be larger */ 302 uvm_vnp_setsize(ovp, length); 303 oip->i_flag |= IN_CHANGE | IN_UPDATE; 304 return (ffs_update(ovp, NULL, NULL, 0)); 305 } 306 if (length > ump->um_maxfilesize) 307 return (EFBIG); 308 309 if ((oip->i_flags & SF_SNAPSHOT) != 0) 310 #ifndef FFS_NO_SNAPSHOT 311 ffs_snapremove(ovp); 312 #else 313 panic("%s: unexpected snapshot", __func__); 314 #endif 315 316 osize = oip->i_size; 317 aflag = ioflag & IO_SYNC ? B_SYNC : 0; 318 319 /* 320 * Lengthen the size of the file. We must ensure that the 321 * last byte of the file is allocated. Since the smallest 322 * value of osize is 0, length will be at least 1. 323 */ 324 325 if (osize < length) { 326 if (ffs_lblkno(fs, osize) < UFS_NDADDR && 327 ffs_lblkno(fs, osize) != ffs_lblkno(fs, length) && 328 ffs_blkroundup(fs, osize) != osize) { 329 off_t eob; 330 331 eob = ffs_blkroundup(fs, osize); 332 uvm_vnp_setwritesize(ovp, eob); 333 error = ufs_balloc_range(ovp, osize, eob - osize, 334 cred, aflag); 335 if (error) { 336 (void) ffs_truncate(ovp, osize, 337 ioflag & IO_SYNC, cred); 338 return error; 339 } 340 if (ioflag & IO_SYNC) { 341 rw_enter(ovp->v_uobj.vmobjlock, RW_WRITER); 342 VOP_PUTPAGES(ovp, 343 trunc_page(osize & fs->fs_bmask), 344 round_page(eob), PGO_CLEANIT | PGO_SYNCIO | 345 PGO_JOURNALLOCKED); 346 } 347 } 348 uvm_vnp_setwritesize(ovp, length); 349 error = ufs_balloc_range(ovp, length - 1, 1, cred, aflag); 350 if (error) { 351 (void) ffs_truncate(ovp, osize, ioflag & IO_SYNC, cred); 352 return (error); 353 } 354 uvm_vnp_setsize(ovp, length); 355 oip->i_flag |= IN_CHANGE | IN_UPDATE; 356 KASSERT(ovp->v_size == oip->i_size); 357 return (ffs_update(ovp, NULL, NULL, 0)); 358 } 359 360 /* 361 * When truncating a regular file down to a non-block-aligned size, 362 * we must zero the part of last block which is past the new EOF. 363 * We must synchronously flush the zeroed pages to disk 364 * since the new pages will be invalidated as soon as we 365 * inform the VM system of the new, smaller size. 366 * We must do this before acquiring the GLOCK, since fetching 367 * the pages will acquire the GLOCK internally. 368 * So there is a window where another thread could see a whole 369 * zeroed page past EOF, but that's life. 370 */ 371 372 offset = ffs_blkoff(fs, length); 373 pgoffset = length & PAGE_MASK; 374 if (ovp->v_type == VREG && (pgoffset != 0 || offset != 0) && 375 osize > length) { 376 daddr_t lbn; 377 voff_t eoz; 378 int size; 379 380 if (offset != 0) { 381 error = ufs_balloc_range(ovp, length - 1, 1, cred, 382 aflag); 383 if (error) 384 return error; 385 } 386 lbn = ffs_lblkno(fs, length); 387 size = ffs_blksize(fs, oip, lbn); 388 eoz = MIN(MAX(ffs_lblktosize(fs, lbn) + size, round_page(pgoffset)), 389 osize); 390 ubc_zerorange(&ovp->v_uobj, length, eoz - length, 391 UBC_VNODE_FLAGS(ovp)); 392 if (round_page(eoz) > round_page(length)) { 393 rw_enter(ovp->v_uobj.vmobjlock, RW_WRITER); 394 error = VOP_PUTPAGES(ovp, round_page(length), 395 round_page(eoz), 396 PGO_CLEANIT | PGO_DEACTIVATE | PGO_JOURNALLOCKED | 397 ((ioflag & IO_SYNC) ? PGO_SYNCIO : 0)); 398 if (error) 399 return error; 400 } 401 } 402 403 genfs_node_wrlock(ovp); 404 oip->i_size = length; 405 DIP_ASSIGN(oip, size, length); 406 uvm_vnp_setsize(ovp, length); 407 /* 408 * Calculate index into inode's block list of 409 * last direct and indirect blocks (if any) 410 * which we want to keep. Lastblock is -1 when 411 * the file is truncated to 0. 412 */ 413 lastblock = ffs_lblkno(fs, length + fs->fs_bsize - 1) - 1; 414 lastiblock[SINGLE] = lastblock - UFS_NDADDR; 415 lastiblock[DOUBLE] = lastiblock[SINGLE] - FFS_NINDIR(fs); 416 lastiblock[TRIPLE] = lastiblock[DOUBLE] - FFS_NINDIR(fs) * FFS_NINDIR(fs); 417 nblocks = btodb(fs->fs_bsize); 418 /* 419 * Update file and block pointers on disk before we start freeing 420 * blocks. If we crash before free'ing blocks below, the blocks 421 * will be returned to the free list. lastiblock values are also 422 * normalized to -1 for calls to ffs_indirtrunc below. 423 */ 424 sync = 0; 425 for (level = TRIPLE; level >= SINGLE; level--) { 426 blks[UFS_NDADDR + level] = DIP(oip, ib[level]); 427 if (lastiblock[level] < 0 && blks[UFS_NDADDR + level] != 0) { 428 sync = 1; 429 DIP_ASSIGN(oip, ib[level], 0); 430 lastiblock[level] = -1; 431 } 432 } 433 for (i = 0; i < UFS_NDADDR; i++) { 434 blks[i] = DIP(oip, db[i]); 435 if (i > lastblock && blks[i] != 0) { 436 sync = 1; 437 DIP_ASSIGN(oip, db[i], 0); 438 } 439 } 440 oip->i_flag |= IN_CHANGE | IN_UPDATE; 441 if (sync) { 442 error = ffs_update(ovp, NULL, NULL, UPDATE_WAIT); 443 if (error && !allerror) 444 allerror = error; 445 } 446 447 /* 448 * Having written the new inode to disk, save its new configuration 449 * and put back the old block pointers long enough to process them. 450 * Note that we save the new block configuration so we can check it 451 * when we are done. 452 */ 453 for (i = 0; i < UFS_NDADDR; i++) { 454 bn = DIP(oip, db[i]); 455 DIP_ASSIGN(oip, db[i], blks[i]); 456 blks[i] = bn; 457 } 458 for (i = 0; i < UFS_NIADDR; i++) { 459 bn = DIP(oip, ib[i]); 460 DIP_ASSIGN(oip, ib[i], blks[UFS_NDADDR + i]); 461 blks[UFS_NDADDR + i] = bn; 462 } 463 464 oip->i_size = osize; 465 DIP_ASSIGN(oip, size, osize); 466 error = vtruncbuf(ovp, lastblock + 1, 0, 0); 467 if (error && !allerror) 468 allerror = error; 469 470 /* 471 * Indirect blocks first. 472 */ 473 indir_lbn[SINGLE] = -UFS_NDADDR; 474 indir_lbn[DOUBLE] = indir_lbn[SINGLE] - FFS_NINDIR(fs) - 1; 475 indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - FFS_NINDIR(fs) * FFS_NINDIR(fs) - 1; 476 for (level = TRIPLE; level >= SINGLE; level--) { 477 bn = ffs_getib(fs, oip, level); 478 if (bn != 0) { 479 if (lastiblock[level] < 0 && 480 oip->i_ump->um_mountp->mnt_wapbl) { 481 error = UFS_WAPBL_REGISTER_DEALLOCATION( 482 oip->i_ump->um_mountp, 483 FFS_FSBTODB(fs, bn), fs->fs_bsize, 484 &dcookie); 485 if (error) 486 goto out; 487 } else { 488 dcookie = NULL; 489 } 490 491 error = ffs_indirtrunc(oip, indir_lbn[level], 492 FFS_FSBTODB(fs, bn), lastiblock[level], level, 493 &blocksreleased); 494 if (error) { 495 if (dcookie) { 496 UFS_WAPBL_UNREGISTER_DEALLOCATION( 497 oip->i_ump->um_mountp, dcookie); 498 } 499 goto out; 500 } 501 502 if (lastiblock[level] < 0) { 503 if (!dcookie) 504 ffs_blkfree(fs, oip->i_devvp, bn, 505 fs->fs_bsize, oip->i_number); 506 DIP_ASSIGN(oip, ib[level], 0); 507 blocksreleased += nblocks; 508 } 509 } 510 if (lastiblock[level] >= 0) 511 goto done; 512 } 513 514 /* 515 * All whole direct blocks or frags. 516 */ 517 for (i = UFS_NDADDR - 1; i > lastblock; i--) { 518 bn = ffs_getdb(fs, oip, i); 519 if (bn == 0) 520 continue; 521 522 bsize = ffs_blksize(fs, oip, i); 523 if ((oip->i_ump->um_mountp->mnt_wapbl) && 524 (ovp->v_type != VREG)) { 525 error = UFS_WAPBL_REGISTER_DEALLOCATION( 526 oip->i_ump->um_mountp, 527 FFS_FSBTODB(fs, bn), bsize, NULL); 528 if (error) 529 goto out; 530 } else 531 ffs_blkfree(fs, oip->i_devvp, bn, bsize, oip->i_number); 532 DIP_ASSIGN(oip, db[i], 0); 533 blocksreleased += btodb(bsize); 534 } 535 if (lastblock < 0) 536 goto done; 537 538 /* 539 * Finally, look for a change in size of the 540 * last direct block; release any frags. 541 */ 542 bn = ffs_getdb(fs, oip, lastblock); 543 if (bn != 0) { 544 long oldspace, newspace; 545 546 /* 547 * Calculate amount of space we're giving 548 * back as old block size minus new block size. 549 */ 550 oldspace = ffs_blksize(fs, oip, lastblock); 551 oip->i_size = length; 552 DIP_ASSIGN(oip, size, length); 553 newspace = ffs_blksize(fs, oip, lastblock); 554 if (newspace == 0) 555 panic("itrunc: newspace"); 556 if (oldspace - newspace > 0) { 557 /* 558 * Block number of space to be free'd is 559 * the old block # plus the number of frags 560 * required for the storage we're keeping. 561 */ 562 bn += ffs_numfrags(fs, newspace); 563 if ((oip->i_ump->um_mountp->mnt_wapbl) && 564 (ovp->v_type != VREG)) { 565 error = UFS_WAPBL_REGISTER_DEALLOCATION( 566 oip->i_ump->um_mountp, FFS_FSBTODB(fs, bn), 567 oldspace - newspace, NULL); 568 if (error) 569 goto out; 570 } else 571 ffs_blkfree(fs, oip->i_devvp, bn, 572 oldspace - newspace, oip->i_number); 573 blocksreleased += btodb(oldspace - newspace); 574 } 575 } 576 577 done: 578 for (level = SINGLE; level <= TRIPLE; level++) 579 KASSERTMSG((blks[UFS_NDADDR + level] == DIP(oip, ib[level])), 580 "itrunc1 blk mismatch: %jx != %jx", 581 (uintmax_t)blks[UFS_NDADDR + level], 582 (uintmax_t)DIP(oip, ib[level])); 583 for (i = 0; i < UFS_NDADDR; i++) 584 KASSERTMSG((blks[i] == DIP(oip, db[i])), 585 "itrunc2 blk mismatch: %jx != %jx", 586 (uintmax_t)blks[i], (uintmax_t)DIP(oip, db[i])); 587 KASSERTMSG((length != 0 || extblocks || LIST_EMPTY(&ovp->v_cleanblkhd)), 588 "itrunc3: zero length and nonempty cleanblkhd"); 589 KASSERTMSG((length != 0 || extblocks || LIST_EMPTY(&ovp->v_dirtyblkhd)), 590 "itrunc3: zero length and nonempty dirtyblkhd"); 591 592 out: 593 /* 594 * Set length back to old size if deallocation failed. Some indirect 595 * blocks were deallocated creating a hole, but that is okay. 596 */ 597 if (error == EAGAIN) { 598 if (!allerror) 599 allerror = error; 600 length = osize; 601 uvm_vnp_setsize(ovp, length); 602 } 603 604 /* 605 * Put back the real size. 606 */ 607 oip->i_size = length; 608 DIP_ASSIGN(oip, size, length); 609 DIP_ADD(oip, blocks, -blocksreleased); 610 genfs_node_unlock(ovp); 611 oip->i_flag |= IN_CHANGE; 612 UFS_WAPBL_UPDATE(ovp, NULL, NULL, 0); 613 #if defined(QUOTA) || defined(QUOTA2) 614 (void) chkdq(oip, -blocksreleased, NOCRED, 0); 615 #endif 616 KASSERT(ovp->v_type != VREG || ovp->v_size == oip->i_size); 617 return (allerror); 618 } 619 620 /* 621 * Release blocks associated with the inode ip and stored in the indirect 622 * block bn. Blocks are free'd in LIFO order up to (but not including) 623 * lastbn. If level is greater than SINGLE, the block is an indirect block 624 * and recursive calls to indirtrunc must be used to cleanse other indirect 625 * blocks. 626 * 627 * NB: triple indirect blocks are untested. 628 */ 629 static int 630 ffs_indirtrunc(struct inode *ip, daddr_t lbn, daddr_t dbn, daddr_t lastbn, 631 int level, int64_t *countp) 632 { 633 int i; 634 struct buf *bp; 635 struct fs *fs = ip->i_fs; 636 int32_t *bap1 = NULL; 637 int64_t *bap2 = NULL; 638 struct vnode *vp; 639 daddr_t nb, nlbn, last; 640 char *copy = NULL; 641 int64_t factor; 642 int64_t nblocks; 643 int error = 0, allerror = 0; 644 const int needswap = UFS_FSNEEDSWAP(fs); 645 const int wapbl = (ip->i_ump->um_mountp->mnt_wapbl != NULL); 646 void *dcookie; 647 648 #define RBAP(ip, i) (((ip)->i_ump->um_fstype == UFS1) ? \ 649 ufs_rw32(bap1[i], needswap) : ufs_rw64(bap2[i], needswap)) 650 #define BAP_ASSIGN(ip, i, value) \ 651 do { \ 652 if ((ip)->i_ump->um_fstype == UFS1) \ 653 bap1[i] = (value); \ 654 else \ 655 bap2[i] = (value); \ 656 } while(0) 657 658 /* 659 * Calculate index in current block of last 660 * block to be kept. -1 indicates the entire 661 * block so we need not calculate the index. 662 */ 663 factor = 1; 664 for (i = SINGLE; i < level; i++) 665 factor *= FFS_NINDIR(fs); 666 last = lastbn; 667 if (lastbn > 0) 668 last /= factor; 669 nblocks = btodb(fs->fs_bsize); 670 /* 671 * Get buffer of block pointers, zero those entries corresponding 672 * to blocks to be free'd, and update on disk copy first. Since 673 * double(triple) indirect before single(double) indirect, calls 674 * to bmap on these blocks will fail. However, we already have 675 * the on disk address, so we have to set the b_blkno field 676 * explicitly instead of letting bread do everything for us. 677 */ 678 vp = ITOV(ip); 679 error = ffs_getblk(vp, lbn, FFS_NOBLK, fs->fs_bsize, false, &bp); 680 if (error) 681 return error; 682 683 if (bp->b_oflags & (BO_DONE | BO_DELWRI)) { 684 /* Braces must be here in case trace evaluates to nothing. */ 685 trace(TR_BREADHIT, pack(vp, fs->fs_bsize), lbn); 686 } else { 687 trace(TR_BREADMISS, pack(vp, fs->fs_bsize), lbn); 688 curlwp->l_ru.ru_inblock++; /* pay for read */ 689 bp->b_flags |= B_READ; 690 bp->b_flags &= ~B_COWDONE; /* we change blkno below */ 691 if (bp->b_bcount > bp->b_bufsize) 692 panic("ffs_indirtrunc: bad buffer size"); 693 bp->b_blkno = dbn; 694 BIO_SETPRIO(bp, BPRIO_TIMECRITICAL); 695 VOP_STRATEGY(vp, bp); 696 error = biowait(bp); 697 if (error == 0) 698 error = fscow_run(bp, true); 699 } 700 if (error) { 701 brelse(bp, 0); 702 return error; 703 } 704 705 /* 706 * Clear reference to blocks to be removed on disk, before actually 707 * reclaiming them, so that fsck is more likely to be able to recover 708 * the filesystem if system goes down during the truncate process. 709 * This assumes the truncate process would not fail, contrary 710 * to the wapbl case. 711 */ 712 if (ip->i_ump->um_fstype == UFS1) 713 bap1 = (int32_t *)bp->b_data; 714 else 715 bap2 = (int64_t *)bp->b_data; 716 if (lastbn >= 0 && !wapbl) { 717 copy = kmem_alloc(fs->fs_bsize, KM_SLEEP); 718 memcpy((void *)copy, bp->b_data, (u_int)fs->fs_bsize); 719 for (i = last + 1; i < FFS_NINDIR(fs); i++) 720 BAP_ASSIGN(ip, i, 0); 721 error = bwrite(bp); 722 if (error) 723 allerror = error; 724 725 if (ip->i_ump->um_fstype == UFS1) 726 bap1 = (int32_t *)copy; 727 else 728 bap2 = (int64_t *)copy; 729 } 730 731 /* 732 * Recursively free totally unused blocks. 733 */ 734 for (i = FFS_NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last; 735 i--, nlbn += factor) { 736 nb = RBAP(ip, i); 737 if (nb == 0) 738 continue; 739 740 if ((ip->i_ump->um_mountp->mnt_wapbl) && 741 ((level > SINGLE) || (ITOV(ip)->v_type != VREG))) { 742 error = UFS_WAPBL_REGISTER_DEALLOCATION( 743 ip->i_ump->um_mountp, 744 FFS_FSBTODB(fs, nb), fs->fs_bsize, 745 &dcookie); 746 if (error) 747 goto out; 748 } else { 749 dcookie = NULL; 750 } 751 752 if (level > SINGLE) { 753 error = ffs_indirtrunc(ip, nlbn, FFS_FSBTODB(fs, nb), 754 (daddr_t)-1, level - 1, countp); 755 if (error) { 756 if (dcookie) { 757 UFS_WAPBL_UNREGISTER_DEALLOCATION( 758 ip->i_ump->um_mountp, dcookie); 759 } 760 761 goto out; 762 } 763 } 764 765 if (!dcookie) 766 ffs_blkfree(fs, ip->i_devvp, nb, fs->fs_bsize, 767 ip->i_number); 768 769 BAP_ASSIGN(ip, i, 0); 770 *countp += nblocks; 771 } 772 773 /* 774 * Recursively free blocks on the now last partial indirect block. 775 */ 776 if (level > SINGLE && lastbn >= 0) { 777 last = lastbn % factor; 778 nb = RBAP(ip, i); 779 if (nb != 0) { 780 error = ffs_indirtrunc(ip, nlbn, FFS_FSBTODB(fs, nb), 781 last, level - 1, countp); 782 if (error) 783 goto out; 784 } 785 } 786 787 out: 788 if (error && !allerror) 789 allerror = error; 790 791 if (copy != NULL) { 792 kmem_free(copy, fs->fs_bsize); 793 } else if (lastbn < 0 && error == 0) { 794 /* all freed, release without writing back */ 795 brelse(bp, BC_INVAL); 796 } else if (wapbl) { 797 /* only partially freed, write the updated block */ 798 error = bwrite(bp); 799 if (!allerror) 800 allerror = error; 801 } 802 803 return (allerror); 804 } 805 806 void 807 ffs_itimes(struct inode *ip, const struct timespec *acc, 808 const struct timespec *mod, const struct timespec *cre) 809 { 810 struct timespec now; 811 812 if (!(ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY))) { 813 return; 814 } 815 816 vfs_timestamp(&now); 817 if (ip->i_flag & IN_ACCESS) { 818 if (acc == NULL) 819 acc = &now; 820 DIP_ASSIGN(ip, atime, acc->tv_sec); 821 DIP_ASSIGN(ip, atimensec, acc->tv_nsec); 822 } 823 if (ip->i_flag & (IN_UPDATE | IN_MODIFY)) { 824 if ((ip->i_flags & SF_SNAPSHOT) == 0) { 825 if (mod == NULL) 826 mod = &now; 827 DIP_ASSIGN(ip, mtime, mod->tv_sec); 828 DIP_ASSIGN(ip, mtimensec, mod->tv_nsec); 829 } 830 ip->i_modrev++; 831 } 832 if (ip->i_flag & (IN_CHANGE | IN_MODIFY)) { 833 if (cre == NULL) 834 cre = &now; 835 DIP_ASSIGN(ip, ctime, cre->tv_sec); 836 DIP_ASSIGN(ip, ctimensec, cre->tv_nsec); 837 } 838 if (ip->i_flag & (IN_ACCESS | IN_MODIFY)) 839 ip->i_flag |= IN_ACCESSED; 840 if (ip->i_flag & (IN_UPDATE | IN_CHANGE)) 841 ip->i_flag |= IN_MODIFIED; 842 ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY); 843 } 844