diff options
| author | ngkaho1234 <ngkaho1234@gmail.com> | 2015-12-15 13:59:52 +0000 |
|---|---|---|
| committer | ngkaho1234 <ngkaho1234@gmail.com> | 2015-12-15 13:59:52 +0000 |
| commit | 85a64ca0685fe854e830c0b25565e5ca015d2dd3 (patch) | |
| tree | 85c83177108972b3c03be3e4281fee22ed8fdb5b | |
| parent | 45d2d1fe5e93955080c8c24cab765d368402f6a2 (diff) | |
ext4_journal: one bugfix plus one code logic changes below.
- fix referencing jbd_buf->block that may be freed.
- allow having multiple transaction checkpoints.
| -rw-r--r-- | lwext4/ext4_journal.c | 51 |
1 files changed, 37 insertions, 14 deletions
diff --git a/lwext4/ext4_journal.c b/lwext4/ext4_journal.c index ff14c53..6e21e44 100644 --- a/lwext4/ext4_journal.c +++ b/lwext4/ext4_journal.c @@ -1125,7 +1125,8 @@ void jbd_journal_cp_trans(struct jbd_journal *journal, struct jbd_trans *trans) 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 @@ static void jbd_trans_end_write(struct ext4_bcache *bc __unused, { 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 @@ void jbd_journal_commit_one(struct jbd_journal *journal) 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 @@ void jbd_journal_commit_one(struct jbd_journal *journal) 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) { |
