1 /* lfs_inode.c 4.12 82/06/10 */ 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 #define INOHASH(dev,ino) (((dev)+(ino))%INOHSZ) 16 short inohash[INOHSZ]; 17 short ifreel; 18 19 /* 20 * Initialize hash links for inodes 21 * and build inode free list. 22 */ 23 ihinit() 24 { 25 register int i; 26 register struct inode *ip = inode; 27 28 ifreel = 0; 29 for (i = 0; i < ninode-1; i++, ip++) 30 ip->i_hlink = i+1; 31 ip->i_hlink = -1; 32 for (i = 0; i < INOHSZ; i++) 33 inohash[i] = -1; 34 } 35 36 /* 37 * Look up an inode by device,inumber. 38 * If it is in core (in the inode structure), 39 * honor the locking protocol. 40 * If it is not in core, read it in from the 41 * specified device. 42 * If the inode is mounted on, perform 43 * the indicated indirection. 44 * In all cases, a pointer to a locked 45 * inode structure is returned. 46 * 47 * panic: no imt -- if the mounted file 48 * system is not in the mount table. 49 * "cannot happen" 50 */ 51 struct inode * 52 iget(dev, fs, ino) 53 dev_t dev; 54 register struct fs *fs; 55 ino_t ino; 56 { 57 register struct inode *ip; 58 register struct mount *mp; 59 register struct buf *bp; 60 register struct dinode *dp; 61 register int slot; 62 63 loop: 64 if (getfs(dev) != fs) 65 panic("iget: bad fs"); 66 slot = INOHASH(dev, ino); 67 ip = &inode[inohash[slot]]; 68 while (ip != &inode[-1]) { 69 if (ino == ip->i_number && dev == ip->i_dev) { 70 if ((ip->i_flag&ILOCK) != 0) { 71 ip->i_flag |= IWANT; 72 sleep((caddr_t)ip, PINOD); 73 goto loop; 74 } 75 if ((ip->i_flag&IMOUNT) != 0) { 76 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 77 if (mp->m_inodp == ip) { 78 dev = mp->m_dev; 79 fs = mp->m_bufp->b_un.b_fs; 80 ino = ROOTINO; 81 goto loop; 82 } 83 panic("no imt"); 84 } 85 ip->i_count++; 86 ip->i_flag |= ILOCK; 87 return(ip); 88 } 89 ip = &inode[ip->i_hlink]; 90 } 91 if (ifreel < 0) { 92 tablefull("inode"); 93 u.u_error = ENFILE; 94 return(NULL); 95 } 96 ip = &inode[ifreel]; 97 ifreel = ip->i_hlink; 98 ip->i_hlink = inohash[slot]; 99 inohash[slot] = ip - inode; 100 ip->i_dev = dev; 101 ip->i_fs = fs; 102 ip->i_number = ino; 103 ip->i_flag = ILOCK; 104 ip->i_count++; 105 ip->i_lastr = 0; 106 bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize); 107 /* 108 * Check I/O errors 109 */ 110 if ((bp->b_flags&B_ERROR) != 0) { 111 brelse(bp); 112 iput(ip); 113 return(NULL); 114 } 115 dp = bp->b_un.b_dino; 116 dp += itoo(fs, ino); 117 ip->i_ic = dp->di_ic; 118 brelse(bp); 119 return (ip); 120 } 121 122 /* 123 * Decrement reference count of 124 * an inode structure. 125 * On the last reference, 126 * write the inode out and if necessary, 127 * truncate and deallocate the file. 128 */ 129 iput(ip) 130 register struct inode *ip; 131 { 132 133 if ((ip->i_flag & ILOCK) == 0) 134 panic("iput"); 135 iunlock(ip); 136 irele(ip); 137 } 138 139 irele(ip) 140 register struct inode *ip; 141 { 142 register int i, x; 143 register struct inode *jp; 144 int mode; 145 146 if (ip->i_count == 1) { 147 ip->i_flag |= ILOCK; 148 if (ip->i_nlink <= 0) { 149 itrunc(ip); 150 mode = ip->i_mode; 151 ip->i_mode = 0; 152 ip->i_flag |= IUPD|ICHG; 153 ifree(ip, ip->i_number, mode); 154 } 155 IUPDAT(ip, &time, &time, 0); 156 iunlock(ip); 157 i = INOHASH(ip->i_dev, ip->i_number); 158 x = ip - inode; 159 if (inohash[i] == x) { 160 inohash[i] = ip->i_hlink; 161 } else { 162 for (jp = &inode[inohash[i]]; jp != &inode[-1]; 163 jp = &inode[jp->i_hlink]) 164 if (jp->i_hlink == x) { 165 jp->i_hlink = ip->i_hlink; 166 goto done; 167 } 168 panic("iput"); 169 } 170 done: 171 ip->i_hlink = ifreel; 172 ifreel = x; 173 ip->i_flag = 0; 174 ip->i_number = 0; 175 } 176 ip->i_count--; 177 } 178 179 /* 180 * Check accessed and update flags on 181 * an inode structure. 182 * If any is on, update the inode 183 * with the current time. 184 * If waitfor is given, then must insure 185 * i/o order so wait for write to complete. 186 */ 187 iupdat(ip, ta, tm, waitfor) 188 register struct inode *ip; 189 time_t *ta, *tm; 190 int waitfor; 191 { 192 register struct buf *bp; 193 struct dinode *dp; 194 register struct fs *fp; 195 196 fp = ip->i_fs; 197 if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) { 198 if (fp->fs_ronly) 199 return; 200 bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)), 201 fp->fs_bsize); 202 if (bp->b_flags & B_ERROR) { 203 brelse(bp); 204 return; 205 } 206 if (ip->i_flag&IACC) 207 ip->i_atime = *ta; 208 if (ip->i_flag&IUPD) 209 ip->i_mtime = *tm; 210 if (ip->i_flag&ICHG) 211 ip->i_ctime = time; 212 ip->i_flag &= ~(IUPD|IACC|ICHG); 213 dp = bp->b_un.b_dino + itoo(fp, ip->i_number); 214 dp->di_ic = ip->i_ic; 215 if (waitfor) 216 bwrite(bp); 217 else 218 bdwrite(bp); 219 } 220 } 221 222 /* 223 * Free all the disk blocks associated 224 * with the specified inode structure. 225 * The blocks of the file are removed 226 * in reverse order. This FILO 227 * algorithm will tend to maintain 228 * a contiguous free list much longer 229 * than FIFO. 230 */ 231 itrunc(ip) 232 register struct inode *ip; 233 { 234 register i; 235 dev_t dev; 236 daddr_t bn; 237 struct inode itmp; 238 register struct fs *fs; 239 240 i = ip->i_mode & IFMT; 241 if (i != IFREG && i != IFDIR && i != IFLNK) 242 return; 243 /* 244 * Clean inode on disk before freeing blocks 245 * to insure no duplicates if system crashes. 246 */ 247 itmp = *ip; 248 itmp.i_size = 0; 249 for (i = 0; i < NDADDR; i++) 250 itmp.i_db[i] = 0; 251 for (i = 0; i < NIADDR; i++) 252 itmp.i_ib[i] = 0; 253 itmp.i_flag |= ICHG|IUPD; 254 iupdat(&itmp, &time, &time, 1); 255 ip->i_flag &= ~(IUPD|IACC|ICHG); 256 257 /* 258 * Now return blocks to free list... if machine 259 * crashes, they will be harmless MISSING blocks. 260 */ 261 dev = ip->i_dev; 262 fs = ip->i_fs; 263 /* 264 * release double indirect block first 265 */ 266 bn = ip->i_ib[NIADDR-1]; 267 if (bn != (daddr_t)0) { 268 ip->i_ib[NIADDR - 1] = (daddr_t)0; 269 tloop(ip, bn, 1); 270 } 271 /* 272 * release single indirect blocks second 273 */ 274 for (i = NIADDR - 2; i >= 0; i--) { 275 bn = ip->i_ib[i]; 276 if (bn != (daddr_t)0) { 277 ip->i_ib[i] = (daddr_t)0; 278 tloop(ip, bn, 0); 279 } 280 } 281 /* 282 * finally release direct blocks 283 */ 284 for (i = NDADDR - 1; i>=0; i--) { 285 bn = ip->i_db[i]; 286 if (bn == (daddr_t)0) 287 continue; 288 ip->i_db[i] = (daddr_t)0; 289 fre(ip, bn, (off_t)blksize(fs, ip, i)); 290 } 291 ip->i_size = 0; 292 /* 293 * Inode was written and flags updated above. 294 * No need to modify flags here. 295 */ 296 } 297 298 tloop(ip, bn, indflg) 299 register struct inode *ip; 300 daddr_t bn; 301 int indflg; 302 { 303 register i; 304 register struct buf *bp; 305 register daddr_t *bap; 306 register struct fs *fs; 307 daddr_t nb; 308 309 bp = NULL; 310 fs = ip->i_fs; 311 for (i = NINDIR(fs) - 1; i >= 0; i--) { 312 if (bp == NULL) { 313 bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize); 314 if (bp->b_flags & B_ERROR) { 315 brelse(bp); 316 return; 317 } 318 bap = bp->b_un.b_daddr; 319 } 320 nb = bap[i]; 321 if (nb == (daddr_t)0) 322 continue; 323 if (indflg) 324 tloop(ip, nb, 0); 325 else 326 fre(ip, nb, fs->fs_bsize); 327 } 328 if (bp != NULL) 329 brelse(bp); 330 fre(ip, bn, fs->fs_bsize); 331 } 332 333 /* 334 * Make a new file. 335 */ 336 struct inode * 337 maknode(mode) 338 int mode; 339 { 340 register struct inode *ip; 341 ino_t ipref; 342 343 if ((mode & IFMT) == IFDIR) 344 ipref = dirpref(u.u_pdir->i_fs); 345 else 346 ipref = u.u_pdir->i_number; 347 ip = ialloc(u.u_pdir, ipref, mode); 348 if (ip == NULL) { 349 iput(u.u_pdir); 350 return(NULL); 351 } 352 ip->i_flag |= IACC|IUPD|ICHG; 353 if ((mode & IFMT) == 0) 354 mode |= IFREG; 355 ip->i_mode = mode & ~u.u_cmask; 356 ip->i_nlink = 1; 357 ip->i_uid = u.u_uid; 358 ip->i_gid = u.u_pdir->i_gid; 359 360 /* 361 * Make sure inode goes to disk before directory entry. 362 */ 363 iupdat(ip, &time, &time, 1); 364 wdir(ip); 365 if (u.u_error) { 366 /* 367 * write error occurred trying to update directory 368 * so must deallocate the inode 369 */ 370 ip->i_nlink = 0; 371 ip->i_flag |= ICHG; 372 iput(ip); 373 return(NULL); 374 } 375 return(ip); 376 } 377 378 /* 379 * Write a directory entry with 380 * parameters left as side effects 381 * to a call to namei. 382 */ 383 wdir(ip) 384 struct inode *ip; 385 { 386 register struct direct *dp, *ndp; 387 struct fs *fs; 388 struct buf *bp; 389 int lbn, bn, base; 390 int loc, dsize, spccnt, newsize; 391 char *dirbuf; 392 393 u.u_dent.d_ino = ip->i_number; 394 u.u_segflg = 1; 395 newsize = DIRSIZ(&u.u_dent); 396 /* 397 * if u.u_count == 0, a new directory block must be allocated. 398 */ 399 if (u.u_count == 0) { 400 u.u_dent.d_reclen = DIRBLKSIZ; 401 u.u_count = newsize; 402 u.u_base = (caddr_t)&u.u_dent; 403 writei(u.u_pdir); 404 iput(u.u_pdir); 405 return; 406 } 407 /* 408 * must read in an existing directory block 409 * to prepare to place the new entry into it. 410 */ 411 fs = u.u_pdir->i_fs; 412 lbn = lblkno(fs, u.u_offset); 413 base = blkoff(fs, u.u_offset); 414 bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count)); 415 if (u.u_offset + u.u_count > u.u_pdir->i_size) 416 u.u_pdir->i_size = u.u_offset + u.u_count; 417 bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn)); 418 if (bp->b_flags & B_ERROR) { 419 brelse(bp); 420 return; 421 } 422 dirbuf = bp->b_un.b_addr + base; 423 dp = (struct direct *)dirbuf; 424 dsize = DIRSIZ(dp); 425 spccnt = dp->d_reclen - dsize; 426 /* 427 * if there is insufficient room to make an entry at this point 428 * namei insures that compacting from u.u_offset for u.u_count 429 * bytes will provide the necessary space. 430 */ 431 for (loc = dp->d_reclen; loc < u.u_count; ) { 432 ndp = (struct direct *)(dirbuf + loc); 433 if (dp->d_ino == 0) { 434 spccnt += dsize; 435 } else { 436 dp->d_reclen = dsize; 437 dp = (struct direct *)((char *)dp + dsize); 438 } 439 dsize = DIRSIZ(ndp); 440 spccnt += ndp->d_reclen - dsize; 441 loc += ndp->d_reclen; 442 bcopy(ndp, dp, dsize); 443 } 444 /* 445 * Update the pointer fields in the previous entry (if any), 446 * copy in the new entry, and write out the block. 447 */ 448 if (dp->d_ino == 0) { 449 if (spccnt + dsize < newsize) 450 panic("wdir: compact failed"); 451 u.u_dent.d_reclen = spccnt + dsize; 452 } else { 453 if (spccnt < newsize) 454 panic("wdir: compact failed"); 455 u.u_dent.d_reclen = spccnt; 456 dp->d_reclen = dsize; 457 dp = (struct direct *)((char *)dp + dsize); 458 } 459 bcopy(&u.u_dent, dp, newsize); 460 bwrite(bp); 461 u.u_pdir->i_flag |= IUPD|ICHG; 462 iput(u.u_pdir); 463 } 464 465 #ifdef ilock 466 #undef ilock 467 #endif 468 #ifdef iunlock 469 #undef iunlock 470 #endif 471 /* 472 * Lock an inode. If its already locked, set the WANT bit and sleep. 473 */ 474 ilock(ip) 475 register struct inode *ip; 476 { 477 478 while (ip->i_flag&ILOCK) { 479 ip->i_flag |= IWANT; 480 sleep((caddr_t)ip, PINOD); 481 } 482 ip->i_flag |= ILOCK; 483 } 484 485 /* 486 * Unlock an inode. If WANT bit is on, wakeup. 487 */ 488 iunlock(ip) 489 register struct inode *ip; 490 { 491 492 ip->i_flag &= ~ILOCK; 493 if (ip->i_flag&IWANT) { 494 ip->i_flag &= ~IWANT; 495 wakeup((caddr_t)ip); 496 } 497 } 498