shithub: lwext4

Download patch

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