diff options
author | Ken Sumrall <ksumrall@android.com> | 2012-06-05 11:59:36 -0700 |
---|---|---|
committer | Ken Sumrall <ksumrall@android.com> | 2012-06-06 20:59:22 -0700 |
commit | 46e96be157785a3582844efb27f4eef38943400b (patch) | |
tree | e50fdd266b28a16b461eb9b430857bc3cccbf274 | |
parent | 8c157a2c73b27b3f3ae566be78279460a35ccbc1 (diff) | |
download | android_external_e2fsprogs-46e96be157785a3582844efb27f4eef38943400b.tar.gz android_external_e2fsprogs-46e96be157785a3582844efb27f4eef38943400b.tar.bz2 android_external_e2fsprogs-46e96be157785a3582844efb27f4eef38943400b.zip |
Better fix for marking fs err in superblock if err set in journal superblock.
The previous fix of flushing out the superblock after setting the
EXT2_ERROR_FS flag was erroneous because running the journal could have
updated the superblock (but not the in-memory copy the code referenced).
So instead, check the journal error conditions after running the journal
and freeing and re-opening the filesystem. Also, make sure to flush
the error state of the superblock to disk before clearing the error state
of the journal.
Change-Id: Ia5cde1a367d86992c9bd3bca652a1289935d1380
-rw-r--r-- | e2fsck/journal.c | 104 |
1 files changed, 49 insertions, 55 deletions
diff --git a/e2fsck/journal.c b/e2fsck/journal.c index 30230575..948f3794 100644 --- a/e2fsck/journal.c +++ b/e2fsck/journal.c @@ -802,61 +802,13 @@ no_has_journal: return retval; } -static errcode_t recover_ext3_journal(e2fsck_t ctx) -{ - struct problem_context pctx; - journal_t *journal; - int retval; - - clear_problem_context(&pctx); - - journal_init_revoke_caches(); - retval = e2fsck_get_journal(ctx, &journal); - if (retval) - return retval; - - retval = e2fsck_journal_load(journal); - if (retval) - goto errout; - - retval = journal_init_revoke(journal, 1024); - if (retval) - goto errout; - - retval = -journal_recover(journal); - if (retval) - goto errout; - - if (journal->j_failed_commit) { - pctx.ino = journal->j_failed_commit; - fix_problem(ctx, PR_0_JNL_TXN_CORRUPT, &pctx); - ctx->fs->super->s_state |= EXT2_ERROR_FS; - ext2fs_mark_super_dirty(ctx->fs); - } - - - if (journal->j_superblock->s_errno) { - ctx->fs->super->s_state |= EXT2_ERROR_FS; - ext2fs_mark_super_dirty(ctx->fs); - journal->j_superblock->s_errno = 0; - mark_buffer_dirty(journal->j_sb_buffer); - } - - if (ctx->fs->flags & EXT2_FLAG_DIRTY) - ext2fs_flush(ctx->fs); /* Force out any modifications */ - -errout: - journal_destroy_revoke(journal); - journal_destroy_revoke_caches(); - e2fsck_journal_release(ctx, journal, 1, 0); - return retval; -} - int e2fsck_run_ext3_journal(e2fsck_t ctx) { + struct problem_context pctx; + journal_t *journal = 0; io_manager io_ptr = ctx->fs->io->manager; int blocksize = ctx->fs->blocksize; - errcode_t retval, recover_retval; + errcode_t retval; io_stats stats = 0; unsigned long long kbytes_written = 0; @@ -870,7 +822,27 @@ int e2fsck_run_ext3_journal(e2fsck_t ctx) if (ctx->fs->flags & EXT2_FLAG_DIRTY) ext2fs_flush(ctx->fs); /* Force out any modifications */ - recover_retval = recover_ext3_journal(ctx); + clear_problem_context(&pctx); + + retval = journal_init_revoke_caches(); + if (retval) + return retval; + + retval = e2fsck_get_journal(ctx, &journal); + if (retval) + goto errout1; + + retval = e2fsck_journal_load(journal); + if (retval) + goto errout2; + + retval = journal_init_revoke(journal, 1024); + if (retval) + goto errout2; + + retval = -journal_recover(journal); + if (retval) + goto errout3; /* * Reload the filesystem context to get up-to-date data from disk @@ -896,9 +868,31 @@ int e2fsck_run_ext3_journal(e2fsck_t ctx) ctx->fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; ctx->fs->super->s_kbytes_written += kbytes_written; - /* Set the superblock flags */ - e2fsck_clear_recover(ctx, recover_retval); - return recover_retval; + if (journal->j_failed_commit) { + pctx.ino = journal->j_failed_commit; + fix_problem(ctx, PR_0_JNL_TXN_CORRUPT, &pctx); + ctx->fs->super->s_state |= EXT2_ERROR_FS; + ext2fs_mark_super_dirty(ctx->fs); + ext2fs_flush(ctx->fs); + } + + if (journal->j_superblock->s_errno) { + journal->j_superblock->s_errno = 0; + mark_buffer_dirty(journal->j_sb_buffer); + ctx->fs->super->s_state |= EXT2_ERROR_FS; + ext2fs_mark_super_dirty(ctx->fs); + ext2fs_flush(ctx->fs); + } + +errout3: + journal_destroy_revoke(journal); +errout2: + e2fsck_journal_release(ctx, journal, 1, 0); +errout1: + journal_destroy_revoke_caches(); + e2fsck_clear_recover(ctx, retval); + return retval; + } /* |