1 /* ffs_inode.c 3.4 07/08/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); 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 */ 212 iupdat(ip, ta, tm) 213 register struct inode *ip; 214 time_t *ta, *tm; 215 { 216 register struct buf *bp; 217 struct dinode *dp; 218 register char *p1, *p2; 219 register int i; 220 221 if((ip->i_flag&(IUPD|IACC|ICHG)) != 0) { 222 if(getfs(ip->i_dev)->s_ronly) 223 return; 224 bp = bread(ip->i_dev, itod(ip->i_number)); 225 if (bp->b_flags & B_ERROR) { 226 brelse(bp); 227 return; 228 } 229 dp = bp->b_un.b_dino; 230 dp += itoo(ip->i_number); 231 dp->di_mode = ip->i_mode; 232 dp->di_nlink = ip->i_nlink; 233 dp->di_uid = ip->i_uid; 234 dp->di_gid = ip->i_gid; 235 dp->di_size = ip->i_size; 236 p1 = (char *)dp->di_addr; 237 p2 = (char *)ip->i_un.i_addr; 238 for(i=0; i<NADDR; i++) { 239 *p1++ = *p2++; 240 *p1++ = *p2++; 241 *p1++ = *p2++; 242 if(*p2++ != 0 && (ip->i_mode&IFMT)!=IFMPC 243 && (ip->i_mode&IFMT)!=IFMPB) 244 printf("iaddress > 2^24\n"); 245 } 246 if(ip->i_flag&IACC) 247 dp->di_atime = *ta; 248 if(ip->i_flag&IUPD) 249 dp->di_mtime = *tm; 250 if(ip->i_flag&ICHG) 251 dp->di_ctime = time; 252 ip->i_flag &= ~(IUPD|IACC|ICHG); 253 bdwrite(bp); 254 } 255 } 256 257 /* 258 * Free all the disk blocks associated 259 * with the specified inode structure. 260 * The blocks of the file are removed 261 * in reverse order. This FILO 262 * algorithm will tend to maintain 263 * a contiguous free list much longer 264 * than FIFO. 265 */ 266 itrunc(ip) 267 register struct inode *ip; 268 { 269 register i; 270 dev_t dev; 271 daddr_t bn; 272 273 if (ip->i_vfdcnt) 274 panic("itrunc"); 275 i = ip->i_mode & IFMT; 276 if (i!=IFREG && i!=IFDIR) 277 return; 278 dev = ip->i_dev; 279 for(i=NADDR-1; i>=0; i--) { 280 bn = ip->i_un.i_addr[i]; 281 if(bn == (daddr_t)0) 282 continue; 283 ip->i_un.i_addr[i] = (daddr_t)0; 284 switch(i) { 285 286 default: 287 free(dev, bn); 288 break; 289 290 case NADDR-3: 291 tloop(dev, bn, 0, 0); 292 break; 293 294 case NADDR-2: 295 tloop(dev, bn, 1, 0); 296 break; 297 298 case NADDR-1: 299 tloop(dev, bn, 1, 1); 300 } 301 } 302 ip->i_size = 0; 303 ip->i_flag |= ICHG|IUPD; 304 } 305 306 tloop(dev, bn, f1, f2) 307 dev_t dev; 308 daddr_t bn; 309 { 310 register i; 311 register struct buf *bp; 312 register daddr_t *bap; 313 daddr_t nb; 314 315 bp = NULL; 316 for(i=NINDIR-1; i>=0; i--) { 317 if(bp == NULL) { 318 bp = bread(dev, bn); 319 if (bp->b_flags & B_ERROR) { 320 brelse(bp); 321 return; 322 } 323 bap = bp->b_un.b_daddr; 324 } 325 nb = bap[i]; 326 if(nb == (daddr_t)0) 327 continue; 328 if(f1) { 329 brelse(bp); 330 bp = NULL; 331 tloop(dev, nb, f2, 0); 332 } else 333 free(dev, nb); 334 } 335 if(bp != NULL) 336 brelse(bp); 337 free(dev, bn); 338 } 339 340 /* 341 * Make a new file. 342 */ 343 struct inode * 344 maknode(mode) 345 { 346 register struct inode *ip; 347 348 ip = ialloc(u.u_pdir->i_dev); 349 if(ip == NULL) { 350 iput(u.u_pdir); 351 return(NULL); 352 } 353 ip->i_flag |= IACC|IUPD|ICHG; 354 if((mode&IFMT) == 0) 355 mode |= IFREG; 356 ip->i_mode = mode & ~u.u_cmask; 357 ip->i_nlink = 1; 358 ip->i_uid = u.u_uid; 359 ip->i_gid = u.u_gid; 360 wdir(ip); 361 return(ip); 362 } 363 364 /* 365 * Write a directory entry with 366 * parameters left as side effects 367 * to a call to namei. 368 */ 369 wdir(ip) 370 struct inode *ip; 371 { 372 373 u.u_dent.d_ino = ip->i_number; 374 bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ); 375 u.u_count = sizeof(struct direct); 376 u.u_segflg = 1; 377 u.u_base = (caddr_t)&u.u_dent; 378 writei(u.u_pdir); 379 iput(u.u_pdir); 380 } 381