1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)lfs_inode.c 7.41 (Berkeley) 09/20/91 8 */ 9 10 #include "param.h" 11 #include "systm.h" 12 #include "mount.h" 13 #include "proc.h" 14 #include "file.h" 15 #include "buf.h" 16 #include "vnode.h" 17 #include "kernel.h" 18 #include "malloc.h" 19 20 #include "../ufs/quota.h" 21 #include "../ufs/inode.h" 22 #include "../ufs/ufsmount.h" 23 #include "lfs.h" 24 #include "lfs_extern.h" 25 26 #define INOHSZ 512 27 #if ((INOHSZ&(INOHSZ-1)) == 0) 28 #define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1)) 29 #else 30 #define INOHASH(dev,ino) (((unsigned)((dev)+(ino)))%INOHSZ) 31 #endif 32 33 union lfsihead { /* LFS */ 34 union lfsihead *ih_head[2]; 35 struct inode *ih_chain[2]; 36 } lfsihead[INOHSZ]; 37 38 /* LFS */ 39 extern int prtactive; /* 1 => print out reclaim of active vnodes */ 40 41 /* 42 * Initialize hash links for inodes. 43 */ 44 lfs_init() 45 { 46 register int i; 47 register union lfsihead *ih = lfsihead; 48 49 printf("lfs_init\n"); 50 #ifndef lint 51 if (VN_MAXPRIVATE < sizeof(struct inode)) 52 panic("ihinit: too small"); 53 #endif /* not lint */ 54 for (i = INOHSZ; --i >= 0; ih++) { 55 ih->ih_head[0] = ih; 56 ih->ih_head[1] = ih; 57 } 58 #ifdef NOTLFS /* LFS */ 59 #ifdef QUOTA 60 dqinit(); 61 #endif /* QUOTA */ 62 #endif 63 } 64 65 lfs_hqueue(ip) 66 struct inode *ip; 67 { 68 union lfsihead *ih; 69 70 printf("lfs_hqueue ino %d\n", ip->i_number); 71 ih = &lfsihead[INOHASH(ip->i_dev, ip->i_number)]; 72 insque(ip, ih); 73 ILOCK(ip); 74 } 75 76 77 /* 78 * Look up a UFS dinode number to find its incore vnode. 79 * If it is not in core, read it in from the specified device. 80 * If it is in core, wait for the lock bit to clear, then 81 * return the inode locked. Detection and handling of mount 82 * points must be done by the calling routine. 83 */ 84 lfs_iget(xp, ino, ipp) 85 struct inode *xp; 86 ino_t ino; 87 struct inode **ipp; 88 { 89 dev_t dev = xp->i_dev; 90 struct mount *mntp = ITOV(xp)->v_mount; 91 register struct lfs *fs = VFSTOUFS(mntp)->um_lfs; /* LFS */ 92 extern struct vnodeops ufs_vnodeops, spec_inodeops; 93 register struct inode *ip, *iq; 94 register struct vnode *vp; 95 struct vnode *nvp; 96 struct buf *bp; 97 union lfsihead *ih; 98 int i, error; 99 100 printf("lfs_iget ino %d\n", ino); 101 ih = &lfsihead[INOHASH(dev, ino)]; 102 loop: 103 for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) { 104 if (ino != ip->i_number || dev != ip->i_dev) 105 continue; 106 if ((ip->i_flag&ILOCKED) != 0) { 107 ip->i_flag |= IWANT; 108 sleep((caddr_t)ip, PINOD); 109 goto loop; 110 } 111 if (vget(ITOV(ip))) 112 goto loop; 113 *ipp = ip; 114 return(0); 115 } 116 117 /* Allocate new vnode/inode. */ 118 error = lfs_vcreate(mntp, ino, &nvp); 119 if (error) { 120 *ipp = 0; 121 return (error); 122 } 123 ip = VTOI(nvp); 124 125 /* 126 * Put it onto its hash chain and lock it so that other requests for 127 * this inode will block if they arrive while we are sleeping waiting 128 * for old data structures to be purged or for the contents of the 129 * disk portion of this inode to be read. 130 */ 131 insque(ip, ih); 132 ILOCK(ip); 133 134 /* Read in the disk contents for the inode, copy into the vnode. */ 135 if (error = bread(VFSTOUFS(mntp)->um_devvp, itod(fs, ino), 136 (int)fs->lfs_bsize, NOCRED, &bp)) { /* LFS */ 137 /* 138 * The inode does not contain anything useful, so it would 139 * be misleading to leave it on its hash chain. 140 * Iput() will take care of putting it back on the free list. 141 */ 142 remque(ip); 143 ip->i_forw = ip; 144 ip->i_back = ip; 145 /* 146 * Unlock and discard unneeded inode. 147 */ 148 iput(ip); 149 brelse(bp); 150 *ipp = 0; 151 return (error); 152 } 153 ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino); 154 brelse(bp); 155 156 /* 157 * Initialize the associated vnode 158 */ 159 vp = ITOV(ip); 160 vp->v_type = IFTOVT(ip->i_mode); 161 if (vp->v_type == VFIFO) { 162 #ifdef FIFO 163 extern struct vnodeops fifo_inodeops; 164 vp->v_op = &fifo_inodeops; 165 #else 166 iput(ip); 167 *ipp = 0; 168 return (EOPNOTSUPP); 169 #endif /* FIFO */ 170 } 171 if (vp->v_type == VCHR || vp->v_type == VBLK) { 172 vp->v_op = &spec_inodeops; 173 if (nvp = checkalias(vp, ip->i_rdev, mntp)) { 174 /* 175 * Reinitialize aliased inode. 176 */ 177 vp = nvp; 178 iq = VTOI(vp); 179 iq->i_vnode = vp; 180 iq->i_flag = 0; 181 ILOCK(iq); 182 iq->i_din = ip->i_din; 183 iq->i_dev = dev; 184 iq->i_number = ino; 185 insque(iq, ih); 186 /* 187 * Discard unneeded vnode 188 */ 189 ip->i_mode = 0; 190 iput(ip); 191 ip = iq; 192 } 193 } 194 if (ino == ROOTINO) 195 vp->v_flag |= VROOT; 196 197 VREF(ip->i_devvp); 198 199 *ipp = ip; 200 return (0); 201 } 202 203 /* 204 * Last reference to an inode, write the inode out and if necessary, 205 * truncate and deallocate the file. 206 */ 207 lfs_inactive(vp, p) 208 struct vnode *vp; 209 struct proc *p; 210 { 211 register struct inode *ip = VTOI(vp); 212 int mode, error = 0; 213 214 printf("lfs_inactive: ino %d mode %d nlink %d\n", 215 ip->i_number, ip->i_mode, ip->i_nlink); 216 217 if (prtactive && vp->v_usecount != 0) 218 vprint("ufs_inactive: pushing active", vp); 219 /* 220 * Get rid of inodes related to stale file handles. 221 */ 222 if (ip->i_mode == 0) { 223 if ((vp->v_flag & VXLOCK) == 0) 224 vgone(vp); 225 return (0); 226 } 227 ILOCK(ip); 228 if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 229 #ifdef QUOTA 230 if (!getinoquota(ip)) 231 (void) chkiq(ip, -1, NOCRED, 0); 232 #endif 233 error = lfs_itrunc(ip, (u_long)0, 0); /* LFS */ 234 mode = ip->i_mode; 235 ip->i_mode = 0; 236 ip->i_rdev = 0; 237 ip->i_flag |= IUPD|ICHG; 238 #ifdef NOTLFS /* LFS */ 239 ifree(ip, ip->i_number, mode); 240 #else 241 lfs_ifree(ip); 242 #endif 243 } 244 ITIMES(ip, &time, &time); 245 IUNLOCK(ip); 246 ip->i_flag = 0; 247 /* 248 * If we are done with the inode, reclaim it 249 * so that it can be reused immediately. 250 */ 251 if (vp->v_usecount == 0 && ip->i_mode == 0) 252 vgone(vp); 253 return (error); 254 } 255 256 /* 257 * Update the access, modified, and inode change times as specified 258 * by the IACC, IMOD, and ICHG flags respectively. The IUPD flag 259 * is used to specify that the inode needs to be updated but that 260 * the times have already been set. The access and modified times 261 * are taken from the second and third parameters; the inode change 262 * time is always taken from the current time. If waitfor is set, 263 * then wait for the disk write of the inode to complete. 264 */ 265 lfs_iupdat(ip, ta, tm, waitfor) 266 register struct inode *ip; 267 struct timeval *ta, *tm; 268 int waitfor; 269 { 270 struct buf *bp; 271 struct vnode *vp = ITOV(ip); 272 struct dinode *dp; 273 register struct lfs *fs; /* LFS */ 274 int error; 275 276 printf("lfs_iupdat: ino %d\n", ip->i_number); 277 fs = ip->i_lfs; /* LFS */ 278 if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0) 279 return (0); 280 if (vp->v_mount->mnt_flag & MNT_RDONLY) 281 return (0); 282 error = bread(ip->i_devvp, fsbtodb(fs, itod(fs, ip->i_number)), 283 (int)fs->lfs_bsize, NOCRED, &bp); 284 if (error) { 285 brelse(bp); 286 return (error); 287 } 288 if (ip->i_flag&IACC) 289 ip->i_atime = ta->tv_sec; 290 if (ip->i_flag&IUPD) 291 ip->i_mtime = tm->tv_sec; 292 if (ip->i_flag&ICHG) 293 ip->i_ctime = time.tv_sec; 294 ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD); /* LFS */ 295 *lfs_ifind(fs, ip->i_number, bp->b_un.b_dino) = ip->i_din; 296 if (waitfor) { 297 return (bwrite(bp)); 298 } else { 299 bdwrite(bp); 300 return (0); 301 } 302 } 303 304 #define SINGLE 0 /* index of single indirect block */ 305 #define DOUBLE 1 /* index of double indirect block */ 306 #define TRIPLE 2 /* index of triple indirect block */ 307 /* 308 * Truncate the inode ip to at most length size. Free affected disk 309 * blocks -- the blocks of the file are removed in reverse order. 310 * 311 * NB: triple indirect blocks are untested. 312 */ 313 lfs_itrunc(oip, length, flags) 314 register struct inode *oip; 315 u_long length; 316 int flags; 317 { 318 #ifdef NOTLFS /* LFS */ 319 register daddr_t lastblock; 320 daddr_t bn, lbn, lastiblock[NIADDR]; 321 register struct fs *fs; 322 register struct inode *ip; 323 struct buf *bp; 324 int offset, osize, size, level; 325 long count, nblocks, blocksreleased = 0; 326 register int i; 327 int aflags, error, allerror; 328 struct inode tip; 329 330 vnode_pager_setsize(ITOV(oip), length); 331 if (oip->i_size <= length) { 332 oip->i_flag |= ICHG|IUPD; 333 error = lfs_iupdat(oip, &time, &time, 1); 334 return (error); 335 } 336 /* 337 * Calculate index into inode's block list of 338 * last direct and indirect blocks (if any) 339 * which we want to keep. Lastblock is -1 when 340 * the file is truncated to 0. 341 */ 342 fs = oip->i_fs; 343 lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1; 344 lastiblock[SINGLE] = lastblock - NDADDR; 345 lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs); 346 lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs); 347 nblocks = btodb(fs->fs_bsize); 348 /* 349 * Update the size of the file. If the file is not being 350 * truncated to a block boundry, the contents of the 351 * partial block following the end of the file must be 352 * zero'ed in case it ever become accessable again because 353 * of subsequent file growth. 354 */ 355 osize = oip->i_size; 356 offset = blkoff(fs, length); 357 if (offset == 0) { 358 oip->i_size = length; 359 } else { 360 lbn = lblkno(fs, length); 361 aflags = B_CLRBUF; 362 if (flags & IO_SYNC) 363 aflags |= B_SYNC; 364 #ifdef QUOTA 365 if (error = getinoquota(oip)) 366 return (error); 367 #endif 368 if (error = balloc(oip, lbn, offset, &bp, aflags)) 369 return (error); 370 oip->i_size = length; 371 size = blksize(fs); /* LFS */ 372 (void) vnode_pager_uncache(ITOV(oip)); 373 bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset)); 374 allocbuf(bp, size); 375 if (flags & IO_SYNC) 376 bwrite(bp); 377 else 378 bdwrite(bp); 379 } 380 /* 381 * Update file and block pointers 382 * on disk before we start freeing blocks. 383 * If we crash before free'ing blocks below, 384 * the blocks will be returned to the free list. 385 * lastiblock values are also normalized to -1 386 * for calls to indirtrunc below. 387 */ 388 tip = *oip; 389 tip.i_size = osize; 390 for (level = TRIPLE; level >= SINGLE; level--) 391 if (lastiblock[level] < 0) { 392 oip->i_ib[level] = 0; 393 lastiblock[level] = -1; 394 } 395 for (i = NDADDR - 1; i > lastblock; i--) 396 oip->i_db[i] = 0; 397 oip->i_flag |= ICHG|IUPD; 398 vinvalbuf(ITOV(oip), (length > 0)); 399 allerror = lfs_iupdat(oip, &time, &time, MNT_WAIT); 400 401 /* 402 * Indirect blocks first. 403 */ 404 ip = &tip; 405 for (level = TRIPLE; level >= SINGLE; level--) { 406 bn = ip->i_ib[level]; 407 if (bn != 0) { 408 error = indirtrunc(ip, bn, lastiblock[level], level, 409 &count); 410 if (error) 411 allerror = error; 412 blocksreleased += count; 413 if (lastiblock[level] < 0) { 414 ip->i_ib[level] = 0; 415 blkfree(ip, bn, (off_t)fs->fs_bsize); 416 blocksreleased += nblocks; 417 } 418 } 419 if (lastiblock[level] >= 0) 420 goto done; 421 } 422 423 /* 424 * All whole direct blocks or frags. 425 */ 426 for (i = NDADDR - 1; i > lastblock; i--) { 427 register off_t bsize; 428 429 bn = ip->i_db[i]; 430 if (bn == 0) 431 continue; 432 ip->i_db[i] = 0; 433 bsize = (off_t)blksize(fs); /* LFS */ 434 blkfree(ip, bn, bsize); 435 blocksreleased += btodb(bsize); 436 } 437 if (lastblock < 0) 438 goto done; 439 440 /* 441 * Finally, look for a change in size of the 442 * last direct block; release any frags. 443 */ 444 bn = ip->i_db[lastblock]; 445 if (bn != 0) { 446 off_t oldspace, newspace; 447 448 /* 449 * Calculate amount of space we're giving 450 * back as old block size minus new block size. 451 */ 452 oldspace = blksize(fs); /* LFS */ 453 ip->i_size = length; 454 newspace = blksize(fs); /* LFS */ 455 if (newspace == 0) 456 panic("lfs_itrunc: newspace"); 457 if (oldspace - newspace > 0) { 458 /* 459 * Block number of space to be free'd is 460 * the old block # plus the number of frags 461 * required for the storage we're keeping. 462 */ 463 bn += numfrags(fs, newspace); 464 blkfree(ip, bn, oldspace - newspace); 465 blocksreleased += btodb(oldspace - newspace); 466 } 467 } 468 done: 469 /* BEGIN PARANOIA */ 470 for (level = SINGLE; level <= TRIPLE; level++) 471 if (ip->i_ib[level] != oip->i_ib[level]) 472 panic("lfs_itrunc1"); 473 for (i = 0; i < NDADDR; i++) 474 if (ip->i_db[i] != oip->i_db[i]) 475 panic("lfs_itrunc2"); 476 /* END PARANOIA */ 477 oip->i_blocks -= blocksreleased; 478 if (oip->i_blocks < 0) /* sanity */ 479 oip->i_blocks = 0; 480 oip->i_flag |= ICHG; 481 #ifdef QUOTA 482 if (!getinoquota(oip)) 483 (void) chkdq(oip, -blocksreleased, NOCRED, 0); 484 #endif 485 return (allerror); 486 #else 487 /* LFS IMPLEMENT -- lfs_itrunc */ 488 panic("lfs_itrunc not implemented"); 489 #endif 490 } 491 492 /* 493 * Release blocks associated with the inode ip and 494 * stored in the indirect block bn. Blocks are free'd 495 * in LIFO order up to (but not including) lastbn. If 496 * level is greater than SINGLE, the block is an indirect 497 * block and recursive calls to indirtrunc must be used to 498 * cleanse other indirect blocks. 499 * 500 * NB: triple indirect blocks are untested. 501 */ 502 lfs_indirtrunc(ip, bn, lastbn, level, countp) 503 register struct inode *ip; 504 daddr_t bn, lastbn; 505 int level; 506 long *countp; 507 { 508 #ifdef NOTLFS 509 register int i; 510 struct buf *bp; 511 register struct fs *fs = ip->i_fs; 512 register daddr_t *bap; 513 daddr_t *copy, nb, last; 514 long blkcount, factor; 515 int nblocks, blocksreleased = 0; 516 int error, allerror = 0; 517 518 /* 519 * Calculate index in current block of last 520 * block to be kept. -1 indicates the entire 521 * block so we need not calculate the index. 522 */ 523 factor = 1; 524 for (i = SINGLE; i < level; i++) 525 factor *= NINDIR(fs); 526 last = lastbn; 527 if (lastbn > 0) 528 last /= factor; 529 nblocks = btodb(fs->fs_bsize); 530 /* 531 * Get buffer of block pointers, zero those 532 * entries corresponding to blocks to be free'd, 533 * and update on disk copy first. 534 */ 535 error = bread(ip->i_devvp, fsbtodb(fs, bn), (int)fs->fs_bsize, 536 NOCRED, &bp); 537 if (error) { 538 brelse(bp); 539 *countp = 0; 540 return (error); 541 } 542 bap = bp->b_un.b_daddr; 543 MALLOC(copy, daddr_t *, fs->fs_bsize, M_TEMP, M_WAITOK); 544 bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->fs_bsize); 545 bzero((caddr_t)&bap[last + 1], 546 (u_int)(NINDIR(fs) - (last + 1)) * sizeof (daddr_t)); 547 if (last == -1) 548 bp->b_flags |= B_INVAL; 549 error = bwrite(bp); 550 if (error) 551 allerror = error; 552 bap = copy; 553 554 /* 555 * Recursively free totally unused blocks. 556 */ 557 for (i = NINDIR(fs) - 1; i > last; i--) { 558 nb = bap[i]; 559 if (nb == 0) 560 continue; 561 if (level > SINGLE) { 562 error = indirtrunc(ip, nb, (daddr_t)-1, level - 1, 563 &blkcount); 564 if (error) 565 allerror = error; 566 blocksreleased += blkcount; 567 } 568 blkfree(ip, nb, (off_t)fs->fs_bsize); 569 blocksreleased += nblocks; 570 } 571 572 /* 573 * Recursively free last partial block. 574 */ 575 if (level > SINGLE && lastbn >= 0) { 576 last = lastbn % factor; 577 nb = bap[i]; 578 if (nb != 0) { 579 error = indirtrunc(ip, nb, last, level - 1, &blkcount); 580 if (error) 581 allerror = error; 582 blocksreleased += blkcount; 583 } 584 } 585 FREE(copy, M_TEMP); 586 *countp = blocksreleased; 587 return (allerror); 588 #else 589 /* LFS IMPLEMENT -- lfs_indirtrunc */ 590 panic("lfs_indirtrunc not implemented"); 591 #endif 592 } 593