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: }