fix iget() bug that allocated in-use inode[] entries

This commit is contained in:
rtm 2006-08-13 15:51:58 +00:00
parent 8abe2bcf15
commit 17e3cf15ba
7 changed files with 20 additions and 61 deletions

14
Notes
View file

@ -357,7 +357,6 @@ OH! recursive interrupts will use up any amount of cpu[].stack!
disk scheduling disk scheduling
mkdir mkdir
more than one directory content block
sh arguments sh arguments
sh redirection sh redirection
indirect blocks indirect blocks
@ -366,17 +365,10 @@ two bugs in unlink: don't just return if nlink > 0,
is there a create/create race for same file name? is there a create/create race for same file name?
resulting in two entries w/ same name in directory? resulting in two entries w/ same name in directory?
namei
return just inode
return offset in dir where found, w/ dir locked, for unlink
return dir locked, for mknod
is the offset alone useful? how do I read/write it?
test: one process unlinks a file while another links to it test: one process unlinks a file while another links to it
test: simultaneous create of same file test: simultaneous create of same file
test: one process opens a file while another deletes it test: one process opens a file while another deletes it
oy, mkfs wants dir size to be last written entry, but i wdir should use writei, to avoid special-case block allocation
want it to be nblocks*512 also readi
maybe fix kernel code to handle former is dir locked? probably

2
fd.c
View file

@ -8,6 +8,8 @@
#include "fd.h" #include "fd.h"
#include "spinlock.h" #include "spinlock.h"
#include "dev.h" #include "dev.h"
#include "fs.h"
#include "fsvar.h"
struct spinlock fd_table_lock; struct spinlock fd_table_lock;
struct devsw devsw[NDEV]; struct devsw devsw[NDEV];

50
fs.c
View file

@ -54,7 +54,6 @@ balloc(uint dev)
if (b >= size) if (b >= size)
panic("balloc: out of blocks\n"); panic("balloc: out of blocks\n");
cprintf ("balloc: allocate block %d\n", b);
bp->data[bi/8] |= 0x1 << (bi % 8); bp->data[bi/8] |= 0x1 << (bi % 8);
bwrite (bp, BBLOCK(b, ninodes)); // mark it allocated on disk bwrite (bp, BBLOCK(b, ninodes)); // mark it allocated on disk
brelse(bp); brelse(bp);
@ -70,7 +69,6 @@ bfree(int dev, uint b)
int ninodes; int ninodes;
uchar m; uchar m;
cprintf ("bfree: free block %d\n", b);
bp = bread(dev, 1); bp = bread(dev, 1);
sb = (struct superblock *) bp->data; sb = (struct superblock *) bp->data;
ninodes = sb->ninodes; ninodes = sb->ninodes;
@ -93,13 +91,14 @@ bfree(int dev, uint b)
struct inode * struct inode *
iget(uint dev, uint inum) iget(uint dev, uint inum)
{ {
struct inode *ip, *nip = 0; struct inode *ip, *nip;
struct dinode *dip; struct dinode *dip;
struct buf *bp; struct buf *bp;
acquire(&inode_table_lock); acquire(&inode_table_lock);
loop: loop:
nip = 0;
for(ip = &inode[0]; ip < &inode[NINODE]; ip++){ for(ip = &inode[0]; ip < &inode[NINODE]; ip++){
if(ip->count > 0 && ip->dev == dev && ip->inum == inum){ if(ip->count > 0 && ip->dev == dev && ip->inum == inum){
if(ip->busy){ if(ip->busy){
@ -180,11 +179,9 @@ ialloc(uint dev, short type)
brelse(bp); brelse(bp);
} }
if (inum >= ninodes) { if (inum >= ninodes)
panic ("ialloc: no inodes left\n"); panic ("ialloc: no inodes left\n");
}
cprintf ("ialloc: %d\n", inum);
dip->type = type; dip->type = type;
bwrite (bp, IBLOCK(inum)); // mark it allocated on the disk bwrite (bp, IBLOCK(inum)); // mark it allocated on the disk
brelse(bp); brelse(bp);
@ -195,7 +192,6 @@ ialloc(uint dev, short type)
static void static void
ifree(struct inode *ip) ifree(struct inode *ip)
{ {
cprintf("ifree: %d\n", ip->inum);
ip->type = 0; ip->type = 0;
iupdate(ip); iupdate(ip);
} }
@ -220,7 +216,7 @@ ilock(struct inode *ip)
void void
iunlock(struct inode *ip) iunlock(struct inode *ip)
{ {
if(ip->busy != 1) if(ip->busy != 1 || ip->count < 1)
panic("iunlock"); panic("iunlock");
acquire(&inode_table_lock); acquire(&inode_table_lock);
@ -271,7 +267,7 @@ iput(struct inode *ip)
if(ip->count < 1 || ip->busy != 1) if(ip->count < 1 || ip->busy != 1)
panic("iput"); panic("iput");
if ((ip->count <= 1) && (ip->nlink <= 0)) if ((ip->count == 1) && (ip->nlink == 0))
iunlink(ip); iunlink(ip);
acquire(&inode_table_lock); acquire(&inode_table_lock);
@ -498,8 +494,6 @@ mknod(char *cp, short type, short major, short minor)
{ {
struct inode *ip, *dp; struct inode *ip, *dp;
cprintf("mknod: %s %d %d %d\n", cp, type, major, minor);
if ((dp = namei(cp, NAMEI_CREATE, 0)) == 0) if ((dp = namei(cp, NAMEI_CREATE, 0)) == 0)
return 0; return 0;
@ -525,24 +519,17 @@ unlink(char *cp)
{ {
struct inode *ip, *dp; struct inode *ip, *dp;
struct dirent de; struct dirent de;
uint off, inum, cc; uint off, inum, dev;
cprintf("unlink(%s)\n", cp); if ((dp = namei(cp, NAMEI_DELETE, &off)) == 0)
if ((dp = namei(cp, NAMEI_DELETE, &off)) == 0) {
cprintf("unlink(%s) it doesn't exist\n", cp);
return -1; return -1;
}
if((cc = readi(dp, (char*)&de, off, sizeof(de))) != sizeof(de) || dev = dp->dev;
de.inum == 0){
cprintf("off %d dp->size %d cc %d de.inum %d", if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de) || de.inum == 0)
off, dp->size, cc, de.inum);
panic("unlink no entry"); panic("unlink no entry");
}
inum = de.inum; inum = de.inum;
cprintf("dinum %d off %d de %s/%d\n",
dp->inum, off, de.name, de.inum);
memset(&de, 0, sizeof(de)); memset(&de, 0, sizeof(de));
if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
@ -551,9 +538,7 @@ unlink(char *cp)
iupdate(dp); iupdate(dp);
iput(dp); iput(dp);
ip = iget(dp->dev, inum); ip = iget(dev, inum);
if(ip == 0)
panic("unlink no inode");
ip->nlink--; ip->nlink--;
@ -568,14 +553,9 @@ link(char *name1, char *name2)
{ {
struct inode *ip, *dp; struct inode *ip, *dp;
cprintf("link(%s, %s)\n", name1, name2); if ((ip = namei(name1, NAMEI_LOOKUP, 0)) == 0)
if ((ip = namei(name1, NAMEI_LOOKUP, 0)) == 0){
cprintf(" failed %s does not exist\n", name1);
return -1; return -1;
}
if(ip->type == T_DIR){ if(ip->type == T_DIR){
cprintf(" failed %s is a dir\n", name1);
iput(ip); iput(ip);
return -1; return -1;
} }
@ -583,12 +563,10 @@ link(char *name1, char *name2)
iunlock(ip); iunlock(ip);
if ((dp = namei(name2, NAMEI_CREATE, 0)) == 0) { if ((dp = namei(name2, NAMEI_CREATE, 0)) == 0) {
cprintf(" failed %s exists\n", name2);
idecref(ip); idecref(ip);
return -1; return -1;
} }
if(dp->dev != ip->dev){ if(dp->dev != ip->dev){
cprintf(" cross-device link\n");
idecref(ip); idecref(ip);
iput(dp); iput(dp);
return -1; return -1;
@ -602,7 +580,5 @@ link(char *name1, char *name2)
iput(dp); iput(dp);
iput(ip); iput(ip);
cprintf(" succeeded\n");
return 0; return 0;
} }

3
init.c
View file

@ -17,10 +17,7 @@ main(void)
open("console", 1); open("console", 1);
open("console", 1); open("console", 1);
puts("init...\n");
while(1){ while(1){
puts("running sh...\n");
pid = fork(); pid = fork();
if(pid == 0){ if(pid == 0){
exec("sh", sh_args); exec("sh", sh_args);

View file

@ -43,7 +43,6 @@ ioapic_init(void)
id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT; id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT;
if (id != ioapic_id) if (id != ioapic_id)
panic ("ioapic_init: id isn't equal to ioapic_id\n"); panic ("ioapic_init: id isn't equal to ioapic_id\n");
cprintf ("ioapic VER: 0x%x id %d nintr %d\n", l, id, nintr);
for (i = 0; i < nintr; i++) { for (i = 0; i < nintr; i++) {
// active-hi and edge-triggered for ISA interrupts // active-hi and edge-triggered for ISA interrupts
// Assume that pin 0 on the first I/O APIC is an ExtINT pin. // Assume that pin 0 on the first I/O APIC is an ExtINT pin.
@ -78,5 +77,4 @@ ioapic_enable (int irq, int cpunum)
h &= ~IOART_DEST; h &= ~IOART_DEST;
h |= (cpunum << APIC_ID_SHIFT); h |= (cpunum << APIC_ID_SHIFT);
ioapic_write(io, IOAPIC_REDTBL_HI(irq), h); ioapic_write(io, IOAPIC_REDTBL_HI(irq), h);
cprintf("cpu%d: intr %d: lo 0x%x hi 0x%x\n", cpu(), irq, l, h);
} }

View file

@ -22,13 +22,6 @@ irq_setmask_8259A(ushort mask)
outb(IO_PIC1+1, (char)mask); outb(IO_PIC1+1, (char)mask);
outb(IO_PIC2+1, (char)(mask >> 8)); outb(IO_PIC2+1, (char)(mask >> 8));
cprintf("%d: enabled interrupts:", cpu());
for (i = 0; i < 16; i++)
if (~mask & (1<<i))
cprintf(" %d", i);
cprintf("\n");
} }
/* Initialize the 8259A interrupt controllers. */ /* Initialize the 8259A interrupt controllers. */

View file

@ -284,7 +284,8 @@ sys_mknod(void)
return -1; return -1;
nip = mknod (cp->mem + arg0, (short) arg1, (short) arg2, (short) arg3); nip = mknod (cp->mem + arg0, (short) arg1, (short) arg2, (short) arg3);
iput(nip); if(nip)
iput(nip);
return (nip == 0) ? -1 : 0; return (nip == 0) ? -1 : 0;
} }