From cd93074e5bed8fdbc84f2960c3219c7cf791b020 Mon Sep 17 00:00:00 2001
From: rtm <rtm>
Date: Sat, 12 Aug 2006 22:34:13 +0000
Subject: [PATCH] LRU disk cache replacement

---
 Notes       |  8 ++++++++
 bio.c       | 37 ++++++++++++++++++++++++++++---------
 buf.h       |  2 ++
 fs.c        |  2 +-
 usertests.c | 14 ++++++++++++--
 5 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/Notes b/Notes
index e1d763d..7d8ac14 100644
--- a/Notes
+++ b/Notes
@@ -357,3 +357,11 @@ OH! recursive interrupts will use up any amount of cpu[].stack!
 
 better buffer cache replacement
 read/write of open file that's been unlinked
+disk scheduling
+mkdir
+more than one directory content block
+sh arguments
+sh redirection
+indirect blocks
+two bugs in unlink
+how come unlink xxx fails? iput problem?
diff --git a/bio.c b/bio.c
index 2db9694..e344343 100644
--- a/bio.c
+++ b/bio.c
@@ -10,27 +10,41 @@
 struct buf buf[NBUF];
 struct spinlock buf_table_lock;
 
+// linked list of all buffers, through prev/next.
+// bufhead->next is most recently used.
+// bufhead->tail is least recently used.
+struct buf bufhead;
+
 void
 binit(void)
 {
+  struct buf *b;
+
   initlock(&buf_table_lock, "buf_table");
+
+  bufhead.prev = &bufhead;
+  bufhead.next = &bufhead;
+  for(b = buf; b < buf+NBUF; b++){
+    b->next = bufhead.next;
+    b->prev = &bufhead;
+    bufhead.next->prev = b;
+    bufhead.next = b;
+  }
 }
 
 struct buf *
 getblk(uint dev, uint sector)
 {
   struct buf *b;
-  static struct buf *scan = buf;
-  int i;
 
   acquire(&buf_table_lock);
 
   while(1){
-    for(b = buf; b < buf+NBUF; b++)
+    for(b = bufhead.next; b != &bufhead; b = b->next)
       if((b->flags & (B_BUSY|B_VALID)) && b->dev == dev && b->sector == sector)
         break;
 
-    if(b < buf+NBUF){
+    if(b != &bufhead){
       if(b->flags & B_BUSY){
         sleep(buf, &buf_table_lock);
       } else {
@@ -39,10 +53,7 @@ getblk(uint dev, uint sector)
         return b;
       }
     } else {
-      for(i = 0; i < NBUF; i++){
-        b = scan++;
-        if(scan >= buf+NBUF)
-          scan = buf;
+      for(b = bufhead.prev; b != &bufhead; b = b->prev){
         if((b->flags & B_BUSY) == 0){
           b->flags = B_BUSY;
           b->dev = dev;
@@ -64,8 +75,9 @@ bread(uint dev, uint sector)
   extern struct spinlock ide_lock;
 
   b = getblk(dev, sector);
-  if(b->flags & B_VALID)
+  if(b->flags & B_VALID){
     return b;
+  }
 
   acquire(&ide_lock);
   c = ide_start_rw(dev & 0xff, sector, b->data, 1, 1);
@@ -99,6 +111,13 @@ brelse(struct buf *b)
   
   acquire(&buf_table_lock);
 
+  b->next->prev = b->prev;
+  b->prev->next = b->next;
+  b->next = bufhead.next;
+  b->prev = &bufhead;
+  bufhead.next->prev = b;
+  bufhead.next = b;
+
   b->flags &= ~B_BUSY;
   wakeup(buf);
 
diff --git a/buf.h b/buf.h
index 7ab352a..a2a3ec1 100644
--- a/buf.h
+++ b/buf.h
@@ -2,6 +2,8 @@ struct buf {
   int flags;
   uint dev;
   uint sector;
+  struct buf *prev;
+  struct buf *next;
   uchar data[512];
 };
 #define B_BUSY 0x1
diff --git a/fs.c b/fs.c
index 4d32aa8..b042bb2 100644
--- a/fs.c
+++ b/fs.c
@@ -505,7 +505,7 @@ unlink(char *cp)
 
   
   if ((ip = namei(cp, &pinum)) == 0) {
-    cprintf("file to be unlinked doesn't exist\n");
+    cprintf("unlink(%s) it doesn't exist\n", cp);
     return -1;
   }
 
diff --git a/usertests.c b/usertests.c
index 9bd144c..3cb4a37 100644
--- a/usertests.c
+++ b/usertests.c
@@ -303,7 +303,7 @@ createdelete()
 void
 unlinkread()
 {
-  int fd;
+  int fd, fd1;
   
   fd = open("unlinkread", O_CREATE | O_RDWR);
   if(fd < 0){
@@ -322,15 +322,25 @@ unlinkread()
     puts("unlink unlinkread failed\n");
     exit();
   }
+
+  fd1 = open("xxx", O_CREATE | O_RDWR);
+  write(fd1, "yyy", 3);
+  close(fd1);
+
   if(read(fd, buf, sizeof(buf)) != 5){
     puts("unlinkread read failed");
     exit();
   }
+  if(buf[0] != 'h'){
+    puts("unlinkread wrong data\n");
+    exit();
+  }
   if(write(fd, buf, 10) != 10){
     puts("unlinkread write failed\n");
     exit();
   }
   close(fd);
+  unlink("xxx");
   puts("unlinkread ok\n");
 }
 
@@ -339,7 +349,7 @@ main(int argc, char *argv[])
 {
   puts("usertests starting\n");
 
-  //unlinkread();
+  unlinkread();
   createdelete();
   twofiles();
   sharedfd();
-- 
GitLab