From 2036534834841641edf3a6d1e142c4798e146b7b Mon Sep 17 00:00:00 2001
From: rtm <rtm>
Date: Fri, 24 Aug 2007 14:56:17 +0000
Subject: [PATCH] add missing iput() at end of _namei()

---
 bootmain.c  |  2 +-
 fs.c        | 10 +++---
 mkfs.c      |  4 +--
 param.h     |  2 +-
 proc.h      | 12 +++----
 runoff      |  2 +-
 usertests.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 110 insertions(+), 17 deletions(-)

diff --git a/bootmain.c b/bootmain.c
index 1882aa8..6494c16 100644
--- a/bootmain.c
+++ b/bootmain.c
@@ -12,7 +12,7 @@
 // BOOT UP STEPS
 //  * when the CPU boots it loads the BIOS into memory and executes it
 //
-//  * the BIOS intializes devices, sets of the interrupt routines, and
+//  * the BIOS intializes devices, sets up the interrupt routines, and
 //    reads the first sector of the boot device(e.g., hard-drive)
 //    into memory and jumps to it.
 //
diff --git a/fs.c b/fs.c
index e47b6fa..a6e1787 100644
--- a/fs.c
+++ b/fs.c
@@ -475,6 +475,7 @@ namecmp(const char *s, const char *t)
 
 // Look for a directory entry in a directory.
 // If found, set *poff to byte offset of entry.
+// Caller must have already locked dp.
 struct uinode*
 dirlookup(struct inode *dp, char *name, uint *poff)
 {
@@ -483,7 +484,7 @@ dirlookup(struct inode *dp, char *name, uint *poff)
   struct dirent *de;
 
   if(dp->type != T_DIR)
-    return 0;
+    panic("dirlookup not DIR");
 
   for(off = 0; off < dp->size; off += BSIZE){
     bp = bread(dp->dev, bmap(dp, off / BSIZE, 0));
@@ -558,7 +559,7 @@ dirlink(struct inode *dp, char *name, uint ino)
 //
 // Examples:
 //   skipelem("a/bb/c", name) = "bb/c", setting name = "a"
-//   skipelem("///a/bb", name) = "b", setting name="a"
+//   skipelem("///a/bb", name) = "bb", setting name="a"
 //   skipelem("", name) = skipelem("////", name) = 0
 //
 static char*
@@ -617,14 +618,15 @@ _namei(char *path, int parent, char *name)
 
     if((ipu = dirlookup(dp, name, &off)) == 0){
       iput(iunlock(dp));
-      iput(ipu);
       return 0;
     }
     iput(iunlock(dp));
     dpu = ipu;
   }
-  if(parent)
+  if(parent){
+    iput(dpu);
     return 0;
+  }
   return dpu;
 }
 
diff --git a/mkfs.c b/mkfs.c
index 462c270..b367f61 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -8,8 +8,8 @@
 #include "param.h"
 #include "fs.h"
 
-int nblocks = 1008;
-int ninodes = 100;
+int nblocks = 995;
+int ninodes = 200;
 int size = 1024;
 
 int fsfd;
diff --git a/param.h b/param.h
index 7ceecb5..343288c 100644
--- a/param.h
+++ b/param.h
@@ -6,6 +6,6 @@
 #define NFILE       100  // open files per system
 #define NBUF         10  // size of disk block cache
 #define NREQUEST   NBUF  // outstanding disk requests
-#define NINODE      100  // maximum number of active i-nodes
+#define NINODE       50  // maximum number of active i-nodes
 #define NDEV         10  // maximum major device number
 #define ROOTDEV       1  // device number of file system root disk
diff --git a/proc.h b/proc.h
index 9750c15..137bda3 100644
--- a/proc.h
+++ b/proc.h
@@ -43,19 +43,15 @@ struct proc {
   char name[16];            // Process name (debugging)
 };
 
-// Process memory is laid out contiguously:
+// Process memory is laid out contiguously, low addresses first:
 //   text
 //   original data and bss
 //   fixed-size stack
 //   expandable heap
 
-// If xv6 was only for uniprocessors, this could be
-//   struct proc *cp;
-// Instead we have an array curproc, one per
-// processor, and #define cp to the right element
-// in the array.  In general such preprocessor 
-// subterfuge is to be avoided, but cp is used 
-// so often that having the shorthand is worth the ugliness.
+// Arrange that cp point to the struct proc that this
+// CPU is currently running.  Such preprocessor 
+// subterfuge can be confusing, but saves a lot of typing.
 extern struct proc *curproc[NCPU];  // Current (running) process per CPU
 #define cp (curproc[cpu()])  // Current process on this CPU
 
diff --git a/runoff b/runoff
index 092c8b6..3869391 100755
--- a/runoff
+++ b/runoff
@@ -18,7 +18,7 @@ files=`grep -v '^#' runoff.list | awk '{print $1}'`
 n=99
 for i in $files
 do
-	runoff1 -n $n $i >fmt/$i
+	./runoff1 -n $n $i >fmt/$i
 	nn=`tail -1 fmt/$i | sed 's/ .*//; s/^0*//'`
 	if [ "x$nn" != x ]; then
 		n=$nn
diff --git a/usertests.c b/usertests.c
index 7132666..3a9cd9a 100644
--- a/usertests.c
+++ b/usertests.c
@@ -1096,6 +1096,99 @@ rmdot(void)
   printf(1, "rmdot ok\n");
 }
 
+void
+dirfile(void)
+{
+  int fd;
+
+  printf(1, "dir vs file\n");
+
+  fd = open("dirfile", O_CREATE);
+  if(fd < 0){
+    printf(1, "create dirfile failed\n");
+    exit();
+  }
+  close(fd);
+  if(chdir("dirfile") == 0){
+    printf(1, "chdir dirfile succeeded!\n");
+    exit();
+  }
+  fd = open("dirfile/xx", 0);
+  if(fd >= 0){
+    printf(1, "create dirfile/xx succeeded!\n");
+    exit();
+  }
+  fd = open("dirfile/xx", O_CREATE);
+  if(fd >= 0){
+    printf(1, "create dirfile/xx succeeded!\n");
+    exit();
+  }
+  if(mkdir("dirfile/xx") == 0){
+    printf(1, "mkdir dirfile/xx succeeded!\n");
+    exit();
+  }
+  if(unlink("dirfile/xx") == 0){
+    printf(1, "unlink dirfile/xx succeeded!\n");
+    exit();
+  }
+  if(link("README", "dirfile/xx") == 0){
+    printf(1, "link to dirfile/xx succeeded!\n");
+    exit();
+  }
+  if(unlink("dirfile") != 0){
+    printf(1, "unlink dirfile failed!\n");
+    exit();
+  }
+
+  fd = open(".", O_RDWR);
+  if(fd >= 0){
+    printf(1, "open . for writing succeeded!\n");
+    exit();
+  }
+  fd = open(".", 0);
+  if(write(fd, "x", 1) > 0){
+    printf(1, "write . succeeded!\n");
+    exit();
+  }
+  close(fd);
+
+  printf(1, "dir vs file OK\n");
+}
+
+// test that iput() is called at the end of _namei()
+void
+iref(void)
+{
+  int i, fd;
+
+  printf(1, "empty file name\n");
+
+  // the 50 is NINODE
+  for(i = 0; i < 50 + 1; i++){
+    if(mkdir("irefd") != 0){
+      printf(1, "mkdir irefd failed\n");
+      exit();
+    }
+    if(chdir("irefd") != 0){
+      printf(1, "chdir irefd failed\n");
+      exit();
+    }
+
+    mkdir("");
+    link("README", "");
+    fd = open("", O_CREATE);
+    if(fd >= 0)
+      close(fd);
+    fd = open("xx", O_CREATE);
+    if(fd >= 0)
+      close(fd);
+    unlink("xx");
+  }
+
+  chdir("/");
+  printf(1, "empty file name OK\n");
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -1128,6 +1221,8 @@ main(int argc, char *argv[])
   createdelete();
   twofiles();
   sharedfd();
+  dirfile();
+  iref();
 
   exectest();
 
-- 
GitLab