diff options
| author | Robert Morris <rtm@csail.mit.edu> | 2014-08-28 05:57:47 -0400 | 
|---|---|---|
| committer | Robert Morris <rtm@csail.mit.edu> | 2014-08-28 05:57:47 -0400 | 
| commit | 48aa917403de1599a02924e429a9f43ea31e9cc1 (patch) | |
| tree | 037648a21b395eacdd2d716a33cfc95e14ff0a61 | |
| parent | 71453f72f285a17ccf0520b9dbdafdc701ff2f4a (diff) | |
| download | xv6-labs-48aa917403de1599a02924e429a9f43ea31e9cc1.tar.gz xv6-labs-48aa917403de1599a02924e429a9f43ea31e9cc1.tar.bz2 xv6-labs-48aa917403de1599a02924e429a9f43ea31e9cc1.zip | |
i think this is a working concurrent logging scheme
| -rw-r--r-- | bio.c | 2 | ||||
| -rw-r--r-- | log.c | 21 | ||||
| -rw-r--r-- | mkfs.c | 2 | ||||
| -rw-r--r-- | param.h | 5 | ||||
| -rw-r--r-- | usertests.c | 178 | 
5 files changed, 113 insertions, 95 deletions
| @@ -80,6 +80,8 @@ bget(uint dev, uint sector)    }    // Not cached; recycle some non-busy and clean buffer. +  // "clean" because B_DIRTY and !B_BUSY means log.c +  // hasn't yet committed the changes to the buffer.    for(b = bcache.head.prev; b != &bcache.head; b = b->prev){      if((b->flags & B_BUSY) == 0 && (b->flags & B_DIRTY) == 0){        b->dev = dev; @@ -52,6 +52,10 @@ struct log log;  static void recover_from_log(void);  static void commit(); +// statistics, delete eventually XXX. +static int maxsize; +static int maxoutstanding; +  void  initlog(void)  { @@ -131,10 +135,15 @@ begin_op(void)    while(1){      if(log.committing){        sleep(&log, &log.lock); +    } else if(log.lh.n + (log.outstanding+1)*MAXOPBLOCKS > LOGSIZE){ +      // this op might exhaust log space; wait for commit. +      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; +      if(log.outstanding > maxoutstanding){ +        maxoutstanding = log.outstanding; +        cprintf("%d outstanding\n", log.outstanding); +      }        release(&log.lock);        break;      } @@ -155,6 +164,9 @@ end_op(void)    if(log.outstanding == 0){      do_commit = 1;      log.committing = 1; +  } else { +    // begin_op() may be waiting for log space. +    wakeup(&log);    }    release(&log.lock); @@ -208,6 +220,11 @@ log_write(struct buf *b)    if (i == log.lh.n)      log.lh.n++;    b->flags |= B_DIRTY; // XXX prevent eviction + +  if(log.lh.n > maxsize){ +    maxsize = log.lh.n; +    cprintf("log size %d/%d\n", log.lh.n, LOGSIZE); +  }  }  //PAGEBREAK! @@ -13,7 +13,7 @@  #define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0) -int nblocks = 985; +int nblocks = (995-LOGSIZE);  int nlog = LOGSIZE;  int ninodes = 200;  int size = 1024; @@ -3,10 +3,11 @@  #define NCPU          8  // maximum number of CPUs  #define NOFILE       16  // open files per process  #define NFILE       100  // open files per system -#define NBUF         10  // size of disk block cache  #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  #define MAXARG       32  // max exec arguments -#define LOGSIZE      10  // max data sectors in on-disk log +#define MAXOPBLOCKS  10  // max # of blocks any FS op writes +#define LOGSIZE      (MAXOPBLOCKS*3)  // max data sectors in on-disk log +#define NBUF         (MAXOPBLOCKS*3)  // size of disk block cache (>= LOGSIZE) diff --git a/usertests.c b/usertests.c index 5a78c7c..22a7bfb 100644 --- a/usertests.c +++ b/usertests.c @@ -512,51 +512,56 @@ sharedfd(void)    }  } -// two processes write two different files at the same +// four processes write different files at the same  // time, to test block allocation.  void -twofiles(void) +fourfiles(void)  { -  int fd, pid, i, j, n, total; +  int fd, pid, i, j, n, total, pi; +  char *names[] = { "f0", "f1", "f2", "f3" };    char *fname; -  printf(1, "twofiles test\n"); +  printf(1, "fourfiles test\n"); -  unlink("f1"); -  unlink("f2"); +  for(pi = 0; pi < 4; pi++){ +    fname = names[pi]; +    unlink(fname); -  pid = fork(); -  if(pid < 0){ -    printf(1, "fork failed\n"); -    exit(); -  } - -  fname = pid ? "f1" : "f2"; -  fd = open(fname, O_CREATE | O_RDWR); -  if(fd < 0){ -    printf(1, "create failed\n"); -    exit(); -  } +    pid = fork(); +    if(pid < 0){ +      printf(1, "fork failed\n"); +      exit(); +    } -  memset(buf, pid?'p':'c', 512); -  for(i = 0; i < 12; i++){ -    if((n = write(fd, buf, 500)) != 500){ -      printf(1, "write failed %d\n", n); +    if(pid == 0){ +      fd = open(fname, O_CREATE | O_RDWR); +      if(fd < 0){ +        printf(1, "create failed\n"); +        exit(); +      } +       +      memset(buf, '0'+pi, 512); +      for(i = 0; i < 12; i++){ +        if((n = write(fd, buf, 500)) != 500){ +          printf(1, "write failed %d\n", n); +          exit(); +        } +      }        exit();      }    } -  close(fd); -  if(pid) + +  for(pi = 0; pi < 4; pi++){      wait(); -  else -    exit(); +  }    for(i = 0; i < 2; i++){ -    fd = open(i?"f1":"f2", 0); +    fname = names[i]; +    fd = open(fname, 0);      total = 0;      while((n = read(fd, buf, sizeof(buf))) > 0){        for(j = 0; j < n; j++){ -        if(buf[j] != (i?'p':'c')){ +        if(buf[j] != '0'+i){            printf(1, "wrong char\n");            exit();          } @@ -568,87 +573,80 @@ twofiles(void)        printf(1, "wrong length %d\n", total);        exit();      } +    unlink(fname);    } -  unlink("f1"); -  unlink("f2"); - -  printf(1, "twofiles ok\n"); +  printf(1, "fourfiles ok\n");  } -// two processes create and delete different files in same directory +// four processes create and delete different files in same directory  void  createdelete(void)  {    enum { N = 20 }; -  int pid, i, fd; +  int pid, i, fd, pi;    char name[32];    printf(1, "createdelete test\n"); -  pid = fork(); -  if(pid < 0){ -    printf(1, "fork failed\n"); -    exit(); -  } -  name[0] = pid ? 'p' : 'c'; -  name[2] = '\0'; -  for(i = 0; i < N; i++){ -    name[1] = '0' + i; -    fd = open(name, O_CREATE | O_RDWR); -    if(fd < 0){ -      printf(1, "create failed\n"); +  for(pi = 0; pi < 4; pi++){ +    pid = fork(); +    if(pid < 0){ +      printf(1, "fork failed\n");        exit();      } -    close(fd); -    if(i > 0 && (i % 2 ) == 0){ -      name[1] = '0' + (i / 2); -      if(unlink(name) < 0){ -        printf(1, "unlink failed\n"); -        exit(); + +    if(pid == 0){ +      name[0] = 'p' + pi; +      name[2] = '\0'; +      for(i = 0; i < N; i++){ +        name[1] = '0' + i; +        fd = open(name, O_CREATE | O_RDWR); +        if(fd < 0){ +          printf(1, "create failed\n"); +          exit(); +        } +        close(fd); +        if(i > 0 && (i % 2 ) == 0){ +          name[1] = '0' + (i / 2); +          if(unlink(name) < 0){ +            printf(1, "unlink failed\n"); +            exit(); +          } +        }        } +      exit();      }    } -  if(pid==0) -    exit(); -  else +  for(pi = 0; pi < 4; pi++){      wait(); +  } +  name[0] = name[1] = name[2] = 0;    for(i = 0; i < N; i++){ -    name[0] = 'p'; -    name[1] = '0' + i; -    fd = open(name, 0); -    if((i == 0 || i >= N/2) && fd < 0){ -      printf(1, "oops createdelete %s didn't exist\n", name); -      exit(); -    } else if((i >= 1 && i < N/2) && fd >= 0){ -      printf(1, "oops createdelete %s did exist\n", name); -      exit(); -    } -    if(fd >= 0) -      close(fd); - -    name[0] = 'c'; -    name[1] = '0' + i; -    fd = open(name, 0); -    if((i == 0 || i >= N/2) && fd < 0){ -      printf(1, "oops createdelete %s didn't exist\n", name); -      exit(); -    } else if((i >= 1 && i < N/2) && fd >= 0){ -      printf(1, "oops createdelete %s did exist\n", name); -      exit(); +    for(pi = 0; pi < 4; pi++){ +      name[0] = 'p' + pi; +      name[1] = '0' + i; +      fd = open(name, 0); +      if((i == 0 || i >= N/2) && fd < 0){ +        printf(1, "oops createdelete %s didn't exist\n", name); +        exit(); +      } else if((i >= 1 && i < N/2) && fd >= 0){ +        printf(1, "oops createdelete %s did exist\n", name); +        exit(); +      } +      if(fd >= 0) +        close(fd);      } -    if(fd >= 0) -      close(fd);    }    for(i = 0; i < N; i++){ -    name[0] = 'p'; -    name[1] = '0' + i; -    unlink(name); -    name[0] = 'c'; -    unlink(name); +    for(pi = 0; pi < 4; pi++){ +      name[0] = 'p' + i; +      name[1] = '0' + i; +      unlink(name); +    }    }    printf(1, "createdelete ok\n"); @@ -1716,6 +1714,12 @@ main(int argc, char *argv[])    }    close(open("usertests.ran", O_CREATE)); +  createdelete(); +  linkunlink(); +  concreate(); +  fourfiles(); +  sharedfd(); +    bigargtest();    bigwrite();    bigargtest(); @@ -1741,18 +1745,12 @@ main(int argc, char *argv[])    fourteen();    bigfile();    subdir(); -  concreate(); -  linkunlink();    linktest();    unlinkread(); -  createdelete(); -  twofiles(); -  sharedfd();    dirfile();    iref();    forktest();    bigdir(); // slow -    exectest();    exit(); | 
