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()?
|
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
|
device interrupts don't clear FL_IF
|
||||||
so a recursive timer interrupt is possible
|
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
|
// fs.c
|
||||||
struct inode * iget(uint dev, uint inum);
|
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);
|
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 inode inode[NINODE];
|
||||||
struct spinlock inode_table_lock;
|
struct spinlock inode_table_lock;
|
||||||
|
|
||||||
|
uint rootdev = 1;
|
||||||
|
|
||||||
|
// returns an inode with busy set and incremented reference count.
|
||||||
struct inode *
|
struct inode *
|
||||||
iget(uint dev, uint inum)
|
iget(uint dev, uint inum)
|
||||||
{
|
{
|
||||||
|
@ -54,15 +57,50 @@ iget(uint dev, uint inum)
|
||||||
nip->nlink = dip->nlink;
|
nip->nlink = dip->nlink;
|
||||||
nip->size = dip->size;
|
nip->size = dip->size;
|
||||||
memmove(nip->addrs, dip->addrs, sizeof(nip->addrs));
|
memmove(nip->addrs, dip->addrs, sizeof(nip->addrs));
|
||||||
cprintf("bn %d off %d\n", inum / IPB + 2, (unsigned)dip - (unsigned)bp->data);
|
|
||||||
brelse(bp);
|
brelse(bp);
|
||||||
|
|
||||||
return nip;
|
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
|
void
|
||||||
iput(struct inode *ip)
|
iput(struct inode *ip)
|
||||||
{
|
{
|
||||||
|
if(ip->count < 1 || ip->busy != 1)
|
||||||
|
panic("iput");
|
||||||
|
|
||||||
acquire(&inode_table_lock);
|
acquire(&inode_table_lock);
|
||||||
|
|
||||||
ip->count -= 1;
|
ip->count -= 1;
|
||||||
|
@ -71,3 +109,82 @@ iput(struct inode *ip)
|
||||||
|
|
||||||
release(&inode_table_lock);
|
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 IPB (512 / sizeof(struct dinode))
|
||||||
|
|
||||||
|
#define DIRSIZ 14
|
||||||
|
|
||||||
struct dirent {
|
struct dirent {
|
||||||
ushort inum;
|
ushort inum;
|
||||||
char name[14];
|
char name[DIRSIZ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
2
fsvar.h
2
fsvar.h
|
@ -10,3 +10,5 @@ struct inode {
|
||||||
uint size;
|
uint size;
|
||||||
uint addrs[NDIRECT];
|
uint addrs[NDIRECT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern uint rootdev;
|
||||||
|
|
16
mkfs.c
16
mkfs.c
|
@ -24,7 +24,7 @@ ushort
|
||||||
xshort(ushort x)
|
xshort(ushort x)
|
||||||
{
|
{
|
||||||
ushort y;
|
ushort y;
|
||||||
uchar *a = &y;
|
uchar *a = (uchar *) &y;
|
||||||
a[0] = x;
|
a[0] = x;
|
||||||
a[1] = x >> 8;
|
a[1] = x >> 8;
|
||||||
return y;
|
return y;
|
||||||
|
@ -34,7 +34,7 @@ uint
|
||||||
xint(uint x)
|
xint(uint x)
|
||||||
{
|
{
|
||||||
uint y;
|
uint y;
|
||||||
uchar *a = &y;
|
uchar *a = (uchar *) &y;
|
||||||
a[0] = x;
|
a[0] = x;
|
||||||
a[1] = x >> 8;
|
a[1] = x >> 8;
|
||||||
a[2] = x >> 16;
|
a[2] = x >> 16;
|
||||||
|
@ -47,16 +47,21 @@ main(int argc, char *argv[])
|
||||||
int i;
|
int i;
|
||||||
struct dinode din;
|
struct dinode din;
|
||||||
char dbuf[512];
|
char dbuf[512];
|
||||||
|
uint bn;
|
||||||
|
|
||||||
if(argc != 2){
|
if(argc != 2){
|
||||||
fprintf(stderr, "Usage: mkfs fs.img\n");
|
fprintf(stderr, "Usage: mkfs fs.img\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sizeof(struct dinode) * IPB != 512){
|
if((512 % sizeof(struct dinode)) != 0){
|
||||||
fprintf(stderr, "sizeof(dinode) must divide 512\n");
|
fprintf(stderr, "sizeof(dinode) must divide 512\n");
|
||||||
exit(1);
|
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);
|
fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
|
||||||
if(fd < 0){
|
if(fd < 0){
|
||||||
|
@ -78,7 +83,8 @@ main(int argc, char *argv[])
|
||||||
din.type = xshort(T_DIR);
|
din.type = xshort(T_DIR);
|
||||||
din.nlink = xshort(2);
|
din.nlink = xshort(2);
|
||||||
din.size = xint(512);
|
din.size = xint(512);
|
||||||
din.addrs[0] = xint(freeblock++);
|
bn = freeblock++;
|
||||||
|
din.addrs[0] = xint(bn);
|
||||||
winode(1, &din);
|
winode(1, &din);
|
||||||
|
|
||||||
bzero(dbuf, sizeof(dbuf));
|
bzero(dbuf, sizeof(dbuf));
|
||||||
|
@ -86,7 +92,7 @@ main(int argc, char *argv[])
|
||||||
strcpy(((struct dirent *) dbuf)[0].name, ".");
|
strcpy(((struct dirent *) dbuf)[0].name, ".");
|
||||||
((struct dirent *) dbuf)[1].inum = xshort(1);
|
((struct dirent *) dbuf)[1].inum = xshort(1);
|
||||||
strcpy(((struct dirent *) dbuf)[1].name, "..");
|
strcpy(((struct dirent *) dbuf)[1].name, "..");
|
||||||
wsect(din.addrs[0], dbuf);
|
wsect(bn, dbuf);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
12
syscall.c
12
syscall.c
|
@ -243,11 +243,21 @@ sys_block(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
ip = iget(1, 1);
|
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->dev, ip->inum, ip->count, ip->busy,
|
||||||
ip->type, ip->nlink, ip->size, ip->addrs[0]);
|
ip->type, ip->nlink, ip->size, ip->addrs[0]);
|
||||||
iput(ip);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue