Skip to content
Snippets Groups Projects
Commit 9d3fb671 authored by rtm's avatar rtm
Browse files

namei

parent 11a9947f
No related branches found
No related tags found
No related merge requests found
......@@ -142,10 +142,22 @@ systematic way to test sleep races?
do you have to be holding the mutex in order to call wakeup()?
should lock around printf, not putc
device interrupts don't clear FL_IF
so a recursive timer interrupt is possible
the sleep/swtch/schedule code that holds over a lock is ugly
what does inode->busy mean?
might be held across disk reads
no-one is allowed to do anything to the inode
protected by inode_table_lock
inode->count counts in-memory pointers to the struct
prevents inode[] element from being re-used
protected by inode_table_lock
blocks and inodes have ad-hoc sleep-locks
provide a single mechanism?
need to lock bufs in bio between bread and brelse
test 14-character file names
and file arguments longer than 14
and directories longer than one sector
......@@ -97,4 +97,8 @@ void brelse(struct buf *);
// fs.c
struct inode * iget(uint dev, uint inum);
void ilock(struct inode *ip);
void iunlock(struct inode *ip);
void iincref(struct inode *ip);
void iput(struct inode *ip);
struct inode * namei(char *path);
......@@ -14,6 +14,9 @@
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)
{
......@@ -54,15 +57,50 @@ iget(uint dev, uint inum)
nip->nlink = dip->nlink;
nip->size = dip->size;
memmove(nip->addrs, dip->addrs, sizeof(nip->addrs));
cprintf("bn %d off %d\n", inum / IPB + 2, (unsigned)dip - (unsigned)bp->data);
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;
......@@ -71,3 +109,82 @@ iput(struct inode *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++;
}
}
......@@ -21,8 +21,10 @@ struct dinode {
#define IPB (512 / sizeof(struct dinode))
#define DIRSIZ 14
struct dirent {
ushort inum;
char name[14];
char name[DIRSIZ];
};
......@@ -10,3 +10,5 @@ struct inode {
uint size;
uint addrs[NDIRECT];
};
extern uint rootdev;
......@@ -24,7 +24,7 @@ ushort
xshort(ushort x)
{
ushort y;
uchar *a = &y;
uchar *a = (uchar *) &y;
a[0] = x;
a[1] = x >> 8;
return y;
......@@ -34,7 +34,7 @@ uint
xint(uint x)
{
uint y;
uchar *a = &y;
uchar *a = (uchar *) &y;
a[0] = x;
a[1] = x >> 8;
a[2] = x >> 16;
......@@ -47,16 +47,21 @@ main(int argc, char *argv[])
int i;
struct dinode din;
char dbuf[512];
uint bn;
if(argc != 2){
fprintf(stderr, "Usage: mkfs fs.img\n");
exit(1);
}
if(sizeof(struct dinode) * IPB != 512){
if((512 % sizeof(struct dinode)) != 0){
fprintf(stderr, "sizeof(dinode) must divide 512\n");
exit(1);
}
if((512 % sizeof(struct dirent)) != 0){
fprintf(stderr, "sizeof(dirent) must divide 512\n");
exit(1);
}
fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
if(fd < 0){
......@@ -78,7 +83,8 @@ main(int argc, char *argv[])
din.type = xshort(T_DIR);
din.nlink = xshort(2);
din.size = xint(512);
din.addrs[0] = xint(freeblock++);
bn = freeblock++;
din.addrs[0] = xint(bn);
winode(1, &din);
bzero(dbuf, sizeof(dbuf));
......@@ -86,7 +92,7 @@ main(int argc, char *argv[])
strcpy(((struct dirent *) dbuf)[0].name, ".");
((struct dirent *) dbuf)[1].inum = xshort(1);
strcpy(((struct dirent *) dbuf)[1].name, "..");
wsect(din.addrs[0], dbuf);
wsect(bn, dbuf);
exit(0);
}
......
......@@ -243,11 +243,21 @@ sys_block(void)
}
ip = iget(1, 1);
cprintf("%d %d %d %d %d %d %d %d\n",
cprintf("iget 1: %d %d %d %d %d %d %d %d\n",
ip->dev, ip->inum, ip->count, ip->busy,
ip->type, ip->nlink, ip->size, ip->addrs[0]);
iput(ip);
ip = namei(".././//./../");
if(ip){
cprintf("namei: %d %d %d %d %d %d %d %d\n",
ip->dev, ip->inum, ip->count, ip->busy,
ip->type, ip->nlink, ip->size, ip->addrs[0]);
iput(ip);
} else {
cprintf("namei failed\n");
}
return 0;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment