7250 # 7251 #include "../param.h" 7252 #include "../systm.h" 7253 #include "../user.h" 7254 #include "../inode.h" 7255 #include "../filsys.h" 7256 #include "../conf.h" 7257 #include "../buf.h" 7258 7259 /* 7260 * Look up an inode by device,inumber. 7261 * If it is in core (in the inode structure), 7262 * honor the locking protocol. 7263 * If it is not in core, read it in from the 7264 * specified device. 7265 * If the inode is mounted on, perform 7266 * the indicated indirection. 7267 * In all cases, a pointer to a locked 7268 * inode structure is returned. 7269 * 7270 * printf warning: no inodes -- if the inode 7271 * structure is full 7272 * panic: no imt -- if the mounted file 7273 * system is not in the mount table. 7274 * "cannot happen" 7275 */ 7276 iget(dev, ino) 7277 { 7278 register struct inode *p; 7279 register *ip2; 7280 int *ip1; 7281 register struct mount *ip; 7282 7283 loop: 7284 ip = NULL; 7285 for(p = &inode[0]; p < &inode[NINODE]; p++) { 7286 if(dev==p->i_dev && ino==p->i_number) { 7287 if((p->i_flag&ILOCK) != 0) { 7288 p->i_flag =| IWANT; 7289 sleep(p, PINOD); 7290 goto loop; 7291 } 7292 if((p->i_flag&IMOUNT) != 0) { 7293 for(ip = &mount[0]; 7294 ip < &mount[NMOUNT]; ip++) 7295 if(ip->m_inodp == p) { 7296 dev = ip->m_dev; 7297 ino = ROOTINO; 7298 goto loop; 7299 } 7300 panic("no imt"); 7301 } 7302 p->i_count++; 7303 p->i_flag =| ILOCK; 7304 return(p); 7305 } 7306 if(ip==NULL && p->i_count==0) 7307 ip = p; 7308 } 7309 if((p=ip) == NULL) { 7310 printf("Inode table overflow\n"); 7311 u.u_error = ENFILE; 7312 return(NULL); 7313 } 7314 p->i_dev = dev; 7315 p->i_number = ino; 7316 p->i_flag = ILOCK; 7317 p->i_count++; 7318 p->i_lastr = -1; 7319 ip = bread(dev, ldiv(ino+31,16)); 7320 /* 7321 * Check I/O errors 7322 */ 7323 if (ip->b_flags&B_ERROR) { 7324 brelse(ip); 7325 iput(p); 7326 return(NULL); 7327 } 7328 ip1 = ip->b_addr + 32*lrem(ino+31, 16); 7329 ip2 = &p->i_mode; 7330 while(ip2 < &p->i_addr[8]) 7331 *ip2++ = *ip1++; 7332 brelse(ip); 7333 return(p); 7334 } 7335 /* ------------------------ */ 7336 7337 /* 7338 * Decrement reference count of 7339 * an inode structure. 7340 * On the last reference, 7341 * write the inode out and if necessary, 7342 * truncate and deallocate the file. 7343 */ 7344 iput(p) 7345 struct inode *p; 7346 { 7347 register *rp; 7348 7349 rp = p; 7350 if(rp->i_count == 1) { 7351 rp->i_flag =| ILOCK; 7352 if(rp->i_nlink <= 0) { 7353 itrunc(rp); 7354 rp->i_mode = 0; 7355 ifree(rp->i_dev, rp->i_number); 7356 } 7357 iupdat(rp, time); 7358 prele(rp); 7359 rp->i_flag = 0; 7360 rp->i_number = 0; 7361 } 7362 rp->i_count--; 7363 prele(rp); 7364 } 7365 /* ------------------------ */ 7366 7367 /* 7368 * Check accessed and update flags on 7369 * an inode structure. 7370 * If either is on, update the inode 7371 * with the corresponding dates 7372 * set to the argument tm. 7373 */ 7374 iupdat(p, tm) 7375 int *p; 7376 int *tm; 7377 { 7378 register *ip1, *ip2, *rp; 7379 int *bp, i; 7380 7381 rp = p; 7382 if((rp->i_flag&(IUPD|IACC)) != 0) { 7383 if(getfs(rp->i_dev)->s_ronly) 7384 return; 7385 i = rp->i_number+31; 7386 bp = bread(rp->i_dev, ldiv(i,16)); 7387 ip1 = bp->b_addr + 32*lrem(i, 16); 7388 ip2 = &rp->i_mode; 7389 while(ip2 < &rp->i_addr[8]) 7390 *ip1++ = *ip2++; 7391 if(rp->i_flag&IACC) { 7392 *ip1++ = time[0]; 7393 *ip1++ = time[1]; 7394 } else 7395 ip1 =+ 2; 7396 if(rp->i_flag&IUPD) { 7397 *ip1++ = *tm++; 7398 *ip1++ = *tm; 7399 } 7400 bwrite(bp); 7401 } 7402 } 7403 /* ------------------------ */ 7404 7405 /* 7406 * Free all the disk blocks associated 7407 * with the specified inode structure. 7408 * The blocks of the file are removed 7409 * in reverse order. This FILO 7410 * algorithm will tend to maintain 7411 * a contiguous free list much longer 7412 * than FIFO. 7413 */ 7414 itrunc(ip) 7415 int *ip; 7416 { 7417 register *rp, *bp, *cp; 7418 int *dp, *ep; 7419 7420 rp = ip; 7421 if((rp->i_mode&(IFCHR&IFBLK)) != 0) 7422 return; 7423 for(ip = &rp->i_addr[7]; ip >= &rp->i_addr[0]; ip--) 7424 if(*ip) { 7425 if((rp->i_mode&ILARG) != 0) { 7426 bp = bread(rp->i_dev, *ip); 7427 for(cp = bp->b_addr+512; cp >= bp->b_addr; 7428 cp--) 7429 if(*cp) { 7430 if(ip == &rp->i_addr[7]) { 7431 dp = bread(rp->i_dev, *cp); 7432 for(ep = dp->b_addr+512; 7433 ep >= dp->b_addr; ep--) 7434 if(*ep) 7435 free(rp->i_dev, *ep); 7436 brelse(dp); 7437 } 7438 free(rp->i_dev, *cp); 7439 } 7440 brelse(bp); 7441 } 7442 free(rp->i_dev, *ip); 7443 *ip = 0; 7444 } 7445 rp->i_mode =& ~ILARG; 7446 rp->i_size0 = 0; 7447 rp->i_size1 = 0; 7448 rp->i_flag =| IUPD; 7449 } 7450 /* ------------------------ */ 7451 7452 /* 7453 * Make a new file. 7454 */ 7455 maknode(mode) 7456 { 7457 register *ip; 7458 7459 ip = ialloc(u.u_pdir->i_dev); 7460 if (ip==NULL) 7461 return(NULL); 7462 ip->i_flag =| IACC|IUPD; 7463 ip->i_mode = mode|IALLOC; 7464 ip->i_nlink = 1; 7465 ip->i_uid = u.u_uid; 7466 ip->i_gid = u.u_gid; 7467 wdir(ip); 7468 return(ip); 7469 } 7470 /* ------------------------ */ 7471 7472 /* 7473 * Write a directory entry with 7474 * parameters left as side effects 7475 * to a call to namei. 7476 */ 7477 wdir(ip) 7478 int *ip; 7479 { 7480 register char *cp1, *cp2; 7481 7482 u.u_dent.u_ino = ip->i_number; 7483 cp1 = &u.u_dent.u_name[0]; 7484 for(cp2 = &u.u_dbuf[0]; cp2 < &u.u_dbuf[DIRSIZ];) 7485 *cp1++ = *cp2++; 7486 u.u_count = DIRSIZ+2; 7487 u.u_segflg = 1; 7488 u.u_base = &u.u_dent; 7489 writei(u.u_pdir); 7490 iput(u.u_pdir); 7491 } 7492 /* ------------------------ */ 7493 7494 7495 7496 7497 7498 7499