]> Devi Nivas Git - cs3210-lab1.git/commitdiff
a start at concurrent FS system calls
authorRobert Morris <rtm@csail.mit.edu>
Wed, 27 Aug 2014 21:15:30 +0000 (17:15 -0400)
committerRobert Morris <rtm@csail.mit.edu>
Wed, 27 Aug 2014 21:15:30 +0000 (17:15 -0400)
defs.h
exec.c
file.c
log.c
proc.c
sysfile.c

diff --git a/defs.h b/defs.h
index 23b1019ba12806d6f2d0551dc67cc3fd85b0b6e6..560b19af0f2a4b2927eb5a608a4e1fceae96220b 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -81,8 +81,8 @@ void            microdelay(int);
 // log.c
 void            initlog(void);
 void            log_write(struct buf*);
-void            begin_trans();
-void            commit_trans();
+void            begin_op();
+void            end_op();
 
 // mp.c
 extern int      ismp;
diff --git a/exec.c b/exec.c
index 7eaef5b5ad1cf4f5fcc0a88424731026b9bbc629..8dbbdb66b1b86d1c09c57ced2264b3bd8935a5d7 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -18,9 +18,9 @@ exec(char *path, char **argv)
   struct proghdr ph;
   pde_t *pgdir, *oldpgdir;
 
-  begin_trans();
+  begin_op();
   if((ip = namei(path)) == 0){
-    commit_trans();
+    end_op();
     return -1;
   }
   ilock(ip);
@@ -50,7 +50,7 @@ exec(char *path, char **argv)
       goto bad;
   }
   iunlockput(ip);
-  commit_trans();
+  end_op();
   ip = 0;
 
   // Allocate two pages at the next page boundary.
@@ -101,7 +101,7 @@ exec(char *path, char **argv)
     freevm(pgdir);
   if(ip){
     iunlockput(ip);
-    commit_trans();
+    end_op();
   }
   return -1;
 }
diff --git a/file.c b/file.c
index 53c5af242fb798ff683daba7de0479c420efed74..98cad1e9a122ee0b83fa6e18a6d91bcc6bc6fee6 100644 (file)
--- a/file.c
+++ b/file.c
@@ -72,9 +72,9 @@ fileclose(struct file *f)
   if(ff.type == FD_PIPE)
     pipeclose(ff.pipe, ff.writable);
   else if(ff.type == FD_INODE){
-    begin_trans();
+    begin_op();
     iput(ff.ip);
-    commit_trans();
+    end_op();
   }
 }
 
@@ -136,12 +136,12 @@ filewrite(struct file *f, char *addr, int n)
       if(n1 > max)
         n1 = max;
 
-      begin_trans();
+      begin_op();
       ilock(f->ip);
       if ((r = writei(f->ip, addr + i, f->off, n1)) > 0)
         f->off += r;
       iunlock(f->ip);
-      commit_trans();
+      end_op();
 
       if(r < 0)
         break;
diff --git a/log.c b/log.c
index 95cc4d5752179bd1bd9dfa1f24b944e8c50f202f..159df986f7567e1185007ba6347c3531d0bf2a55 100644 (file)
--- a/log.c
+++ b/log.c
@@ -5,18 +5,22 @@
 #include "fs.h"
 #include "buf.h"
 
-// Simple logging. Each file system system call
-// should be surrounded with begin_trans() and commit_trans() calls.
+// Simple logging that allows concurrent FS system calls.
 //
-// The log holds at most one transaction at a time. Commit forces
-// the log (with commit record) to disk, then installs the affected
-// blocks to disk, then erases the log. begin_trans() ensures that
-// only one system call can be in a transaction; others must wait.
-// 
-// Allowing only one transaction at a time means that the file
-// system code doesn't have to worry about the possibility of
-// one transaction reading a block that another one has modified,
-// for example an i-node block.
+// A log transaction contains the updates of *multiple* FS system
+// calls. The logging systems only commits when there are
+// no FS system calls active. Thus there is never
+// any reasoning required about whether a commit might
+// write an uncommitted system call's updates to disk.
+//
+// A system call should call begin_op()/end_op() to mark
+// its start and end. Usually begin_op() just increments
+// the count of in-progress FS system calls and returns.
+// But if it thinks the log is close to running out, it
+// blocks this system call, and causes the system to wait
+// until end_op() indicates there are no executing FS
+// system calls, at which point the last end_op() commits
+// all the system calls' writes.
 //
 // The log is a physical re-do log containing disk blocks.
 // The on-disk log format:
@@ -38,13 +42,15 @@ struct log {
   struct spinlock lock;
   int start;
   int size;
-  int busy; // a transaction is active
+  int outstanding; // how many FS sys calls are executing.
+  int committing;  // in commit(), please wait.
   int dev;
   struct logheader lh;
 };
 struct log log;
 
 static void recover_from_log(void);
+static void commit();
 
 void
 initlog(void)
@@ -117,19 +123,52 @@ recover_from_log(void)
   write_head(); // clear the log
 }
 
+// an FS system call should call begin_op() when it starts.
 void
-begin_trans(void)
+begin_op(void)
 {
   acquire(&log.lock);
-  while (log.busy) {
-    sleep(&log, &log.lock);
+  while(1){
+    if(log.committing){
+      sleep(&log, &log.lock);
+    } else {
+      // XXX wait (for a commit) if log is longish.
+      //     need to reserve to avoid over-commit of log space.
+      log.outstanding += 1;
+      release(&log.lock);
+      break;
+    }
   }
-  log.busy = 1;
-  release(&log.lock);
 }
 
+// an FS system call should call end_op() after it finishes.
+// can't write the disk &c while holding locks, thus do_commit.
 void
-commit_trans(void)
+end_op(void)
+{
+  int do_commit = 0;
+
+  acquire(&log.lock);
+  log.outstanding -= 1;
+  if(log.committing)
+    panic("log.committing");
+  if(log.outstanding == 0){
+    do_commit = 1;
+    log.committing = 1;
+  }
+  release(&log.lock);
+
+  if(do_commit){
+    commit();
+    acquire(&log.lock);
+    log.committing = 0;
+    wakeup(&log);
+    release(&log.lock);
+  }
+}
+
+static void
+commit()
 {
   if (log.lh.n > 0) {
     write_head();    // Write header to disk -- the real commit
@@ -137,11 +176,6 @@ commit_trans(void)
     log.lh.n = 0; 
     write_head();    // Erase the transaction from the log
   }
-  
-  acquire(&log.lock);
-  log.busy = 0;
-  wakeup(&log);
-  release(&log.lock);
 }
 
 // Caller has modified b->data and is done with the buffer.
@@ -159,7 +193,7 @@ log_write(struct buf *b)
 
   if (log.lh.n >= LOGSIZE || log.lh.n >= log.size - 1)
     panic("too big a transaction");
-  if (!log.busy)
+  if (log.outstanding < 1)
     panic("write outside of trans");
 
   for (i = 0; i < log.lh.n; i++) {
diff --git a/proc.c b/proc.c
index db0e9c7b8269f396fb71737cf14bf2f2f8e4aebc..a642f5a4da13a05c49404653a2259a571273413d 100644 (file)
--- a/proc.c
+++ b/proc.c
@@ -186,9 +186,9 @@ exit(void)
     }
   }
 
-  begin_trans();
+  begin_op();
   iput(proc->cwd);
-  commit_trans();
+  end_op();
   proc->cwd = 0;
 
   acquire(&ptable.lock);
index 095fca749fe7340f2d717a26e82f4971a0b360f5..2209f6e1eb8072c215c4b479b2969f2e2875a213 100644 (file)
--- a/sysfile.c
+++ b/sysfile.c
@@ -121,16 +121,16 @@ sys_link(void)
   if(argstr(0, &old) < 0 || argstr(1, &new) < 0)
     return -1;
 
-  begin_trans();
+  begin_op();
   if((ip = namei(old)) == 0){
-    commit_trans();
+    end_op();
     return -1;
   }
 
   ilock(ip);
   if(ip->type == T_DIR){
     iunlockput(ip);
-    commit_trans();
+    end_op();
     return -1;
   }
 
@@ -148,7 +148,7 @@ sys_link(void)
   iunlockput(dp);
   iput(ip);
 
-  commit_trans();
+  end_op();
 
   return 0;
 
@@ -157,7 +157,7 @@ bad:
   ip->nlink--;
   iupdate(ip);
   iunlockput(ip);
-  commit_trans();
+  end_op();
   return -1;
 }
 
@@ -189,9 +189,9 @@ sys_unlink(void)
   if(argstr(0, &path) < 0)
     return -1;
 
-  begin_trans();
+  begin_op();
   if((dp = nameiparent(path, name)) == 0){
-    commit_trans();
+    end_op();
     return -1;
   }
 
@@ -225,13 +225,13 @@ sys_unlink(void)
   iupdate(ip);
   iunlockput(ip);
 
-  commit_trans();
+  end_op();
 
   return 0;
 
 bad:
   iunlockput(dp);
-  commit_trans();
+  end_op();
   return -1;
 }
 
@@ -291,23 +291,23 @@ sys_open(void)
   if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
     return -1;
 
-  begin_trans();
+  begin_op();
 
   if(omode & O_CREATE){
     ip = create(path, T_FILE, 0, 0);
     if(ip == 0){
-      commit_trans();
+      end_op();
       return -1;
     }
   } else {
     if((ip = namei(path)) == 0){
-      commit_trans();
+      end_op();
       return -1;
     }
     ilock(ip);
     if(ip->type == T_DIR && omode != O_RDONLY){
       iunlockput(ip);
-      commit_trans();
+      end_op();
       return -1;
     }
   }
@@ -316,11 +316,11 @@ sys_open(void)
     if(f)
       fileclose(f);
     iunlockput(ip);
-    commit_trans();
+    end_op();
     return -1;
   }
   iunlock(ip);
-  commit_trans();
+  end_op();
 
   f->type = FD_INODE;
   f->ip = ip;
@@ -336,13 +336,13 @@ sys_mkdir(void)
   char *path;
   struct inode *ip;
 
-  begin_trans();
+  begin_op();
   if(argstr(0, &path) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0){
-    commit_trans();
+    end_op();
     return -1;
   }
   iunlockput(ip);
-  commit_trans();
+  end_op();
   return 0;
 }
 
@@ -354,16 +354,16 @@ sys_mknod(void)
   int len;
   int major, minor;
   
-  begin_trans();
+  begin_op();
   if((len=argstr(0, &path)) < 0 ||
      argint(1, &major) < 0 ||
      argint(2, &minor) < 0 ||
      (ip = create(path, T_DEV, major, minor)) == 0){
-    commit_trans();
+    end_op();
     return -1;
   }
   iunlockput(ip);
-  commit_trans();
+  end_op();
   return 0;
 }
 
@@ -373,20 +373,20 @@ sys_chdir(void)
   char *path;
   struct inode *ip;
 
-  begin_trans();
+  begin_op();
   if(argstr(0, &path) < 0 || (ip = namei(path)) == 0){
-    commit_trans();
+    end_op();
     return -1;
   }
   ilock(ip);
   if(ip->type != T_DIR){
     iunlockput(ip);
-    commit_trans();
+    end_op();
     return -1;
   }
   iunlock(ip);
   iput(proc->cwd);
-  commit_trans();
+  end_op();
   proc->cwd = ip;
   return 0;
 }