ref: 85a64ca0685fe854e830c0b25565e5ca015d2dd3
parent: 45d2d1fe5e93955080c8c24cab765d368402f6a2
author: ngkaho1234 <[email protected]>
date: Tue Dec 15 08:59:52 EST 2015
ext4_journal: one bugfix plus one code logic changes below. - fix referencing jbd_buf->block that may be freed. - allow having multiple transaction checkpoints.
--- a/lwext4/ext4_journal.c
+++ b/lwext4/ext4_journal.c
@@ -1125,7 +1125,8 @@
struct ext4_fs *fs = journal->jbd_fs->inode_ref.fs;
LIST_FOREACH_SAFE(jbd_buf, &trans->buf_list, buf_node,
tmp) {
- ext4_block_set(fs->bdev, &jbd_buf->block);
+ struct ext4_block block = jbd_buf->block;
+ ext4_block_set(fs->bdev, &block);
}
}
@@ -1136,26 +1137,41 @@
{
struct jbd_trans *trans = arg;
struct jbd_journal *journal = trans->journal;
+ bool first_in_queue =
+ trans == TAILQ_FIRST(&journal->cp_queue);
if (res != EOK)
trans->error = res;
trans->written_cnt++;
if (trans->written_cnt == trans->data_cnt) {
-again:
TAILQ_REMOVE(&journal->cp_queue, trans, trans_node);
- journal->start = trans->start_iblock +
- trans->alloc_blocks;
- journal->trans_id = trans->trans_id + 1;
- jbd_journal_write_sb(journal);
- jbd_write_sb(journal->jbd_fs);
+
+ if (first_in_queue) {
+ journal->start = trans->start_iblock +
+ trans->alloc_blocks;
+ journal->trans_id = trans->trans_id + 1;
+ }
jbd_journal_free_trans(journal, trans, false);
- if ((trans = TAILQ_FIRST(&journal->cp_queue))) {
- if (trans->data_cnt) {
- jbd_journal_cp_trans(journal, trans);
- return;
+ if (first_in_queue) {
+ while ((trans = TAILQ_FIRST(&journal->cp_queue))) {
+ if (!trans->data_cnt) {
+ TAILQ_REMOVE(&journal->cp_queue,
+ trans,
+ trans_node);
+ journal->start = trans->start_iblock +
+ trans->alloc_blocks;
+ journal->trans_id = trans->trans_id + 1;
+ jbd_journal_free_trans(journal,
+ trans, false);
+ } else {
+ journal->start = trans->start_iblock;
+ journal->trans_id = trans->trans_id;
+ break;
+ }
}
- goto again;
+ jbd_journal_write_sb(journal);
+ jbd_write_sb(journal->jbd_fs);
}
}
}
@@ -1187,6 +1203,10 @@
journal->alloc_trans_id++;
if (TAILQ_EMPTY(&journal->cp_queue)) {
if (trans->data_cnt) {
+ journal->start = trans->start_iblock;
+ journal->trans_id = trans->trans_id;
+ jbd_journal_write_sb(journal);
+ jbd_write_sb(journal->jbd_fs);
TAILQ_INSERT_TAIL(&journal->cp_queue, trans,
trans_node);
jbd_journal_cp_trans(journal, trans);
@@ -1195,12 +1215,15 @@
trans->alloc_blocks;
journal->trans_id = trans->trans_id + 1;
jbd_journal_write_sb(journal);
- jbd_write_sb(journal->jbd_fs);
jbd_journal_free_trans(journal, trans, false);
}
- } else
+ } else {
TAILQ_INSERT_TAIL(&journal->cp_queue, trans,
trans_node);
+ if (trans->data_cnt)
+ jbd_journal_cp_trans(journal, trans);
+
+ }
}
Finish:
if (rc != EOK) {