1 /* lfs_inode.c 4.9 82/02/27 */ 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/ino.h" 10 #include "../h/filsys.h" 11 #include "../h/conf.h" 12 #include "../h/buf.h" 13 #include "../h/inline.h" 14 15 #define INOHSZ 63 16 #define INOHASH(dev,ino) (((dev)+(ino))%INOHSZ) 17 short inohash[INOHSZ]; 18 short ifreel; 19 20 /* 21 * Initialize hash links for inodes 22 * and build inode free list. 23 */ 24 ihinit() 25 { 26 register int i; 27 register struct inode *ip = inode; 28 29 ifreel = 0; 30 for (i = 0; i < ninode-1; i++, ip++) 31 ip->i_hlink = i+1; 32 ip->i_hlink = -1; 33 for (i = 0; i < INOHSZ; i++) 34 inohash[i] = -1; 35 } 36 37 /* 38 * Find an inode if it is incore. 39 * This is the equivalent, for inodes, 40 * of ``incore'' in bio.c or ``pfind'' in subr.c. 41 */ 42 struct inode * 43 ifind(dev, ino) 44 dev_t dev; 45 ino_t ino; 46 { 47 register struct inode *ip; 48 49 for (ip = &inode[inohash[INOHASH(dev,ino)]]; ip != &inode[-1]; 50 ip = &inode[ip->i_hlink]) 51 if (ino==ip->i_number && dev==ip->i_dev) 52 return (ip); 53 return ((struct inode *)0); 54 } 55 56 /* 57 * Look up an inode by device,inumber. 58 * If it is in core (in the inode structure), 59 * honor the locking protocol. 60 * If it is not in core, read it in from the 61 * specified device. 62 * If the inode is mounted on, perform 63 * the indicated indirection. 64 * In all cases, a pointer to a locked 65 * inode structure is returned. 66 * 67 * panic: no imt -- if the mounted file 68 * system is not in the mount table. 69 * "cannot happen" 70 */ 71 struct inode * 72 iget(dev, ino) 73 dev_t dev; 74 ino_t ino; 75 { 76 register struct inode *ip; 77 register struct mount *mp; 78 register struct buf *bp; 79 register struct dinode *dp; 80 register int slot; 81 82 loop: 83 slot = INOHASH(dev, ino); 84 ip = &inode[inohash[slot]]; 85 while (ip != &inode[-1]) { 86 if (ino == ip->i_number && dev == ip->i_dev) { 87 if ((ip->i_flag&ILOCK) != 0) { 88 ip->i_flag |= IWANT; 89 sleep((caddr_t)ip, PINOD); 90 goto loop; 91 } 92 if ((ip->i_flag&IMOUNT) != 0) { 93 for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 94 if (mp->m_inodp == ip) { 95 dev = mp->m_dev; 96 ino = ROOTINO; 97 goto loop; 98 } 99 panic("no imt"); 100 } 101 ip->i_count++; 102 ip->i_flag |= ILOCK; 103 return(ip); 104 } 105 ip = &inode[ip->i_hlink]; 106 } 107 if (ifreel < 0) { 108 tablefull("inode"); 109 u.u_error = ENFILE; 110 return(NULL); 111 } 112 ip = &inode[ifreel]; 113 ifreel = ip->i_hlink; 114 ip->i_hlink = inohash[slot]; 115 inohash[slot] = ip - inode; 116 ip->i_dev = dev; 117 ip->i_number = ino; 118 ip->i_flag = ILOCK; 119 ip->i_count++; 120 ip->i_un.i_lastr = 0; 121 bp = bread(dev, itod(ino)); 122 /* 123 * Check I/O errors 124 */ 125 if ((bp->b_flags&B_ERROR) != 0) { 126 brelse(bp); 127 iput(ip); 128 return(NULL); 129 } 130 dp = bp->b_un.b_dino; 131 dp += itoo(ino); 132 iexpand(ip, dp); 133 brelse(bp); 134 return(ip); 135 } 136 137 iexpand(ip, dp) 138 register struct inode *ip; 139 register struct dinode *dp; 140 { 141 register char *p1, *p2; 142 register int i; 143 144 ip->i_mode = dp->di_mode; 145 ip->i_nlink = dp->di_nlink; 146 ip->i_uid = dp->di_uid; 147 ip->i_gid = dp->di_gid; 148 ip->i_size = dp->di_size; 149 p1 = (char *)ip->i_un.i_addr; 150 p2 = (char *)dp->di_addr; 151 for(i=0; i<NADDR; i++) { 152 *p1++ = *p2++; 153 *p1++ = *p2++; 154 *p1++ = *p2++; 155 *p1++ = 0; 156 } 157 } 158 159 /* 160 * Decrement reference count of 161 * an inode structure. 162 * On the last reference, 163 * write the inode out and if necessary, 164 * truncate and deallocate the file. 165 */ 166 iput(ip) 167 register struct inode *ip; 168 { 169 register int i, x; 170 register struct inode *jp; 171 172 if (ip->i_count == 1) { 173 ip->i_flag |= ILOCK; 174 if (ip->i_nlink <= 0) { 175 itrunc(ip); 176 ip->i_mode = 0; 177 ip->i_flag |= IUPD|ICHG; 178 ifree(ip->i_dev, ip->i_number); 179 } 180 IUPDAT(ip, &time, &time, 0); 181 irele(ip); 182 i = INOHASH(ip->i_dev, ip->i_number); 183 x = ip - inode; 184 if (inohash[i] == x) { 185 inohash[i] = ip->i_hlink; 186 } else { 187 for (jp = &inode[inohash[i]]; jp != &inode[-1]; 188 jp = &inode[jp->i_hlink]) 189 if (jp->i_hlink == x) { 190 jp->i_hlink = ip->i_hlink; 191 goto done; 192 } 193 panic("iput"); 194 } 195 done: 196 ip->i_hlink = ifreel; 197 ifreel = x; 198 ip->i_flag = 0; 199 ip->i_number = 0; 200 } else 201 irele(ip); 202 ip->i_count--; 203 } 204 205 /* 206 * Check accessed and update flags on 207 * an inode structure. 208 * If any is on, update the inode 209 * with the current time. 210 * If waitfor is given, then must insure 211 * i/o order so wait for write to complete. 212 */ 213 iupdat(ip, ta, tm, waitfor) 214 register struct inode *ip; 215 time_t *ta, *tm; 216 int waitfor; 217 { 218 register struct buf *bp; 219 struct dinode *dp; 220 register char *p1, *p2; 221 register int i; 222 223 if ((ip->i_flag&(IUPD|IACC|ICHG)) != 0) { 224 if (getfs(ip->i_dev)->s_ronly) 225 return; 226 bp = bread(ip->i_dev, itod(ip->i_number)); 227 if (bp->b_flags & B_ERROR) { 228 brelse(bp); 229 return; 230 } 231 dp = bp->b_un.b_dino; 232 dp += itoo(ip->i_number); 233 dp->di_mode = ip->i_mode; 234 dp->di_nlink = ip->i_nlink; 235 dp->di_uid = ip->i_uid; 236 dp->di_gid = ip->i_gid; 237 dp->di_size = ip->i_size; 238 p1 = (char *)dp->di_addr; 239 p2 = (char *)ip->i_un.i_addr; 240 for(i=0; i<NADDR; i++) { 241 *p1++ = *p2++; 242 *p1++ = *p2++; 243 *p1++ = *p2++; 244 if (*p2++ != 0) 245 printf("iaddress > 2^24\n"); 246 } 247 if (ip->i_flag&IACC) 248 dp->di_atime = *ta; 249 if (ip->i_flag&IUPD) 250 dp->di_mtime = *tm; 251 if (ip->i_flag&ICHG) 252 dp->di_ctime = time; 253 ip->i_flag &= ~(IUPD|IACC|ICHG); 254 if (waitfor) 255 bwrite(bp); 256 else 257 bdwrite(bp); 258 } 259 } 260 261 /* 262 * Free all the disk blocks associated 263 * with the specified inode structure. 264 * The blocks of the file are removed 265 * in reverse order. This FILO 266 * algorithm will tend to maintain 267 * a contiguous free list much longer 268 * than FIFO. 269 */ 270 itrunc(ip) 271 register struct inode *ip; 272 { 273 register i; 274 dev_t dev; 275 daddr_t bn; 276 struct inode itmp; 277 278 i = ip->i_mode & IFMT; 279 if (i!=IFREG && i!=IFDIR && i!=IFLNK) 280 return; 281 282 /* 283 * Clean inode on disk before freeing blocks 284 * to insure no duplicates if system crashes. 285 */ 286 itmp = *ip; 287 itmp.i_size = 0; 288 for (i = 0; i < NADDR; i++) 289 itmp.i_un.i_addr[i] = 0; 290 itmp.i_flag |= ICHG|IUPD; 291 iupdat(&itmp, &time, &time, 1); 292 ip->i_flag &= ~(IUPD|IACC|ICHG); 293 294 /* 295 * Now return blocks to free list... if machine 296 * crashes, they will be harmless MISSING blocks. 297 */ 298 dev = ip->i_dev; 299 for(i=NADDR-1; i>=0; i--) { 300 bn = ip->i_un.i_addr[i]; 301 if (bn == (daddr_t)0) 302 continue; 303 ip->i_un.i_addr[i] = (daddr_t)0; 304 switch(i) { 305 306 default: 307 free(dev, bn); 308 break; 309 310 case NADDR-3: 311 tloop(dev, bn, 0, 0); 312 break; 313 314 case NADDR-2: 315 tloop(dev, bn, 1, 0); 316 break; 317 318 case NADDR-1: 319 tloop(dev, bn, 1, 1); 320 } 321 } 322 ip->i_size = 0; 323 /* 324 * Inode was written and flags updated above. 325 * No need to modify flags here. 326 */ 327 } 328 329 tloop(dev, bn, f1, f2) 330 dev_t dev; 331 daddr_t bn; 332 { 333 register i; 334 register struct buf *bp; 335 register daddr_t *bap; 336 daddr_t nb; 337 338 bp = NULL; 339 for(i=NINDIR-1; i>=0; i--) { 340 if (bp == NULL) { 341 bp = bread(dev, bn); 342 if (bp->b_flags & B_ERROR) { 343 brelse(bp); 344 return; 345 } 346 bap = bp->b_un.b_daddr; 347 } 348 nb = bap[i]; 349 if (nb == (daddr_t)0) 350 continue; 351 if (f1) { 352 brelse(bp); 353 bp = NULL; 354 tloop(dev, nb, f2, 0); 355 } else 356 free(dev, nb); 357 } 358 if (bp != NULL) 359 brelse(bp); 360 free(dev, bn); 361 } 362 363 /* 364 * Make a new file. 365 */ 366 struct inode * 367 maknode(mode) 368 { 369 register struct inode *ip; 370 371 ip = ialloc(u.u_pdir->i_dev); 372 if (ip == NULL) { 373 iput(u.u_pdir); 374 return(NULL); 375 } 376 ip->i_flag |= IACC|IUPD|ICHG; 377 if ((mode&IFMT) == 0) 378 mode |= IFREG; 379 ip->i_mode = mode & ~u.u_cmask; 380 ip->i_nlink = 1; 381 ip->i_uid = u.u_uid; 382 ip->i_gid = u.u_pdir->i_gid; 383 384 /* 385 * Make sure inode goes to disk before directory entry. 386 */ 387 iupdat(ip, &time, &time, 1); 388 389 wdir(ip); 390 return(ip); 391 } 392 393 /* 394 * Write a directory entry with 395 * parameters left as side effects 396 * to a call to namei. 397 */ 398 wdir(ip) 399 struct inode *ip; 400 { 401 402 u.u_dent.d_ino = ip->i_number; 403 bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ); 404 u.u_count = sizeof(struct direct); 405 u.u_segflg = 1; 406 u.u_base = (caddr_t)&u.u_dent; 407 writei(u.u_pdir); 408 iput(u.u_pdir); 409 } 410 411 #ifdef ilock 412 #undef ilock 413 #endif 414 #ifdef irele 415 #undef irele 416 #endif 417 /* 418 * Lock an inode. If its already locked, set the WANT bit and sleep. 419 */ 420 ilock(ip) 421 register struct inode *ip; 422 { 423 424 while (ip->i_flag&ILOCK) { 425 ip->i_flag |= IWANT; 426 sleep((caddr_t)ip, PINOD); 427 } 428 ip->i_flag |= ILOCK; 429 } 430 431 /* 432 * Unlock an inode. If WANT bit is on, wakeup. 433 */ 434 irele(ip) 435 register struct inode *ip; 436 { 437 438 ip->i_flag &= ~ILOCK; 439 if (ip->i_flag&IWANT) { 440 ip->i_flag &= ~IWANT; 441 wakeup((caddr_t)ip); 442 } 443 } 444