diff --git a/fs.c b/fs.c
index fa71c6e805baf7d280e5af9e2172593165780245..d5cc8991f581e4373aa91fa45241ff342256a587 100644
--- a/fs.c
+++ b/fs.c
@@ -412,6 +412,8 @@ namei(char *path, uint *ret_pinum)
     pinum = dp->inum;
     iput(dp);
     dp = iget(dev, ninum);
+    if(dp->type == 0 || dp->nlink < 1)
+      panic("namei");
     while(*cp == '/')
       cp++;
   }
@@ -443,7 +445,7 @@ mknod(char *cp, short type, short major, short minor)
   ip->major = major;
   ip->minor = minor;
   ip->size = 0;
-  ip->nlink = 0;
+  ip->nlink = 1;
 
   iupdate (ip);  // write new inode to disk
 
@@ -467,8 +469,8 @@ mknod(char *cp, short type, short major, short minor)
   brelse(bp);
   dp->size += sizeof(struct dirent);   // update directory inode
   iupdate (dp);
-  iput(dp);
-  return ip;
+          iput(dp);
+          return ip;
 }
 
 int
diff --git a/usertests.c b/usertests.c
index 12fa6f8f342a29726eff88d245fd949676114202..a3bb2848b337b968a2fc404ab7b448d69f92d732 100644
--- a/usertests.c
+++ b/usertests.c
@@ -157,6 +157,7 @@ sharedfd()
     }
   }
   close(fd);
+  unlink("sharedfd");
   if(nc == 1000 && np == 1000)
     printf(1, "sharedfd ok\n");
   else
@@ -219,14 +220,127 @@ twofiles()
     }
   }
 
+  unlink("f1");
+  unlink("f2");
+
   puts("twofiles ok\n");
 }
 
+// two processes create and delete files in same directory
+void
+createdelete()
+{
+  int pid, i, fd;
+  int n = 10; // for now, fit in one directory block
+  char name[32];
+
+  pid = fork();
+  if(pid < 0){
+    puts("fork failed\n");
+    exit();
+  }
+
+  name[0] = pid ? 'p' : 'c';
+  name[2] = '\0';
+  for(i = 0; i < n; i++){
+    name[1] = '0' + i;
+    fd = open(name, O_CREATE | O_RDWR);
+    if(fd < 0){
+      puts("create failed\n");
+      exit();
+    }
+    close(fd);
+    if(i > 0 && (i % 2 ) == 0){
+      name[1] = '0' + (i / 2);
+      if(unlink(name) < 0){
+        puts("unlink failed\n");
+        exit();
+      }
+    }
+  }
+
+  if(pid)
+    wait();
+  else
+    exit();
+
+  for(i = 0; i < n; i++){
+    name[0] = 'p';
+    name[1] = '0' + i;
+    fd = open(name, 0);
+    if((i == 0 || i >= n/2) && fd < 0){
+      printf(1, "oops createdelete %s didn't exist\n", name);
+    } else if((i >= 1 && i < n/2) && fd >= 0){
+      printf(1, "oops createdelete %s did exist\n", name);
+    }
+    if(fd >= 0)
+      close(fd);
+
+    name[0] = 'c';
+    name[1] = '0' + i;
+    fd = open(name, 0);
+    if((i == 0 || i >= n/2) && fd < 0){
+      printf(1, "oops createdelete %s didn't exist\n", name);
+    } else if((i >= 1 && i < n/2) && fd >= 0){
+      printf(1, "oops createdelete %s did exist\n", name);
+    }
+    if(fd >= 0)
+      close(fd);
+  }
+
+  for(i = 0; i < n; i++){
+    name[0] = 'p';
+    name[1] = '0' + i;
+    unlink(name);
+    name[0] = 'c';
+    unlink(name);
+  }
+
+  printf(1, "createdelete ok\n");
+}
+
+// can I unlink a file and still read it?
+void
+unlinkread()
+{
+  int fd;
+  
+  fd = open("unlinkread", O_CREATE | O_RDWR);
+  if(fd < 0){
+    puts("create unlinkread failed\n");
+    exit();
+  }
+  write(fd, "hello", 5);
+  close(fd);
+
+  fd = open("unlinkread", O_RDWR);
+  if(fd < 0){
+    puts("open unlinkread failed\n");
+    exit();
+  }
+  if(unlink("unlinkread") != 0){
+    puts("unlink unlinkread failed\n");
+    exit();
+  }
+  if(read(fd, buf, sizeof(buf)) != 5){
+    puts("unlinkread read failed");
+    exit();
+  }
+  if(write(fd, buf, 10) != 10){
+    puts("unlinkread write failed\n");
+    exit();
+  }
+  close(fd);
+  puts("unlinkread ok\n");
+}
+
 int
 main(int argc, char *argv[])
 {
   puts("usertests starting\n");
 
+  unlinkread();
+  createdelete();
   twofiles();
   sharedfd();
   pipe1();