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