ext4_journal: code logic optimization. See below.
[lwext4.git] / lwext4 / ext4_journal.c
index 4f5ca5970c9273f22cb8a26f48b904d3804423f7..86366a1bf044a5792dea5395908bc37a6c7f104c 100644 (file)
@@ -1266,17 +1266,43 @@ int jbd_journal_start(struct jbd_fs *jbd_fs,
        return jbd_write_sb(jbd_fs);
 }
 
+static void jbd_trans_end_write(struct ext4_bcache *bc __unused,
+                         struct ext4_buf *buf __unused,
+                         int res,
+                         void *arg);
+
 static void jbd_journal_flush_trans(struct jbd_trans *trans)
 {
        struct jbd_buf *jbd_buf, *tmp;
        struct jbd_journal *journal = trans->journal;
        struct ext4_fs *fs = journal->jbd_fs->inode_ref.fs;
+       void *tmp_data = malloc(journal->block_size);
+       ext4_assert(tmp_data);
+
        TAILQ_FOREACH_SAFE(jbd_buf, &trans->buf_queue, buf_node,
                        tmp) {
                struct ext4_buf *buf = jbd_buf->block_rec->buf;
-               if (buf)
-                       ext4_block_flush_buf(fs->bdev, buf);
+               /* The buffer in memory is still dirty. */
+               if (buf) {
+                       if (jbd_buf->block_rec->trans != trans) {
+                               int r;
+                               struct ext4_block jbd_block = EXT4_BLOCK_ZERO();
+                               ext4_assert(ext4_block_get(fs->bdev,
+                                                       &jbd_block,
+                                                       jbd_buf->jbd_lba) == EOK);
+                               memcpy(tmp_data, jbd_block.data,
+                                               journal->block_size);
+                               ext4_block_set(fs->bdev, &jbd_block);
+                               r = ext4_blocks_set_direct(fs->bdev, tmp_data,
+                                               buf->lba, 1);
+                               jbd_trans_end_write(fs->bdev->bc, buf, r, jbd_buf);
+                       } else
+                               ext4_block_flush_buf(fs->bdev, buf);
+
+               }
        }
+
+       free(tmp_data);
 }
 
 static void
@@ -1344,9 +1370,6 @@ int jbd_journal_stop(struct jbd_journal *journal)
        struct jbd_fs *jbd_fs = journal->jbd_fs;
        uint32_t features_incompatible;
 
-       /* Commit all the transactions to the journal.*/
-       jbd_journal_commit_all(journal);
-
        /* Make sure that journalled content have reached
         * the disk.*/
        jbd_journal_purge_cp_trans(journal, true);
@@ -1416,11 +1439,6 @@ jbd_journal_new_trans(struct jbd_journal *journal)
        return trans;
 }
 
-static void jbd_trans_end_write(struct ext4_bcache *bc __unused,
-                         struct ext4_buf *buf __unused,
-                         int res,
-                         void *arg);
-
 /**@brief  gain access to it before making any modications.
  * @param  journal current journal session
  * @param  trans transaction
@@ -1775,10 +1793,12 @@ static int jbd_journal_prepare(struct jbd_journal *journal,
                        jbd_buf,
                        dirty_buf_node);
 
+               jbd_buf->block.buf->end_write = NULL;
+               jbd_buf->block.buf->end_write_arg = NULL;
                jbd_trans_finish_callback(journal,
                                trans,
                                jbd_buf->block_rec,
-                               false);
+                               true);
 
                /* The buffer has not been modified, just release
                 * that jbd_buf. */
@@ -1786,8 +1806,6 @@ static int jbd_journal_prepare(struct jbd_journal *journal,
                                jbd_buf->block_rec, trans);
                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);
@@ -1802,10 +1820,12 @@ static int jbd_journal_prepare(struct jbd_journal *journal,
                                        jbd_buf,
                                        dirty_buf_node);
 
+                       jbd_buf->block.buf->end_write = NULL;
+                       jbd_buf->block.buf->end_write_arg = NULL;
                        jbd_trans_finish_callback(journal,
                                        trans,
                                        jbd_buf->block_rec,
-                                       false);
+                                       true);
 
                        /* The buffer has not been modified, just release
                         * that jbd_buf. */
@@ -1813,8 +1833,6 @@ static int jbd_journal_prepare(struct jbd_journal *journal,
                                        jbd_buf->block_rec, trans);
                        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);
@@ -1999,18 +2017,6 @@ again:
        return rc;
 }
 
-/**@brief  Submit the transaction to transaction queue.
- * @param  journal current journal session
- * @param  trans transaction*/
-void
-jbd_journal_submit_trans(struct jbd_journal *journal,
-                        struct jbd_trans *trans)
-{
-       TAILQ_INSERT_TAIL(&journal->trans_queue,
-                         trans,
-                         trans_node);
-}
-
 /**@brief  Put references of block descriptors in a transaction.
  * @param  journal current journal session
  * @param  trans transaction*/
@@ -2034,6 +2040,7 @@ static void jbd_trans_end_write(struct ext4_bcache *bc __unused,
 {
        struct jbd_buf *jbd_buf = arg;
        struct jbd_trans *trans = jbd_buf->trans;
+       struct jbd_block_rec *block_rec = jbd_buf->block_rec;
        struct jbd_journal *journal = trans->journal;
        bool first_in_queue =
                trans == TAILQ_FIRST(&journal->cp_queue);
@@ -2041,19 +2048,22 @@ static void jbd_trans_end_write(struct ext4_bcache *bc __unused,
                trans->error = res;
 
        TAILQ_REMOVE(&trans->buf_queue, jbd_buf, buf_node);
-       TAILQ_REMOVE(&jbd_buf->block_rec->dirty_buf_queue,
+       TAILQ_REMOVE(&block_rec->dirty_buf_queue,
                        jbd_buf,
                        dirty_buf_node);
+
        jbd_trans_finish_callback(journal,
                        trans,
                        jbd_buf->block_rec,
                        false);
-       jbd_buf->block_rec->buf = NULL;
-       free(jbd_buf);
+       if (block_rec->trans == trans) {
+               block_rec->buf = NULL;
+               /* Clear the end_write and end_write_arg fields. */
+               buf->end_write = NULL;
+               buf->end_write_arg = NULL;
+       }
 
-       /* Clear the end_write and end_write_arg fields. */
-       buf->end_write = NULL;
-       buf->end_write_arg = NULL;
+       free(jbd_buf);
 
        trans->written_cnt++;
        if (trans->written_cnt == trans->data_cnt) {
@@ -2143,29 +2153,6 @@ Finish:
        return rc;
 }
 
-/**@brief  Commit one transaction on transaction queue
- *         to the journal.
- * @param  journal current journal session.*/
-void jbd_journal_commit_one(struct jbd_journal *journal)
-{
-       struct jbd_trans *trans;
-
-       if ((trans = TAILQ_FIRST(&journal->trans_queue))) {
-               TAILQ_REMOVE(&journal->trans_queue, trans, trans_node);
-               jbd_journal_commit_trans(journal, trans);
-       }
-}
-
-/**@brief  Commit all the transactions on transaction queue
- *         to the journal.
- * @param  journal current journal session.*/
-void jbd_journal_commit_all(struct jbd_journal *journal)
-{
-       while (!TAILQ_EMPTY(&journal->trans_queue)) {
-               jbd_journal_commit_one(journal);
-       }
-}
-
 /**
  * @}
  */