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