ref: 5fa8a1a7d4f49a8c36196f6a73249bb016a1abad
parent: c3271e5e56ed89a01d5a95442422f0cc9e5a3077
author: ngkaho1234 <ngkaho1234@gmail.com>
date: Wed Dec 2 14:36:23 EST 2015
ext4_bcache & ext4_blockdev: unify buffer flushing code.
--- 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 @@
/*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 @@
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 @@
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))
--- a/lwext4/ext4_bcache.h
+++ b/lwext4/ext4_bcache.h
@@ -89,6 +89,9 @@
/**@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 @@
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 {
@@ -116,6 +140,9 @@
/**@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;
--- a/lwext4/ext4_blockdev.c
+++ b/lwext4/ext4_blockdev.c
@@ -63,6 +63,7 @@
{
ext4_assert(bdev && bc);
bdev->bc = bc;
+ bc->bdev = bdev;
return EOK;
}
@@ -85,8 +86,7 @@
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 @@
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,10 +192,6 @@
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);
@@ -205,37 +198,7 @@
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,
--- a/lwext4/ext4_blockdev.h
+++ b/lwext4/ext4_blockdev.h
@@ -139,6 +139,12 @@
* @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)