diff options
| author | Frans Kaashoek <kaashoek@mit.edu> | 2019-08-01 15:46:50 -0400 | 
|---|---|---|
| committer | Frans Kaashoek <kaashoek@mit.edu> | 2019-08-01 15:46:50 -0400 | 
| commit | 62ece4b09e6a568ede0e3b524af959194e0cb792 (patch) | |
| tree | 72553e7a6c57a3298193b288db07eb1a4eab17d0 /kernel | |
| parent | fb8a0099d48643775d0bca626af1a73a3ab618a4 (diff) | |
| parent | 9c4f62e8e3e7f114c6f82a75579a815e6329d767 (diff) | |
| download | xv6-labs-62ece4b09e6a568ede0e3b524af959194e0cb792.tar.gz xv6-labs-62ece4b09e6a568ede0e3b524af959194e0cb792.tar.bz2 xv6-labs-62ece4b09e6a568ede0e3b524af959194e0cb792.zip | |
Merge branch 'riscv-bcache' into riscv
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/bio.c | 36 | ||||
| -rw-r--r-- | kernel/buf.h | 5 | ||||
| -rw-r--r-- | kernel/defs.h | 4 | ||||
| -rw-r--r-- | kernel/log.c | 8 | ||||
| -rw-r--r-- | kernel/virtio_disk.c | 21 | 
5 files changed, 43 insertions, 31 deletions
| diff --git a/kernel/bio.c b/kernel/bio.c index a08884b..a1074f2 100644 --- a/kernel/bio.c +++ b/kernel/bio.c @@ -12,11 +12,7 @@  // * Do not use the buffer after calling brelse.  // * Only one process at a time can use a buffer,  //     so do not keep them longer than necessary. -// -// The implementation uses two state flags internally: -// * B_VALID: the buffer data has been read from the disk. -// * B_DIRTY: the buffer data has been modified -//     and needs to be written to disk. +  #include "types.h"  #include "param.h" @@ -76,13 +72,11 @@ bget(uint dev, uint blockno)    }    // Not cached; recycle an unused buffer. -  // Even if refcnt==0, B_DIRTY indicates a buffer is in use -  // because log.c has modified it but not yet committed it.    for(b = bcache.head.prev; b != &bcache.head; b = b->prev){ -    if(b->refcnt == 0 && (b->flags & B_DIRTY) == 0) { +    if(b->refcnt == 0) {        b->dev = dev;        b->blockno = blockno; -      b->flags = 0; +      b->valid = 0;        b->refcnt = 1;        release(&bcache.lock);        acquiresleep(&b->lock); @@ -99,8 +93,9 @@ bread(uint dev, uint blockno)    struct buf *b;    b = bget(dev, blockno); -  if((b->flags & B_VALID) == 0) { -    virtio_disk_rw(b); +  if(!b->valid) { +    virtio_disk_rw(b, 0); +    b->valid = 1;    }    return b;  } @@ -111,8 +106,7 @@ bwrite(struct buf *b)  {    if(!holdingsleep(&b->lock))      panic("bwrite"); -  b->flags |= B_DIRTY; -  virtio_disk_rw(b); +  virtio_disk_rw(b, 1);  }  // Release a locked buffer. @@ -139,3 +133,19 @@ brelse(struct buf *b)    release(&bcache.lock);  } + +void +bpin(struct buf *b) { +  acquire(&bcache.lock); +  b->refcnt++; +  release(&bcache.lock); +} + +void +bunpin(struct buf *b) { +  acquire(&bcache.lock); +  b->refcnt--; +  release(&bcache.lock); +} + + diff --git a/kernel/buf.h b/kernel/buf.h index 3266495..4a3a39d 100644 --- a/kernel/buf.h +++ b/kernel/buf.h @@ -1,5 +1,6 @@  struct buf { -  int flags; +  int valid;   // has data been read from disk? +  int disk;    // does disk "own" buf?    uint dev;    uint blockno;    struct sleeplock lock; @@ -9,6 +10,4 @@ struct buf {    struct buf *qnext; // disk queue    uchar data[BSIZE];  }; -#define B_VALID 0x2  // buffer has been read from disk -#define B_DIRTY 0x4  // buffer needs to be written to disk diff --git a/kernel/defs.h b/kernel/defs.h index de4acfd..2689bed 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -14,6 +14,8 @@ void            binit(void);  struct buf*     bread(uint, uint);  void            brelse(struct buf*);  void            bwrite(struct buf*); +void            bpin(struct buf*); +void            bunpin(struct buf*);  // console.c  void            consoleinit(void); @@ -177,7 +179,7 @@ void            plic_complete(int);  // virtio_disk.c  void            virtio_disk_init(void); -void            virtio_disk_rw(struct buf *); +void            virtio_disk_rw(struct buf *, int);  void            virtio_disk_intr();  // number of elements in fixed-size array diff --git a/kernel/log.c b/kernel/log.c index c8f7e62..59984db 100644 --- a/kernel/log.c +++ b/kernel/log.c @@ -77,6 +77,7 @@ install_trans(void)      struct buf *dbuf = bread(log.dev, log.lh.block[tail]); // read dst      memmove(dbuf->data, lbuf->data, BSIZE);  // copy block to dst      bwrite(dbuf);  // write dst to disk +    bunpin(dbuf);      brelse(lbuf);      brelse(dbuf);    } @@ -203,7 +204,7 @@ commit()  }  // Caller has modified b->data and is done with the buffer. -// Record the block number and pin in the cache with B_DIRTY. +// Record the block number and pin in the cache by increasing refcnt.  // commit()/write_log() will do the disk write.  //  // log_write() replaces bwrite(); a typical use is: @@ -227,9 +228,10 @@ log_write(struct buf *b)        break;    }    log.lh.block[i] = b->blockno; -  if (i == log.lh.n) +  if (i == log.lh.n) {  // Add new block to log? +    bpin(b);      log.lh.n++; -  b->flags |= B_DIRTY; // prevent eviction +  }    release(&log.lock);  } diff --git a/kernel/virtio_disk.c b/kernel/virtio_disk.c index 3ace5ef..14c718d 100644 --- a/kernel/virtio_disk.c +++ b/kernel/virtio_disk.c @@ -164,7 +164,7 @@ alloc3_desc(int *idx)  }  void -virtio_disk_rw(struct buf *b) +virtio_disk_rw(struct buf *b, int write)  {    uint64 sector = b->blockno * (BSIZE / 512); @@ -192,7 +192,7 @@ virtio_disk_rw(struct buf *b)      uint64 sector;    } buf0; -  if(b->flags & B_DIRTY) +  if(write)      buf0.type = VIRTIO_BLK_T_OUT; // write the disk    else      buf0.type = VIRTIO_BLK_T_IN; // read the disk @@ -208,7 +208,7 @@ virtio_disk_rw(struct buf *b)    desc[idx[1]].addr = (uint64) b->data;    desc[idx[1]].len = BSIZE; -  if(b->flags & B_DIRTY) +  if(write)      desc[idx[1]].flags = 0; // device reads b->data    else      desc[idx[1]].flags = VRING_DESC_F_WRITE; // device writes b->data @@ -222,6 +222,7 @@ virtio_disk_rw(struct buf *b)    desc[idx[2]].next = 0;    // record struct buf for virtio_disk_intr(). +  b->disk = 1;    info[idx[0]].b = b;    // avail[0] is flags @@ -235,10 +236,13 @@ virtio_disk_rw(struct buf *b)    *R(VIRTIO_MMIO_QUEUE_NOTIFY) = 0; // value is queue number    // Wait for virtio_disk_intr() to say request has finished. -  while((b->flags & (B_VALID|B_DIRTY)) != B_VALID){ +  while(b->disk == 1) {      sleep(b, &vdisk_lock);    } +  info[idx[0]].b = 0; +  free_chain(idx[0]); +    release(&vdisk_lock);  } @@ -252,15 +256,10 @@ virtio_disk_intr()      if(info[id].status != 0)        panic("virtio_disk_intr status"); - -    info[id].b->flags |= B_VALID; -    info[id].b->flags &= ~B_DIRTY; - +     +    info[id].b->disk = 0;   // disk is done with buf      wakeup(info[id].b); -    info[id].b = 0; -    free_chain(id); -      used_idx = (used_idx + 1) % NUM;    } | 
