ref: 23644a4048b147390df8bef84b1e9cf4dbea2b8e
parent: 754d2885b461161dee8d49eb0e0a50269ba634a0
author: ngkaho1234 <ngkaho1234@gmail.com>
date: Sat Nov 7 12:35:15 EST 2015
Reworks on buffer management 1. ext4_bcache: use flags arrayinstead of dirty boolean array. 2. ext4_blockdev: ext4_block_get_noread added.
--- a/lwext4/ext4_bcache.c
+++ b/lwext4/ext4_bcache.c
@@ -115,6 +115,7 @@
/*Set valid cache data and id*/
b->data = bc->data + i * bc->itemsize;
b->cache_id = i;
+ b->uptodate = ext4_bcache_test_flag(bc, i, BC_UPTODATE);
return EOK;
}
@@ -154,6 +155,8 @@
/*Set valid cache data and id*/
b->data = bc->data + cache_id * bc->itemsize;
b->cache_id = cache_id;
+ ext4_bcache_clear_flag(bc, cache_id, BC_UPTODATE);
+ b->uptodate = false;
/*Statistics*/
bc->ref_blocks++;
@@ -199,6 +202,7 @@
b->lb_id = 0;
b->data = 0;
b->cache_id = 0;
+ b->uptodate = false;
return EOK;
}
--- a/lwext4/ext4_bcache.h
+++ b/lwext4/ext4_bcache.h
@@ -42,10 +42,13 @@
#include <stdint.h>
#include <stdbool.h>
-#define EXT4_BLOCK_ZERO() {.dirty = 0, .lb_id = 0, .cache_id = 0, .data = 0}
+#define EXT4_BLOCK_ZERO() {.uptodate = 0, .dirty = 0, .lb_id = 0, .cache_id = 0, .data = 0}
/**@brief Single block descriptor*/
struct ext4_block {
+ /**@brief Uptodate flag*/
+ bool uptodate;
+
/**@brief Dirty flag*/
bool dirty;
@@ -83,8 +86,8 @@
/**@brief Logical block table*/
uint64_t lba[CONFIG_BLOCK_DEV_CACHE_SIZE];
- /**@brief Dirty mark*/
- bool dirty[CONFIG_BLOCK_DEV_CACHE_SIZE];
+ /**@brief Flags*/
+ int flags[CONFIG_BLOCK_DEV_CACHE_SIZE];
/**@brief Cache data buffers*/
uint8_t *data;
@@ -95,6 +98,20 @@
/**@brief Maximum referenced datablocks*/
uint32_t max_ref_blocks;
};
+
+enum bcache_state_bits {
+ BC_UPTODATE,
+ BC_DIRTY
+};
+
+#define ext4_bcache_set_flag(bc, id, b) \
+ (bc)->flags[id] |= 1 << (b)
+
+#define ext4_bcache_clear_flag(bc, id, b) \
+ (bc)->flags[id] &= ~(1 << (b))
+
+#define ext4_bcache_test_flag(bc, id, b) \
+ (((bc)->flags[id] & (1 << (b))) >> (b))
/**@brief Static initializer of block cache structure.*/
#define EXT4_BCACHE_STATIC_INSTANCE(__name, __cnt, __itemsize) \
--- a/lwext4/ext4_blockdev.c
+++ b/lwext4/ext4_blockdev.c
@@ -85,11 +85,9 @@
return bdev->close(bdev);
}
-int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b,
- uint64_t lba)
+int ext4_block_get_noread(struct ext4_blockdev *bdev, struct ext4_block *b,
+ uint64_t lba)
{
- uint64_t pba;
- uint32_t pb_cnt;
uint32_t i;
bool is_new;
int r;
@@ -149,14 +147,26 @@
if (r != EOK)
return r;
- if (!is_new) {
+ if (!b->data)
+ return ENOMEM;
+
+ return EOK;
+}
+
+int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b,
+ uint64_t lba)
+{
+ uint64_t pba;
+ uint32_t pb_cnt;
+ int r = ext4_block_get_noread(bdev, b, lba);
+ if (r != EOK)
+ return r;
+
+ if (b->uptodate) {
/*Block is in cache. Read from physical device is not required*/
return EOK;
}
- if (!b->data)
- return ENOMEM;
-
pba = (lba * bdev->lg_bsize) / bdev->ph_bsize;
pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
@@ -168,6 +178,8 @@
return r;
}
+ ext4_bcache_set_flag(bdev->bc, b->cache_id, BC_UPTODATE);
+ b->uptodate = true;
bdev->bread_ctr++;
return EOK;
}
@@ -183,11 +195,17 @@
if (!(bdev->flags & EXT4_BDEV_INITIALIZED))
return EIO;
+ /*Buffer is not marked dirty and is stale*/
+ if (!b->uptodate && !b->dirty)
+ ext4_bcache_clear_flag(bdev->bc, b->cache_id, BC_UPTODATE);
+
/*No need to write.*/
- if (!b->dirty && !bdev->bc->dirty[b->cache_id]) {
+ if (!b->dirty &&
+ !ext4_bcache_test_flag(bdev->bc, b->cache_id, BC_DIRTY)) {
ext4_bcache_free(bdev->bc, b, 0);
return EOK;
}
+ ext4_bcache_set_flag(bdev->bc, b->cache_id, BC_UPTODATE);
/*Free cache delay mode*/
if (bdev->cache_write_back) {
@@ -197,7 +215,7 @@
}
if (bdev->bc->refctr[b->cache_id] > 1) {
- bdev->bc->dirty[b->cache_id] = true;
+ ext4_bcache_set_flag(bdev->bc, b->cache_id, BC_DIRTY);
return ext4_bcache_free(bdev->bc, b, 0);
}
@@ -205,9 +223,10 @@
pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
r = bdev->bwrite(bdev, b->data, pba, pb_cnt);
- bdev->bc->dirty[b->cache_id] = false;
+ ext4_bcache_clear_flag(bdev->bc, b->cache_id, BC_DIRTY);
if (r != EOK) {
b->dirty = false;
+ ext4_bcache_clear_flag(bdev->bc, b->cache_id, BC_UPTODATE);
ext4_bcache_free(bdev->bc, b, 0);
return r;
}
--- a/lwext4/ext4_blockdev.h
+++ b/lwext4/ext4_blockdev.h
@@ -141,6 +141,14 @@
* @return standard error code*/
void ext4_block_set_lb_size(struct ext4_blockdev *bdev, uint64_t lb_bsize);
+/**@brief Block get function (through cache, don't read).
+ * @param bdev block device descriptor
+ * @param b block descriptor
+ * @param lba logical block address
+ * @return standard error code*/
+int ext4_block_get_noread(struct ext4_blockdev *bdev, struct ext4_block *b,
+ uint64_t lba);
+
/**@brief Block get function (through cache).
* @param bdev block device descriptor
* @param b block descriptor