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
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);
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
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. */
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);
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. */
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);
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*/
{
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);
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) {
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);
- }
-}
-
/**
* @}
*/