From 3808f903625f42f58aa95e43e3caca3efaa4d118 Mon Sep 17 00:00:00 2001
From: Sanjit Bhat <sanjit.bhat@gmail.com>
Date: Mon, 30 Oct 2023 14:39:28 -0500
Subject: lock: release lab

---
 user/bcachetest.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 189 insertions(+)
 create mode 100644 user/bcachetest.c

(limited to 'user/bcachetest.c')

diff --git a/user/bcachetest.c b/user/bcachetest.c
new file mode 100644
index 0000000..5dc46ef
--- /dev/null
+++ b/user/bcachetest.c
@@ -0,0 +1,189 @@
+#include "kernel/fcntl.h"
+#include "kernel/param.h"
+#include "kernel/types.h"
+#include "kernel/stat.h"
+#include "kernel/riscv.h"
+#include "kernel/fs.h"
+#include "user/user.h"
+
+void test0();
+void test1();
+
+#define SZ 4096
+char buf[SZ];
+
+int
+main(int argc, char *argv[])
+{
+  test0();
+  test1();
+  exit(0);
+}
+
+void
+createfile(char *file, int nblock)
+{
+  int fd;
+  char buf[BSIZE];
+  int i;
+  
+  fd = open(file, O_CREATE | O_RDWR);
+  if(fd < 0){
+    printf("createfile %s failed\n", file);
+    exit(-1);
+  }
+  for(i = 0; i < nblock; i++) {
+    if(write(fd, buf, sizeof(buf)) != sizeof(buf)) {
+      printf("write %s failed\n", file);
+      exit(-1);
+    }
+  }
+  close(fd);
+}
+
+void
+readfile(char *file, int nbytes, int inc)
+{
+  char buf[BSIZE];
+  int fd;
+  int i;
+
+  if(inc > BSIZE) {
+    printf("readfile: inc too large\n");
+    exit(-1);
+  }
+  if ((fd = open(file, O_RDONLY)) < 0) {
+    printf("readfile open %s failed\n", file);
+    exit(-1);
+  }
+  for (i = 0; i < nbytes; i += inc) {
+    if(read(fd, buf, inc) != inc) {
+      printf("read %s failed for block %d (%d)\n", file, i, nbytes);
+      exit(-1);
+    }
+  }
+  close(fd);
+}
+
+int ntas(int print)
+{
+  int n;
+  char *c;
+
+  if (statistics(buf, SZ) <= 0) {
+    fprintf(2, "ntas: no stats\n");
+  }
+  c = strchr(buf, '=');
+  n = atoi(c+2);
+  if(print)
+    printf("%s", buf);
+  return n;
+}
+
+// Test reading small files concurrently
+void
+test0()
+{
+  char file[2];
+  char dir[2];
+  enum { N = 10, NCHILD = 3 };
+  int m, n;
+
+  dir[0] = '0';
+  dir[1] = '\0';
+  file[0] = 'F';
+  file[1] = '\0';
+
+  printf("start test0\n");
+  for(int i = 0; i < NCHILD; i++){
+    dir[0] = '0' + i;
+    mkdir(dir);
+    if (chdir(dir) < 0) {
+      printf("chdir failed\n");
+      exit(1);
+    }
+    unlink(file);
+    createfile(file, N);
+    if (chdir("..") < 0) {
+      printf("chdir failed\n");
+      exit(1);
+    }
+  }
+  m = ntas(0);
+  for(int i = 0; i < NCHILD; i++){
+    dir[0] = '0' + i;
+    int pid = fork();
+    if(pid < 0){
+      printf("fork failed");
+      exit(-1);
+    }
+    if(pid == 0){
+      if (chdir(dir) < 0) {
+        printf("chdir failed\n");
+        exit(1);
+      }
+
+      readfile(file, N*BSIZE, 1);
+
+      exit(0);
+    }
+  }
+
+  for(int i = 0; i < NCHILD; i++){
+    wait(0);
+  }
+  printf("test0 results:\n");
+  n = ntas(1);
+  if (n-m < 500)
+    printf("test0: OK\n");
+  else
+    printf("test0: FAIL\n");
+}
+
+// Test bcache evictions by reading a large file concurrently
+void test1()
+{
+  char file[3];
+  enum { N = 200, BIG=100, NCHILD=2 };
+  
+  printf("start test1\n");
+  file[0] = 'B';
+  file[2] = '\0';
+  for(int i = 0; i < NCHILD; i++){
+    file[1] = '0' + i;
+    unlink(file);
+    if (i == 0) {
+      createfile(file, BIG);
+    } else {
+      createfile(file, 1);
+    }
+  }
+  for(int i = 0; i < NCHILD; i++){
+    file[1] = '0' + i;
+    int pid = fork();
+    if(pid < 0){
+      printf("fork failed");
+      exit(-1);
+    }
+    if(pid == 0){
+      if (i==0) {
+        for (i = 0; i < N; i++) {
+          readfile(file, BIG*BSIZE, BSIZE);
+        }
+        unlink(file);
+        exit(0);
+      } else {
+        for (i = 0; i < N*20; i++) {
+          readfile(file, 1, BSIZE);
+        }
+        unlink(file);
+      }
+      exit(0);
+    }
+  }
+
+  for(int i = 0; i < NCHILD; i++){
+    wait(0);
+  }
+  printf("test1 OK\n");
+}
-- 
cgit v1.2.3


From 3c0a25fc4383140b3f8bf83f5eef4cbb14062e94 Mon Sep 17 00:00:00 2001
From: Robert Morris <rtm@csail.mit.edu>
Date: Tue, 2 Jan 2024 10:04:23 -0500
Subject: x

---
 user/bcachetest.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 129 insertions(+)

(limited to 'user/bcachetest.c')

diff --git a/user/bcachetest.c b/user/bcachetest.c
index 5dc46ef..ccf7516 100644
--- a/user/bcachetest.c
+++ b/user/bcachetest.c
@@ -8,6 +8,7 @@
 
 void test0();
 void test1();
+void test2();
 
 #define SZ 4096
 char buf[SZ];
@@ -17,6 +18,7 @@ main(int argc, char *argv[])
 {
   test0();
   test1();
+  test2();
   exit(0);
 }
 
@@ -187,3 +189,130 @@ void test1()
   }
   printf("test1 OK\n");
 }
+
+//
+// test concurrent creates.
+//
+void
+test2()
+{
+  int nc = 4;
+  char file[16];
+
+  printf("start test2\n");
+  
+  mkdir("d2");
+
+  file[0] = 'd';
+  file[1] = '2';
+  file[2] = '/';
+
+  // remove any stale existing files.
+  for(int i = 0; i < 50; i++){
+    for(int ci = 0; ci < nc; ci++){
+      file[3] = 'a' + ci;
+      file[4] = '0' + i;
+      file[5] = '\0';
+      unlink(file);
+    }
+  }
+
+  int pids[nc];
+  for(int ci = 0; ci < nc; ci++){
+    pids[ci] = fork();
+    if(pids[ci] < 0){
+      printf("test2: fork failed\n");
+      exit(1);
+    }
+    if(pids[ci] == 0){
+      char me = "abcdefghijklmnop"[ci];
+      int pid = getpid();
+      int nf = (ci == 0 ? 10 : 15);
+
+      // create nf files.
+      for(int i = 0; i < nf; i++){
+        file[3] = me;
+        file[4] = '0' + i;
+        file[5] = '\0';
+        // printf("w %s\n", file);
+        int fd = open(file, O_CREATE | O_RDWR);
+        if(fd < 0){
+          printf("test2: create %s failed\n", file);
+          exit(1);
+        }
+        int xx = (pid << 16) | i;
+        for(int nw = 0; nw < 2; nw++){
+          // the sleep() increases the chance of simultaneous
+          // calls to bget().
+          sleep(1);
+          if(write(fd, &xx, sizeof(xx)) <= 0){
+            printf("test2: write %s failed\n", file);
+            exit(1);
+          }
+        }
+        close(fd);
+      }
+
+      // read back the nf files.
+      for(int i = 0; i < nf; i++){
+        file[3] = me;
+        file[4] = '0' + i;
+        file[5] = '\0';
+        // printf("r %s\n", file);
+        int fd = open(file, O_RDWR);
+        if(fd < 0){
+          printf("test2: open %s failed\n", file);
+          exit(1);
+        }
+        int xx = (pid << 16) | i;
+        for(int nr = 0; nr < 2; nr++){
+          int z = 0;
+          sleep(1);
+          int n = read(fd, &z, sizeof(z));
+          if(n != sizeof(z)){
+            printf("test2: read %s returned %d, expected %d\n", file, n, sizeof(z));
+            exit(1);
+          }
+          if(z != xx){
+            printf("test2: file %s contained %d, not %d\n", file, z, xx);
+            exit(1);
+          }
+        }
+        close(fd);
+      }
+
+      // delete the nf files.
+      for(int i = 0; i < nf; i++){
+        file[3] = me;
+        file[4] = '0' + i;
+        file[5] = '\0';
+        //printf("u %s\n", file);
+        if(unlink(file) != 0){
+          printf("test2: unlink %s failed\n", file);
+          exit(1);
+        }
+      }
+
+      exit(0);
+    }
+  }
+
+  int ok = 1;
+
+  for(int ci = 0; ci < nc; ci++){
+    int st = 0;
+    int ret = wait(&st);
+    if(ret <= 0){
+      printf("test2: wait() failed\n");
+      ok = 0;
+    }
+    if(st != 0)
+      ok = 0;
+  }
+  
+  if(ok){
+    printf("test2 OK\n");
+  } else {
+    printf("test2 failed\n");
+  }
+}
-- 
cgit v1.2.3