#include "types.h" #include "param.h" #include "x86.h" #include "mmu.h" #include "proc.h" #include "defs.h" #include "spinlock.h" #include "buf.h" #include "fs.h" #include "fsvar.h" // these are inodes currently in use // an entry is free if count == 0 struct inode inode[NINODE]; struct spinlock inode_table_lock; uint rootdev = 1; // returns an inode with busy set and incremented reference count. struct inode * iget(uint dev, uint inum) { struct inode *ip, *nip = 0; struct dinode *dip; struct buf *bp; acquire(&inode_table_lock); loop: for(ip = &inode[0]; ip < &inode[NINODE]; ip++){ if(ip->count > 0 && ip->dev == dev && ip->inum == inum){ if(ip->busy){ sleep(ip, &inode_table_lock); goto loop; } ip->count++; release(&inode_table_lock); return ip; } if(nip == 0 && ip->count == 0) nip = ip; } if(nip == 0) panic("out of inodes"); nip->dev = dev; nip->inum = inum; nip->count = 1; nip->busy = 1; release(&inode_table_lock); bp = bread(dev, inum / IPB + 2); dip = &((struct dinode *)(bp->data))[inum % IPB]; nip->type = dip->type; nip->nlink = dip->nlink; nip->size = dip->size; memmove(nip->addrs, dip->addrs, sizeof(nip->addrs)); brelse(bp); return nip; } void ilock(struct inode *ip) { if(ip->count < 1) panic("ilock"); acquire(&inode_table_lock); while(ip->busy) sleep(ip, &inode_table_lock); ip->busy = 1; release(&inode_table_lock); } // caller is holding onto a reference to this inode, but no // longer needs to examine or change it, so clear ip->busy. void iunlock(struct inode *ip) { if(ip->busy != 1) panic("iunlock"); acquire(&inode_table_lock); ip->busy = 0; wakeup(ip); release(&inode_table_lock); } // caller is releasing a reference to this inode. // you must have the inode lock. void iput(struct inode *ip) { if(ip->count < 1 || ip->busy != 1) panic("iput"); acquire(&inode_table_lock); ip->count -= 1; ip->busy = 0; wakeup(ip); release(&inode_table_lock); } void iincref(struct inode *ip) { acquire(&inode_table_lock); ip->count += 1; release(&inode_table_lock); } uint bmap(struct inode *ip, uint bn) { unsigned x; if(bn >= NDIRECT) panic("bmap 1"); x = ip->addrs[bn]; if(x == 0) panic("bmap 2"); return x; } struct inode * namei(char *path) { struct inode *dp; char *cp = path; uint off, dev; struct buf *bp; struct dirent *ep; int i; unsigned ninum; dp = iget(rootdev, 1); while(*cp == '/') cp++; while(1){ if(*cp == '\0') return dp; if(dp->type != T_DIR){ iput(dp); return 0; } for(off = 0; off < dp->size; off += 512){ bp = bread(dp->dev, bmap(dp, off / 512)); for(ep = (struct dirent *) bp->data; ep < (struct dirent *) (bp->data + 512); ep++){ if(ep->inum == 0) continue; for(i = 0; i < DIRSIZ && cp[i] != '/' && cp[i]; i++) if(cp[i] != ep->name[i]) break; if((cp[i] == '\0' || cp[i] == '/') && (i >= DIRSIZ || ep->name[i] == '\0')){ ninum = ep->inum; brelse(bp); cp += i; goto found; } } brelse(bp); } iput(dp); return 0; found: dev = dp->dev; iput(dp); dp = iget(dev, ninum); while(*cp == '/') cp++; } }