diff --git a/fs.c b/fs.c
index d5cc8991f581e4373aa91fa45241ff342256a587..4d32aa8a48a217b939189758df269bddc257c7ca 100644
--- a/fs.c
+++ b/fs.c
@@ -226,6 +226,38 @@ iunlock(struct inode *ip)
   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;
+}
+
+void 
+iunlink(struct inode *ip)
+{
+  int i;
+
+  // 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?
+}
+
 // caller is releasing a reference to this inode.
 // you must have the inode lock.
 void
@@ -234,6 +266,9 @@ iput(struct inode *ip)
   if(ip->count < 1 || ip->busy != 1)
     panic("iput");
 
+  if ((ip->count <= 1) && (ip->nlink <= 0)) 
+    iunlink(ip);
+
   acquire(&inode_table_lock);
 
   ip->count -= 1;
@@ -256,21 +291,6 @@ idecref(struct inode *ip)
   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;
-}
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
 void
 stati(struct inode *ip, struct stat *st)
 {
@@ -281,6 +301,8 @@ stati(struct inode *ip, struct stat *st)
   st->st_size = ip->size;
 }
 
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
 int
 readi(struct inode *ip, char *dst, uint off, uint n)
 {
@@ -307,8 +329,6 @@ readi(struct inode *ip, char *dst, uint off, uint n)
   return target - n;
 }
 
-#define MIN(a, b) ((a < b) ? a : b)
-
 int
 writei(struct inode *ip, char *addr, uint off, uint n)
 {
@@ -330,7 +350,7 @@ writei(struct inode *ip, char *addr, uint off, uint n)
 	if (b <= 0) return r;
 	ip->addrs[lbn] = b;
       }
-      m = MIN(BSIZE - off % BSIZE, n-r);
+      m = min(BSIZE - off % BSIZE, n-r);
       bp = bread(ip->dev, bmap(ip, off / BSIZE));
       memmove (bp->data + off % BSIZE, addr, m);
       bwrite (ip->dev, bp, bmap(ip, off/BSIZE));
@@ -476,12 +496,13 @@ mknod(char *cp, short type, short major, short minor)
 int
 unlink(char *cp)
 {
-  int i;
-  struct inode *ip, *dp;
+  struct inode *ip;
+  struct inode *dp;
   struct dirent *ep = 0;
   int off;
   struct buf *bp = 0;
   uint pinum;
+
   
   if ((ip = namei(cp, &pinum)) == 0) {
     cprintf("file to be unlinked doesn't exist\n");
@@ -490,24 +511,10 @@ unlink(char *cp)
 
   ip->nlink--;
   if (ip->nlink > 0) {
-    iupdate(ip);
-    iput(ip); // is this the right order?
+    iput(ip);
     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, pinum);
   for(off = 0; off < dp->size; off += BSIZE) {
     bp = bread(dp->dev, bmap(dp, off / BSIZE));
@@ -526,8 +533,8 @@ unlink(char *cp)
   ep->inum = 0;
   bwrite (dp->dev, bp, bmap(dp, off/BSIZE));   // write directory block
   brelse(bp);
-  iput(ip);
   iupdate (dp);
   iput(dp);
+  iput(ip);
   return 0;
 }