From cd93074e5bed8fdbc84f2960c3219c7cf791b020 Mon Sep 17 00:00:00 2001 From: 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();