1 /* $NetBSD: lfs_inode.c,v 1.51 2001/05/30 11:57:18 mrg Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Konrad E. Schroder <perseant@hhhh.org>. 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 /* 39 * Copyright (c) 1986, 1989, 1991, 1993 40 * The Regents of the University of California. All rights reserved. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. All advertising materials mentioning features or use of this software 51 * must display the following acknowledgement: 52 * This product includes software developed by the University of 53 * California, Berkeley and its contributors. 54 * 4. Neither the name of the University nor the names of its contributors 55 * may be used to endorse or promote products derived from this software 56 * without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * SUCH DAMAGE. 69 * 70 * @(#)lfs_inode.c 8.9 (Berkeley) 5/8/95 71 */ 72 73 #if defined(_KERNEL_OPT) 74 #include "opt_quota.h" 75 #endif 76 77 #include <sys/param.h> 78 #include <sys/systm.h> 79 #include <sys/mount.h> 80 #include <sys/proc.h> 81 #include <sys/file.h> 82 #include <sys/buf.h> 83 #include <sys/vnode.h> 84 #include <sys/kernel.h> 85 #include <sys/malloc.h> 86 #include <sys/trace.h> 87 #include <sys/resourcevar.h> 88 89 #include <ufs/ufs/quota.h> 90 #include <ufs/ufs/inode.h> 91 #include <ufs/ufs/ufsmount.h> 92 #include <ufs/ufs/ufs_extern.h> 93 94 #include <ufs/lfs/lfs.h> 95 #include <ufs/lfs/lfs_extern.h> 96 97 extern int locked_queue_count; 98 extern long locked_queue_bytes; 99 100 static int lfs_update_seguse(struct lfs *, long, size_t); 101 static int lfs_indirtrunc (struct inode *, ufs_daddr_t, ufs_daddr_t, 102 ufs_daddr_t, int, long *, long *, long *, size_t *, 103 struct proc *); 104 static int lfs_blkfree (struct lfs *, daddr_t, size_t, long *, size_t *); 105 static int lfs_vtruncbuf(struct vnode *, daddr_t, int, int); 106 107 /* Search a block for a specific dinode. */ 108 struct dinode * 109 lfs_ifind(fs, ino, bp) 110 struct lfs *fs; 111 ino_t ino; 112 struct buf *bp; 113 { 114 int cnt; 115 struct dinode *dip = (struct dinode *)bp->b_data; 116 struct dinode *ldip; 117 118 for (cnt = INOPB(fs), ldip = dip + (cnt - 1); cnt--; --ldip) 119 if (ldip->di_inumber == ino) 120 return (ldip); 121 122 printf("offset is 0x%x (seg %d)\n", fs->lfs_offset, 123 datosn(fs,fs->lfs_offset)); 124 printf("block is 0x%x (seg %d)\n", bp->b_blkno, 125 datosn(fs,bp->b_blkno)); 126 panic("lfs_ifind: dinode %u not found", ino); 127 /* NOTREACHED */ 128 } 129 130 int 131 lfs_update(v) 132 void *v; 133 { 134 struct vop_update_args /* { 135 struct vnode *a_vp; 136 struct timespec *a_access; 137 struct timespec *a_modify; 138 int a_flags; 139 } */ *ap = v; 140 struct inode *ip; 141 struct vnode *vp = ap->a_vp; 142 int oflag; 143 struct timespec ts; 144 struct lfs *fs = VFSTOUFS(vp->v_mount)->um_lfs; 145 146 if (vp->v_mount->mnt_flag & MNT_RDONLY) 147 return (0); 148 ip = VTOI(vp); 149 150 /* 151 * If we are called from vinvalbuf, and the file's blocks have 152 * already been scheduled for writing, but the writes have not 153 * yet completed, lfs_vflush will not be called, and vinvalbuf 154 * will cause a panic. So, we must wait until any pending write 155 * for our inode completes, if we are called with UPDATE_WAIT set. 156 */ 157 while((ap->a_flags & (UPDATE_WAIT|UPDATE_DIROP)) == UPDATE_WAIT && 158 WRITEINPROG(vp)) { 159 #ifdef DEBUG_LFS 160 printf("lfs_update: sleeping on inode %d (in-progress)\n", 161 ip->i_number); 162 #endif 163 tsleep(vp, (PRIBIO+1), "lfs_update", 0); 164 } 165 oflag = ip->i_flag; 166 TIMEVAL_TO_TIMESPEC(&time, &ts); 167 LFS_ITIMES(ip, 168 ap->a_access ? ap->a_access : &ts, 169 ap->a_modify ? ap->a_modify : &ts, &ts); 170 if ((ip->i_flag & (IN_MODIFIED | IN_ACCESSED | IN_CLEANING)) == 0) { 171 return (0); 172 } 173 174 /* If sync, push back the vnode and any dirty blocks it may have. */ 175 if((ap->a_flags & (UPDATE_WAIT|UPDATE_DIROP))==UPDATE_WAIT) { 176 /* Avoid flushing VDIROP. */ 177 ++fs->lfs_diropwait; 178 while(vp->v_flag & VDIROP) { 179 #ifdef DEBUG_LFS 180 printf("lfs_update: sleeping on inode %d (dirops)\n", 181 ip->i_number); 182 printf("lfs_update: vflags 0x%lx, iflags 0x%x\n", 183 vp->v_flag, ip->i_flag); 184 #endif 185 if(fs->lfs_dirops == 0) 186 lfs_flush_fs(fs, SEGM_SYNC); 187 else 188 tsleep(&fs->lfs_writer, PRIBIO+1, "lfs_fsync", 189 0); 190 /* XXX KS - by falling out here, are we writing the vn 191 twice? */ 192 } 193 --fs->lfs_diropwait; 194 return lfs_vflush(vp); 195 } 196 return 0; 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 /* VOP_BWRITE 1 + NIADDR + VOP_BALLOC == 2 + 2*NIADDR times */ 207 int 208 lfs_truncate(v) 209 void *v; 210 { 211 struct vop_truncate_args /* { 212 struct vnode *a_vp; 213 off_t a_length; 214 int a_flags; 215 struct ucred *a_cred; 216 struct proc *a_p; 217 } */ *ap = v; 218 struct vnode *ovp = ap->a_vp; 219 ufs_daddr_t lastblock; 220 struct inode *oip; 221 ufs_daddr_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR]; 222 ufs_daddr_t newblks[NDADDR + NIADDR]; 223 off_t length = ap->a_length; 224 struct lfs *fs; 225 struct buf *bp; 226 int offset, size, level; 227 long count, rcount, nblocks, blocksreleased = 0, real_released = 0; 228 int i; 229 int aflags, error, allerror = 0; 230 off_t osize; 231 long lastseg; 232 size_t bc; 233 int obufsize, odb; 234 235 if (length < 0) 236 return (EINVAL); 237 oip = VTOI(ovp); 238 239 /* 240 * Just return and not update modification times. 241 */ 242 if (oip->i_ffs_size == length) 243 return (0); 244 245 if (ovp->v_type == VLNK && 246 (oip->i_ffs_size < ovp->v_mount->mnt_maxsymlinklen || 247 (ovp->v_mount->mnt_maxsymlinklen == 0 && 248 oip->i_din.ffs_din.di_blocks == 0))) { 249 #ifdef DIAGNOSTIC 250 if (length != 0) 251 panic("lfs_truncate: partial truncate of symlink"); 252 #endif 253 memset((char *)&oip->i_ffs_shortlink, 0, (u_int)oip->i_ffs_size); 254 oip->i_ffs_size = 0; 255 oip->i_flag |= IN_CHANGE | IN_UPDATE; 256 return (VOP_UPDATE(ovp, NULL, NULL, 0)); 257 } 258 if (oip->i_ffs_size == length) { 259 oip->i_flag |= IN_CHANGE | IN_UPDATE; 260 return (VOP_UPDATE(ovp, NULL, NULL, 0)); 261 } 262 #ifdef QUOTA 263 if ((error = getinoquota(oip)) != 0) 264 return (error); 265 #endif 266 fs = oip->i_lfs; 267 lfs_imtime(fs); 268 osize = oip->i_ffs_size; 269 ovp->v_lasta = ovp->v_clen = ovp->v_cstart = ovp->v_lastw = 0; 270 271 /* 272 * Lengthen the size of the file. We must ensure that the 273 * last byte of the file is allocated. Since the smallest 274 * value of osize is 0, length will be at least 1. 275 */ 276 if (osize < length) { 277 if (length > fs->lfs_maxfilesize) 278 return (EFBIG); 279 aflags = B_CLRBUF; 280 if (ap->a_flags & IO_SYNC) 281 aflags |= B_SYNC; 282 error = lfs_reserve(fs, ovp, fsbtodb(fs, NIADDR + 2)); 283 if (error) 284 return (error); 285 error = VOP_BALLOC(ovp, length - 1, 1, ap->a_cred, aflags, &bp); 286 lfs_reserve(fs, ovp, -fsbtodb(fs, NIADDR + 2)); 287 if (error) 288 return (error); 289 oip->i_ffs_size = length; 290 uvm_vnp_setsize(ovp, length); 291 (void) VOP_BWRITE(bp); 292 oip->i_flag |= IN_CHANGE | IN_UPDATE; 293 return (VOP_UPDATE(ovp, NULL, NULL, 0)); 294 } 295 296 if ((error = lfs_reserve(fs, ovp, fsbtodb(fs, 2 * NIADDR + 3))) != 0) 297 return (error); 298 /* 299 * Make sure no writes to this inode can happen while we're 300 * truncating. Otherwise, blocks which are accounted for on the 301 * inode *and* which have been created for cleaning can coexist, 302 * and cause an overcounting. 303 * 304 * (We don't need to *hold* the seglock, though, because we already 305 * hold the inode lock; draining the seglock is sufficient.) 306 */ 307 if (ovp != fs->lfs_unlockvp) { 308 while(fs->lfs_seglock) { 309 tsleep(&fs->lfs_seglock, PRIBIO+1, "lfs_truncate", 0); 310 } 311 } 312 313 /* 314 * Shorten the size of the file. If the file is not being 315 * truncated to a block boundary, the contents of the 316 * partial block following the end of the file must be 317 * zero'ed in case it ever becomes accessible again because 318 * of subsequent file growth. Directories however are not 319 * zero'ed as they should grow back initialized to empty. 320 */ 321 offset = blkoff(fs, length); 322 lastseg = -1; 323 bc = 0; 324 if (offset == 0) { 325 oip->i_ffs_size = length; 326 } else { 327 lbn = lblkno(fs, length); 328 aflags = B_CLRBUF; 329 if (ap->a_flags & IO_SYNC) 330 aflags |= B_SYNC; 331 error = VOP_BALLOC(ovp, length - 1, 1, ap->a_cred, aflags, &bp); 332 if (error) { 333 lfs_reserve(fs, ovp, -fsbtodb(fs, 2 * NIADDR + 3)); 334 return (error); 335 } 336 obufsize = bp->b_bufsize; 337 odb = btodb(bp->b_bcount); 338 oip->i_ffs_size = length; 339 size = blksize(fs, oip, lbn); 340 if (ovp->v_type != VDIR) 341 memset((char *)bp->b_data + offset, 0, 342 (u_int)(size - offset)); 343 allocbuf(bp, size); 344 if (bp->b_flags & B_DELWRI) { 345 if ((bp->b_flags & (B_LOCKED | B_CALL)) == B_LOCKED) 346 locked_queue_bytes -= obufsize - bp->b_bufsize; 347 fs->lfs_avail += odb - btodb(size); 348 } 349 (void) VOP_BWRITE(bp); 350 } 351 uvm_vnp_setsize(ovp, length); 352 /* 353 * Calculate index into inode's block list of 354 * last direct and indirect blocks (if any) 355 * which we want to keep. Lastblock is -1 when 356 * the file is truncated to 0. 357 */ 358 lastblock = lblkno(fs, length + fs->lfs_bsize - 1) - 1; 359 lastiblock[SINGLE] = lastblock - NDADDR; 360 lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs); 361 lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs); 362 nblocks = btodb(fs->lfs_bsize); 363 /* 364 * Record changed file and block pointers before we start 365 * freeing blocks. lastiblock values are also normalized to -1 366 * for calls to lfs_indirtrunc below. 367 */ 368 memcpy((caddr_t)newblks, (caddr_t)&oip->i_ffs_db[0], sizeof newblks); 369 for (level = TRIPLE; level >= SINGLE; level--) 370 if (lastiblock[level] < 0) { 371 newblks[NDADDR+level] = 0; 372 lastiblock[level] = -1; 373 } 374 for (i = NDADDR - 1; i > lastblock; i--) 375 newblks[i] = 0; 376 377 oip->i_ffs_size = osize; 378 error = lfs_vtruncbuf(ovp, lastblock + 1, 0, 0); 379 if (error && !allerror) 380 allerror = error; 381 382 /* 383 * Indirect blocks first. 384 */ 385 indir_lbn[SINGLE] = -NDADDR; 386 indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1; 387 indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1; 388 for (level = TRIPLE; level >= SINGLE; level--) { 389 bn = oip->i_ffs_ib[level]; 390 if (bn != 0) { 391 error = lfs_indirtrunc(oip, indir_lbn[level], 392 bn, lastiblock[level], 393 level, &count, &rcount, 394 &lastseg, &bc, ap->a_p); 395 if (error) 396 allerror = error; 397 real_released += rcount; 398 blocksreleased += count; 399 if (lastiblock[level] < 0) { 400 if (oip->i_ffs_ib[level] > 0) 401 real_released += nblocks; 402 blocksreleased += nblocks; 403 oip->i_ffs_ib[level] = 0; 404 lfs_blkfree(fs, bn, fs->lfs_bsize, &lastseg, &bc); 405 } 406 } 407 if (lastiblock[level] >= 0) 408 goto done; 409 } 410 411 /* 412 * All whole direct blocks or frags. 413 */ 414 for (i = NDADDR - 1; i > lastblock; i--) { 415 long bsize; 416 417 bn = oip->i_ffs_db[i]; 418 if (bn == 0) 419 continue; 420 bsize = blksize(fs, oip, i); 421 if (oip->i_ffs_db[i] > 0) 422 real_released += btodb(bsize); 423 blocksreleased += btodb(bsize); 424 oip->i_ffs_db[i] = 0; 425 lfs_blkfree(fs, bn, bsize, &lastseg, &bc); 426 } 427 if (lastblock < 0) 428 goto done; 429 430 /* 431 * Finally, look for a change in size of the 432 * last direct block; release any frags. 433 */ 434 bn = oip->i_ffs_db[lastblock]; 435 if (bn != 0) { 436 long oldspace, newspace; 437 438 /* 439 * Calculate amount of space we're giving 440 * back as old block size minus new block size. 441 */ 442 oldspace = blksize(fs, oip, lastblock); 443 oip->i_ffs_size = length; 444 newspace = blksize(fs, oip, lastblock); 445 if (newspace == 0) 446 panic("itrunc: newspace"); 447 if (oldspace - newspace > 0) { 448 lfs_blkfree(fs, bn, oldspace - newspace, &lastseg, &bc); 449 if (bn > 0) 450 real_released += btodb(oldspace - newspace); 451 blocksreleased += btodb(oldspace - newspace); 452 } 453 } 454 455 done: 456 /* Finish segment accounting corrections */ 457 lfs_update_seguse(fs, lastseg, bc); 458 #ifdef DIAGNOSTIC 459 for (level = SINGLE; level <= TRIPLE; level++) 460 if (newblks[NDADDR + level] != oip->i_ffs_ib[level]) 461 panic("lfs itrunc1"); 462 for (i = 0; i < NDADDR; i++) 463 if (newblks[i] != oip->i_ffs_db[i]) 464 panic("lfs itrunc2"); 465 if (length == 0 && 466 (!LIST_EMPTY(&ovp->v_cleanblkhd) || !LIST_EMPTY(&ovp->v_dirtyblkhd))) 467 panic("lfs itrunc3"); 468 #endif /* DIAGNOSTIC */ 469 /* 470 * Put back the real size. 471 */ 472 oip->i_ffs_size = length; 473 oip->i_lfs_effnblks -= blocksreleased; 474 oip->i_ffs_blocks -= real_released; 475 fs->lfs_bfree += blocksreleased; 476 #ifdef DIAGNOSTIC 477 if (oip->i_ffs_size == 0 && oip->i_ffs_blocks != 0) { 478 printf("lfs_truncate: truncate to 0 but %d blocks on inode\n", 479 oip->i_ffs_blocks); 480 panic("lfs_truncate: persistent blocks\n"); 481 } 482 #endif 483 oip->i_flag |= IN_CHANGE; 484 #ifdef QUOTA 485 (void) chkdq(oip, -blocksreleased, NOCRED, 0); 486 #endif 487 lfs_reserve(fs, ovp, -fsbtodb(fs, 2 * NIADDR + 3)); 488 return (allerror); 489 } 490 491 /* Update segment usage information when removing a block. */ 492 static int 493 lfs_blkfree(struct lfs *fs, daddr_t daddr, size_t bsize, long *lastseg, 494 size_t *num) 495 { 496 long seg; 497 int error = 0; 498 499 bsize = fragroundup(fs, bsize); 500 if (daddr > 0) { 501 if (*lastseg != (seg = datosn(fs, daddr))) { 502 error = lfs_update_seguse(fs, *lastseg, *num); 503 *num = bsize; 504 *lastseg = seg; 505 } else 506 *num += bsize; 507 } 508 return error; 509 } 510 511 /* Finish the accounting updates for a segment. */ 512 static int 513 lfs_update_seguse(struct lfs *fs, long lastseg, size_t num) 514 { 515 SEGUSE *sup; 516 struct buf *bp; 517 518 if (lastseg < 0 || num == 0) 519 return 0; 520 521 522 LFS_SEGENTRY(sup, fs, lastseg, bp); 523 if (num > sup->su_nbytes) { 524 printf("lfs_truncate: segment %ld short by %ld\n", 525 lastseg, (long)num - sup->su_nbytes); 526 panic("lfs_truncate: negative bytes"); 527 sup->su_nbytes = num; 528 } 529 sup->su_nbytes -= num; 530 return (VOP_BWRITE(bp)); /* Ifile */ 531 } 532 533 /* 534 * Release blocks associated with the inode ip and stored in the indirect 535 * block bn. Blocks are free'd in LIFO order up to (but not including) 536 * lastbn. If level is greater than SINGLE, the block is an indirect block 537 * and recursive calls to indirtrunc must be used to cleanse other indirect 538 * blocks. 539 * 540 * NB: triple indirect blocks are untested. 541 */ 542 static int 543 lfs_indirtrunc(struct inode *ip, ufs_daddr_t lbn, daddr_t dbn, 544 ufs_daddr_t lastbn, int level, long *countp, 545 long *rcountp, long *lastsegp, size_t *bcp, struct proc *p) 546 { 547 int i; 548 struct buf *bp; 549 struct lfs *fs = ip->i_lfs; 550 ufs_daddr_t *bap; 551 struct vnode *vp; 552 ufs_daddr_t *copy = NULL, nb, nlbn, last; 553 long blkcount, rblkcount, factor; 554 int nblocks, blocksreleased = 0, real_released = 0; 555 int error = 0, allerror = 0; 556 557 /* 558 * Calculate index in current block of last 559 * block to be kept. -1 indicates the entire 560 * block so we need not calculate the index. 561 */ 562 factor = 1; 563 for (i = SINGLE; i < level; i++) 564 factor *= NINDIR(fs); 565 last = lastbn; 566 if (lastbn > 0) 567 last /= factor; 568 nblocks = btodb(fs->lfs_bsize); 569 /* 570 * Get buffer of block pointers, zero those entries corresponding 571 * to blocks to be free'd, and update on disk copy first. Since 572 * double(triple) indirect before single(double) indirect, calls 573 * to bmap on these blocks will fail. However, we already have 574 * the on disk address, so we have to set the b_blkno field 575 * explicitly instead of letting bread do everything for us. 576 */ 577 vp = ITOV(ip); 578 bp = getblk(vp, lbn, (int)fs->lfs_bsize, 0, 0); 579 if (bp->b_flags & (B_DONE | B_DELWRI)) { 580 /* Braces must be here in case trace evaluates to nothing. */ 581 trace(TR_BREADHIT, pack(vp, fs->lfs_bsize), lbn); 582 } else { 583 trace(TR_BREADMISS, pack(vp, fs->lfs_bsize), lbn); 584 p->p_stats->p_ru.ru_inblock++; /* pay for read */ 585 bp->b_flags |= B_READ; 586 if (bp->b_bcount > bp->b_bufsize) 587 panic("lfs_indirtrunc: bad buffer size"); 588 bp->b_blkno = dbn; 589 VOP_STRATEGY(bp); 590 error = biowait(bp); 591 } 592 if (error) { 593 brelse(bp); 594 *countp = *rcountp = 0; 595 return (error); 596 } 597 598 bap = (ufs_daddr_t *)bp->b_data; 599 if (lastbn >= 0) { 600 MALLOC(copy, ufs_daddr_t *, fs->lfs_bsize, M_TEMP, M_WAITOK); 601 memcpy((caddr_t)copy, (caddr_t)bap, (u_int)fs->lfs_bsize); 602 memset((caddr_t)&bap[last + 1], 0, 603 (u_int)(NINDIR(fs) - (last + 1)) * sizeof (ufs_daddr_t)); 604 error = VOP_BWRITE(bp); 605 if (error) 606 allerror = error; 607 bap = copy; 608 } 609 610 /* 611 * Recursively free totally unused blocks. 612 */ 613 for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last; 614 i--, nlbn += factor) { 615 nb = bap[i]; 616 if (nb == 0) 617 continue; 618 if (level > SINGLE) { 619 error = lfs_indirtrunc(ip, nlbn, nb, 620 (ufs_daddr_t)-1, level - 1, 621 &blkcount, &rblkcount, 622 lastsegp, bcp, p); 623 if (error) 624 allerror = error; 625 blocksreleased += blkcount; 626 real_released += rblkcount; 627 } 628 lfs_blkfree(fs, nb, fs->lfs_bsize, lastsegp, bcp); 629 if (bap[i] > 0) 630 real_released += nblocks; 631 blocksreleased += nblocks; 632 } 633 634 /* 635 * Recursively free last partial block. 636 */ 637 if (level > SINGLE && lastbn >= 0) { 638 last = lastbn % factor; 639 nb = bap[i]; 640 if (nb != 0) { 641 error = lfs_indirtrunc(ip, nlbn, nb, 642 last, level - 1, &blkcount, 643 &rblkcount, lastsegp, bcp, p); 644 if (error) 645 allerror = error; 646 real_released += rblkcount; 647 blocksreleased += blkcount; 648 } 649 } 650 651 if (copy != NULL) { 652 FREE(copy, M_TEMP); 653 } else { 654 if (bp->b_flags & B_DELWRI) { 655 LFS_UNLOCK_BUF(bp); 656 fs->lfs_avail += btodb(bp->b_bcount); 657 wakeup(&fs->lfs_avail); 658 } 659 bp->b_flags |= B_INVAL; 660 brelse(bp); 661 } 662 663 *countp = blocksreleased; 664 *rcountp = real_released; 665 return (allerror); 666 } 667 668 /* 669 * Destroy any in core blocks past the truncation length. 670 * Inlined from vtruncbuf, so that lfs_avail could be updated. 671 */ 672 static int 673 lfs_vtruncbuf(vp, lbn, slpflag, slptimeo) 674 struct vnode *vp; 675 daddr_t lbn; 676 int slpflag, slptimeo; 677 { 678 struct buf *bp, *nbp; 679 int s, error; 680 struct lfs *fs; 681 682 fs = VTOI(vp)->i_lfs; 683 s = splbio(); 684 685 restart: 686 for (bp = LIST_FIRST(&vp->v_cleanblkhd); bp; bp = nbp) { 687 nbp = LIST_NEXT(bp, b_vnbufs); 688 if (bp->b_lblkno < lbn) 689 continue; 690 if (bp->b_flags & B_BUSY) { 691 bp->b_flags |= B_WANTED; 692 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), 693 "lfs_vtruncbuf", slptimeo); 694 if (error) { 695 splx(s); 696 return (error); 697 } 698 goto restart; 699 } 700 bp->b_flags |= B_BUSY | B_INVAL | B_VFLUSH; 701 if (bp->b_flags & B_DELWRI) { 702 bp->b_flags &= ~B_DELWRI; 703 fs->lfs_avail += btodb(bp->b_bcount); 704 wakeup(&fs->lfs_avail); 705 } 706 LFS_UNLOCK_BUF(bp); 707 brelse(bp); 708 } 709 710 for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { 711 nbp = LIST_NEXT(bp, b_vnbufs); 712 if (bp->b_lblkno < lbn) 713 continue; 714 if (bp->b_flags & B_BUSY) { 715 bp->b_flags |= B_WANTED; 716 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), 717 "lfs_vtruncbuf", slptimeo); 718 if (error) { 719 splx(s); 720 return (error); 721 } 722 goto restart; 723 } 724 bp->b_flags |= B_BUSY | B_INVAL | B_VFLUSH; 725 if (bp->b_flags & B_DELWRI) { 726 bp->b_flags &= ~B_DELWRI; 727 fs->lfs_avail += btodb(bp->b_bcount); 728 wakeup(&fs->lfs_avail); 729 } 730 LFS_UNLOCK_BUF(bp); 731 brelse(bp); 732 } 733 734 splx(s); 735 736 return (0); 737 } 738 739