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