X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fext4_journal.c;h=fbdf23308aa5052134be703949b1aa57ead8b781;hb=dd3f008d8931f870814d139c4b61852cc4d449cb;hp=b4fe24a0e216f8d72a466af099f38560d82bde9d;hpb=384424b2e0043f0aaf6fdeece1f6b7f54e897c5a;p=lwext4.git diff --git a/src/ext4_journal.c b/src/ext4_journal.c index b4fe24a..fbdf233 100644 --- a/src/ext4_journal.c +++ b/src/ext4_journal.c @@ -35,18 +35,18 @@ * @brief Journal handle functions */ -#include "ext4_config.h" -#include "ext4_types.h" -#include "ext4_misc.h" -#include "ext4_errno.h" -#include "ext4_debug.h" - -#include "ext4_fs.h" -#include "ext4_super.h" -#include "ext4_journal.h" -#include "ext4_blockdev.h" -#include "ext4_crc32.h" -#include "ext4_journal.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include #include #include @@ -458,25 +458,26 @@ int jbd_get_fs(struct ext4_fs *fs, rc = ext4_fs_get_inode_ref(fs, journal_ino, &jbd_fs->inode_ref); - if (rc != EOK) { - memset(jbd_fs, 0, sizeof(struct jbd_fs)); + if (rc != EOK) return rc; - } + rc = jbd_sb_read(jbd_fs, &jbd_fs->sb); - if (rc != EOK) { - memset(jbd_fs, 0, sizeof(struct jbd_fs)); - ext4_fs_put_inode_ref(&jbd_fs->inode_ref); - return rc; - } + if (rc != EOK) + goto Error; + if (!jbd_verify_sb(&jbd_fs->sb)) { - memset(jbd_fs, 0, sizeof(struct jbd_fs)); - ext4_fs_put_inode_ref(&jbd_fs->inode_ref); rc = EIO; + goto Error; } if (rc == EOK) jbd_fs->bdev = fs->bdev; + return rc; +Error: + ext4_fs_put_inode_ref(&jbd_fs->inode_ref); + memset(jbd_fs, 0, sizeof(struct jbd_fs)); + return rc; } @@ -1157,11 +1158,13 @@ static int jbd_iterate_log(struct jbd_fs *jbd_fs, ext4_dbg(DEBUG_JBD, "Commit block: %" PRIu32", " "trans_id: %" PRIu32"\n", this_block, this_trans_id); - /* This is the end of a transaction, + /* + * This is the end of a transaction, * we may now proceed to the next transaction. */ this_trans_id++; - info->trans_cnt++; + if (action == ACTION_SCAN) + info->trans_cnt++; break; case JBD_REVOKE_BLOCK: if (!jbd_verify_meta_csum(jbd_fs, header)) { @@ -1236,6 +1239,7 @@ int jbd_recover(struct jbd_fs *jbd_fs) ext4_get32(&jbd_fs->inode_ref.fs->sb, features_incompatible); jbd_set32(&jbd_fs->sb, start, 0); + jbd_set32(&jbd_fs->sb, sequence, info.last_trans_id); features_incompatible &= ~EXT4_FINCOM_RECOVER; ext4_set32(&jbd_fs->inode_ref.fs->sb, features_incompatible, @@ -1267,7 +1271,6 @@ int jbd_journal_start(struct jbd_fs *jbd_fs, uint32_t features_incompatible = ext4_get32(&jbd_fs->inode_ref.fs->sb, features_incompatible); - struct ext4_block block = EXT4_BLOCK_ZERO(); features_incompatible |= EXT4_FINCOM_RECOVER; ext4_set32(&jbd_fs->inode_ref.fs->sb, features_incompatible, @@ -1280,26 +1283,16 @@ int jbd_journal_start(struct jbd_fs *jbd_fs, journal->first = jbd_get32(&jbd_fs->sb, first); journal->start = journal->first; journal->last = journal->first; - journal->trans_id = 1; - journal->alloc_trans_id = 1; + /* + * To invalidate any stale records we need to start from + * the checkpoint transaction ID of the previous journalling session + * plus 1. + */ + journal->trans_id = jbd_get32(&jbd_fs->sb, sequence) + 1; + journal->alloc_trans_id = journal->trans_id; journal->block_size = jbd_get32(&jbd_fs->sb, blocksize); - r = jbd_block_get_noread(jbd_fs, - &block, - journal->start); - if (r != EOK) { - memset(journal, 0, sizeof(struct jbd_journal)); - return r; - } - memset(block.data, 0, journal->block_size); - ext4_bcache_set_dirty(block.buf); - r = jbd_block_set(jbd_fs, &block); - if (r != EOK) { - memset(journal, 0, sizeof(struct jbd_journal)); - return r; - } - TAILQ_INIT(&journal->cp_queue); RB_INIT(&journal->block_rec_root); journal->jbd_fs = jbd_fs; @@ -1467,10 +1460,12 @@ static uint32_t jbd_journal_alloc_block(struct jbd_journal *journal, trans->alloc_blocks++; wrap(&journal->jbd_fs->sb, journal->last); - /* If there is no space left, flush all journalled - * blocks to disk first.*/ - if (journal->last == journal->start) - jbd_journal_purge_cp_trans(journal, true, false); + /* If there is no space left, flush just one journalled + * transaction.*/ + if (journal->last == journal->start) { + jbd_journal_purge_cp_trans(journal, true, true); + ext4_assert(journal->last != journal->start); + } return start_block; } @@ -1773,29 +1768,12 @@ static int jbd_trans_write_commit_block(struct jbd_trans *trans) int rc; struct ext4_block block; struct jbd_commit_header *header; - uint32_t commit_iblock, orig_commit_iblock; + uint32_t commit_iblock; struct jbd_journal *journal = trans->journal; commit_iblock = jbd_journal_alloc_block(journal, trans); - orig_commit_iblock = commit_iblock; - commit_iblock++; - wrap(&journal->jbd_fs->sb, commit_iblock); - /* To prevent accidental reference to stale journalling metadata. */ - if (orig_commit_iblock < commit_iblock) { - rc = jbd_block_get_noread(journal->jbd_fs, &block, commit_iblock); - if (rc != EOK) - return rc; - - memset(block.data, 0, journal->block_size); - ext4_bcache_set_dirty(block.buf); - ext4_bcache_set_flag(block.buf, BC_TMP); - rc = jbd_block_set(journal->jbd_fs, &block); - if (rc != EOK) - return rc; - } - - rc = jbd_block_get_noread(journal->jbd_fs, &block, orig_commit_iblock); + rc = jbd_block_get_noread(journal->jbd_fs, &block, commit_iblock); if (rc != EOK) return rc; @@ -1980,6 +1958,9 @@ again: data = data_block.data; memcpy(data, jbd_buf->block.data, journal->block_size); + if (is_escape) + ((struct jbd_bhdr *)data)->magic = 0; + ext4_bcache_set_dirty(data_block.buf); ext4_bcache_set_flag(data_block.buf, BC_TMP); rc = jbd_block_set(journal->jbd_fs, &data_block);