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 17*9d3fb671Srtm uint rootdev = 1; 18*9d3fb671Srtm 19*9d3fb671Srtm // 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 66*9d3fb671Srtm ilock(struct inode *ip) 67*9d3fb671Srtm { 68*9d3fb671Srtm if(ip->count < 1) 69*9d3fb671Srtm panic("ilock"); 70*9d3fb671Srtm 71*9d3fb671Srtm acquire(&inode_table_lock); 72*9d3fb671Srtm 73*9d3fb671Srtm while(ip->busy) 74*9d3fb671Srtm sleep(ip, &inode_table_lock); 75*9d3fb671Srtm ip->busy = 1; 76*9d3fb671Srtm 77*9d3fb671Srtm release(&inode_table_lock); 78*9d3fb671Srtm } 79*9d3fb671Srtm 80*9d3fb671Srtm // caller is holding onto a reference to this inode, but no 81*9d3fb671Srtm // longer needs to examine or change it, so clear ip->busy. 82*9d3fb671Srtm void 83*9d3fb671Srtm iunlock(struct inode *ip) 84*9d3fb671Srtm { 85*9d3fb671Srtm if(ip->busy != 1) 86*9d3fb671Srtm panic("iunlock"); 87*9d3fb671Srtm 88*9d3fb671Srtm acquire(&inode_table_lock); 89*9d3fb671Srtm 90*9d3fb671Srtm ip->busy = 0; 91*9d3fb671Srtm wakeup(ip); 92*9d3fb671Srtm 93*9d3fb671Srtm release(&inode_table_lock); 94*9d3fb671Srtm } 95*9d3fb671Srtm 96*9d3fb671Srtm // caller is releasing a reference to this inode. 97*9d3fb671Srtm // you must have the inode lock. 98*9d3fb671Srtm void 9911a9947fSrtm iput(struct inode *ip) 10011a9947fSrtm { 101*9d3fb671Srtm if(ip->count < 1 || ip->busy != 1) 102*9d3fb671Srtm panic("iput"); 103*9d3fb671Srtm 10411a9947fSrtm acquire(&inode_table_lock); 10511a9947fSrtm 10611a9947fSrtm ip->count -= 1; 10711a9947fSrtm ip->busy = 0; 10811a9947fSrtm wakeup(ip); 10911a9947fSrtm 11011a9947fSrtm release(&inode_table_lock); 11111a9947fSrtm } 112*9d3fb671Srtm 113*9d3fb671Srtm void 114*9d3fb671Srtm iincref(struct inode *ip) 115*9d3fb671Srtm { 116*9d3fb671Srtm acquire(&inode_table_lock); 117*9d3fb671Srtm 118*9d3fb671Srtm ip->count += 1; 119*9d3fb671Srtm 120*9d3fb671Srtm release(&inode_table_lock); 121*9d3fb671Srtm } 122*9d3fb671Srtm 123*9d3fb671Srtm uint 124*9d3fb671Srtm bmap(struct inode *ip, uint bn) 125*9d3fb671Srtm { 126*9d3fb671Srtm unsigned x; 127*9d3fb671Srtm 128*9d3fb671Srtm if(bn >= NDIRECT) 129*9d3fb671Srtm panic("bmap 1"); 130*9d3fb671Srtm x = ip->addrs[bn]; 131*9d3fb671Srtm if(x == 0) 132*9d3fb671Srtm panic("bmap 2"); 133*9d3fb671Srtm return x; 134*9d3fb671Srtm } 135*9d3fb671Srtm 136*9d3fb671Srtm struct inode * 137*9d3fb671Srtm namei(char *path) 138*9d3fb671Srtm { 139*9d3fb671Srtm struct inode *dp; 140*9d3fb671Srtm char *cp = path; 141*9d3fb671Srtm uint off, dev; 142*9d3fb671Srtm struct buf *bp; 143*9d3fb671Srtm struct dirent *ep; 144*9d3fb671Srtm int i; 145*9d3fb671Srtm unsigned ninum; 146*9d3fb671Srtm 147*9d3fb671Srtm dp = iget(rootdev, 1); 148*9d3fb671Srtm 149*9d3fb671Srtm while(*cp == '/') 150*9d3fb671Srtm cp++; 151*9d3fb671Srtm 152*9d3fb671Srtm while(1){ 153*9d3fb671Srtm if(*cp == '\0') 154*9d3fb671Srtm return dp; 155*9d3fb671Srtm 156*9d3fb671Srtm if(dp->type != T_DIR){ 157*9d3fb671Srtm iput(dp); 158*9d3fb671Srtm return 0; 159*9d3fb671Srtm } 160*9d3fb671Srtm 161*9d3fb671Srtm for(off = 0; off < dp->size; off += 512){ 162*9d3fb671Srtm bp = bread(dp->dev, bmap(dp, off / 512)); 163*9d3fb671Srtm for(ep = (struct dirent *) bp->data; 164*9d3fb671Srtm ep < (struct dirent *) (bp->data + 512); 165*9d3fb671Srtm ep++){ 166*9d3fb671Srtm if(ep->inum == 0) 167*9d3fb671Srtm continue; 168*9d3fb671Srtm for(i = 0; i < DIRSIZ && cp[i] != '/' && cp[i]; i++) 169*9d3fb671Srtm if(cp[i] != ep->name[i]) 170*9d3fb671Srtm break; 171*9d3fb671Srtm if((cp[i] == '\0' || cp[i] == '/') && (i >= DIRSIZ || ep->name[i] == '\0')){ 172*9d3fb671Srtm ninum = ep->inum; 173*9d3fb671Srtm brelse(bp); 174*9d3fb671Srtm cp += i; 175*9d3fb671Srtm goto found; 176*9d3fb671Srtm } 177*9d3fb671Srtm } 178*9d3fb671Srtm brelse(bp); 179*9d3fb671Srtm } 180*9d3fb671Srtm iput(dp); 181*9d3fb671Srtm return 0; 182*9d3fb671Srtm 183*9d3fb671Srtm found: 184*9d3fb671Srtm dev = dp->dev; 185*9d3fb671Srtm iput(dp); 186*9d3fb671Srtm dp = iget(dev, ninum); 187*9d3fb671Srtm while(*cp == '/') 188*9d3fb671Srtm cp++; 189*9d3fb671Srtm } 190*9d3fb671Srtm } 191