]> Devi Nivas Git - cs3210-lab1.git/commitdiff
namei
authorrtm <rtm>
Fri, 21 Jul 2006 22:10:40 +0000 (22:10 +0000)
committerrtm <rtm>
Fri, 21 Jul 2006 22:10:40 +0000 (22:10 +0000)
Notes
defs.h
fs.c
fs.h
fsvar.h
mkfs.c
syscall.c

diff --git a/Notes b/Notes
index 681d69a0b89bc5cfdd4c5f952e355acf7a87057a..f0955b8e5a718629bacbb1041cef6d7ce13881d0 100644 (file)
--- a/Notes
+++ b/Notes
@@ -142,10 +142,22 @@ systematic way to test sleep races?
 
 do you have to be holding the mutex in order to call wakeup()?
 
-should lock around printf, not putc
-
 device interrupts don't clear FL_IF
   so a recursive timer interrupt is possible
 
-the sleep/swtch/schedule code that holds over a lock is ugly
+what does inode->busy mean?
+  might be held across disk reads
+  no-one is allowed to do anything to the inode
+  protected by inode_table_lock
+inode->count counts in-memory pointers to the struct
+  prevents inode[] element from being re-used
+  protected by inode_table_lock
+
+blocks and inodes have ad-hoc sleep-locks
+  provide a single mechanism?
+
+need to lock bufs in bio between bread and brelse
 
+test 14-character file names
+and file arguments longer than 14
+and directories longer than one sector
diff --git a/defs.h b/defs.h
index 0ed71bb7ae6060d78afdbcd31f3f8d2e65a3a81e..35a71399124fe58fd5357c8a9ec1691fe1173508 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -97,4 +97,8 @@ void brelse(struct buf *);
 
 // fs.c
 struct inode * iget(uint dev, uint inum);
+void ilock(struct inode *ip);
+void iunlock(struct inode *ip);
+void iincref(struct inode *ip);
 void iput(struct inode *ip);
+struct inode * namei(char *path);
diff --git a/fs.c b/fs.c
index 48c943acafc112e787868395562f34236851e16e..3eda6e958ae5f85a14d8733d1ce1d67efd814dbc 100644 (file)
--- a/fs.c
+++ b/fs.c
@@ -14,6 +14,9 @@
 struct inode inode[NINODE];
 struct spinlock inode_table_lock;
 
+uint rootdev = 1;
+
+// returns an inode with busy set and incremented reference count.
 struct inode *
 iget(uint dev, uint inum)
 {
@@ -54,15 +57,50 @@ iget(uint dev, uint inum)
   nip->nlink = dip->nlink;
   nip->size = dip->size;
   memmove(nip->addrs, dip->addrs, sizeof(nip->addrs));
-  cprintf("bn %d off %d\n", inum / IPB + 2, (unsigned)dip - (unsigned)bp->data);
   brelse(bp);
 
   return nip;
 }
 
+void
+ilock(struct inode *ip)
+{
+  if(ip->count < 1)
+    panic("ilock");
+
+  acquire(&inode_table_lock);
+
+  while(ip->busy)
+    sleep(ip, &inode_table_lock);
+  ip->busy = 1;
+
+  release(&inode_table_lock);
+}
+
+// caller is holding onto a reference to this inode, but no
+// longer needs to examine or change it, so clear ip->busy.
+void
+iunlock(struct inode *ip)
+{
+  if(ip->busy != 1)
+    panic("iunlock");
+
+  acquire(&inode_table_lock);
+
+  ip->busy = 0;
+  wakeup(ip);
+
+  release(&inode_table_lock);
+}
+
+// caller is releasing a reference to this inode.
+// you must have the inode lock.
 void
 iput(struct inode *ip)
 {
+  if(ip->count < 1 || ip->busy != 1)
+    panic("iput");
+
   acquire(&inode_table_lock);
 
   ip->count -= 1;
@@ -71,3 +109,82 @@ iput(struct inode *ip)
 
   release(&inode_table_lock);
 }
+
+void
+iincref(struct inode *ip)
+{
+  acquire(&inode_table_lock);
+
+  ip->count += 1;
+
+  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;
+}
+
+struct inode *
+namei(char *path)
+{
+  struct inode *dp;
+  char *cp = path;
+  uint off, dev;
+  struct buf *bp;
+  struct dirent *ep;
+  int i;
+  unsigned ninum;
+
+  dp = iget(rootdev, 1);
+
+  while(*cp == '/')
+    cp++;
+
+  while(1){
+    if(*cp == '\0')
+      return dp;
+
+    if(dp->type != T_DIR){
+      iput(dp);
+      return 0;
+    }
+
+    for(off = 0; off < dp->size; off += 512){
+      bp = bread(dp->dev, bmap(dp, off / 512));
+      for(ep = (struct dirent *) bp->data;
+          ep < (struct dirent *) (bp->data + 512);
+          ep++){
+        if(ep->inum == 0) 
+          continue;
+        for(i = 0; i < DIRSIZ && cp[i] != '/' && cp[i]; i++)
+          if(cp[i] != ep->name[i])
+            break;
+        if((cp[i] == '\0' || cp[i] == '/') && (i >= DIRSIZ || ep->name[i] == '\0')){
+          ninum = ep->inum;
+          brelse(bp);
+          cp += i;
+          goto found;
+        }
+      }
+      brelse(bp);
+    }
+    iput(dp);
+    return 0;
+
+  found:
+    dev = dp->dev;
+    iput(dp);
+    dp = iget(dev, ninum);
+    while(*cp == '/')
+      cp++;
+  }
+}
diff --git a/fs.h b/fs.h
index b710e1c5ec336fce837578fd68ae7f51891efdc3..a842e64294f354a73500bc5b2545dc0a5defdab4 100644 (file)
--- a/fs.h
+++ b/fs.h
@@ -21,8 +21,10 @@ struct dinode {
 
 #define IPB (512 / sizeof(struct dinode))
 
+#define DIRSIZ 14
+
 struct dirent {
   ushort inum;
-  char name[14];
+  char name[DIRSIZ];
 };
 
diff --git a/fsvar.h b/fsvar.h
index 4388f75cb5088e7a29225d9314d7652577dacb6c..dba45d524b5fc26f4d607d6a077187c8069bc739 100644 (file)
--- a/fsvar.h
+++ b/fsvar.h
@@ -10,3 +10,5 @@ struct inode {
   uint size;
   uint addrs[NDIRECT];
 };
+
+extern uint rootdev;
diff --git a/mkfs.c b/mkfs.c
index 033e064a975c9b4db02212f9759fc22051eb1556..9dcb29c3549601cc14fc2c90ecb7d18722942980 100644 (file)
--- a/mkfs.c
+++ b/mkfs.c
@@ -24,7 +24,7 @@ ushort
 xshort(ushort x)
 {
   ushort y;
-  uchar *a = &y;
+  uchar *a = (uchar *) &y;
   a[0] = x;
   a[1] = x >> 8;
   return y;
@@ -34,7 +34,7 @@ uint
 xint(uint x)
 {
   uint y;
-  uchar *a = &y;
+  uchar *a = (uchar *) &y;
   a[0] = x;
   a[1] = x >> 8;
   a[2] = x >> 16;
@@ -47,16 +47,21 @@ main(int argc, char *argv[])
   int i;
   struct dinode din;
   char dbuf[512];
+  uint bn;
 
   if(argc != 2){
     fprintf(stderr, "Usage: mkfs fs.img\n");
     exit(1);
   }
 
-  if(sizeof(struct dinode) * IPB != 512){
+  if((512 % sizeof(struct dinode)) != 0){
     fprintf(stderr, "sizeof(dinode) must divide 512\n");
     exit(1);
   }
+  if((512 % sizeof(struct dirent)) != 0){
+    fprintf(stderr, "sizeof(dirent) must divide 512\n");
+    exit(1);
+  }
 
   fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
   if(fd < 0){
@@ -78,7 +83,8 @@ main(int argc, char *argv[])
   din.type = xshort(T_DIR);
   din.nlink = xshort(2);
   din.size = xint(512);
-  din.addrs[0] = xint(freeblock++);
+  bn = freeblock++;
+  din.addrs[0] = xint(bn);
   winode(1, &din);
 
   bzero(dbuf, sizeof(dbuf));
@@ -86,7 +92,7 @@ main(int argc, char *argv[])
   strcpy(((struct dirent *) dbuf)[0].name, ".");
   ((struct dirent *) dbuf)[1].inum = xshort(1);
   strcpy(((struct dirent *) dbuf)[1].name, "..");
-  wsect(din.addrs[0], dbuf);
+  wsect(bn, dbuf);
 
   exit(0);
 }
index 68af208c098643c1725926945ae560ff12e5ebbb..c6ae0db0cc6fe5bf487befb7373a7fc1d558bdea 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -243,11 +243,21 @@ sys_block(void)
   }
 
   ip = iget(1, 1);
-  cprintf("%d %d %d %d %d %d %d %d\n",
+  cprintf("iget 1: %d %d %d %d %d %d %d %d\n",
           ip->dev, ip->inum, ip->count, ip->busy,
           ip->type, ip->nlink, ip->size, ip->addrs[0]);
   iput(ip);
 
+  ip = namei(".././//./../");
+  if(ip){
+    cprintf("namei: %d %d %d %d %d %d %d %d\n",
+            ip->dev, ip->inum, ip->count, ip->busy,
+            ip->type, ip->nlink, ip->size, ip->addrs[0]);
+    iput(ip);
+  } else {
+    cprintf("namei failed\n");
+  }
+
   return 0;
 }