diff --git a/Notes b/Notes
index 54b93dbf95e92940e18ca2321087bc31442a5229..9cebfab9d7b6c302a609118eb6e46a40cc46a8c6 100644
--- a/Notes
+++ b/Notes
@@ -114,17 +114,10 @@ why does shell often ignore first line of input?
 
 test: one process unlinks a file while another links to it
 test: one process opens a file while another deletes it
-test: mkdir. deadlock d/.. vs ../d
-test: sub-sub directories. mkdir("d1/d2")
+test: mkdir. deadlock d/.. vs ../d, two processes.
 test: dup() shared fd->off
-test: indirect blocks. files and directories.
 test: sbrk
 test: does echo foo > x truncate x?
-test: does create/mkdir/link extract last component correctly?
-      does namei insist that all the intermediate directories exist?
-test: creat/link/mkdir w/ / in name
-test: try to create dir ents when intermediate dir doesn't exist
-      or is a file, not a dir   
 
 make proc[0] runnable
 cpu early tss and gdt
diff --git a/fstests.c b/fstests.c
index a51d487cb796bc36ff8257faeced8b7d32adc61f..d6356ac8955fa817f6ca7c163c562eae370a865a 100644
--- a/fstests.c
+++ b/fstests.c
@@ -450,6 +450,19 @@ subdir()
     exit();
   }
 
+  if(chdir("dd") != 0){
+    puts("chdir dd failed\n");
+    exit();
+  }
+  if(chdir("dd/../../dd") != 0){
+    puts("chdir dd/../../dd failed\n");
+    exit();
+  }
+  if(chdir("./..") != 0){
+    puts("chdir ./.. failed\n");
+    exit();
+  }
+
   fd = open("dd/dd/ffff", 0);
   if(fd < 0){
     puts("open dd/dd/ffff failed\n");
@@ -506,6 +519,14 @@ subdir()
     puts("unlink dd/ff/ff succeeded!\n");
     exit();
   }
+  if(chdir("dd/ff") == 0){
+    puts("chdir dd/ff succeeded!\n");
+    exit();
+  }
+  if(chdir("dd/xx") == 0){
+    puts("chdir dd/xx succeeded!\n");
+    exit();
+  }
 
   if(unlink("dd/dd/ffff") != 0){
     puts("unlink dd/dd/ff failed\n");
@@ -522,11 +543,66 @@ subdir()
   puts("subdir ok\n");
 }
 
+void
+bigfile()
+{
+  int fd, i, total, cc;
+
+  unlink("bigfile");
+  fd = open("bigfile", O_CREATE | O_RDWR);
+  if(fd < 0){
+    puts("cannot create bigfile");
+    exit();
+  }
+  for(i = 0; i < 20; i++){
+    memset(buf, i, 600);
+    if(write(fd, buf, 600) != 600){
+      puts("write bigfile failed\n");
+      exit();
+    }
+  }
+  close(fd);
+  
+  fd = open("bigfile", 0);
+  if(fd < 0){
+    puts("cannot open bigfile\n");
+    exit();
+  }
+  total = 0;
+  for(i = 0; ; i++){
+    cc = read(fd, buf, 300);
+    if(cc < 0){
+      puts("read bigfile failed\n");
+      exit();
+    }
+    if(cc == 0)
+      break;
+    if(cc != 300){
+      puts("short read bigfile\n");
+      exit();
+    }
+    if(buf[0] != i/2 || buf[299] != i/2){
+      puts("read bigfile wrong data\n");
+      exit();
+    }
+    total += cc;
+  }
+  close(fd);
+  if(total != 20*600){
+    puts("read bigfile wrong total\n");
+    exit();
+  }
+  unlink("bigfile");
+
+  puts("bigfile ok\n");
+}
+
 int
 main(int argc, char *argv[])
 {
   puts("fstests starting\n");
 
+  bigfile();
   subdir();
   // bigdir(); // slow
   concreate();
diff --git a/syscall.c b/syscall.c
index 8571cca85e164195ccde0186f317874457a9b4e4..9e256a8b4474945aa27506cbf83a7e5f5dc95fd2 100644
--- a/syscall.c
+++ b/syscall.c
@@ -320,6 +320,8 @@ sys_mkdir(void)
     return -1;
 
   nip = mknod (cp->mem + arg0, T_DIR, 0, 0);
+  if(nip == 0)
+    return -1;
   
   memset (de.name, '\0', DIRSIZ);
   de.name[0] = '.';
@@ -356,7 +358,7 @@ sys_chdir(void)
 
   if ((ip = namei(cp->mem + arg0, NAMEI_LOOKUP, 0, 0, 0)) == 0)
     return -1;
-  
+
   if (ip == cp->cwd) {
     iput (ip);
     return 0;
@@ -364,7 +366,7 @@ sys_chdir(void)
 
   if (ip->type != T_DIR) {
     iput(ip);
-    return 0;
+    return -1;
   }
 
   idecref(cp->cwd);