|
|
1.1 ! root 1: #include "sys/param.h" ! 2: #include "sys/user.h" ! 3: #include "sys/inode.h" ! 4: #include "sys/conf.h" ! 5: ! 6: #define INOHSZ 63 ! 7: /* INOHASH can't depend on fstype as long as unmount changes fstyp to err-fs */ ! 8: #define INOHASH(dev, ino) (((dev)+(ino))%INOHSZ) ! 9: struct inode *inohash[INOHSZ]; ! 10: struct inode *ifreel; ! 11: ! 12: /* ! 13: * Initialize hash links for inodes ! 14: * and build inode free list. ! 15: */ ! 16: ihinit() ! 17: { ! 18: register int i; ! 19: register struct inode *ip = inode; ! 20: ! 21: ifreel = inode; ! 22: for (i = 0; i < inodecnt-1; i++, ip++) ! 23: ip->i_hlink = ip + 1; ! 24: ip->i_hlink = NULL; ! 25: for (i = 0; i < INOHSZ; i++) ! 26: inohash[i] = NULL; ! 27: } ! 28: ! 29: /* ! 30: * Find an inode if it is incore. ! 31: */ ! 32: struct inode * ! 33: ifind(hp, ino) ! 34: register struct inode *hp; ! 35: register ino_t ino; ! 36: { ! 37: register struct inode *ip; ! 38: ! 39: for (ip = inohash[INOHASH(hp->i_dev,ino)]; ip; ip = ip->i_hlink) ! 40: if (ino==ip->i_number && hp->i_dev==ip->i_dev && hp->i_fstyp==ip->i_fstyp) ! 41: return (ip); ! 42: return ((struct inode *)0); ! 43: } ! 44: ! 45: /* ! 46: * see if there are any inodes save the given one ! 47: * in the same filesystem ! 48: * used by unmount routines to decide whether fs is busy ! 49: * try to unmount anything mounted atop this fs ! 50: * -- botch: deeply nested filesystems may run the system ! 51: * out of stack and cause a crash ! 52: */ ! 53: ! 54: int ! 55: ifsbusy(rip) ! 56: register struct inode *rip; ! 57: { ! 58: register struct inode *ip; ! 59: ! 60: for (ip = inode; ip < inodeNINODE; ip++) { ! 61: if (ip->i_count == 0) ! 62: continue; ! 63: if (ip->i_mpoint != rip->i_mpoint) ! 64: continue; ! 65: if (ip->i_mroot) { /* something mounted here? */ ! 66: ip->i_count++; ! 67: (*fstypsw[ip->i_mroot->i_fstyp]->t_mount)((struct inode *)NULL, ! 68: ip, 0, 0, ip->i_mroot->i_fstyp); ! 69: if (ip->i_count == 1) { /* just our reference left? */ ! 70: idec(ip); ! 71: continue; ! 72: } ! 73: idec(ip); ! 74: } ! 75: if (ip != rip) ! 76: return (1); ! 77: } ! 78: return (0); ! 79: } ! 80: ! 81: /* ! 82: * mark inaccessible all i-nodes in this filesystem ! 83: * used for forced unmounting ! 84: * any further IO through those inodes will produce an error ! 85: * -- it's annoying that ERRFS must be manifest ! 86: */ ! 87: ! 88: #define ERRFS 5 ! 89: ifsinacc(rip) ! 90: register struct inode *rip; ! 91: { ! 92: register struct inode *ip; ! 93: ! 94: rip = rip->i_mpoint; ! 95: for (ip = inode; ip < inodeNINODE; ip++) { ! 96: if (ip->i_count == 0) ! 97: continue; ! 98: if (ip->i_mpoint != rip) ! 99: continue; ! 100: ip->i_fstyp = ERRFS; /* yes, always */ ! 101: ip->i_mpoint = rootdir; /* hmm */ ! 102: if (ip->i_mroot) ! 103: (*fstypsw[ip->i_mroot->i_fstyp]->t_mount)((struct inode *)NULL, ! 104: ip, 0, 0, ip->i_mroot->i_fstyp); ! 105: } ! 106: } ! 107: ! 108: #ifndef plock /* done inline */ ! 109: /* ! 110: * Lock an inode ! 111: * If its already locked, ! 112: * set the WANT bit and sleep. ! 113: */ ! 114: plock(ip) ! 115: register struct inode *ip; ! 116: { ! 117: ! 118: while(ip->i_flag&ILOCK) { ! 119: ip->i_flag |= IWANT; ! 120: sleep((caddr_t)ip, PINOD); ! 121: } ! 122: ip->i_flag |= ILOCK; ! 123: } ! 124: ! 125: /* ! 126: * Unlock an inode. ! 127: * If WANT bit is on, ! 128: * wakeup. ! 129: */ ! 130: prele(ip) ! 131: register struct inode *ip; ! 132: { ! 133: ip->i_flag &= ~ILOCK; ! 134: if(ip->i_flag&IWANT) { ! 135: ip->i_flag &= ~IWANT; ! 136: wakeup((caddr_t)ip); ! 137: } ! 138: } ! 139: #endif ! 140: ! 141: ! 142: /* ! 143: * Look up an inode by filsys, i-number. ! 144: * filsys is denoted by some inode in that filesystem. ! 145: * If the inode is mounted on, perform ! 146: * the indicated indirection. ! 147: * If it is in core (in the inode structure), ! 148: * honor the locking protocol. ! 149: * If it is not in core, fill in the fields that ! 150: * signify the inode`s `name' (number, dev, filsys, fstyp) ! 151: * and leave the rest blank, to be filled in by the caller. ! 152: * A `blank' inode has i_count == 1. ! 153: * In all cases, a pointer to a locked ! 154: * inode structure is returned. ! 155: */ ! 156: struct inode * ! 157: iget(fip, dev, ino) ! 158: register struct inode *fip; ! 159: dev_t dev; ! 160: register ino_t ino; ! 161: { ! 162: register struct inode *ip; ! 163: register int slot; ! 164: ! 165: loop: ! 166: slot = INOHASH(dev, ino); ! 167: for (ip = inohash[slot]; ip; ip = ip->i_hlink) { ! 168: if(ino == ip->i_number && dev == ip->i_dev ! 169: && fip->i_fstyp == ip->i_fstyp) { ! 170: mloop: ! 171: if((ip->i_flag&ILOCK) != 0) { ! 172: ip->i_flag |= IWANT; ! 173: sleep((caddr_t)ip, PINOD); ! 174: goto loop; ! 175: } ! 176: if(ip->i_mroot != NULL) { ! 177: ip = ip->i_mroot; ! 178: goto mloop; ! 179: } ! 180: ip->i_count++; ! 181: ip->i_flag |= ILOCK; ! 182: return(ip); ! 183: } ! 184: } ! 185: if(ifreel == NULL) { ! 186: tablefull("inode"); ! 187: u.u_error = ENFILE; ! 188: return(NULL); ! 189: } ! 190: ip = ifreel; ! 191: ifreel = ip->i_hlink; ! 192: ip->i_hlink = inohash[slot]; ! 193: inohash[slot] = ip; ! 194: ip->i_dev = dev; ! 195: ip->i_fstyp = fip->i_fstyp; ! 196: ip->i_number = ino; ! 197: ip->i_flag = ILOCK; ! 198: ip->i_count = 1; ! 199: ip->i_sptr = NULL; ! 200: ip->i_mroot = NULL; ! 201: ip->i_mpoint = fip->i_mpoint; ! 202: return (ip); ! 203: } ! 204: ! 205: /* ! 206: * Decrement reference count of ! 207: * an inode structure. ! 208: * On the last reference, ! 209: * call closei to close the file. ! 210: * Don't unlock unless we were the only reference. ! 211: */ ! 212: idec(ip) ! 213: register struct inode *ip; ! 214: { ! 215: register int i; ! 216: register struct inode *jp; ! 217: ! 218: if (ip->i_count == 0) ! 219: panic("i_count==0"); ! 220: if (ip->i_count == 1) { ! 221: ip->i_flag |= ILOCK; ! 222: closei(ip); ! 223: (*fstypsw[ip->i_fstyp]->t_put)(ip); ! 224: i = INOHASH(ip->i_dev, ip->i_number); ! 225: if (inohash[i] == ip) ! 226: inohash[i] = ip->i_hlink; ! 227: else { ! 228: for (jp = inohash[i]; jp; jp = jp->i_hlink) ! 229: if (jp->i_hlink == ip) { ! 230: jp->i_hlink = ip->i_hlink; ! 231: goto done; ! 232: } ! 233: panic("idec"); ! 234: } ! 235: done: ! 236: prele(ip); ! 237: ip->i_flag = 0; ! 238: ip->i_number = 0; ! 239: ip->i_hlink = ifreel; ! 240: ifreel = ip; ! 241: } ! 242: ip->i_count--; ! 243: } ! 244: ! 245: /* ! 246: * decrement the count for a locked inode. ! 247: * unlock. ! 248: * perhaps this should be a macro later ! 249: */ ! 250: ! 251: iput(ip) ! 252: register struct inode *ip; ! 253: { ! 254: #if NOTDEF ! 255: if ((ip->i_flag & ILOCK) == 0) ! 256: panic("iput"); ! 257: #endif ! 258: if (ip->i_count == 0) ! 259: panic("i_count==0"); ! 260: if (ip->i_count == 1) ! 261: idec(ip); /* will take care of lock too */ ! 262: else { ! 263: ip->i_count--; ! 264: prele(ip); ! 265: } ! 266: } ! 267: ! 268: /* ! 269: * Check accessed and update flags on ! 270: * an inode structure. ! 271: * If any is on, update the inode ! 272: * with the current time. ! 273: * If waitfor is given, then must insure ! 274: * i/o order so wait for write to complete. ! 275: */ ! 276: iupdat(ip, ta, tm, waitfor) ! 277: register struct inode *ip; ! 278: time_t *ta, *tm; ! 279: int waitfor; ! 280: { ! 281: ! 282: if((ip->i_flag&(IUPD|IACC|ICHG)) != 0) ! 283: (*fstypsw[ip->i_fstyp]->t_updat)(ip, ta, tm, waitfor); ! 284: } ! 285: ! 286: /* ! 287: * allocate an in-core-only inode with no filesystem counterpart ! 288: * used for pipes and similar things ! 289: * a locked inode is returned, filled in and useable, ! 290: * but not a member of any filesystem ! 291: */ ! 292: struct inode * ! 293: iuniq(fstyp) ! 294: int fstyp; ! 295: { ! 296: struct inode *ip; ! 297: static ino_t ino=0; ! 298: ino_t inostart; ! 299: struct inode pi; /* primer */ ! 300: ! 301: pi.i_dev = NODEV; ! 302: pi.i_fstyp = fstyp; ! 303: pi.i_mpoint = NULL; ! 304: for (inostart = ino++; ino != inostart; ino++) { ! 305: if (ifind(&pi, ino)) /* already in use */ ! 306: continue; ! 307: if ((ip = iget(&pi, NODEV, ino)) == NULL) ! 308: return (NULL); /* no inodes, or something */ ! 309: if (ip->i_count != 1) { /* already in use -- safety */ ! 310: iput(ip); ! 311: continue; ! 312: } ! 313: ip->i_mode = IFREG | (0666 & ~u.u_cmask); ! 314: ip->i_uid = u.u_uid; ! 315: ip->i_gid = u.u_gid; ! 316: ip->i_nlink = 0; ! 317: return(ip); ! 318: } ! 319: tablefull("fake inode"); ! 320: u.u_error = ENFILE; ! 321: return(NULL); ! 322: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.