1 /* lfs_inode.c 4.13 82/06/29 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/mount.h" 6 #include "../h/dir.h" 7 #include "../h/user.h" 8 #include "../h/inode.h" 9 #include "../h/fs.h" 10 #include "../h/conf.h" 11 #include "../h/buf.h" 12 #include "../h/inline.h" 13 14 #define INOHSZ 63 15 #if ((INOHSZ&(INOHSZ-1)) == 0) 16 #define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1)) 17 #else 18 #define INOHASH(dev,ino) (((dev)+(ino))%INOHSZ) 19 #endif 20 21 union ihead { /* inode LRU cache, Chris Maltby */ 22 union ihead *ih_head[2]; 23 struct inode *ih_chain[2]; 24 } ihead[INOHSZ]; 25 26 struct inode *ifreeh, **ifreet; 27 28 /* 29 * Initialize hash links for inodes 30 * and build inode free list. 31 */ 32 ihinit() 33 { 34 register int i; 35 register struct inode *ip = inode; 36 register union ihead *ih = ihead; 37 38 for (i = INOHSZ; --i >= 0; ih++) { 39 ih->ih_head[0] = ih; 40 ih->ih_head[1] = ih; 41 } 42 ifreeh = ip; 43 ifreet = &ip->i_freef; 44 ip->i_freeb = &ifreeh; 45 ip->i_forw = ip; 46 ip->i_back = ip; 47 for (i = ninode; --i > 0; ) { 48 ++ip; 49 ip->i_forw = ip; 50 ip->i_back = ip; 51 *ifreet = ip; 52 ip->i_freeb = ifreet; 53 ifreet = &ip->i_freef; 54 } 55 ip->i_freef = NULL; 56 } 57 58 #ifdef notdef 59 /* 60 * Find an inode if it is incore. 61 * This is the equivalent, for inodes, 62 * of ``incore'' in bio.c or ``pfind'' in subr.c. 63 */ 64 struct inode * 65 ifind(dev, ino) 66 dev_t dev; 67 ino_t ino; 68 { 69 register struct inode *ip; 70 register union ihead *ih; 71 72 ih = &ihead[INOHASH(dev, ino)]; 73 for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) 74 if (ino==ip->i_number && dev==ip->i_dev) 75 return (ip); 76 return ((struct inode *)0); 77 } 78 #endif notdef 79 80 /* 81 * Look up an inode by device,inumber. 82 * If it is in core (in the inode structure), 83 * honor the locking protocol. 84 * If it is not in core, read it in from the 85 * specified device. 86 * If the inode is mounted on, perform 87 * the indicated indirection. 88 * In all cases, a pointer to a locked 89 * inode structure is returned. 90 * 91 * panic: no imt -- if the mounted file 92 * system is not in the mount table. 93 * "cannot happen" 94 */ 95 struct inode * 96 iget(dev, fs, ino) 97 dev_t dev; 98 register struct fs *fs; 99 ino_t ino; 100 { 101 register struct inode *ip; /* known to be r11 - see "asm" below */ 102 register union ihead *ih; /* known to be r10 - see "asm" below */ 103 register struct mount *mp; 104 register struct buf *bp; 105 register struct dinode *dp; 106 register struct inode *iq; 107 108 loop: 109 if (getfs(dev) != fs) 110 panic("iget: bad fs"); 111 ih = &ihead[INOHASH(dev, ino)]; 112 for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) 113 if (ino == ip->i_number && dev == ip->i_dev) { 114 if ((ip->i_flag&ILOCK) != 0) { 115 ip->i_flag |= IWANT; 116 sleep((caddr_t)ip, PINOD); 117 goto loop; 118 } 119 if ((ip->i_flag&IMOUNT) != 0) { 120 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 121 if(mp->m_inodp == ip) { 122 dev = mp->m_dev; 123 fs = mp->m_bufp->b_un.b_fs; 124 ino = ROOTINO; 125 goto loop; 126 } 127 panic("no imt"); 128 } 129 if (ip->i_count == 0) { /* ino on free list */ 130 if (iq = ip->i_freef) 131 iq->i_freeb = ip->i_freeb; 132 else 133 ifreet = ip->i_freeb; 134 *ip->i_freeb = iq; 135 ip->i_freef = NULL; 136 ip->i_freeb = NULL; 137 } 138 ip->i_count++; 139 ip->i_flag |= ILOCK; 140 return(ip); 141 } 142 143 if ((ip = ifreeh) == NULL) { 144 tablefull("inode"); 145 u.u_error = ENFILE; 146 return(NULL); 147 } 148 if (iq = ip->i_freef) 149 iq->i_freeb = &ifreeh; 150 ifreeh = iq; 151 ip->i_freef = NULL; 152 ip->i_freeb = NULL; 153 /* 154 * Now to take inode off the hash chain it was on 155 * (initially, or after an iflush, it is on a "hash chain" 156 * consisting entirely of itself, and pointed to by no-one, 157 * but that doesn't matter), and put it on the chain for 158 * its new (ino, dev) pair 159 */ 160 #ifndef UNFAST 161 asm("remque (r11),r0"); 162 asm("insque (r11),(r10)"); 163 #else 164 /* remque */ 165 ip->i_back->i_forw = ip->i_forw; 166 ip->i_forw->i_back = ip->i_back; 167 /* insque */ 168 ip->i_forw = ih->ih_chain[0]; 169 ip->i_back = (struct inode *)ih; 170 ih->ih_chain[0]->i_back = ip; 171 ih->ih_chain[0] = ip; 172 #endif 173 ip->i_dev = dev; 174 ip->i_fs = fs; 175 ip->i_number = ino; 176 ip->i_flag = ILOCK; 177 ip->i_count++; 178 ip->i_lastr = 0; 179 bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize); 180 /* 181 * Check I/O errors 182 */ 183 if ((bp->b_flags&B_ERROR) != 0) { 184 brelse(bp); 185 /* 186 * the inode doesn't contain anything useful, so it would 187 * be misleading to leave it on its hash chain. 188 * 'iput' will take care of putting it back on the free list. 189 */ 190 #ifndef UNFAST 191 asm("remque (r11),r0"); 192 #else 193 ip->i_back->i_forw = ip->i_forw; 194 ip->i_forw->i_back = ip->i_back; 195 #endif 196 ip->i_forw = ip; 197 ip->i_back = ip; 198 /* 199 * we also loose its inumber, just in case (as iput 200 * doesn't do that any more) - but as it isn't on its 201 * hash chain, I doubt if this is really necessary .. kre 202 * (probably the two methods are interchangable) 203 */ 204 ip->i_number = 0; 205 iput(ip); 206 return(NULL); 207 } 208 dp = bp->b_un.b_dino; 209 dp += itoo(fs, ino); 210 ip->i_ic = dp->di_ic; 211 brelse(bp); 212 return (ip); 213 } 214 215 /* 216 * Decrement reference count of 217 * an inode structure. 218 * On the last reference, 219 * write the inode out and if necessary, 220 * truncate and deallocate the file. 221 */ 222 iput(ip) 223 register struct inode *ip; 224 { 225 226 if ((ip->i_flag & ILOCK) == 0) 227 panic("iput"); 228 iunlock(ip); 229 irele(ip); 230 } 231 232 irele(ip) 233 register struct inode *ip; 234 { 235 register int i, x; 236 register struct inode *jp; 237 int mode; 238 239 if (ip->i_count == 1) { 240 ip->i_flag |= ILOCK; 241 if (ip->i_nlink <= 0) { 242 itrunc(ip); 243 mode = ip->i_mode; 244 ip->i_mode = 0; 245 ip->i_flag |= IUPD|ICHG; 246 ifree(ip, ip->i_number, mode); 247 } 248 IUPDAT(ip, &time, &time, 0); 249 iunlock(ip); 250 ip->i_flag = 0; 251 /* 252 * Put the inode on the end of the free list. 253 * Possibly in some cases it would be better to 254 * put the inode at the head of the free list, 255 * (eg: where i_mode == 0 || i_number == 0) 256 * but I will think about that later .. kre 257 * (i_number is rarely 0 - only after an i/o error in iget, 258 * where i_mode == 0, the inode will probably be wanted 259 * again soon for an ialloc, so possibly we should keep it) 260 */ 261 if (ifreeh) { 262 *ifreet = ip; 263 ip->i_freeb = ifreet; 264 } else { 265 ifreeh = ip; 266 ip->i_freeb = &ifreeh; 267 } 268 ip->i_freef = NULL; 269 ifreet = &ip->i_freef; 270 } 271 ip->i_count--; 272 } 273 274 /* 275 * Check accessed and update flags on 276 * an inode structure. 277 * If any is on, update the inode 278 * with the current time. 279 * If waitfor is given, then must insure 280 * i/o order so wait for write to complete. 281 */ 282 iupdat(ip, ta, tm, waitfor) 283 register struct inode *ip; 284 time_t *ta, *tm; 285 int waitfor; 286 { 287 register struct buf *bp; 288 struct dinode *dp; 289 register struct fs *fp; 290 291 fp = ip->i_fs; 292 if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) { 293 if (fp->fs_ronly) 294 return; 295 bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)), 296 fp->fs_bsize); 297 if (bp->b_flags & B_ERROR) { 298 brelse(bp); 299 return; 300 } 301 if (ip->i_flag&IACC) 302 ip->i_atime = *ta; 303 if (ip->i_flag&IUPD) 304 ip->i_mtime = *tm; 305 if (ip->i_flag&ICHG) 306 ip->i_ctime = time; 307 ip->i_flag &= ~(IUPD|IACC|ICHG); 308 if (waitfor) 309 bwrite(bp); 310 else 311 bdwrite(bp); 312 } 313 } 314 315 /* 316 * Free all the disk blocks associated 317 * with the specified inode structure. 318 * The blocks of the file are removed 319 * in reverse order. This FILO 320 * algorithm will tend to maintain 321 * a contiguous free list much longer 322 * than FIFO. 323 */ 324 itrunc(ip) 325 register struct inode *ip; 326 { 327 register i; 328 dev_t dev; 329 daddr_t bn; 330 struct inode itmp; 331 register struct fs *fs; 332 333 i = ip->i_mode & IFMT; 334 if (i != IFREG && i != IFDIR && i != IFLNK) 335 return; 336 /* 337 * Clean inode on disk before freeing blocks 338 * to insure no duplicates if system crashes. 339 */ 340 itmp = *ip; 341 itmp.i_size = 0; 342 for (i = 0; i < NDADDR; i++) 343 itmp.i_db[i] = 0; 344 for (i = 0; i < NIADDR; i++) 345 itmp.i_ib[i] = 0; 346 itmp.i_flag |= ICHG|IUPD; 347 iupdat(&itmp, &time, &time, 1); 348 ip->i_flag &= ~(IUPD|IACC|ICHG); 349 350 /* 351 * Now return blocks to free list... if machine 352 * crashes, they will be harmless MISSING blocks. 353 */ 354 dev = ip->i_dev; 355 fs = ip->i_fs; 356 /* 357 * release double indirect block first 358 */ 359 bn = ip->i_ib[NIADDR-1]; 360 if (bn != (daddr_t)0) { 361 ip->i_ib[NIADDR - 1] = (daddr_t)0; 362 tloop(ip, bn, 1); 363 } 364 /* 365 * release single indirect blocks second 366 */ 367 for (i = NIADDR - 2; i >= 0; i--) { 368 bn = ip->i_ib[i]; 369 if (bn != (daddr_t)0) { 370 ip->i_ib[i] = (daddr_t)0; 371 tloop(ip, bn, 0); 372 } 373 } 374 /* 375 * finally release direct blocks 376 */ 377 for (i = NDADDR - 1; i>=0; i--) { 378 bn = ip->i_db[i]; 379 if (bn == (daddr_t)0) 380 continue; 381 ip->i_db[i] = (daddr_t)0; 382 fre(ip, bn, (off_t)blksize(fs, ip, i)); 383 } 384 ip->i_size = 0; 385 /* 386 * Inode was written and flags updated above. 387 * No need to modify flags here. 388 */ 389 } 390 391 tloop(ip, bn, indflg) 392 register struct inode *ip; 393 daddr_t bn; 394 int indflg; 395 { 396 register i; 397 register struct buf *bp; 398 register daddr_t *bap; 399 register struct fs *fs; 400 daddr_t nb; 401 402 bp = NULL; 403 fs = ip->i_fs; 404 for (i = NINDIR(fs) - 1; i >= 0; i--) { 405 if (bp == NULL) { 406 bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize); 407 if (bp->b_flags & B_ERROR) { 408 brelse(bp); 409 return; 410 } 411 bap = bp->b_un.b_daddr; 412 } 413 nb = bap[i]; 414 if (nb == (daddr_t)0) 415 continue; 416 if (indflg) 417 tloop(ip, nb, 0); 418 else 419 fre(ip, nb, fs->fs_bsize); 420 } 421 if (bp != NULL) 422 brelse(bp); 423 fre(ip, bn, fs->fs_bsize); 424 } 425 426 /* 427 * Make a new file. 428 */ 429 struct inode * 430 maknode(mode) 431 int mode; 432 { 433 register struct inode *ip; 434 ino_t ipref; 435 436 if ((mode & IFMT) == IFDIR) 437 ipref = dirpref(u.u_pdir->i_fs); 438 else 439 ipref = u.u_pdir->i_number; 440 ip = ialloc(u.u_pdir, ipref, mode); 441 if (ip == NULL) { 442 iput(u.u_pdir); 443 return(NULL); 444 } 445 ip->i_flag |= IACC|IUPD|ICHG; 446 if ((mode & IFMT) == 0) 447 mode |= IFREG; 448 ip->i_mode = mode & ~u.u_cmask; 449 ip->i_nlink = 1; 450 ip->i_uid = u.u_uid; 451 ip->i_gid = u.u_pdir->i_gid; 452 453 /* 454 * Make sure inode goes to disk before directory entry. 455 */ 456 iupdat(ip, &time, &time, 1); 457 wdir(ip); 458 if (u.u_error) { 459 /* 460 * write error occurred trying to update directory 461 * so must deallocate the inode 462 */ 463 ip->i_nlink = 0; 464 ip->i_flag |= ICHG; 465 iput(ip); 466 return(NULL); 467 } 468 return(ip); 469 } 470 471 /* 472 * Write a directory entry with 473 * parameters left as side effects 474 * to a call to namei. 475 */ 476 wdir(ip) 477 struct inode *ip; 478 { 479 register struct direct *dp, *ndp; 480 struct fs *fs; 481 struct buf *bp; 482 int lbn, bn, base; 483 int loc, dsize, spccnt, newsize; 484 char *dirbuf; 485 486 u.u_dent.d_ino = ip->i_number; 487 u.u_segflg = 1; 488 newsize = DIRSIZ(&u.u_dent); 489 /* 490 * if u.u_count == 0, a new directory block must be allocated. 491 */ 492 if (u.u_count == 0) { 493 u.u_dent.d_reclen = DIRBLKSIZ; 494 u.u_count = newsize; 495 u.u_base = (caddr_t)&u.u_dent; 496 writei(u.u_pdir); 497 iput(u.u_pdir); 498 return; 499 } 500 /* 501 * must read in an existing directory block 502 * to prepare to place the new entry into it. 503 */ 504 fs = u.u_pdir->i_fs; 505 lbn = lblkno(fs, u.u_offset); 506 base = blkoff(fs, u.u_offset); 507 bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count)); 508 if (u.u_offset + u.u_count > u.u_pdir->i_size) 509 u.u_pdir->i_size = u.u_offset + u.u_count; 510 bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn)); 511 if (bp->b_flags & B_ERROR) { 512 brelse(bp); 513 return; 514 } 515 dirbuf = bp->b_un.b_addr + base; 516 dp = (struct direct *)dirbuf; 517 dsize = DIRSIZ(dp); 518 spccnt = dp->d_reclen - dsize; 519 /* 520 * if there is insufficient room to make an entry at this point 521 * namei insures that compacting from u.u_offset for u.u_count 522 * bytes will provide the necessary space. 523 */ 524 for (loc = dp->d_reclen; loc < u.u_count; ) { 525 ndp = (struct direct *)(dirbuf + loc); 526 if (dp->d_ino == 0) { 527 spccnt += dsize; 528 } else { 529 dp->d_reclen = dsize; 530 dp = (struct direct *)((char *)dp + dsize); 531 } 532 dsize = DIRSIZ(ndp); 533 spccnt += ndp->d_reclen - dsize; 534 loc += ndp->d_reclen; 535 bcopy(ndp, dp, dsize); 536 } 537 /* 538 * Update the pointer fields in the previous entry (if any), 539 * copy in the new entry, and write out the block. 540 */ 541 if (dp->d_ino == 0) { 542 if (spccnt + dsize < newsize) 543 panic("wdir: compact failed"); 544 u.u_dent.d_reclen = spccnt + dsize; 545 } else { 546 if (spccnt < newsize) 547 panic("wdir: compact failed"); 548 u.u_dent.d_reclen = spccnt; 549 dp->d_reclen = dsize; 550 dp = (struct direct *)((char *)dp + dsize); 551 } 552 bcopy(&u.u_dent, dp, newsize); 553 bwrite(bp); 554 u.u_pdir->i_flag |= IUPD|ICHG; 555 iput(u.u_pdir); 556 } 557 558 /* 559 * remove any inodes in the inode cache belonging to dev 560 * 561 * There should not be any active ones, return error if any are found 562 * (nb: this is a user error, not a system err) 563 * 564 * Also, count the references to dev by block devices - this really 565 * has nothing to do with the object of the procedure, but as we have 566 * to scan the inode table here anyway, we might as well get the 567 * extra benefit. 568 * 569 * this is called from sumount()/sys3.c when dev is being unmounted 570 */ 571 iflush(dev) 572 dev_t dev; 573 { 574 register struct inode *ip; /* known to be r11 - see 'asm' below */ 575 register open = 0; 576 577 for (ip = inode; ip < inodeNINODE; ip++) { 578 if (ip->i_dev == dev) 579 if (ip->i_count) 580 return(-1); 581 else { 582 #ifndef UNFAST 583 asm("remque (r11),r0"); 584 #else 585 ip->i_back->i_forw = ip->i_forw; 586 ip->i_forw->i_back = ip->i_back; 587 #endif 588 ip->i_forw = ip; 589 ip->i_back = ip; 590 /* 591 * as i_count == 0, the inode was on the free 592 * list already, just leave it there, it will 593 * fall off the bottom eventually. We could 594 * perhaps move it to the head of the free 595 * list, but as umounts are done so 596 * infrequently, we would gain very little, 597 * while making the code bigger. 598 */ 599 } 600 else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK && 601 ip->i_rdev == dev) 602 open++; 603 } 604 return (open); 605 } 606 607 #ifdef ilock 608 #undef ilock 609 #endif 610 #ifdef iunlock 611 #undef iunlock 612 #endif 613 /* 614 * Lock an inode. If its already locked, set the WANT bit and sleep. 615 */ 616 ilock(ip) 617 register struct inode *ip; 618 { 619 620 while (ip->i_flag&ILOCK) { 621 ip->i_flag |= IWANT; 622 sleep((caddr_t)ip, PINOD); 623 } 624 ip->i_flag |= ILOCK; 625 } 626 627 /* 628 * Unlock an inode. If WANT bit is on, wakeup. 629 */ 630 iunlock(ip) 631 register struct inode *ip; 632 { 633 634 ip->i_flag &= ~ILOCK; 635 if (ip->i_flag&IWANT) { 636 ip->i_flag &= ~IWANT; 637 wakeup((caddr_t)ip); 638 } 639 } 640