namei
This commit is contained in:
parent
11a9947f1a
commit
9d3fb67141
7 changed files with 164 additions and 11 deletions
18
Notes
18
Notes
|
@ -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
|
||||
|
|
4
defs.h
4
defs.h
|
@ -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);
|
||||
|
|
119
fs.c
119
fs.c
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
4
fs.h
4
fs.h
|
@ -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];
|
||||
};
|
||||
|
||||
|
|
2
fsvar.h
2
fsvar.h
|
@ -10,3 +10,5 @@ struct inode {
|
|||
uint size;
|
||||
uint addrs[NDIRECT];
|
||||
};
|
||||
|
||||
extern uint rootdev;
|
||||
|
|
16
mkfs.c
16
mkfs.c
|
@ -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);
|
||||
}
|
||||
|
|
12
syscall.c
12
syscall.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue