1: /*
   2:  *	SCCS id	@(#)iget.c	2.1 (Berkeley)	9/1/83
   3:  */
   4: 
   5: #include "param.h"
   6: #include <sys/systm.h>
   7: #include <sys/dir.h>
   8: #include <sys/user.h>
   9: #include <sys/inode.h>
  10: #include <sys/ino.h>
  11: #include <sys/filsys.h>
  12: #include <sys/mount.h>
  13: #include <sys/conf.h>
  14: #include <sys/buf.h>
  15: #ifdef  UCB_QUOTAS
  16: #include <sys/quota.h>
  17: #endif
  18: #include <sys/inline.h>
  19: 
  20: 
  21: #ifdef  UCB_QUOTAS
  22: #define IFREE(dev, ip, bn)      qfree(ip, bn)
  23: #define TLOOP(dev, bn, f1, f2, ip)  tloop(dev, bn, f1, f2, ip)
  24: #else
  25: #define IFREE(dev, ip, bn)      free(dev, bn)
  26: #define TLOOP(dev, bn, f1, f2, ip)  tloop(dev, bn, f1, f2)
  27: #endif
  28: 
  29: 
  30: #ifdef  UCB_IHASH
  31: 
  32: #ifdef  SMALL
  33: #define INOHSZ  16      /* must be power of two */
  34: #else
  35: #define INOHSZ  64      /* must be power of two */
  36: #endif
  37: #define INOHASH(dev,ino)    (((dev) + (ino)) & (INOHSZ - 1))
  38: struct  inode   *ihash[INOHSZ];
  39: struct  inode   *ifreelist;
  40: 
  41: /*
  42:  * Initialize hash links for inodes
  43:  * and build inode free list.
  44:  */
  45: ihinit()
  46: {
  47:     register struct inode *ip;
  48: 
  49:     ifreelist = &inode[0];
  50:     for(ip = inode; ip < inodeNINODE - 1; ip++)
  51:         ip->i_link = ip + 1;
  52: }
  53: 
  54: /*
  55:  * Find an inode if it is incore.
  56:  * This is the equivalent, for inodes,
  57:  * of ``incore'' in bio.c or ``pfind'' in subr.c.
  58:  */
  59: struct inode *
  60: ifind(dev, ino)
  61: dev_t dev;
  62: ino_t ino;
  63: {
  64:     register struct inode *ip;
  65: 
  66:     for (ip = ihash[INOHASH(dev,ino)]; ip != NULL;
  67:         ip = ip->i_link)
  68:         if (ino==ip->i_number && dev==ip->i_dev)
  69:             return (ip);
  70:     return ((struct inode *)NULL);
  71: }
  72: 
  73: #endif	UCB_IHASH
  74: 
  75: /*
  76:  * Look up an inode by device,inumber.
  77:  * If it is in core (in the inode structure),
  78:  * honor the locking protocol.
  79:  * If it is not in core, read it in from the
  80:  * specified device.
  81:  * If the inode is mounted on, perform
  82:  * the indicated indirection.
  83:  * In all cases, a pointer to a locked
  84:  * inode structure is returned.
  85:  *
  86:  * printf warning: no inodes -- if the inode
  87:  *	structure is full
  88:  * panic: no imt -- if the mounted file
  89:  *	system is not in the mount table.
  90:  *	"cannot happen"
  91:  */
  92: struct inode *
  93: iget(dev, ino)
  94: dev_t dev;
  95: ino_t ino;
  96: {
  97:     register struct inode *ip;
  98:     register struct mount *mp;
  99: #ifdef  UCB_IHASH
 100:     register int slot;
 101: #else
 102:     register struct inode *oip;
 103: #endif
 104:     struct buf *bp;
 105:     struct dinode *dp;
 106: 
 107: loop:
 108: #ifdef  UCB_IHASH
 109:     slot = INOHASH(dev, ino);
 110:     ip = ihash[slot];
 111:     while (ip != NULL)
 112: #else
 113:     oip = NULL;
 114:     for(ip = inode; ip < inodeNINODE; ip++)
 115: #endif
 116:     {
 117:         if(ino == ip->i_number && dev == ip->i_dev) {
 118:     again:
 119:             if((ip->i_flag&ILOCK) != 0) {
 120:                 ip->i_flag |= IWANT;
 121:                 sleep((caddr_t)ip, PINOD);
 122:                 if(ino == ip->i_number && dev == ip->i_dev)
 123:                     goto again;
 124:                 goto loop;
 125:             }
 126:             if((ip->i_flag&IMOUNT) != 0) {
 127:                 for(mp = mount; mp < mountNMOUNT; mp++)
 128:                 if(mp->m_inodp == ip) {
 129:                     dev = mp->m_dev;
 130:                     ino = ROOTINO;
 131:                     goto loop;
 132:                 }
 133:                 panic("no imt");
 134:             }
 135:             ip->i_count++;
 136:             ip->i_flag |= ILOCK;
 137:             return(ip);
 138:         }
 139: #ifdef  UCB_IHASH
 140:         ip = ip->i_link;
 141: #else
 142:         if(oip==NULL && ip->i_count==0)
 143:             oip = ip;
 144: #endif
 145:     }
 146: #ifdef  UCB_IHASH
 147:     if (ifreelist == NULL)
 148: #else
 149:     ip = oip;
 150:     if(ip == NULL)
 151: #endif
 152:     {
 153:         tablefull("inode");
 154:         u.u_error = ENFILE;
 155:         return(NULL);
 156:     }
 157: #ifdef  UCB_IHASH
 158:     ip = ifreelist;
 159:     ifreelist = ip->i_link;
 160:     ip->i_link = ihash[slot];
 161:     ihash[slot] = ip;
 162: #endif
 163:     ip->i_dev = dev;
 164:     ip->i_number = ino;
 165:     ip->i_flag = ILOCK;
 166:     ip->i_count++;
 167:     ip->i_un.i_lastr = 0;
 168: #ifdef  UCB_QUOTAS
 169:     ip->i_quot = NULL;
 170: #endif
 171: 
 172:     bp = bread(dev, itod(ino));
 173: 
 174:     /*
 175: 	 * Check I/O errors
 176: 	 */
 177:     if (((bp->b_flags&B_ERROR) != 0) || bp->b_resid) {
 178:         brelse(bp);
 179:         /*
 180: 		 * This was an iput(ip), but if i_nlink happens to be 0,
 181: 		 * the itrunc() in iput() might be successful.
 182: 		 */
 183:         ip->i_count = 0;
 184:         ip->i_number = 0;
 185:         ip->i_flag = 0;
 186: #ifdef  UCB_IHASH
 187:         ihash[slot] = ip->i_link;
 188:         ip->i_link = ifreelist;
 189:         ifreelist = ip;
 190: #endif
 191:         return(NULL);
 192:     }
 193:     dp = (struct dinode *) mapin(bp);
 194:     dp += itoo(ino);
 195:     iexpand(ip, dp);
 196:     mapout(bp);
 197:     brelse(bp);
 198:     return(ip);
 199: }
 200: 
 201: iexpand(ip, dp)
 202: register struct inode *ip;
 203: register struct dinode *dp;
 204: {
 205:     register char *p1;
 206:     char *p2;
 207:     int i;
 208: 
 209:     ip->i_mode = dp->di_mode;
 210:     ip->i_nlink = dp->di_nlink;
 211:     ip->i_uid = dp->di_uid;
 212:     ip->i_gid = dp->di_gid;
 213:     ip->i_size = dp->di_size;
 214:     p1 = (char *)ip->i_un.i_addr;
 215:     p2 = (char *)dp->di_addr;
 216:     for(i=0; i<NADDR; i++) {
 217:         *p1++ = *p2++;
 218:         *p1++ = 0;
 219:         *p1++ = *p2++;
 220:         *p1++ = *p2++;
 221:     }
 222: }
 223: 
 224: /*
 225:  * Decrement reference count of
 226:  * an inode structure.
 227:  * On the last reference,
 228:  * write the inode out and if necessary,
 229:  * truncate and deallocate the file.
 230:  */
 231: iput(ip)
 232: register struct inode *ip;
 233: {
 234: #ifdef  UCB_QUOTAS
 235:     register struct inode *qp;
 236: #endif
 237: #ifdef  UCB_IHASH
 238:     register struct inode *jp;
 239:     register int i;
 240: # endif
 241: 
 242: #ifdef  UCB_QUOTAS
 243: 
 244:     /*
 245: 	 * Berkeley's quota system is hierarchical
 246: 	 * so this loop is necessary to de-reference all
 247: 	 * quota nodes still hanging around
 248: 	 */
 249:     do {
 250:     qp = NULL;
 251: #endif
 252:     if(ip->i_count == 1) {
 253:         ip->i_flag |= ILOCK;
 254:         if(ip->i_nlink <= 0) {
 255:             itrunc(ip);
 256:             ip->i_mode = 0;
 257:             ip->i_flag |= IUPD|ICHG;
 258:             ifree(ip->i_dev, ip->i_number);
 259:         }
 260: #ifdef  UCB_QUOTAS
 261:         qp = ip->i_quot;
 262:         if (qp != NULL)
 263:             ip->i_quot = NULL;
 264: #endif
 265: #ifdef UCB_FSFIX
 266:         IUPDAT(ip, &time, &time, 0);
 267: #else
 268:         IUPDAT(ip, &time, &time);
 269: #endif
 270:         prele(ip);
 271: #ifdef  UCB_IHASH
 272:         i = INOHASH(ip->i_dev, ip->i_number);
 273:         if (ihash[i] == ip)
 274:             ihash[i] = ip->i_link;
 275:         else {
 276:             for (jp = ihash[i]; jp != NULL; jp = jp->i_link)
 277:                 if (jp->i_link == ip) {
 278:                     jp->i_link = ip->i_link;
 279:                     goto done;
 280:                 }
 281:             panic("iput");
 282:         }
 283: done:
 284:         ip->i_link = ifreelist;
 285:         ifreelist = ip;
 286: #endif
 287:         ip->i_flag = 0;
 288:         ip->i_number = 0;
 289:     }
 290:     else
 291:         prele(ip);
 292:     ip->i_count--;
 293: #ifdef  UCB_QUOTAS
 294:     } while ((ip = qp) != NULL);
 295: #endif
 296: }
 297: 
 298: /*
 299:  * Check accessed and update flags on
 300:  * an inode structure.
 301:  * If any are on, update the inode
 302:  * with the current time.
 303:  */
 304: #ifdef UCB_FSFIX
 305: /*
 306:  * If waitfor set, then must insure
 307:  * i/o order by waiting for the write
 308:  * to complete.
 309:  */
 310: 
 311: iupdat(ip, ta, tm, waitfor)
 312: #else
 313: iupdat(ip, ta, tm)
 314: #endif
 315: register struct inode *ip;
 316: time_t *ta, *tm;
 317: #ifdef UCB_FSFIX
 318: int waitfor;
 319: #endif
 320: {
 321:     register struct buf *bp;
 322:     register struct dinode *dp;
 323:     struct filsys *fp;
 324:     char *p1, *p2;
 325:     int i;
 326: 
 327:     if((ip->i_flag&(IUPD|IACC|ICHG)) != 0) {
 328:         if ((fp = getfs(ip->i_dev)) == NULL || fp->s_ronly)
 329:             return;
 330:         bp = bread(ip->i_dev, itod(ip->i_number));
 331:         if ((bp->b_flags & B_ERROR) || bp->b_resid) {
 332:             brelse(bp);
 333:             return;
 334:         }
 335:         dp = (struct dinode *) mapin(bp);
 336:         dp += itoo(ip->i_number);
 337:         dp->di_mode = ip->i_mode;
 338:         dp->di_nlink = ip->i_nlink;
 339:         dp->di_uid = ip->i_uid;
 340:         dp->di_gid = ip->i_gid;
 341:         dp->di_size = ip->i_size;
 342:         p1 = (char *)dp->di_addr;
 343:         p2 = (char *)ip->i_un.i_addr;
 344:         for(i=0; i<NADDR; i++) {
 345:             *p1++ = *p2++;
 346: #ifdef  MPX_FILS
 347:             if(*p2++ != 0 && (ip->i_mode&IFMT)!=IFMPC
 348:                && (ip->i_mode&IFMT)!=IFMPB)
 349: #else
 350:             if(*p2++ != 0)
 351: #endif
 352:                printf("iaddr[%d] > 2^24(%D), inum = %d, dev = %d\n",
 353:                 i, ip->i_un.i_addr[i], ip->i_number, ip->i_dev);
 354:             *p1++ = *p2++;
 355:             *p1++ = *p2++;
 356:         }
 357:         if(ip->i_flag&IACC)
 358:             dp->di_atime = *ta;
 359:         if(ip->i_flag&IUPD)
 360:             dp->di_mtime = *tm;
 361:         if(ip->i_flag&ICHG)
 362:             dp->di_ctime = time;
 363:         ip->i_flag &= ~(IUPD|IACC|ICHG);
 364:         mapout(bp);
 365: #ifdef UCB_FSFIX
 366:         if (waitfor)
 367:             bwrite(bp);
 368:         else
 369: #endif
 370:             bdwrite(bp);
 371:     }
 372: }
 373: 
 374: /*
 375:  * Free all the disk blocks associated
 376:  * with the specified inode structure.
 377:  * The blocks of the file are removed
 378:  * in reverse order. This FILO
 379:  * algorithm will tend to maintain
 380:  * a contiguous free list much longer
 381:  * than FIFO.
 382:  */
 383: itrunc(ip)
 384: register struct inode *ip;
 385: {
 386:     register i;
 387:     register dev_t dev;
 388:     daddr_t bn;
 389: #ifdef UCB_FSFIX
 390:     struct inode itmp;
 391: #endif
 392: 
 393:     i = ip->i_mode & IFMT;
 394: #ifndef UCB_SYMLINKS
 395:     if (i!=IFREG && i!=IFDIR)
 396: #else
 397:     if (i!=IFREG && i!=IFDIR && i!=IFLNK)
 398: #endif
 399:         return;
 400: 
 401: #ifdef UCB_FSFIX
 402:     /*
 403: 	 * Clean inode on disk before freeing blocks
 404: 	 * to insure no duplicates if system crashes.
 405: 	 */
 406:     itmp = *ip;
 407:     itmp.i_size = 0;
 408:     for (i = 0; i < NADDR; i++)
 409:         itmp.i_un.i_addr[i] = 0;
 410:     itmp.i_flag |= ICHG|IUPD;
 411:     iupdat(&itmp, &time, &time, 1);
 412:     ip->i_flag &= ~(IUPD|IACC|ICHG);
 413: 
 414:     /*
 415: 	 * Now return blocks to free list... if machine
 416: 	 * crashes, they will be harmless MISSING blocks.
 417: 	 */
 418: #endif
 419: 
 420:     dev = ip->i_dev;
 421:     for(i=NADDR-1; i>=0; i--) {
 422:         bn = ip->i_un.i_addr[i];
 423:         if(bn == (daddr_t)0)
 424:             continue;
 425:         ip->i_un.i_addr[i] = (daddr_t)0;
 426:         switch(i) {
 427: 
 428:         default:
 429:             IFREE(dev, ip, bn);
 430:             break;
 431: 
 432:         case NADDR-3:
 433:             TLOOP(dev, bn, 0, 0, ip);
 434:             break;
 435: 
 436:         case NADDR-2:
 437:             TLOOP(dev, bn, 1, 0, ip);
 438:             break;
 439: 
 440:         case NADDR-1:
 441:             TLOOP(dev, bn, 1, 1, ip);
 442:         }
 443:     }
 444:     ip->i_size = 0;
 445: #ifndef UCB_FSFIX
 446:     ip->i_flag |= ICHG|IUPD;
 447: #else
 448:     /* Inode was written and flags updated above.
 449: 	 * No need to modify flags here.
 450: 	 */
 451: #endif
 452: 
 453: }
 454: 
 455: #ifdef  UCB_QUOTAS
 456: tloop(dev, bn, f1, f2, ip)
 457: #else
 458: tloop(dev, bn, f1, f2)
 459: #endif
 460: dev_t dev;
 461: daddr_t bn;
 462: #ifdef  UCB_QUOTAS
 463: struct inode    *ip;
 464: #endif
 465: {
 466:     register i;
 467:     register struct buf *bp;
 468:     register daddr_t *bap;
 469:     daddr_t nb;
 470: 
 471:     bp = NULL;
 472:     for(i=NINDIR-1; i>=0; i--) {
 473:         if(bp == NULL) {
 474:             bp = bread(dev, bn);
 475:             if ((bp->b_flags & B_ERROR) || bp->b_resid) {
 476:                 brelse(bp);
 477:                 return;
 478:             }
 479:         }
 480:         bap = (daddr_t *) mapin(bp);
 481:         nb = bap[i];
 482:         mapout(bp);
 483:         if(nb == (daddr_t)0)
 484:             continue;
 485:         if(f1) {
 486:             brelse(bp);
 487:             bp = NULL;
 488:             TLOOP(dev, nb, f2, 0, ip);
 489:         } else
 490:             IFREE(dev, ip, nb);
 491:     }
 492:     if(bp != NULL)
 493:         brelse(bp);
 494:     IFREE(dev, ip, bn);
 495: }
 496: 
 497: /*
 498:  * Make a new file.
 499:  */
 500: struct inode *
 501: maknode(mode)
 502: {
 503:     register struct inode *ip;
 504: 
 505:     ip = ialloc(u.u_pdir->i_dev);
 506:     if(ip == NULL) {
 507:         iput(u.u_pdir);
 508:         return(NULL);
 509:     }
 510:     ip->i_flag |= IACC|IUPD|ICHG;
 511:     if((mode&IFMT) == 0)
 512:         mode |= IFREG;
 513:     ip->i_mode = mode & ~u.u_cmask;
 514:     ip->i_nlink = 1;
 515:     ip->i_uid = u.u_uid;
 516:     ip->i_gid = u.u_gid;
 517: 
 518: #ifdef UCB_FSFIX
 519:     /*
 520: 	 * Make sure inode goes to disk before directory entry.
 521: 	 */
 522:     iupdat(ip, &time, &time, 1);
 523: #endif
 524: 
 525:     wdir(ip);
 526:     return(ip);
 527: }
 528: 
 529: /*
 530:  * Write a directory entry with
 531:  * parameters left as side effects
 532:  * to a call to namei.
 533:  */
 534: wdir(ip)
 535: struct inode *ip;
 536: {
 537: 
 538:     if (u.u_pdir->i_nlink <= 0) {
 539:         u.u_error = ENOTDIR;
 540:         goto out;
 541:     }
 542:     u.u_dent.d_ino = ip->i_number;
 543:     bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ);
 544:     u.u_count = sizeof(struct direct);
 545:     u.u_segflg = 1;
 546:     u.u_base = (caddr_t)&u.u_dent;
 547:     writei(u.u_pdir);
 548: #ifdef  UCB_QUOTAS
 549:     /*
 550: 	 * Copy quota for new file
 551: 	 */
 552:     if (!u.u_error)
 553:         qcopy(u.u_pdir, ip);
 554: #endif
 555: out:
 556:     iput(u.u_pdir);
 557: }

Defined functions

iexpand defined in line 201; used 1 times
ifind defined in line 59; used 1 times
iget defined in line 92; used 9 times
ihinit defined in line 45; used 1 times
itrunc defined in line 383; used 4 times
iupdat defined in line 311; used 10 times
tloop defined in line 456; used 2 times
wdir defined in line 534; used 2 times

Defined variables

ifreelist defined in line 39; used 8 times
ihash defined in line 38; used 8 times

Defined macros

IFREE defined in line 25; used 3 times
INOHASH defined in line 37; used 3 times
INOHSZ defined in line 35; used 2 times
TLOOP defined in line 26; used 4 times
Last modified: 1983-09-02
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1246
Valid CSS Valid XHTML 1.0 Strict