This commit is contained in:
rtm 2006-07-21 22:10:40 +00:00
parent 11a9947f1a
commit 9d3fb67141
7 changed files with 164 additions and 11 deletions

18
Notes
View file

@ -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
View file

@ -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
View file

@ -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
View file

@ -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];
}; };

View file

@ -10,3 +10,5 @@ struct inode {
uint size; uint size;
uint addrs[NDIRECT]; uint addrs[NDIRECT];
}; };
extern uint rootdev;

16
mkfs.c
View file

@ -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);
} }

View file

@ -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;
} }