From 24437cd554995f729969299e72699e2ba5d9b068 Mon Sep 17 00:00:00 2001 From: kaashoek Date: Fri, 11 Aug 2006 18:18:38 +0000 Subject: [PATCH] fix deadlock---iput(dp) asap working unlink, but doesn't free dir blocks that become empty remove out-of-date comment in ioapic --- defs.h | 1 + fs.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- ioapic.c | 2 +- syscall.c | 36 ++++++++------------------------- userfs.c | 7 ++++--- 5 files changed, 73 insertions(+), 33 deletions(-) diff --git a/defs.h b/defs.h index 5e3c1e4..91e0602 100644 --- a/defs.h +++ b/defs.h @@ -118,4 +118,5 @@ struct inode * namei(char *path); int readi(struct inode *ip, char *xdst, uint off, uint n); int writei(struct inode *ip, char *addr, uint off, uint n); struct inode *mknod(struct inode *, char *, short, short, short); +int unlink(char *cp); void iupdate (struct inode *ip); diff --git a/fs.c b/fs.c index cbf417e..0f4ed79 100644 --- a/fs.c +++ b/fs.c @@ -187,7 +187,7 @@ ialloc(uint dev, short type) } static void -ifree(uint dev, struct inode *ip) +ifree(struct inode *ip) { ip->type = 0; iupdate(ip); @@ -440,3 +440,61 @@ mknod(struct inode *dp, char *cp, short type, short major, short minor) return ip; } + +int +unlink(char *cp) +{ + int i; + struct inode *ip, *dp; + struct dirent *ep = 0; + int off; + struct buf *bp = 0; + + if ((ip = namei(cp)) == 0) { + cprintf("file to be unlinked doesn't exist\n"); + return -1; + } + + ip->nlink--; + if (ip->nlink > 0) { + iupdate(ip); + iput(ip); // is this the right order? + return 0; + } + + // free inode, its blocks, and remove dir entry + for (i = 0; i < NDIRECT; i++) { + if (ip->addrs[i] != 0) { + bfree(ip->dev, ip->addrs[i]); + ip->addrs[i] = 0; + } + } + ip->size = 0; + ip->major = 0; + ip->minor = 0; + iupdate(ip); + ifree(ip); // is this the right order? + + dp = iget(rootdev, 1); // XXX should parse name + for(off = 0; off < dp->size; off += BSIZE) { + bp = bread(dp->dev, bmap(dp, off / BSIZE)); + for(ep = (struct dirent *) bp->data; + ep < (struct dirent *) (bp->data + BSIZE); + ep++){ + if(ep->inum == ip->inum) { + goto found; + } + } + brelse(bp); + } + panic("mknod: XXXX no dir entry free\n"); + + found: + ep->inum = 0; + bwrite (dp->dev, bp, bmap(dp, off/BSIZE)); // write directory block + brelse(bp); + iput(ip); + iupdate (dp); + iput(dp); + return 0; +} diff --git a/ioapic.c b/ioapic.c index b926863..0bd672a 100644 --- a/ioapic.c +++ b/ioapic.c @@ -76,7 +76,7 @@ ioapic_enable (int irq, int cpunum) ioapic_write(io, IOAPIC_REDTBL_LO(irq), l); h = ioapic_read(io, IOAPIC_REDTBL_HI(irq)); h &= ~IOART_DEST; - h |= (cpunum << APIC_ID_SHIFT); // for fun, disk interrupts to cpu 1 + h |= (cpunum << APIC_ID_SHIFT); ioapic_write(io, IOAPIC_REDTBL_HI(irq), h); cprintf("cpu%d: intr %d: lo 0x%x hi 0x%x\n", cpu(), irq, l, h); } diff --git a/syscall.c b/syscall.c index 6ba185e..324926e 100644 --- a/syscall.c +++ b/syscall.c @@ -265,10 +265,9 @@ sys_open(void) if (l >= DIRSIZ) return -1; dp = iget(rootdev, 1); // XXX should parse name - if (dp->type != T_DIR) - return -1; - if ((ip = mknod (dp, cp->mem + arg0, T_FILE, 0, 0)) == 0) - return -1; + ip = mknod (dp, cp->mem + arg0, T_FILE, 0, 0); + iput(dp); + if (ip == 0) return -1; } else return -1; } if((fd = fd_alloc()) == 0){ @@ -319,45 +318,26 @@ sys_mknod(void) return -1; dp = iget(rootdev, 1); // XXX should parse name - if (dp->type != T_DIR) { - iput(dp); - return -1; - } - nip = mknod (dp, cp->mem + arg0, (short) arg1, (short) arg2, (short) arg3); - iput(dp); - - if (nip == 0) return -1; - iput(nip); - - return 0; + return (nip == 0) ? -1 : 0; } int sys_unlink(void) { struct proc *cp = curproc[cpu()]; - struct inode *ip; uint arg0; - + int r; + if(fetcharg(0, &arg0) < 0) return -1; - if(checkstring(arg0) < 0) return -1; - - ip = namei(cp->mem + arg0); - ip->nlink--; - if (ip->nlink <= 0) { - panic("sys_link: unimplemented\n"); - } - iupdate(ip); - iput(ip); - - return 0; + r = unlink(cp->mem + arg0); + return r; } int diff --git a/userfs.c b/userfs.c index af87561..8c6121b 100644 --- a/userfs.c +++ b/userfs.c @@ -5,7 +5,7 @@ // file system tests -char buf[2000]; +char buf[3000]; char *echo_args[] = { "echo", "hello", "goodbye", 0 }; char *cat_args[] = { "cat", "README", 0 }; @@ -62,13 +62,14 @@ main(void) } else { printf(stdout, "error: open doesnotexist failed!\n"); } - i = read(fd, buf, 10000); + i = read(fd, buf, 2000); if (i == 2000) { - printf(stdout, "read succeeded\\n"); + printf(stdout, "read succeeded\n"); } else { printf(stdout, "read failed\n"); } close(fd); + unlink("doesnotexist"); //exec("echo", echo_args); printf(stdout, "about to do exec\n"); exec("cat", cat_args);