diff --git a/defs.h b/defs.h
index 5e3c1e43612ca65360959f35ef234358584fef33..91e06022cf18590505607990717d219f8de42e1d 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 cbf417eb37f7d82269ef878f20b27293dde77a9b..0f4ed79a4dd85fde4d8fd8cef13ded51634a3e1a 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 b926863b4539023ad3587608b0e115a0f89ceeee..0bd672a340be29c85ffe2f334b8f121bc95bca4c 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 6ba185ebc02a1b0e19081563ac3b93bb42981318..324926eff7757e7ecddadf4858be5f8b5f662dfb 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 af875617204a605eafd385951c256ec6360aa5b5..8c6121b8235790c6e2608a3de9e9a0610feab6ee 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);