1 /* $NetBSD: ffs_inode.c,v 1.99 2008/08/30 08:25:53 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.99 2008/08/30 08:25:53 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/malloc.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 and we are not doing 107 * softupdates, then wait for the 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) && !DOINGSOFTDEP(vp)) 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 fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), 152 (int)fs->fs_bsize, NOCRED, B_MODIFY, &bp); 153 if (error) { 154 brelse(bp, 0); 155 return (error); 156 } 157 ip->i_flag &= ~(IN_MODIFIED | IN_ACCESSED); 158 if (DOINGSOFTDEP(vp)) { 159 softdep_update_inodeblock(ip, bp, waitfor); 160 } else if (ip->i_ffs_effnlink != ip->i_nlink) 161 panic("ffs_update: bad link cnt"); 162 /* Keep unlinked inode list up to date */ 163 KDASSERT(DIP(ip, nlink) == ip->i_nlink); 164 if (ip->i_mode) { 165 if (ip->i_nlink > 0) { 166 UFS_WAPBL_UNREGISTER_INODE(ip->i_ump->um_mountp, 167 ip->i_number, ip->i_mode); 168 } else { 169 UFS_WAPBL_REGISTER_INODE(ip->i_ump->um_mountp, 170 ip->i_number, ip->i_mode); 171 } 172 } 173 if (fs->fs_magic == FS_UFS1_MAGIC) { 174 cp = (char *)bp->b_data + 175 (ino_to_fsbo(fs, ip->i_number) * DINODE1_SIZE); 176 #ifdef FFS_EI 177 if (UFS_FSNEEDSWAP(fs)) 178 ffs_dinode1_swap(ip->i_din.ffs1_din, 179 (struct ufs1_dinode *)cp); 180 else 181 #endif 182 memcpy(cp, ip->i_din.ffs1_din, DINODE1_SIZE); 183 } else { 184 cp = (char *)bp->b_data + 185 (ino_to_fsbo(fs, ip->i_number) * DINODE2_SIZE); 186 #ifdef FFS_EI 187 if (UFS_FSNEEDSWAP(fs)) 188 ffs_dinode2_swap(ip->i_din.ffs2_din, 189 (struct ufs2_dinode *)cp); 190 else 191 #endif 192 memcpy(cp, ip->i_din.ffs2_din, DINODE2_SIZE); 193 } 194 if (waitfor) { 195 return (bwrite(bp)); 196 } else { 197 bdwrite(bp); 198 return (0); 199 } 200 } 201 202 #define SINGLE 0 /* index of single indirect block */ 203 #define DOUBLE 1 /* index of double indirect block */ 204 #define TRIPLE 2 /* index of triple indirect block */ 205 /* 206 * Truncate the inode oip to at most length size, freeing the 207 * disk blocks. 208 */ 209 int 210 ffs_truncate(struct vnode *ovp, off_t length, int ioflag, kauth_cred_t cred) 211 { 212 daddr_t lastblock; 213 struct inode *oip = VTOI(ovp); 214 daddr_t bn, lastiblock[NIADDR], indir_lbn[NIADDR]; 215 daddr_t blks[NDADDR + NIADDR]; 216 struct fs *fs; 217 int offset, pgoffset, level; 218 int64_t count, blocksreleased = 0; 219 int i, aflag, nblocks; 220 int error, allerror = 0; 221 off_t osize; 222 int sync; 223 struct ufsmount *ump = oip->i_ump; 224 225 if (ovp->v_type == VCHR || ovp->v_type == VBLK || 226 ovp->v_type == VFIFO || ovp->v_type == VSOCK) { 227 KASSERT(oip->i_size == 0); 228 return 0; 229 } 230 231 if (length < 0) 232 return (EINVAL); 233 234 if (ovp->v_type == VLNK && 235 (oip->i_size < ump->um_maxsymlinklen || 236 (ump->um_maxsymlinklen == 0 && DIP(oip, blocks) == 0))) { 237 KDASSERT(length == 0); 238 memset(SHORTLINK(oip), 0, (size_t)oip->i_size); 239 oip->i_size = 0; 240 DIP_ASSIGN(oip, size, 0); 241 oip->i_flag |= IN_CHANGE | IN_UPDATE; 242 return (ffs_update(ovp, NULL, NULL, 0)); 243 } 244 if (oip->i_size == length) { 245 oip->i_flag |= IN_CHANGE | IN_UPDATE; 246 return (ffs_update(ovp, NULL, NULL, 0)); 247 } 248 fs = oip->i_fs; 249 if (length > ump->um_maxfilesize) 250 return (EFBIG); 251 252 if ((oip->i_flags & SF_SNAPSHOT) != 0) 253 ffs_snapremove(ovp); 254 255 osize = oip->i_size; 256 aflag = ioflag & IO_SYNC ? B_SYNC : 0; 257 258 /* 259 * Lengthen the size of the file. We must ensure that the 260 * last byte of the file is allocated. Since the smallest 261 * value of osize is 0, length will be at least 1. 262 */ 263 264 if (osize < length) { 265 if (lblkno(fs, osize) < NDADDR && 266 lblkno(fs, osize) != lblkno(fs, length) && 267 blkroundup(fs, osize) != osize) { 268 off_t eob; 269 270 eob = blkroundup(fs, osize); 271 uvm_vnp_setwritesize(ovp, eob); 272 error = ufs_balloc_range(ovp, osize, eob - osize, 273 cred, aflag); 274 if (error) 275 return error; 276 if (ioflag & IO_SYNC) { 277 mutex_enter(&ovp->v_interlock); 278 VOP_PUTPAGES(ovp, 279 trunc_page(osize & fs->fs_bmask), 280 round_page(eob), PGO_CLEANIT | PGO_SYNCIO | 281 PGO_JOURNALLOCKED); 282 } 283 } 284 uvm_vnp_setwritesize(ovp, length); 285 error = ufs_balloc_range(ovp, length - 1, 1, cred, aflag); 286 if (error) { 287 (void) ffs_truncate(ovp, osize, ioflag & IO_SYNC, cred); 288 return (error); 289 } 290 uvm_vnp_setsize(ovp, length); 291 oip->i_flag |= IN_CHANGE | IN_UPDATE; 292 KASSERT(ovp->v_size == oip->i_size); 293 return (ffs_update(ovp, NULL, NULL, 0)); 294 } 295 296 /* 297 * When truncating a regular file down to a non-block-aligned size, 298 * we must zero the part of last block which is past the new EOF. 299 * We must synchronously flush the zeroed pages to disk 300 * since the new pages will be invalidated as soon as we 301 * inform the VM system of the new, smaller size. 302 * We must do this before acquiring the GLOCK, since fetching 303 * the pages will acquire the GLOCK internally. 304 * So there is a window where another thread could see a whole 305 * zeroed page past EOF, but that's life. 306 */ 307 308 offset = blkoff(fs, length); 309 pgoffset = length & PAGE_MASK; 310 if (ovp->v_type == VREG && (pgoffset != 0 || offset != 0) && 311 osize > length) { 312 daddr_t lbn; 313 voff_t eoz; 314 int size; 315 316 if (offset != 0) { 317 error = ufs_balloc_range(ovp, length - 1, 1, cred, 318 aflag); 319 if (error) 320 return error; 321 } 322 lbn = lblkno(fs, length); 323 size = blksize(fs, oip, lbn); 324 eoz = MIN(MAX(lblktosize(fs, lbn) + size, round_page(pgoffset)), 325 osize); 326 uvm_vnp_zerorange(ovp, length, eoz - length); 327 if (round_page(eoz) > round_page(length)) { 328 mutex_enter(&ovp->v_interlock); 329 error = VOP_PUTPAGES(ovp, round_page(length), 330 round_page(eoz), 331 PGO_CLEANIT | PGO_DEACTIVATE | PGO_JOURNALLOCKED | 332 ((ioflag & IO_SYNC) ? PGO_SYNCIO : 0)); 333 if (error) 334 return error; 335 } 336 } 337 338 genfs_node_wrlock(ovp); 339 340 if (DOINGSOFTDEP(ovp)) { 341 if (length > 0) { 342 /* 343 * If a file is only partially truncated, then 344 * we have to clean up the data structures 345 * describing the allocation past the truncation 346 * point. Finding and deallocating those structures 347 * is a lot of work. Since partial truncation occurs 348 * rarely, we solve the problem by syncing the file 349 * so that it will have no data structures left. 350 */ 351 if ((error = VOP_FSYNC(ovp, cred, FSYNC_WAIT, 352 0, 0)) != 0) { 353 genfs_node_unlock(ovp); 354 return (error); 355 } 356 mutex_enter(&ump->um_lock); 357 if (oip->i_flag & IN_SPACECOUNTED) 358 fs->fs_pendingblocks -= DIP(oip, blocks); 359 mutex_exit(&ump->um_lock); 360 } else { 361 uvm_vnp_setsize(ovp, length); 362 #ifdef QUOTA 363 (void) chkdq(oip, -DIP(oip, blocks), NOCRED, 0); 364 #endif 365 softdep_setup_freeblocks(oip, length, 0); 366 (void) vinvalbuf(ovp, 0, cred, curlwp, 0, 0); 367 genfs_node_unlock(ovp); 368 oip->i_flag |= IN_CHANGE | IN_UPDATE; 369 return (ffs_update(ovp, NULL, NULL, 0)); 370 } 371 } 372 oip->i_size = length; 373 DIP_ASSIGN(oip, size, length); 374 uvm_vnp_setsize(ovp, length); 375 /* 376 * Calculate index into inode's block list of 377 * last direct and indirect blocks (if any) 378 * which we want to keep. Lastblock is -1 when 379 * the file is truncated to 0. 380 */ 381 lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1; 382 lastiblock[SINGLE] = lastblock - NDADDR; 383 lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs); 384 lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs); 385 nblocks = btodb(fs->fs_bsize); 386 /* 387 * Update file and block pointers on disk before we start freeing 388 * blocks. If we crash before free'ing blocks below, the blocks 389 * will be returned to the free list. lastiblock values are also 390 * normalized to -1 for calls to ffs_indirtrunc below. 391 */ 392 sync = 0; 393 for (level = TRIPLE; level >= SINGLE; level--) { 394 blks[NDADDR + level] = DIP(oip, ib[level]); 395 if (lastiblock[level] < 0 && blks[NDADDR + level] != 0) { 396 sync = 1; 397 DIP_ASSIGN(oip, ib[level], 0); 398 lastiblock[level] = -1; 399 } 400 } 401 for (i = 0; i < NDADDR; i++) { 402 blks[i] = DIP(oip, db[i]); 403 if (i > lastblock && blks[i] != 0) { 404 sync = 1; 405 DIP_ASSIGN(oip, db[i], 0); 406 } 407 } 408 oip->i_flag |= IN_CHANGE | IN_UPDATE; 409 if (sync) { 410 error = ffs_update(ovp, NULL, NULL, UPDATE_WAIT); 411 if (error && !allerror) 412 allerror = error; 413 } 414 415 /* 416 * Having written the new inode to disk, save its new configuration 417 * and put back the old block pointers long enough to process them. 418 * Note that we save the new block configuration so we can check it 419 * when we are done. 420 */ 421 for (i = 0; i < NDADDR; i++) { 422 bn = DIP(oip, db[i]); 423 DIP_ASSIGN(oip, db[i], blks[i]); 424 blks[i] = bn; 425 } 426 for (i = 0; i < NIADDR; i++) { 427 bn = DIP(oip, ib[i]); 428 DIP_ASSIGN(oip, ib[i], blks[NDADDR + i]); 429 blks[NDADDR + i] = bn; 430 } 431 432 oip->i_size = osize; 433 DIP_ASSIGN(oip, size, osize); 434 error = vtruncbuf(ovp, lastblock + 1, 0, 0); 435 if (error && !allerror) 436 allerror = error; 437 438 /* 439 * Indirect blocks first. 440 */ 441 indir_lbn[SINGLE] = -NDADDR; 442 indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1; 443 indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1; 444 for (level = TRIPLE; level >= SINGLE; level--) { 445 if (oip->i_ump->um_fstype == UFS1) 446 bn = ufs_rw32(oip->i_ffs1_ib[level],UFS_FSNEEDSWAP(fs)); 447 else 448 bn = ufs_rw64(oip->i_ffs2_ib[level],UFS_FSNEEDSWAP(fs)); 449 if (bn != 0) { 450 error = ffs_indirtrunc(oip, indir_lbn[level], 451 fsbtodb(fs, bn), lastiblock[level], level, &count); 452 if (error) 453 allerror = error; 454 blocksreleased += count; 455 if (lastiblock[level] < 0) { 456 DIP_ASSIGN(oip, ib[level], 0); 457 if (oip->i_ump->um_mountp->mnt_wapbl) { 458 UFS_WAPBL_REGISTER_DEALLOCATION( 459 oip->i_ump->um_mountp, 460 fsbtodb(fs, bn), fs->fs_bsize); 461 } else 462 ffs_blkfree(fs, oip->i_devvp, bn, 463 fs->fs_bsize, oip->i_number); 464 blocksreleased += nblocks; 465 } 466 } 467 if (lastiblock[level] >= 0) 468 goto done; 469 } 470 471 /* 472 * All whole direct blocks or frags. 473 */ 474 for (i = NDADDR - 1; i > lastblock; i--) { 475 long bsize; 476 477 if (oip->i_ump->um_fstype == UFS1) 478 bn = ufs_rw32(oip->i_ffs1_db[i], UFS_FSNEEDSWAP(fs)); 479 else 480 bn = ufs_rw64(oip->i_ffs2_db[i], UFS_FSNEEDSWAP(fs)); 481 if (bn == 0) 482 continue; 483 DIP_ASSIGN(oip, db[i], 0); 484 bsize = blksize(fs, oip, i); 485 if ((oip->i_ump->um_mountp->mnt_wapbl) && 486 (ovp->v_type != VREG)) { 487 UFS_WAPBL_REGISTER_DEALLOCATION(oip->i_ump->um_mountp, 488 fsbtodb(fs, bn), bsize); 489 } else 490 ffs_blkfree(fs, oip->i_devvp, bn, bsize, oip->i_number); 491 blocksreleased += btodb(bsize); 492 } 493 if (lastblock < 0) 494 goto done; 495 496 /* 497 * Finally, look for a change in size of the 498 * last direct block; release any frags. 499 */ 500 if (oip->i_ump->um_fstype == UFS1) 501 bn = ufs_rw32(oip->i_ffs1_db[lastblock], UFS_FSNEEDSWAP(fs)); 502 else 503 bn = ufs_rw64(oip->i_ffs2_db[lastblock], UFS_FSNEEDSWAP(fs)); 504 if (bn != 0) { 505 long oldspace, newspace; 506 507 /* 508 * Calculate amount of space we're giving 509 * back as old block size minus new block size. 510 */ 511 oldspace = blksize(fs, oip, lastblock); 512 oip->i_size = length; 513 DIP_ASSIGN(oip, size, length); 514 newspace = blksize(fs, oip, lastblock); 515 if (newspace == 0) 516 panic("itrunc: newspace"); 517 if (oldspace - newspace > 0) { 518 /* 519 * Block number of space to be free'd is 520 * the old block # plus the number of frags 521 * required for the storage we're keeping. 522 */ 523 bn += numfrags(fs, newspace); 524 if ((oip->i_ump->um_mountp->mnt_wapbl) && 525 (ovp->v_type != VREG)) { 526 UFS_WAPBL_REGISTER_DEALLOCATION( 527 oip->i_ump->um_mountp, fsbtodb(fs, bn), 528 oldspace - newspace); 529 } else 530 ffs_blkfree(fs, oip->i_devvp, bn, 531 oldspace - newspace, oip->i_number); 532 blocksreleased += btodb(oldspace - newspace); 533 } 534 } 535 536 done: 537 #ifdef DIAGNOSTIC 538 for (level = SINGLE; level <= TRIPLE; level++) 539 if (blks[NDADDR + level] != DIP(oip, ib[level])) 540 panic("itrunc1"); 541 for (i = 0; i < NDADDR; i++) 542 if (blks[i] != DIP(oip, db[i])) 543 panic("itrunc2"); 544 if (length == 0 && 545 (!LIST_EMPTY(&ovp->v_cleanblkhd) || !LIST_EMPTY(&ovp->v_dirtyblkhd))) 546 panic("itrunc3"); 547 #endif /* DIAGNOSTIC */ 548 /* 549 * Put back the real size. 550 */ 551 oip->i_size = length; 552 DIP_ASSIGN(oip, size, length); 553 DIP_ADD(oip, blocks, -blocksreleased); 554 genfs_node_unlock(ovp); 555 oip->i_flag |= IN_CHANGE; 556 UFS_WAPBL_UPDATE(ovp, NULL, NULL, 0); 557 #ifdef QUOTA 558 (void) chkdq(oip, -blocksreleased, NOCRED, 0); 559 #endif 560 KASSERT(ovp->v_type != VREG || ovp->v_size == oip->i_size); 561 return (allerror); 562 } 563 564 /* 565 * Release blocks associated with the inode ip and stored in the indirect 566 * block bn. Blocks are free'd in LIFO order up to (but not including) 567 * lastbn. If level is greater than SINGLE, the block is an indirect block 568 * and recursive calls to indirtrunc must be used to cleanse other indirect 569 * blocks. 570 * 571 * NB: triple indirect blocks are untested. 572 */ 573 static int 574 ffs_indirtrunc(struct inode *ip, daddr_t lbn, daddr_t dbn, daddr_t lastbn, 575 int level, int64_t *countp) 576 { 577 int i; 578 struct buf *bp; 579 struct fs *fs = ip->i_fs; 580 int32_t *bap1 = NULL; 581 int64_t *bap2 = NULL; 582 struct vnode *vp; 583 daddr_t nb, nlbn, last; 584 char *copy = NULL; 585 int64_t blkcount, factor, blocksreleased = 0; 586 int nblocks; 587 int error = 0, allerror = 0; 588 #ifdef FFS_EI 589 const int needswap = UFS_FSNEEDSWAP(fs); 590 #endif 591 #define RBAP(ip, i) (((ip)->i_ump->um_fstype == UFS1) ? \ 592 ufs_rw32(bap1[i], needswap) : ufs_rw64(bap2[i], needswap)) 593 #define BAP_ASSIGN(ip, i, value) \ 594 do { \ 595 if ((ip)->i_ump->um_fstype == UFS1) \ 596 bap1[i] = (value); \ 597 else \ 598 bap2[i] = (value); \ 599 } while(0) 600 601 /* 602 * Calculate index in current block of last 603 * block to be kept. -1 indicates the entire 604 * block so we need not calculate the index. 605 */ 606 factor = 1; 607 for (i = SINGLE; i < level; i++) 608 factor *= NINDIR(fs); 609 last = lastbn; 610 if (lastbn > 0) 611 last /= factor; 612 nblocks = btodb(fs->fs_bsize); 613 /* 614 * Get buffer of block pointers, zero those entries corresponding 615 * to blocks to be free'd, and update on disk copy first. Since 616 * double(triple) indirect before single(double) indirect, calls 617 * to bmap on these blocks will fail. However, we already have 618 * the on disk address, so we have to set the b_blkno field 619 * explicitly instead of letting bread do everything for us. 620 */ 621 vp = ITOV(ip); 622 error = ffs_getblk(vp, lbn, FFS_NOBLK, fs->fs_bsize, false, &bp); 623 if (error) { 624 *countp = 0; 625 return error; 626 } 627 if (bp->b_oflags & (BO_DONE | BO_DELWRI)) { 628 /* Braces must be here in case trace evaluates to nothing. */ 629 trace(TR_BREADHIT, pack(vp, fs->fs_bsize), lbn); 630 } else { 631 trace(TR_BREADMISS, pack(vp, fs->fs_bsize), lbn); 632 curlwp->l_ru.ru_inblock++; /* pay for read */ 633 bp->b_flags |= B_READ; 634 bp->b_flags &= ~B_COWDONE; /* we change blkno below */ 635 if (bp->b_bcount > bp->b_bufsize) 636 panic("ffs_indirtrunc: bad buffer size"); 637 bp->b_blkno = dbn; 638 BIO_SETPRIO(bp, BPRIO_TIMECRITICAL); 639 VOP_STRATEGY(vp, bp); 640 error = biowait(bp); 641 if (error == 0) 642 error = fscow_run(bp, true); 643 } 644 if (error) { 645 brelse(bp, 0); 646 *countp = 0; 647 return (error); 648 } 649 650 if (ip->i_ump->um_fstype == UFS1) 651 bap1 = (int32_t *)bp->b_data; 652 else 653 bap2 = (int64_t *)bp->b_data; 654 if (lastbn >= 0) { 655 copy = malloc(fs->fs_bsize, M_TEMP, M_WAITOK); 656 memcpy((void *)copy, bp->b_data, (u_int)fs->fs_bsize); 657 for (i = last + 1; i < NINDIR(fs); i++) 658 BAP_ASSIGN(ip, i, 0); 659 error = bwrite(bp); 660 if (error) 661 allerror = error; 662 if (ip->i_ump->um_fstype == UFS1) 663 bap1 = (int32_t *)copy; 664 else 665 bap2 = (int64_t *)copy; 666 } 667 668 /* 669 * Recursively free totally unused blocks. 670 */ 671 for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last; 672 i--, nlbn += factor) { 673 nb = RBAP(ip, i); 674 if (nb == 0) 675 continue; 676 if (level > SINGLE) { 677 error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb), 678 (daddr_t)-1, level - 1, 679 &blkcount); 680 if (error) 681 allerror = error; 682 blocksreleased += blkcount; 683 } 684 if ((ip->i_ump->um_mountp->mnt_wapbl) && 685 ((level > SINGLE) || (ITOV(ip)->v_type != VREG))) { 686 UFS_WAPBL_REGISTER_DEALLOCATION(ip->i_ump->um_mountp, 687 fsbtodb(fs, nb), fs->fs_bsize); 688 } else 689 ffs_blkfree(fs, ip->i_devvp, nb, fs->fs_bsize, 690 ip->i_number); 691 blocksreleased += nblocks; 692 } 693 694 /* 695 * Recursively free last partial block. 696 */ 697 if (level > SINGLE && lastbn >= 0) { 698 last = lastbn % factor; 699 nb = RBAP(ip, i); 700 if (nb != 0) { 701 error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb), 702 last, level - 1, &blkcount); 703 if (error) 704 allerror = error; 705 blocksreleased += blkcount; 706 } 707 } 708 709 if (copy != NULL) { 710 FREE(copy, M_TEMP); 711 } else { 712 brelse(bp, BC_INVAL); 713 } 714 715 *countp = blocksreleased; 716 return (allerror); 717 } 718 719 void 720 ffs_itimes(struct inode *ip, const struct timespec *acc, 721 const struct timespec *mod, const struct timespec *cre) 722 { 723 struct timespec now; 724 725 if (!(ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY))) { 726 return; 727 } 728 729 vfs_timestamp(&now); 730 if (ip->i_flag & IN_ACCESS) { 731 if (acc == NULL) 732 acc = &now; 733 DIP_ASSIGN(ip, atime, acc->tv_sec); 734 DIP_ASSIGN(ip, atimensec, acc->tv_nsec); 735 } 736 if (ip->i_flag & (IN_UPDATE | IN_MODIFY)) { 737 if ((ip->i_flags & SF_SNAPSHOT) == 0) { 738 if (mod == NULL) 739 mod = &now; 740 DIP_ASSIGN(ip, mtime, mod->tv_sec); 741 DIP_ASSIGN(ip, mtimensec, mod->tv_nsec); 742 } 743 ip->i_modrev++; 744 } 745 if (ip->i_flag & (IN_CHANGE | IN_MODIFY)) { 746 if (cre == NULL) 747 cre = &now; 748 DIP_ASSIGN(ip, ctime, cre->tv_sec); 749 DIP_ASSIGN(ip, ctimensec, cre->tv_nsec); 750 } 751 if (ip->i_flag & (IN_ACCESS | IN_MODIFY)) 752 ip->i_flag |= IN_ACCESSED; 753 if (ip->i_flag & (IN_UPDATE | IN_CHANGE)) 754 ip->i_flag |= IN_MODIFIED; 755 ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY); 756 } 757