1 /* ufs_inode.c 4.5 81/04/28 */ 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 prele(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 prele(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 && (ip->i_mode&IFMT)!=IFMPC 245 && (ip->i_mode&IFMT)!=IFMPB) 246 printf("iaddress > 2^24\n"); 247 } 248 if(ip->i_flag&IACC) 249 dp->di_atime = *ta; 250 if(ip->i_flag&IUPD) 251 dp->di_mtime = *tm; 252 if(ip->i_flag&ICHG) 253 dp->di_ctime = time; 254 ip->i_flag &= ~(IUPD|IACC|ICHG); 255 if (waitfor) 256 bwrite(bp); 257 else 258 bdwrite(bp); 259 } 260 } 261 262 /* 263 * Free all the disk blocks associated 264 * with the specified inode structure. 265 * The blocks of the file are removed 266 * in reverse order. This FILO 267 * algorithm will tend to maintain 268 * a contiguous free list much longer 269 * than FIFO. 270 */ 271 itrunc(ip) 272 register struct inode *ip; 273 { 274 register i; 275 dev_t dev; 276 daddr_t bn; 277 struct inode itmp; 278 279 if (ip->i_vfdcnt) 280 panic("itrunc"); 281 i = ip->i_mode & IFMT; 282 if (i!=IFREG && i!=IFDIR) 283 return; 284 285 /* 286 * Clean inode on disk before freeing blocks 287 * to insure no duplicates if system crashes. 288 */ 289 itmp = *ip; 290 itmp.i_size = 0; 291 for (i = 0; i < NADDR; i++) 292 itmp.i_un.i_addr[i] = 0; 293 itmp.i_flag |= ICHG|IUPD; 294 iupdat(&itmp, &time, &time, 1); 295 ip->i_flag &= ~(IUPD|IACC|ICHG); 296 297 /* 298 * Now return blocks to free list... if machine 299 * crashes, they will be harmless MISSING blocks. 300 */ 301 dev = ip->i_dev; 302 for(i=NADDR-1; i>=0; i--) { 303 bn = ip->i_un.i_addr[i]; 304 if(bn == (daddr_t)0) 305 continue; 306 ip->i_un.i_addr[i] = (daddr_t)0; 307 switch(i) { 308 309 default: 310 free(dev, bn); 311 break; 312 313 case NADDR-3: 314 tloop(dev, bn, 0, 0); 315 break; 316 317 case NADDR-2: 318 tloop(dev, bn, 1, 0); 319 break; 320 321 case NADDR-1: 322 tloop(dev, bn, 1, 1); 323 } 324 } 325 ip->i_size = 0; 326 /* 327 * Inode was written and flags updated above. 328 * No need to modify flags here. 329 */ 330 } 331 332 tloop(dev, bn, f1, f2) 333 dev_t dev; 334 daddr_t bn; 335 { 336 register i; 337 register struct buf *bp; 338 register daddr_t *bap; 339 daddr_t nb; 340 341 bp = NULL; 342 for(i=NINDIR-1; i>=0; i--) { 343 if(bp == NULL) { 344 bp = bread(dev, bn); 345 if (bp->b_flags & B_ERROR) { 346 brelse(bp); 347 return; 348 } 349 bap = bp->b_un.b_daddr; 350 } 351 nb = bap[i]; 352 if(nb == (daddr_t)0) 353 continue; 354 if(f1) { 355 brelse(bp); 356 bp = NULL; 357 tloop(dev, nb, f2, 0); 358 } else 359 free(dev, nb); 360 } 361 if(bp != NULL) 362 brelse(bp); 363 free(dev, bn); 364 } 365 366 /* 367 * Make a new file. 368 */ 369 struct inode * 370 maknode(mode) 371 { 372 register struct inode *ip; 373 374 ip = ialloc(u.u_pdir->i_dev); 375 if(ip == NULL) { 376 iput(u.u_pdir); 377 return(NULL); 378 } 379 ip->i_flag |= IACC|IUPD|ICHG; 380 if((mode&IFMT) == 0) 381 mode |= IFREG; 382 ip->i_mode = mode & ~u.u_cmask; 383 ip->i_nlink = 1; 384 ip->i_uid = u.u_uid; 385 ip->i_gid = u.u_gid; 386 387 /* 388 * Make sure inode goes to disk before directory entry. 389 */ 390 iupdat(ip, &time, &time, 1); 391 392 wdir(ip); 393 return(ip); 394 } 395 396 /* 397 * Write a directory entry with 398 * parameters left as side effects 399 * to a call to namei. 400 */ 401 wdir(ip) 402 struct inode *ip; 403 { 404 405 u.u_dent.d_ino = ip->i_number; 406 bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ); 407 u.u_count = sizeof(struct direct); 408 u.u_segflg = 1; 409 u.u_base = (caddr_t)&u.u_dent; 410 writei(u.u_pdir); 411 iput(u.u_pdir); 412 } 413 414 #ifdef plock 415 #undef plock 416 #endif 417 #ifdef prele 418 #undef prele 419 #endif 420 /* 421 * Lock an inode (should be called ilock). 422 * If its already locked, 423 * set the WANT bit and sleep. 424 */ 425 plock(ip) 426 register struct inode *ip; 427 { 428 429 while(ip->i_flag&ILOCK) { 430 ip->i_flag |= IWANT; 431 sleep((caddr_t)ip, PINOD); 432 } 433 ip->i_flag |= ILOCK; 434 } 435 436 /* 437 * Unlock an inode. 438 * If WANT bit is on, 439 * wakeup. 440 */ 441 prele(ip) 442 register struct inode *ip; 443 { 444 445 ip->i_flag &= ~ILOCK; 446 if(ip->i_flag&IWANT) { 447 ip->i_flag &= ~IWANT; 448 wakeup((caddr_t)ip); 449 } 450 } 451