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;
};