diff options
| author | ngkaho1234 <ngkaho1234@gmail.com> | 2015-12-02 19:36:23 +0800 |
|---|---|---|
| committer | ngkaho1234 <ngkaho1234@gmail.com> | 2015-12-02 19:39:37 +0800 |
| commit | 5fa8a1a7d4f49a8c36196f6a73249bb016a1abad (patch) | |
| tree | 209973a6a019fc532dc71ffff5d59d9346571d61 | |
| parent | c3271e5e56ed89a01d5a95442422f0cc9e5a3077 (diff) | |
ext4_bcache & ext4_blockdev: unify buffer flushing code.
| -rw-r--r-- | lwext4/ext4_bcache.c | 19 | ||||
| -rw-r--r-- | lwext4/ext4_bcache.h | 27 | ||||
| -rw-r--r-- | lwext4/ext4_blockdev.c | 45 | ||||
| -rw-r--r-- | lwext4/ext4_blockdev.h | 6 |
4 files changed, 46 insertions, 51 deletions
diff --git a/lwext4/ext4_bcache.c b/lwext4/ext4_bcache.c index 00be898..5e04a84 100644 --- a/lwext4/ext4_bcache.c +++ b/lwext4/ext4_bcache.c @@ -36,6 +36,7 @@ #include "ext4_config.h" #include "ext4_bcache.h" +#include "ext4_blockdev.h" #include "ext4_debug.h" #include "ext4_errno.h" @@ -156,10 +157,7 @@ void ext4_bcache_drop_buf(struct ext4_bcache *bc, struct ext4_buf *buf) /*Forcibly drop dirty buffer.*/ if (ext4_bcache_test_flag(buf, BC_DIRTY)) - SLIST_REMOVE(&bc->dirty_list, - buf, - ext4_buf, - dirty_node); + ext4_bcache_remove_dirty_node(bc, buf); ext4_buf_free(buf); bc->ref_blocks--; @@ -178,10 +176,7 @@ int ext4_bcache_alloc(struct ext4_bcache *bc, struct ext4_block *b, buf->lru_id = ++bc->lru_ctr; RB_REMOVE(ext4_buf_lru, &bc->lru_root, buf); if (ext4_bcache_test_flag(buf, BC_DIRTY)) - SLIST_REMOVE(&bc->dirty_list, - buf, - ext4_buf, - dirty_node); + ext4_bcache_remove_dirty_node(bc, buf); } @@ -255,8 +250,12 @@ int ext4_bcache_free(struct ext4_bcache *bc, struct ext4_block *b) if (!buf->refctr) { RB_INSERT(ext4_buf_lru, &bc->lru_root, buf); /* This buffer is ready to be flushed. */ - if (ext4_bcache_test_flag(buf, BC_DIRTY)) - SLIST_INSERT_HEAD(&bc->dirty_list, buf, dirty_node); + if (ext4_bcache_test_flag(buf, BC_DIRTY)) { + if (bc->bdev->cache_write_back) + ext4_bcache_insert_dirty_node(bc, buf); + else + ext4_block_flush_buf(bc->bdev, buf); + } /* The buffer is invalidated...drop it. */ if (!ext4_bcache_test_flag(buf, BC_UPTODATE)) diff --git a/lwext4/ext4_bcache.h b/lwext4/ext4_bcache.h index d35e32b..a7e514a 100644 --- a/lwext4/ext4_bcache.h +++ b/lwext4/ext4_bcache.h @@ -89,6 +89,9 @@ struct ext4_buf { /**@brief Reference count table*/ uint32_t refctr; + /**@brief Whether or not buffer is on dirty list.*/ + bool on_dirty_list; + /**@brief LBA tree node*/ RB_ENTRY(ext4_buf) lba_node; @@ -99,6 +102,27 @@ struct ext4_buf { SLIST_ENTRY(ext4_buf) dirty_node; }; +#define ext4_bcache_insert_dirty_node(bc, buf) \ +do { \ + if (!(buf)->on_dirty_list) { \ + SLIST_INSERT_HEAD(&(bc)->dirty_list, \ + (buf), \ + dirty_node); \ + (buf)->on_dirty_list = true; \ + } \ +} while (0) + +#define ext4_bcache_remove_dirty_node(bc, buf) \ +do { \ + if ((buf)->on_dirty_list) { \ + SLIST_REMOVE(&(bc)->dirty_list, \ + (buf), \ + ext4_buf, \ + dirty_node); \ + (buf)->on_dirty_list = false; \ + } \ +} while (0) + /**@brief Block cache descriptor*/ struct ext4_bcache { @@ -117,6 +141,9 @@ struct ext4_bcache { /**@brief Maximum referenced datablocks*/ uint32_t max_ref_blocks; + /**@brief The blockdev binded to this block cache*/ + struct ext4_blockdev *bdev; + /**@brief A tree holding all bufs*/ RB_HEAD(ext4_buf_lba, ext4_buf) lba_root; diff --git a/lwext4/ext4_blockdev.c b/lwext4/ext4_blockdev.c index 923acad..6a18232 100644 --- a/lwext4/ext4_blockdev.c +++ b/lwext4/ext4_blockdev.c @@ -63,6 +63,7 @@ int ext4_block_bind_bcache(struct ext4_blockdev *bdev, struct ext4_bcache *bc) { ext4_assert(bdev && bc); bdev->bc = bc; + bc->bdev = bdev; return EOK; } @@ -85,8 +86,7 @@ int ext4_block_fini(struct ext4_blockdev *bdev) return bdev->close(bdev); } -static int -ext4_block_flush_buf(struct ext4_blockdev *bdev, struct ext4_buf *buf) +int ext4_block_flush_buf(struct ext4_blockdev *bdev, struct ext4_buf *buf) { int r; struct ext4_bcache *bc = bdev->bc; @@ -98,10 +98,7 @@ ext4_block_flush_buf(struct ext4_blockdev *bdev, struct ext4_buf *buf) if (r) return r; - SLIST_REMOVE(&bc->dirty_list, - buf, - ext4_buf, - dirty_node); + ext4_bcache_remove_dirty_node(bc, buf); ext4_bcache_clear_flag(buf, BC_DIRTY); } return EOK; @@ -195,47 +192,13 @@ int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b, int ext4_block_set(struct ext4_blockdev *bdev, struct ext4_block *b) { - uint64_t pba; - uint32_t pb_cnt; - int r; - ext4_assert(bdev && b); ext4_assert(b->buf); if (!(bdev->flags & EXT4_BDEV_INITIALIZED)) return EIO; - /*Free cache delay mode*/ - if (bdev->cache_write_back) { - - /*Free cache block and mark as free delayed*/ - return ext4_bcache_free(bdev->bc, b); - } - - if (b->buf->refctr > 1) - return ext4_bcache_free(bdev->bc, b); - - /*We handle the dirty flag ourselves.*/ - if (ext4_bcache_test_flag(b->buf, BC_DIRTY) || b->dirty) { - b->uptodate = true; - ext4_bcache_set_flag(b->buf, BC_UPTODATE); - - pba = (b->lb_id * bdev->lg_bsize) / bdev->ph_bsize; - pb_cnt = bdev->lg_bsize / bdev->ph_bsize; - - r = bdev->bwrite(bdev, b->data, pba, pb_cnt); - ext4_bcache_clear_flag(b->buf, BC_DIRTY); - if (r != EOK) { - b->dirty = true; - ext4_bcache_free(bdev->bc, b); - return r; - } - - b->dirty = false; - bdev->bwrite_ctr++; - } - ext4_bcache_free(bdev->bc, b); - return EOK; + return ext4_bcache_free(bdev->bc, b); } int ext4_blocks_get_direct(struct ext4_blockdev *bdev, void *buf, uint64_t lba, diff --git a/lwext4/ext4_blockdev.h b/lwext4/ext4_blockdev.h index 0b22052..e0d6620 100644 --- a/lwext4/ext4_blockdev.h +++ b/lwext4/ext4_blockdev.h @@ -139,6 +139,12 @@ int ext4_block_bind_bcache(struct ext4_blockdev *bdev, struct ext4_bcache *bc); * @return standard error code*/ int ext4_block_fini(struct ext4_blockdev *bdev); +/**@brief Flush data in given buffer to disk. + * @param bdev block device descriptor + * @param buf buffer + * @return standard error code*/ +int ext4_block_flush_buf(struct ext4_blockdev *bdev, struct ext4_buf *buf); + /**@brief Set logical block size in block device. * @param bdev block device descriptor * @param lb_size logical block size (in bytes) |
