ref: 044019786032626a52374d141b6241c704ddc55d
parent: 2c277c67ec7d39f81113de58ec8f9a7cae9f6640
author: ngkaho1234 <ngkaho1234@gmail.com>
date: Thu Dec 10 10:53:03 EST 2015
ext4_journal: introduce checkpoint mechanism.
--- a/lwext4/ext4_journal.c
+++ b/lwext4/ext4_journal.c
@@ -775,6 +775,7 @@
journal->start = journal->first;
journal->last = journal->first;
journal->trans_id = 1;
+ journal->alloc_trans_id = 1;
journal->block_size = jbd_get32(&jbd_fs->sb, blocksize);
@@ -792,9 +793,11 @@
return jbd_write_sb(journal->jbd_fs);
}
-static uint32_t jbd_journal_alloc_block(struct jbd_journal *journal)
+static uint32_t jbd_journal_alloc_block(struct jbd_journal *journal,
+ struct jbd_trans *trans)
{
uint32_t start_block = journal->last++;
+ trans->alloc_blocks++;
wrap(&journal->jbd_fs->sb, journal->last);
return start_block;
}
@@ -813,6 +816,11 @@
return trans;
}
+static void jbd_trans_end_write(struct ext4_bcache *bc __unused,
+ struct ext4_buf *buf __unused,
+ int res,
+ void *arg);
+
int jbd_trans_add_block(struct jbd_trans *trans,
struct ext4_block *block)
{
@@ -823,6 +831,10 @@
buf->trans = trans;
buf->block = *block;
ext4_bcache_inc_ref(block->buf);
+
+ block->buf->end_write = jbd_trans_end_write;
+ block->buf->end_write_arg = trans;
+
trans->data_cnt++;
LIST_INSERT_HEAD(&trans->buf_list, buf, buf_node);
return EOK;
@@ -861,15 +873,6 @@
free(trans);
}
-static void jbd_trans_end_write(struct ext4_bcache *bc __unused,
- struct ext4_buf *buf __unused,
- int res,
- void *arg)
-{
- struct jbd_trans *trans = arg;
- trans->error = res;
-}
-
static int jbd_trans_write_commit_block(struct jbd_trans *trans)
{
int rc;
@@ -878,7 +881,7 @@
struct ext4_block commit_block;
struct jbd_journal *journal = trans->journal;
- commit_iblock = jbd_journal_alloc_block(trans->journal);
+ commit_iblock = jbd_journal_alloc_block(journal, trans);
rc = jbd_block_get_noread(journal->jbd_fs,
&commit_block, commit_iblock);
if (rc != EOK)
@@ -914,7 +917,7 @@
again:
if (!desc_iblock) {
struct jbd_bhdr *bhdr;
- desc_iblock = jbd_journal_alloc_block(journal);
+ desc_iblock = jbd_journal_alloc_block(journal, trans);
rc = jbd_block_get_noread(journal->jbd_fs,
&desc_block, desc_iblock);
if (!rc)
@@ -952,7 +955,7 @@
goto again;
}
- data_iblock = jbd_journal_alloc_block(journal);
+ data_iblock = jbd_journal_alloc_block(journal, trans);
rc = jbd_block_get_noread(journal->jbd_fs,
&data_block, data_iblock);
if (rc != EOK)
@@ -1000,7 +1003,7 @@
again:
if (!desc_iblock) {
struct jbd_bhdr *bhdr;
- desc_iblock = jbd_journal_alloc_block(journal);
+ desc_iblock = jbd_journal_alloc_block(journal, trans);
rc = jbd_block_get_noread(journal->jbd_fs,
&desc_block, desc_iblock);
if (!rc) {
@@ -1060,64 +1063,60 @@
trans_node);
}
+static void jbd_trans_end_write(struct ext4_bcache *bc __unused,
+ struct ext4_buf *buf __unused,
+ int res,
+ void *arg)
+{
+ struct jbd_trans *trans = arg;
+ struct jbd_journal *journal = trans->journal;
+ if (res != EOK)
+ trans->error = res;
+
+ trans->written_cnt++;
+ if (trans->written_cnt == trans->data_cnt) {
+ TAILQ_REMOVE(&journal->cp_queue, trans, trans_node);
+ journal->start += trans->alloc_blocks;
+ journal->trans_id = ++trans->trans_id;
+ jbd_journal_write_sb(journal);
+ jbd_journal_free_trans(journal, trans);
+ }
+}
+
/*
* XXX: one should disable cache writeback first.
*/
-void
-jbd_journal_commit_to_disk(struct jbd_journal *journal)
+static void
+jbd_journal_commit_one(struct jbd_journal *journal)
{
- int rc;
- uint32_t last = journal->last,
- trans_id = journal->trans_id,
- start = journal->start;
- struct jbd_trans *trans, *tmp;
- TAILQ_FOREACH_SAFE(trans, &journal->trans_queue,
- trans_node,
- tmp) {
- struct jbd_buf *jbd_buf;
+ int rc = EOK;
+ uint32_t last = journal->last;
+ struct jbd_trans *trans;
+ if ((trans = TAILQ_FIRST(&journal->trans_queue))) {
TAILQ_REMOVE(&journal->trans_queue, trans, trans_node);
- trans->trans_id = trans_id + 1;
+ trans->trans_id = journal->alloc_trans_id;
rc = jbd_journal_prepare(journal, trans);
- if (rc != EOK) {
- journal->last = last;
- jbd_journal_free_trans(journal, trans);
- continue;
- }
+ if (rc != EOK)
+ goto Finish;
+
rc = jbd_journal_prepare_revoke(journal, trans);
- if (rc != EOK) {
- journal->last = last;
- jbd_journal_free_trans(journal, trans);
- continue;
- }
+ if (rc != EOK)
+ goto Finish;
+
rc = jbd_trans_write_commit_block(trans);
- if (rc != EOK) {
- journal->last = last;
- jbd_journal_free_trans(journal, trans);
- continue;
- }
- LIST_FOREACH(jbd_buf, &trans->buf_list, buf_node) {
- struct ext4_block *block = &jbd_buf->block;
- block->buf->end_write = jbd_trans_end_write;
- block->buf->end_write_arg = trans;
- ext4_block_set(journal->jbd_fs->inode_ref.fs->bdev,
- block);
- }
- if (trans->error != EOK) {
- journal->last = last;
- jbd_journal_free_trans(journal, trans);
- continue;
- }
+ if (rc != EOK)
+ goto Finish;
- start = last;
- trans_id++;
- last = journal->last;
+ journal->alloc_trans_id++;
+ TAILQ_INSERT_TAIL(&journal->cp_queue, trans,
+ trans_node);
+ }
+Finish:
+ if (rc != EOK) {
+ journal->last = last;
jbd_journal_free_trans(journal, trans);
}
-
- journal->start = start;
- journal->trans_id = trans_id;
- jbd_journal_write_sb(journal);
}
/**
--- a/lwext4/ext4_types.h
+++ b/lwext4/ext4_types.h
@@ -1107,7 +1107,9 @@
struct jbd_trans {
uint32_t trans_id;
+ int alloc_blocks;
int data_cnt;
+ int written_cnt;
int error;
struct jbd_journal *journal;
@@ -1122,10 +1124,12 @@
uint32_t start;
uint32_t last;
uint32_t trans_id;
+ uint32_t alloc_trans_id;
uint32_t block_size;
TAILQ_HEAD(jbd_trans_queue, jbd_trans) trans_queue;
+ TAILQ_HEAD(jbd_cp_queue, jbd_trans) cp_queue;
struct jbd_fs *jbd_fs;
};