111a9947fSrtm #include "types.h" 211a9947fSrtm #include "param.h" 311a9947fSrtm #include "x86.h" 411a9947fSrtm #include "mmu.h" 511a9947fSrtm #include "proc.h" 611a9947fSrtm #include "defs.h" 711a9947fSrtm #include "spinlock.h" 811a9947fSrtm #include "buf.h" 911a9947fSrtm #include "fs.h" 1011a9947fSrtm #include "fsvar.h" 1111a9947fSrtm 1211a9947fSrtm // these are inodes currently in use 1311a9947fSrtm // an entry is free if count == 0 1411a9947fSrtm struct inode inode[NINODE]; 1511a9947fSrtm struct spinlock inode_table_lock; 1611a9947fSrtm 179d3fb671Srtm uint rootdev = 1; 189d3fb671Srtm 199d3fb671Srtm // returns an inode with busy set and incremented reference count. 2011a9947fSrtm struct inode * 2111a9947fSrtm iget(uint dev, uint inum) 2211a9947fSrtm { 2311a9947fSrtm struct inode *ip, *nip = 0; 2411a9947fSrtm struct dinode *dip; 2511a9947fSrtm struct buf *bp; 2611a9947fSrtm 2711a9947fSrtm acquire(&inode_table_lock); 2811a9947fSrtm 2911a9947fSrtm loop: 3011a9947fSrtm for(ip = &inode[0]; ip < &inode[NINODE]; ip++){ 3111a9947fSrtm if(ip->count > 0 && ip->dev == dev && ip->inum == inum){ 3211a9947fSrtm if(ip->busy){ 3311a9947fSrtm sleep(ip, &inode_table_lock); 3411a9947fSrtm goto loop; 3511a9947fSrtm } 3611a9947fSrtm ip->count++; 3711a9947fSrtm release(&inode_table_lock); 3811a9947fSrtm return ip; 3911a9947fSrtm } 4011a9947fSrtm if(nip == 0 && ip->count == 0) 4111a9947fSrtm nip = ip; 4211a9947fSrtm } 4311a9947fSrtm 4411a9947fSrtm if(nip == 0) 4511a9947fSrtm panic("out of inodes"); 4611a9947fSrtm 4711a9947fSrtm nip->dev = dev; 4811a9947fSrtm nip->inum = inum; 4911a9947fSrtm nip->count = 1; 5011a9947fSrtm nip->busy = 1; 5111a9947fSrtm 5211a9947fSrtm release(&inode_table_lock); 5311a9947fSrtm 5411a9947fSrtm bp = bread(dev, inum / IPB + 2); 5511a9947fSrtm dip = &((struct dinode *)(bp->data))[inum % IPB]; 5611a9947fSrtm nip->type = dip->type; 5711a9947fSrtm nip->nlink = dip->nlink; 5811a9947fSrtm nip->size = dip->size; 5911a9947fSrtm memmove(nip->addrs, dip->addrs, sizeof(nip->addrs)); 6011a9947fSrtm brelse(bp); 6111a9947fSrtm 6211a9947fSrtm return nip; 6311a9947fSrtm } 6411a9947fSrtm 6511a9947fSrtm void 669d3fb671Srtm ilock(struct inode *ip) 679d3fb671Srtm { 689d3fb671Srtm if(ip->count < 1) 699d3fb671Srtm panic("ilock"); 709d3fb671Srtm 719d3fb671Srtm acquire(&inode_table_lock); 729d3fb671Srtm 739d3fb671Srtm while(ip->busy) 749d3fb671Srtm sleep(ip, &inode_table_lock); 759d3fb671Srtm ip->busy = 1; 769d3fb671Srtm 779d3fb671Srtm release(&inode_table_lock); 789d3fb671Srtm } 799d3fb671Srtm 809d3fb671Srtm // caller is holding onto a reference to this inode, but no 819d3fb671Srtm // longer needs to examine or change it, so clear ip->busy. 829d3fb671Srtm void 839d3fb671Srtm iunlock(struct inode *ip) 849d3fb671Srtm { 859d3fb671Srtm if(ip->busy != 1) 869d3fb671Srtm panic("iunlock"); 879d3fb671Srtm 889d3fb671Srtm acquire(&inode_table_lock); 899d3fb671Srtm 909d3fb671Srtm ip->busy = 0; 919d3fb671Srtm wakeup(ip); 929d3fb671Srtm 939d3fb671Srtm release(&inode_table_lock); 949d3fb671Srtm } 959d3fb671Srtm 969d3fb671Srtm // caller is releasing a reference to this inode. 979d3fb671Srtm // you must have the inode lock. 989d3fb671Srtm void 9911a9947fSrtm iput(struct inode *ip) 10011a9947fSrtm { 1019d3fb671Srtm if(ip->count < 1 || ip->busy != 1) 1029d3fb671Srtm panic("iput"); 1039d3fb671Srtm 10411a9947fSrtm acquire(&inode_table_lock); 10511a9947fSrtm 10611a9947fSrtm ip->count -= 1; 10711a9947fSrtm ip->busy = 0; 10811a9947fSrtm wakeup(ip); 10911a9947fSrtm 11011a9947fSrtm release(&inode_table_lock); 11111a9947fSrtm } 1129d3fb671Srtm 1139d3fb671Srtm void 1149d3fb671Srtm iincref(struct inode *ip) 1159d3fb671Srtm { 1169d3fb671Srtm acquire(&inode_table_lock); 1179d3fb671Srtm 1189d3fb671Srtm ip->count += 1; 1199d3fb671Srtm 1209d3fb671Srtm release(&inode_table_lock); 1219d3fb671Srtm } 1229d3fb671Srtm 1239d3fb671Srtm uint 1249d3fb671Srtm bmap(struct inode *ip, uint bn) 1259d3fb671Srtm { 1269d3fb671Srtm unsigned x; 1279d3fb671Srtm 1289d3fb671Srtm if(bn >= NDIRECT) 1299d3fb671Srtm panic("bmap 1"); 1309d3fb671Srtm x = ip->addrs[bn]; 1319d3fb671Srtm if(x == 0) 1329d3fb671Srtm panic("bmap 2"); 1339d3fb671Srtm return x; 1349d3fb671Srtm } 1359d3fb671Srtm 136*c59361f1Srtm #define min(a, b) ((a) < (b) ? (a) : (b)) 137*c59361f1Srtm 138*c59361f1Srtm int 139*c59361f1Srtm readi(struct inode *ip, void *xdst, uint off, uint n) 140*c59361f1Srtm { 141*c59361f1Srtm char *dst = (char *) xdst; 142*c59361f1Srtm uint target = n, n1; 143*c59361f1Srtm struct buf *bp; 144*c59361f1Srtm 145*c59361f1Srtm while(n > 0 && off < ip->size){ 146*c59361f1Srtm bp = bread(ip->dev, bmap(ip, off / 512)); 147*c59361f1Srtm n1 = min(n, ip->size - off); 148*c59361f1Srtm n1 = min(n1, 512 - (off % 512)); 149*c59361f1Srtm memmove(dst, bp->data + (off % 512), n1); 150*c59361f1Srtm n -= n1; 151*c59361f1Srtm off += n1; 152*c59361f1Srtm dst += n1; 153*c59361f1Srtm brelse(bp); 154*c59361f1Srtm } 155*c59361f1Srtm 156*c59361f1Srtm return target - n; 157*c59361f1Srtm } 158*c59361f1Srtm 1599d3fb671Srtm struct inode * 1609d3fb671Srtm namei(char *path) 1619d3fb671Srtm { 1629d3fb671Srtm struct inode *dp; 1639d3fb671Srtm char *cp = path; 1649d3fb671Srtm uint off, dev; 1659d3fb671Srtm struct buf *bp; 1669d3fb671Srtm struct dirent *ep; 1679d3fb671Srtm int i; 1689d3fb671Srtm unsigned ninum; 1699d3fb671Srtm 1709d3fb671Srtm dp = iget(rootdev, 1); 1719d3fb671Srtm 1729d3fb671Srtm while(*cp == '/') 1739d3fb671Srtm cp++; 1749d3fb671Srtm 1759d3fb671Srtm while(1){ 1769d3fb671Srtm if(*cp == '\0') 1779d3fb671Srtm return dp; 1789d3fb671Srtm 1799d3fb671Srtm if(dp->type != T_DIR){ 1809d3fb671Srtm iput(dp); 1819d3fb671Srtm return 0; 1829d3fb671Srtm } 1839d3fb671Srtm 1849d3fb671Srtm for(off = 0; off < dp->size; off += 512){ 1859d3fb671Srtm bp = bread(dp->dev, bmap(dp, off / 512)); 1869d3fb671Srtm for(ep = (struct dirent *) bp->data; 1879d3fb671Srtm ep < (struct dirent *) (bp->data + 512); 1889d3fb671Srtm ep++){ 1899d3fb671Srtm if(ep->inum == 0) 1909d3fb671Srtm continue; 1919d3fb671Srtm for(i = 0; i < DIRSIZ && cp[i] != '/' && cp[i]; i++) 1929d3fb671Srtm if(cp[i] != ep->name[i]) 1939d3fb671Srtm break; 1949d3fb671Srtm if((cp[i] == '\0' || cp[i] == '/') && (i >= DIRSIZ || ep->name[i] == '\0')){ 1959d3fb671Srtm ninum = ep->inum; 1969d3fb671Srtm brelse(bp); 1979d3fb671Srtm cp += i; 1989d3fb671Srtm goto found; 1999d3fb671Srtm } 2009d3fb671Srtm } 2019d3fb671Srtm brelse(bp); 2029d3fb671Srtm } 2039d3fb671Srtm iput(dp); 2049d3fb671Srtm return 0; 2059d3fb671Srtm 2069d3fb671Srtm found: 2079d3fb671Srtm dev = dp->dev; 2089d3fb671Srtm iput(dp); 2099d3fb671Srtm dp = iget(dev, ninum); 2109d3fb671Srtm while(*cp == '/') 2119d3fb671Srtm cp++; 2129d3fb671Srtm } 2139d3fb671Srtm } 214