From 24437cd554995f729969299e72699e2ba5d9b068 Mon Sep 17 00:00:00 2001
From: kaashoek <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);
-- 
GitLab