shithub: lwext4

Download patch

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)