diff options
| author | Robert Morris <rtm@csail.mit.edu> | 2014-08-27 17:15:30 -0400 | 
|---|---|---|
| committer | Robert Morris <rtm@csail.mit.edu> | 2014-08-27 17:15:30 -0400 | 
| commit | 71453f72f285a17ccf0520b9dbdafdc701ff2f4a (patch) | |
| tree | 978d30844e643e67a807a73db20ccc5d2823f8f2 | |
| parent | 2c56547272e43b483d560a61692f1e24926a82fb (diff) | |
| download | xv6-labs-71453f72f285a17ccf0520b9dbdafdc701ff2f4a.tar.gz xv6-labs-71453f72f285a17ccf0520b9dbdafdc701ff2f4a.tar.bz2 xv6-labs-71453f72f285a17ccf0520b9dbdafdc701ff2f4a.zip | |
a start at concurrent FS system calls
| -rw-r--r-- | defs.h | 4 | ||||
| -rw-r--r-- | exec.c | 8 | ||||
| -rw-r--r-- | file.c | 8 | ||||
| -rw-r--r-- | log.c | 82 | ||||
| -rw-r--r-- | proc.c | 4 | ||||
| -rw-r--r-- | sysfile.c | 50 | 
6 files changed, 95 insertions, 61 deletions
| @@ -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; @@ -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;  } @@ -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; @@ -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++) { @@ -186,9 +186,9 @@ exit(void)      }    } -  begin_trans(); +  begin_op();    iput(proc->cwd); -  commit_trans(); +  end_op();    proc->cwd = 0;    acquire(&ptable.lock); @@ -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;  } | 
