shithub: lwext4

Download patch

ref: c5ea10075711ba4814084b7ef3bc56c537fd91b0
parent: 5cf3ed9bc1a227e6dac367d6b9408d81f972af67
author: ngkaho1234 <ngkaho1234@gmail.com>
date: Tue Dec 29 19:39:55 EST 2015

ext4_journal: reimplement buffer list as buffer queue in jbd_trans.

With this modification, we can first remove non-dirty buffers from the
tail of of a buffer queue before iterating the entries on the buffer queue.

--- a/lwext4/ext4_journal.c
+++ b/lwext4/ext4_journal.c
@@ -992,7 +992,7 @@
 	struct jbd_buf *jbd_buf, *tmp;
 	struct jbd_journal *journal = trans->journal;
 	struct ext4_fs *fs = journal->jbd_fs->inode_ref.fs;
-	LIST_FOREACH_SAFE(jbd_buf, &trans->buf_list, buf_node,
+	TAILQ_FOREACH_SAFE(jbd_buf, &trans->buf_queue, buf_node,
 			tmp) {
 		struct ext4_block block = jbd_buf->block;
 		ext4_block_flush_buf(fs->bdev, block.buf);
@@ -1223,7 +1223,7 @@
 		block->buf->end_write_arg = buf;
 
 		trans->data_cnt++;
-		LIST_INSERT_HEAD(&trans->buf_list, buf, buf_node);
+		TAILQ_INSERT_HEAD(&trans->buf_queue, buf, buf_node);
 
 		ext4_bcache_set_dirty(block->buf);
 	}
@@ -1290,7 +1290,7 @@
 	struct jbd_buf *jbd_buf, *tmp;
 	struct jbd_revoke_rec *rec, *tmp2;
 	struct ext4_fs *fs = journal->jbd_fs->inode_ref.fs;
-	LIST_FOREACH_SAFE(jbd_buf, &trans->buf_list, buf_node,
+	TAILQ_FOREACH_SAFE(jbd_buf, &trans->buf_queue, buf_node,
 			  tmp) {
 		if (abort) {
 			jbd_buf->block.buf->end_write = NULL;
@@ -1300,7 +1300,7 @@
 		}
 
 		jbd_trans_remove_block_rec(journal, jbd_buf);
-		LIST_REMOVE(jbd_buf, buf_node);
+		TAILQ_REMOVE(&trans->buf_queue, jbd_buf, buf_node);
 		free(jbd_buf);
 	}
 	LIST_FOREACH_SAFE(rec, &trans->revoke_list, revoke_node,
@@ -1358,7 +1358,28 @@
 	struct ext4_block desc_block, data_block;
 	struct ext4_fs *fs = journal->jbd_fs->inode_ref.fs;
 
-	LIST_FOREACH_SAFE(jbd_buf, &trans->buf_list, buf_node, tmp) {
+	/* Try to remove any non-dirty buffers from the tail of
+	 * buf_queue. */
+	TAILQ_FOREACH_REVERSE_SAFE(jbd_buf, &trans->buf_queue,
+			jbd_trans_buf, buf_node, tmp) {
+		/* We stop the iteration when we find a dirty buffer. */
+		if (ext4_bcache_test_flag(jbd_buf->block.buf,
+					BC_DIRTY))
+			break;
+
+		/* The buffer has not been modified, just release
+		 * that jbd_buf. */
+		jbd_trans_remove_block_rec(journal, jbd_buf);
+		trans->data_cnt--;
+
+		jbd_buf->block.buf->end_write = NULL;
+		jbd_buf->block.buf->end_write_arg = NULL;
+		ext4_block_set(fs->bdev, &jbd_buf->block);
+		TAILQ_REMOVE(&trans->buf_queue, jbd_buf, buf_node);
+		free(jbd_buf);
+	}
+
+	TAILQ_FOREACH_SAFE(jbd_buf, &trans->buf_queue, buf_node, tmp) {
 		struct tag_info tag_info;
 		bool uuid_exist = false;
 		if (!ext4_bcache_test_flag(jbd_buf->block.buf,
@@ -1371,7 +1392,7 @@
 			jbd_buf->block.buf->end_write = NULL;
 			jbd_buf->block.buf->end_write_arg = NULL;
 			ext4_block_set(fs->bdev, &jbd_buf->block);
-			LIST_REMOVE(jbd_buf, buf_node);
+			TAILQ_REMOVE(&trans->buf_queue, jbd_buf, buf_node);
 			free(jbd_buf);
 			continue;
 		}
@@ -1550,7 +1571,7 @@
 {
 	struct jbd_buf *jbd_buf, *tmp;
 	struct ext4_fs *fs = journal->jbd_fs->inode_ref.fs;
-	LIST_FOREACH_SAFE(jbd_buf, &trans->buf_list, buf_node,
+	TAILQ_FOREACH_SAFE(jbd_buf, &trans->buf_queue, buf_node,
 			tmp) {
 		struct ext4_block block = jbd_buf->block;
 		ext4_block_set(fs->bdev, &block);
@@ -1572,7 +1593,7 @@
 	if (res != EOK)
 		trans->error = res;
 
-	LIST_REMOVE(jbd_buf, buf_node);
+	TAILQ_REMOVE(&trans->buf_queue, jbd_buf, buf_node);
 	jbd_buf->block_rec->buf = NULL;
 	jbd_trans_remove_block_rec(journal, jbd_buf);
 	free(jbd_buf);
@@ -1633,7 +1654,7 @@
 	if (rc != EOK)
 		goto Finish;
 
-	if (LIST_EMPTY(&trans->buf_list) &&
+	if (TAILQ_EMPTY(&trans->buf_queue) &&
 	    LIST_EMPTY(&trans->revoke_list)) {
 		/* Since there are no entries in both buffer list
 		 * and revoke entry list, we do not consider trans as
--- a/lwext4/ext4_types.h
+++ b/lwext4/ext4_types.h
@@ -1101,7 +1101,7 @@
 	struct ext4_block block;
 	struct jbd_trans *trans;
 	struct jbd_block_rec *block_rec;
-	LIST_ENTRY(jbd_buf) buf_node;
+	TAILQ_ENTRY(jbd_buf) buf_node;
 };
 
 struct jbd_revoke_rec {
@@ -1127,7 +1127,7 @@
 
 	struct jbd_journal *journal;
 
-	LIST_HEAD(jbd_trans_buf, jbd_buf) buf_list;
+	TAILQ_HEAD(jbd_trans_buf, jbd_buf) buf_queue;
 	LIST_HEAD(jbd_revoke_list, jbd_revoke_rec) revoke_list;
 	TAILQ_ENTRY(jbd_trans) trans_node;
 };