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