summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorngkaho1234 <ngkaho1234@gmail.com>2015-12-02 19:36:23 +0800
committerngkaho1234 <ngkaho1234@gmail.com>2015-12-02 19:39:37 +0800
commit5fa8a1a7d4f49a8c36196f6a73249bb016a1abad (patch)
tree209973a6a019fc532dc71ffff5d59d9346571d61
parentc3271e5e56ed89a01d5a95442422f0cc9e5a3077 (diff)
ext4_bcache & ext4_blockdev: unify buffer flushing code.
-rw-r--r--lwext4/ext4_bcache.c19
-rw-r--r--lwext4/ext4_bcache.h27
-rw-r--r--lwext4/ext4_blockdev.c45
-rw-r--r--lwext4/ext4_blockdev.h6
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)