ref: 2c277c67ec7d39f81113de58ec8f9a7cae9f6640
parent: 093f60969f083427b5354ba3344297b6194ed106
author: ngkaho1234 <ngkaho1234@gmail.com>
date: Thu Dec 10 08:02:57 EST 2015
ext4_journal: journal write v1.
--- a/lwext4/ext4_journal.c
+++ b/lwext4/ext4_journal.c
@@ -792,17 +792,6 @@
return jbd_write_sb(journal->jbd_fs);
}
-static inline bool jbd_has_enough_space(struct jbd_journal *journal,
- uint32_t blk_cnt)
-{
- uint32_t new_last = journal->last + blk_cnt;
- wrap(&journal->jbd_fs->sb, new_last);
- if (new_last >= journal->start)
- return false;
-
- return true;
-}
-
static uint32_t jbd_journal_alloc_block(struct jbd_journal *journal)
{
uint32_t start_block = journal->last++;
@@ -811,7 +800,7 @@
}
struct jbd_trans *
-jbd_journal_new_trans()
+jbd_journal_new_trans(struct jbd_journal *journal)
{
struct jbd_trans *trans = calloc(1, sizeof(struct jbd_trans));
if (!trans)
@@ -819,6 +808,8 @@
/* We will assign a trans_id to this transaction,
* once it has been committed.*/
+ trans->journal = journal;
+ trans->error = EOK;
return trans;
}
@@ -832,7 +823,7 @@
buf->trans = trans;
buf->block = *block;
ext4_bcache_inc_ref(block->buf);
- trans->buf_cnt++;
+ trans->data_cnt++;
LIST_INSERT_HEAD(&trans->buf_list, buf, buf_node);
return EOK;
}
@@ -846,21 +837,20 @@
return ENOMEM;
rec->lba = lba;
- trans->revoke_cnt++;
LIST_INSERT_HEAD(&trans->revoke_list, rec, revoke_node);
return EOK;
}
-void jbd_journal_abort_trans(struct jbd_journal *journal,
- struct jbd_trans *trans)
+void jbd_journal_free_trans(struct jbd_journal *journal,
+ struct jbd_trans *trans)
{
- struct jbd_buf *var, *tmp;
+ struct jbd_buf *jbd_buf, *tmp;
struct jbd_revoke_rec *rec, *tmp2;
- LIST_FOREACH_SAFE(var, &trans->buf_list, buf_node,
+ LIST_FOREACH_SAFE(jbd_buf, &trans->buf_list, buf_node,
tmp) {
- ext4_block_set(journal->jbd_fs->bdev, &var->block);
- LIST_REMOVE(var, buf_node);
- free(var);
+ ext4_block_set(journal->jbd_fs->bdev, &jbd_buf->block);
+ LIST_REMOVE(jbd_buf, buf_node);
+ free(jbd_buf);
}
LIST_FOREACH_SAFE(rec, &trans->revoke_list, revoke_node,
tmp2) {
@@ -871,9 +861,40 @@
free(trans);
}
-static void jbd_journal_end_write()
+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;
+ struct jbd_commit_header *header;
+ uint32_t commit_iblock = 0;
+ struct ext4_block commit_block;
+ struct jbd_journal *journal = trans->journal;
+
+ commit_iblock = jbd_journal_alloc_block(trans->journal);
+ rc = jbd_block_get_noread(journal->jbd_fs,
+ &commit_block, commit_iblock);
+ if (rc != EOK)
+ return rc;
+
+ header = (struct jbd_commit_header *)commit_block.data;
+ header->header.magic = JBD_MAGIC_NUMBER;
+ header->header.blocktype = JBD_COMMIT_BLOCK;
+ header->header.sequence = trans->trans_id;
+
+ ext4_bcache_set_dirty(commit_block.buf);
+ rc = jbd_block_set(journal->jbd_fs, &commit_block);
+ if (rc != EOK)
+ return rc;
+
+ return EOK;
}
static int jbd_journal_prepare(struct jbd_journal *journal,
@@ -914,7 +935,7 @@
}
tag_info.block = jbd_buf->block.lb_id;
tag_info.uuid_exist = uuid_exist;
- if (i == trans->buf_cnt - 1)
+ if (i == trans->data_cnt - 1)
tag_info.last_tag = true;
if (uuid_exist)
@@ -951,10 +972,7 @@
i++;
}
- if (rc != EOK)
- jbd_journal_abort_trans(journal, trans);
-
- if (desc_iblock)
+ if (rc == EOK && desc_iblock)
jbd_block_set(journal->jbd_fs, &desc_block);
return rc;
@@ -968,7 +986,7 @@
int32_t tag_tbl_size;
uint32_t desc_iblock = 0;
char *blocks_entry = NULL;
- struct jbd_revoke_rec *rec;
+ struct jbd_revoke_rec *rec, *tmp;
struct ext4_block desc_block;
struct jbd_revoke_header *header = NULL;
int32_t record_len = 4;
@@ -977,7 +995,8 @@
JBD_FEATURE_INCOMPAT_64BIT))
record_len = 8;
- LIST_FOREACH(rec, &trans->revoke_list, revoke_node) {
+ LIST_FOREACH_SAFE(rec, &trans->revoke_list, revoke_node,
+ tmp) {
again:
if (!desc_iblock) {
struct jbd_bhdr *bhdr;
@@ -984,8 +1003,9 @@
desc_iblock = jbd_journal_alloc_block(journal);
rc = jbd_block_get_noread(journal->jbd_fs,
&desc_block, desc_iblock);
- if (!rc)
+ if (!rc) {
break;
+ }
ext4_bcache_set_dirty(desc_block.buf);
@@ -997,7 +1017,7 @@
header = (struct jbd_revoke_header *)bhdr;
blocks_entry = (char *)(header + 1);
tag_tbl_size = journal->block_size -
- sizeof(struct jbd_bhdr);
+ sizeof(struct jbd_revoke_header);
}
if (tag_tbl_size < record_len) {
@@ -1021,10 +1041,7 @@
i++;
}
- if (rc != EOK)
- jbd_journal_abort_trans(journal, trans);
-
- if (desc_iblock) {
+ if (rc == EOK && desc_iblock) {
if (header != NULL)
header->count = journal->block_size - tag_tbl_size;
@@ -1035,13 +1052,72 @@
}
void
-jbd_journal_commit_trans(struct jbd_journal *journal,
+jbd_journal_submit_trans(struct jbd_journal *journal,
struct jbd_trans *trans)
{
- trans->trans_id = journal->trans_id++;
TAILQ_INSERT_TAIL(&journal->trans_queue,
trans,
trans_node);
+}
+
+/*
+ * XXX: one should disable cache writeback first.
+ */
+void
+jbd_journal_commit_to_disk(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;
+ TAILQ_REMOVE(&journal->trans_queue, trans, trans_node);
+
+ trans->trans_id = trans_id + 1;
+ rc = jbd_journal_prepare(journal, trans);
+ if (rc != EOK) {
+ journal->last = last;
+ jbd_journal_free_trans(journal, trans);
+ continue;
+ }
+ rc = jbd_journal_prepare_revoke(journal, trans);
+ if (rc != EOK) {
+ journal->last = last;
+ jbd_journal_free_trans(journal, trans);
+ continue;
+ }
+ 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;
+ }
+
+ start = last;
+ trans_id++;
+ last = journal->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,8 +1107,11 @@
struct jbd_trans {
uint32_t trans_id;
- int buf_cnt;
- int revoke_cnt;
+ int data_cnt;
+ int error;
+
+ struct jbd_journal *journal;
+
LIST_HEAD(jbd_trans_buf, jbd_buf) buf_list;
LIST_HEAD(jbd_revoke_list, jbd_revoke_rec) revoke_list;
TAILQ_ENTRY(jbd_trans) trans_node;