2000-07-07 12:13:21 +08:00
|
|
|
/*
|
|
|
|
* journal.c --- code for handling the "ext3" journal
|
2000-08-14 22:25:19 +08:00
|
|
|
*
|
|
|
|
* Copyright (C) 2000 Andreas Dilger
|
|
|
|
* Copyright (C) 2000 Theodore Ts'o
|
|
|
|
*
|
|
|
|
* Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
|
|
|
|
* Copyright (C) 1999 Red Hat Software
|
|
|
|
*
|
|
|
|
* This file may be redistributed under the terms of the
|
|
|
|
* GNU General Public License version 2 or at your discretion
|
|
|
|
* any later version.
|
2000-07-07 12:13:21 +08:00
|
|
|
*/
|
|
|
|
|
2000-08-14 22:25:19 +08:00
|
|
|
#ifdef HAVE_SYS_MOUNT_H
|
|
|
|
#include <sys/mount.h>
|
|
|
|
#define MNT_FL (MS_MGC_VAL | MS_RDONLY)
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_STAT_H
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#endif
|
2000-07-07 12:13:21 +08:00
|
|
|
|
2000-08-14 22:25:19 +08:00
|
|
|
#include "jfs.h"
|
|
|
|
#include "problem.h"
|
|
|
|
#include "uuid/uuid.h"
|
2000-07-07 12:13:21 +08:00
|
|
|
|
2000-08-14 22:25:19 +08:00
|
|
|
#ifdef JFS_DEBUG
|
|
|
|
static int bh_count = 0;
|
|
|
|
int jfs_enable_debug = 2;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int bmap(struct inode *inode, int block)
|
|
|
|
{
|
|
|
|
int retval;
|
|
|
|
blk_t phys;
|
|
|
|
|
|
|
|
retval = ext2fs_bmap(inode->i_ctx->fs, inode->i_ino, &inode->i_ext2,
|
|
|
|
NULL, 0, block, &phys);
|
|
|
|
|
|
|
|
if (retval)
|
|
|
|
com_err(inode->i_ctx->device_name, retval,
|
|
|
|
_("bmap journal inode %ld, block %d\n"),
|
|
|
|
inode->i_ino, block);
|
|
|
|
|
|
|
|
return phys;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct buffer_head *getblk(e2fsck_t ctx, blk_t blocknr, int blocksize)
|
|
|
|
{
|
|
|
|
struct buffer_head *bh;
|
|
|
|
|
|
|
|
bh = e2fsck_allocate_memory(ctx, sizeof(*bh), "block buffer");
|
|
|
|
if (!bh)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
jfs_debug(4, "getblk for block %lu (%d bytes)(total %d)\n",
|
|
|
|
blocknr, blocksize, ++bh_count);
|
|
|
|
|
|
|
|
bh->b_ctx = ctx;
|
|
|
|
bh->b_size = blocksize;
|
|
|
|
bh->b_blocknr = blocknr;
|
|
|
|
|
|
|
|
return bh;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ll_rw_block(int rw, int dummy, struct buffer_head *bh)
|
|
|
|
{
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
if (rw == READ && !bh->b_uptodate) {
|
|
|
|
jfs_debug(3, "reading block %lu/%p\n", bh->b_blocknr, bh);
|
|
|
|
retval = io_channel_read_blk(bh->b_ctx->fs->io, bh->b_blocknr,
|
|
|
|
1, bh->b_data);
|
|
|
|
if (retval) {
|
|
|
|
com_err(bh->b_ctx->device_name, retval,
|
|
|
|
"while reading block %ld\n", bh->b_blocknr);
|
|
|
|
bh->b_err = retval;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
bh->b_uptodate = 1;
|
|
|
|
} else if (rw == WRITE && bh->b_dirty) {
|
|
|
|
jfs_debug(3, "writing block %lu/%p\n", bh->b_blocknr, bh);
|
|
|
|
retval = io_channel_write_blk(bh->b_ctx->fs->io, bh->b_blocknr,
|
|
|
|
1, bh->b_data);
|
|
|
|
if (retval) {
|
|
|
|
com_err(bh->b_ctx->device_name, retval,
|
|
|
|
"while writing block %ld\n", bh->b_blocknr);
|
|
|
|
bh->b_err = retval;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
bh->b_dirty = 0;
|
|
|
|
bh->b_uptodate = 1;
|
|
|
|
} else
|
|
|
|
jfs_debug(3, "no-op %s for block %lu\n",
|
|
|
|
rw == READ ? "read" : "write", bh->b_blocknr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mark_buffer_dirty(struct buffer_head *bh, int dummy)
|
|
|
|
{
|
|
|
|
bh->b_dirty = dummy | 1; /* use dummy to avoid unused variable */
|
|
|
|
}
|
|
|
|
|
|
|
|
void brelse(struct buffer_head *bh)
|
|
|
|
{
|
|
|
|
if (bh->b_dirty)
|
|
|
|
ll_rw_block(WRITE, 1, bh);
|
|
|
|
jfs_debug(3, "freeing block %lu/%p (total %d)\n",
|
|
|
|
bh->b_blocknr, bh, --bh_count);
|
|
|
|
ext2fs_free_mem((void **) &bh);
|
|
|
|
}
|
|
|
|
|
|
|
|
int buffer_uptodate(struct buffer_head *bh)
|
|
|
|
{
|
|
|
|
return bh->b_uptodate;
|
|
|
|
}
|
|
|
|
|
|
|
|
void wait_on_buffer(struct buffer_head *bh)
|
|
|
|
{
|
|
|
|
if (!bh->b_uptodate)
|
|
|
|
ll_rw_block(READ, 1, bh);
|
|
|
|
}
|
|
|
|
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
|
2000-08-14 22:25:19 +08:00
|
|
|
static void e2fsck_clear_recover(e2fsck_t ctx, int error)
|
|
|
|
{
|
|
|
|
struct ext2fs_sb *s = (struct ext2fs_sb *)ctx->fs->super;
|
|
|
|
|
|
|
|
s->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
|
|
|
|
|
|
|
|
/* if we had an error doing journal recovery, we need a full fsck */
|
|
|
|
if (error)
|
|
|
|
s->s_state &= ~EXT2_VALID_FS;
|
|
|
|
ext2fs_mark_super_dirty(ctx->fs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int e2fsck_journal_init_inode(e2fsck_t ctx, struct ext2fs_sb *s,
|
|
|
|
ino_t journal_inum, journal_t **journal)
|
|
|
|
{
|
|
|
|
struct inode *inode;
|
|
|
|
const char *cmdname = ctx->program_name;
|
|
|
|
struct buffer_head *bh;
|
|
|
|
blk_t start;
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
jfs_debug(1, "Using journal inode %lu\n", journal_inum);
|
|
|
|
*journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
|
|
|
|
if (!*journal) {
|
|
|
|
return EXT2_ET_NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
inode = e2fsck_allocate_memory(ctx, sizeof(*inode), "journal inode");
|
|
|
|
if (!inode) {
|
|
|
|
retval = EXT2_ET_NO_MEMORY;
|
|
|
|
goto exit_journal;
|
|
|
|
}
|
|
|
|
|
|
|
|
inode->i_ctx = ctx;
|
|
|
|
inode->i_ino = journal_inum;
|
|
|
|
retval = ext2fs_read_inode(ctx->fs, journal_inum, &inode->i_ext2);
|
|
|
|
if (retval)
|
|
|
|
goto exit_inode;
|
|
|
|
|
|
|
|
(*journal)->j_dev = ctx;
|
|
|
|
(*journal)->j_inode = inode;
|
|
|
|
(*journal)->j_blocksize = ctx->fs->blocksize;
|
|
|
|
(*journal)->j_maxlen = inode->i_ext2.i_size / (*journal)->j_blocksize;
|
|
|
|
|
|
|
|
if (!inode->i_ext2.i_links_count ||
|
|
|
|
!LINUX_S_ISREG(inode->i_ext2.i_mode) ||
|
|
|
|
(*journal)->j_maxlen < JFS_MIN_JOURNAL_BLOCKS ||
|
|
|
|
(start = bmap(inode, 0)) == 0) {
|
|
|
|
retval = EXT2_ET_BAD_INODE_NUM;
|
|
|
|
goto exit_inode;
|
|
|
|
}
|
|
|
|
|
|
|
|
bh = getblk(ctx, start, (*journal)->j_blocksize);
|
|
|
|
if (!bh) {
|
|
|
|
retval = EXT2_ET_NO_MEMORY;
|
|
|
|
goto exit_inode;
|
|
|
|
}
|
|
|
|
(*journal)->j_sb_buffer = bh;
|
|
|
|
(*journal)->j_superblock = (journal_superblock_t *)bh->b_data;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
exit_inode:
|
|
|
|
ext2fs_free_mem((void **)&inode);
|
|
|
|
exit_journal:
|
|
|
|
ext2fs_free_mem((void **)journal);
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int e2fsck_get_journal(e2fsck_t ctx, journal_t **journal)
|
|
|
|
{
|
|
|
|
char uuid_str[40];
|
|
|
|
struct problem_context pctx;
|
|
|
|
struct ext2fs_sb *s = (struct ext2fs_sb *)ctx->fs->super;
|
|
|
|
int recover = s->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
|
|
|
|
|
|
|
|
clear_problem_context(&pctx);
|
|
|
|
|
|
|
|
if (s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
|
|
|
|
if (s->s_journal_dev) {
|
|
|
|
pctx.num = s->s_journal_dev;
|
|
|
|
/* this problem aborts on -y, -p, unsupported on -n */
|
|
|
|
if (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_DEV, &pctx))
|
|
|
|
return EXT2_ET_UNSUPP_FEATURE;
|
|
|
|
s->s_journal_dev = 0;
|
|
|
|
s->s_state &= ~EXT2_VALID_FS;
|
|
|
|
ext2fs_mark_super_dirty(ctx->fs);
|
|
|
|
}
|
|
|
|
if (!uuid_is_null(s->s_journal_uuid)) {
|
|
|
|
uuid_unparse(s->s_journal_uuid, uuid_str);
|
|
|
|
pctx.str = uuid_str;
|
|
|
|
/* this problem aborts on -y, -p, unsupported on -n */
|
|
|
|
if (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_UUID, &pctx))
|
|
|
|
return EXT2_ET_UNSUPP_FEATURE;
|
|
|
|
uuid_clear(s->s_journal_uuid);
|
|
|
|
s->s_state &= ~EXT2_VALID_FS;
|
|
|
|
ext2fs_mark_super_dirty(ctx->fs);
|
|
|
|
}
|
|
|
|
if (!s->s_journal_inum)
|
|
|
|
return EXT2_ET_BAD_INODE_NUM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s->s_journal_dev) {
|
|
|
|
pctx.num = s->s_journal_dev;
|
|
|
|
if (!fix_problem(ctx, PR_0_JOURNAL_BAD_DEV, &pctx))
|
|
|
|
return EXT2_ET_UNSUPP_FEATURE;
|
|
|
|
s->s_journal_dev = 0;
|
|
|
|
s->s_state &= ~EXT2_VALID_FS;
|
|
|
|
ext2fs_mark_super_dirty(ctx->fs);
|
|
|
|
}
|
|
|
|
if (!uuid_is_null(s->s_journal_uuid)) {
|
|
|
|
uuid_unparse(s->s_journal_uuid, uuid_str);
|
|
|
|
pctx.str = uuid_str;
|
|
|
|
if (!fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx))
|
|
|
|
return EXT2_ET_UNSUPP_FEATURE;
|
|
|
|
uuid_clear(s->s_journal_uuid);
|
|
|
|
s->s_state &= ~EXT2_VALID_FS;
|
|
|
|
ext2fs_mark_super_dirty(ctx->fs);
|
|
|
|
}
|
|
|
|
|
|
|
|
return e2fsck_journal_init_inode(ctx, s, s->s_journal_inum, journal);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
|
|
|
|
struct problem_context *pctx)
|
|
|
|
{
|
|
|
|
struct ext2fs_sb *s = (struct ext2fs_sb *)ctx->fs->super;
|
|
|
|
int recover = s->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
|
|
|
|
int has_journal = s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL;
|
|
|
|
|
|
|
|
if (has_journal || s->s_journal_inum) {
|
|
|
|
/* The journal inode is bogus, remove and force full fsck */
|
|
|
|
if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
|
|
|
|
struct ext2fs_sb *s =(struct ext2fs_sb *)ctx->fs->super;
|
|
|
|
|
|
|
|
if (has_journal && s->s_journal_inum)
|
|
|
|
printf("*** ext3 journal has been deleted - "
|
|
|
|
"filesystem is now ext2 only ***\n\n");
|
|
|
|
s->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
|
|
|
|
s->s_journal_inum = 0;
|
|
|
|
e2fsck_clear_recover(ctx, 1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return EXT2_ET_BAD_INODE_NUM;
|
|
|
|
} else if (recover) {
|
|
|
|
if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
|
|
|
|
e2fsck_clear_recover(ctx, 1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return EXT2_ET_UNSUPP_FEATURE;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int e2fsck_journal_fix_unsupported_super(e2fsck_t ctx,
|
|
|
|
struct problem_context *pctx)
|
|
|
|
{
|
|
|
|
struct ext2fs_sb *s = (struct ext2fs_sb *)ctx->fs->super;
|
|
|
|
|
|
|
|
/* Unsupported journal superblock - first choice is abort.
|
|
|
|
* Declining that gives the option to reset the superblock.
|
|
|
|
*
|
|
|
|
* Otherwise we get the chance to delete the journal, and
|
|
|
|
* failing that we abort because we can't handle this.
|
|
|
|
*/
|
|
|
|
if (s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
|
|
|
|
fix_problem(ctx, PR_0_JOURNAL_UNSUPP_SUPER, pctx))
|
|
|
|
return EXT2_ET_CORRUPT_SUPERBLOCK;
|
|
|
|
|
|
|
|
if (e2fsck_journal_fix_bad_inode(ctx, pctx))
|
|
|
|
return EXT2_ET_UNSUPP_FEATURE;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int e2fsck_journal_load(journal_t *journal)
|
|
|
|
{
|
|
|
|
e2fsck_t ctx = journal->j_dev;
|
|
|
|
journal_superblock_t *jsb;
|
|
|
|
struct buffer_head *jbh = journal->j_sb_buffer;
|
|
|
|
struct problem_context pctx;
|
|
|
|
|
|
|
|
clear_problem_context(&pctx);
|
|
|
|
|
|
|
|
ll_rw_block(READ, 1, jbh);
|
|
|
|
if (jbh->b_err) {
|
|
|
|
com_err(ctx->device_name, jbh->b_err,
|
|
|
|
_("reading journal superblock\n"));
|
|
|
|
return jbh->b_err;
|
|
|
|
}
|
|
|
|
|
|
|
|
jsb = journal->j_superblock;
|
|
|
|
/* If we don't even have JFS_MAGIC, we probably have a wrong inode */
|
|
|
|
if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
|
|
|
|
return e2fsck_journal_fix_bad_inode(ctx, &pctx);
|
|
|
|
|
|
|
|
if (jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK) ||
|
|
|
|
jsb->s_blocksize != htonl(journal->j_blocksize)) {
|
|
|
|
com_err(ctx->device_name, EXT2_ET_CORRUPT_SUPERBLOCK,
|
|
|
|
_("%s: no valid journal superblock found\n"));
|
|
|
|
return EXT2_ET_CORRUPT_SUPERBLOCK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK)) {
|
|
|
|
pctx.num = ntohl(jsb->s_header.h_blocktype);
|
|
|
|
return e2fsck_journal_fix_unsupported_super(ctx, &pctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
|
|
|
|
journal->j_maxlen = ntohl(jsb->s_maxlen);
|
|
|
|
else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
|
|
|
|
com_err(ctx->device_name, EXT2_ET_CORRUPT_SUPERBLOCK,
|
|
|
|
_("%s: journal too short\n"));
|
|
|
|
return EXT2_ET_CORRUPT_SUPERBLOCK;
|
|
|
|
}
|
|
|
|
|
|
|
|
journal->j_tail_sequence = ntohl(jsb->s_sequence);
|
ChangeLog, journal.c, message.c, problem.c, problem.h, super.c:
journal.c (e2fsck_journal_load): Fix **nasty** bug which caused
e2fsck_check_ext3_journal to smash the journal because
journal->j_transaction_sequence wasn't getting initialized.
journal.c: (recover_ext3_journal, e2fsck_run_ext3_journal): Move call
to e2fsck_clear_recover from recover_ext3_journal to after the
filesystem has been closed and reopened. Otherwise, the superblock in
the filesystem handle will probably be stale, and will overwrite the
newer version of the superblock written by the log recovery.
message.c (expand_inode_expression): Add support for %Iu and %Ig
problem.h (PR_0_CLEAR_ORPHAN_INODE): Add new problem code.
super.c (release_orphan_inodes, release_inode_block,
release_inode_blocks): Update the block group descriptor counts when
freeing the orphan inode. Use PR_0_CLEAR_ORPHAN_INODE to report when
we clear an orphan.
journal.c (e2fsck_run_ext3_journal): Fix a bug where we attempted to
reopen the filesystem using the device name instead of the filesystem
name.
2000-08-21 06:06:31 +08:00
|
|
|
journal->j_transaction_sequence = journal->j_tail_sequence;
|
2000-08-14 22:25:19 +08:00
|
|
|
journal->j_tail = ntohl(jsb->s_start);
|
|
|
|
journal->j_first = ntohl(jsb->s_first);
|
|
|
|
journal->j_last = ntohl(jsb->s_maxlen);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
|
|
|
|
blk_t size)
|
|
|
|
{
|
|
|
|
jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
|
|
|
|
jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK);
|
|
|
|
jsb->s_blocksize = htonl(ctx->fs->blocksize);
|
|
|
|
jsb->s_maxlen = htonl(size);
|
|
|
|
jsb->s_first = 1;
|
|
|
|
jsb->s_sequence = htonl(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int e2fsck_journal_fix_corrupt_super(e2fsck_t ctx, journal_t *journal,
|
|
|
|
struct problem_context *pctx)
|
|
|
|
{
|
|
|
|
struct ext2fs_sb *s = (struct ext2fs_sb *)ctx->fs->super;
|
|
|
|
int recover = s->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
|
|
|
|
|
|
|
|
pctx->num = journal->j_inode->i_ino;
|
|
|
|
|
|
|
|
if (s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
|
|
|
|
if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
|
|
|
|
journal_superblock_t *jsb = journal->j_superblock;
|
|
|
|
|
|
|
|
e2fsck_journal_reset_super(ctx, jsb, journal->j_maxlen);
|
|
|
|
|
|
|
|
journal->j_transaction_sequence = 1;
|
|
|
|
e2fsck_clear_recover(ctx, recover);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return EXT2_ET_CORRUPT_SUPERBLOCK;
|
|
|
|
} else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
|
|
|
|
return EXT2_ET_CORRUPT_SUPERBLOCK;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal, int reset)
|
|
|
|
{
|
|
|
|
journal_superblock_t *jsb;
|
|
|
|
|
|
|
|
if (!(ctx->options & E2F_OPT_READONLY)) {
|
|
|
|
jsb = journal->j_superblock;
|
|
|
|
jsb->s_sequence = htonl(journal->j_transaction_sequence);
|
|
|
|
if (reset)
|
|
|
|
jsb->s_start = 0; /* this marks the journal as empty */
|
|
|
|
mark_buffer_dirty(journal->j_sb_buffer, 1);
|
|
|
|
}
|
|
|
|
brelse(journal->j_sb_buffer);
|
|
|
|
|
|
|
|
if (journal->j_inode)
|
|
|
|
free(journal->j_inode);
|
|
|
|
ext2fs_free_mem((void **)&journal);
|
|
|
|
}
|
|
|
|
|
|
|
|
int e2fsck_check_ext3_journal(e2fsck_t ctx)
|
|
|
|
{
|
|
|
|
struct ext2fs_sb *s = (struct ext2fs_sb *)ctx->fs->super;
|
|
|
|
journal_t *journal;
|
|
|
|
int recover = s->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
|
|
|
|
struct problem_context pctx;
|
|
|
|
int reset = 0;
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
/* If we don't have any journal features, don't do anything more */
|
|
|
|
if (!(s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
|
|
|
|
!recover && s->s_journal_inum == 0 && s->s_journal_dev == 0 &&
|
|
|
|
uuid_is_null(s->s_journal_uuid))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
clear_problem_context(&pctx);
|
|
|
|
pctx.num = s->s_journal_inum;
|
|
|
|
|
|
|
|
retval = e2fsck_get_journal(ctx, &journal);
|
|
|
|
if (retval) {
|
|
|
|
if (retval == EXT2_ET_BAD_INODE_NUM)
|
|
|
|
return e2fsck_journal_fix_bad_inode(ctx, &pctx);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
retval = e2fsck_journal_load(journal);
|
|
|
|
if (retval) {
|
|
|
|
if (retval == EXT2_ET_CORRUPT_SUPERBLOCK)
|
|
|
|
return e2fsck_journal_fix_corrupt_super(ctx, journal,
|
|
|
|
&pctx);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We want to make the flags consistent here. We will not leave with
|
|
|
|
* needs_recovery set but has_journal clear. We can't get in a loop
|
|
|
|
* with -y, -n, or -p, only if a user isn't making up their mind.
|
|
|
|
*/
|
|
|
|
no_has_journal:
|
|
|
|
if (!(s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
|
|
|
|
recover = s->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
|
|
|
|
pctx.str = "inode";
|
|
|
|
if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
|
|
|
|
if (recover &&
|
|
|
|
!fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
|
|
|
|
goto no_has_journal;
|
|
|
|
s->s_journal_inum = 0;
|
|
|
|
e2fsck_clear_recover(ctx, recover);
|
|
|
|
} else if (!(ctx->options & E2F_OPT_READONLY)) {
|
|
|
|
s->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
|
|
|
|
ext2fs_mark_super_dirty(ctx->fs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
|
|
|
|
!(s->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
|
|
|
|
journal->j_superblock->s_start != 0) {
|
|
|
|
if (fix_problem(ctx, PR_0_JOURNAL_RESET_JOURNAL, &pctx))
|
|
|
|
reset = 1;
|
|
|
|
/* I refuse to enable recovery for journal */
|
|
|
|
}
|
|
|
|
|
|
|
|
e2fsck_journal_release(ctx, journal, reset);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
static int recover_ext3_journal(e2fsck_t ctx)
|
2000-08-14 22:25:19 +08:00
|
|
|
{
|
|
|
|
ext2_filsys fs = ctx->fs;
|
|
|
|
journal_t *journal;
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
retval = e2fsck_get_journal(ctx, &journal);
|
|
|
|
if (retval)
|
ChangeLog, journal.c, message.c, problem.c, problem.h, super.c:
journal.c (e2fsck_journal_load): Fix **nasty** bug which caused
e2fsck_check_ext3_journal to smash the journal because
journal->j_transaction_sequence wasn't getting initialized.
journal.c: (recover_ext3_journal, e2fsck_run_ext3_journal): Move call
to e2fsck_clear_recover from recover_ext3_journal to after the
filesystem has been closed and reopened. Otherwise, the superblock in
the filesystem handle will probably be stale, and will overwrite the
newer version of the superblock written by the log recovery.
message.c (expand_inode_expression): Add support for %Iu and %Ig
problem.h (PR_0_CLEAR_ORPHAN_INODE): Add new problem code.
super.c (release_orphan_inodes, release_inode_block,
release_inode_blocks): Update the block group descriptor counts when
freeing the orphan inode. Use PR_0_CLEAR_ORPHAN_INODE to report when
we clear an orphan.
journal.c (e2fsck_run_ext3_journal): Fix a bug where we attempted to
reopen the filesystem using the device name instead of the filesystem
name.
2000-08-21 06:06:31 +08:00
|
|
|
return retval;
|
|
|
|
|
2000-08-14 22:25:19 +08:00
|
|
|
retval = e2fsck_journal_load(journal);
|
|
|
|
if (retval)
|
ChangeLog, journal.c, message.c, problem.c, problem.h, super.c:
journal.c (e2fsck_journal_load): Fix **nasty** bug which caused
e2fsck_check_ext3_journal to smash the journal because
journal->j_transaction_sequence wasn't getting initialized.
journal.c: (recover_ext3_journal, e2fsck_run_ext3_journal): Move call
to e2fsck_clear_recover from recover_ext3_journal to after the
filesystem has been closed and reopened. Otherwise, the superblock in
the filesystem handle will probably be stale, and will overwrite the
newer version of the superblock written by the log recovery.
message.c (expand_inode_expression): Add support for %Iu and %Ig
problem.h (PR_0_CLEAR_ORPHAN_INODE): Add new problem code.
super.c (release_orphan_inodes, release_inode_block,
release_inode_blocks): Update the block group descriptor counts when
freeing the orphan inode. Use PR_0_CLEAR_ORPHAN_INODE to report when
we clear an orphan.
journal.c (e2fsck_run_ext3_journal): Fix a bug where we attempted to
reopen the filesystem using the device name instead of the filesystem
name.
2000-08-21 06:06:31 +08:00
|
|
|
return retval;
|
2000-08-14 22:25:19 +08:00
|
|
|
|
|
|
|
retval = -journal_recover(journal);
|
|
|
|
e2fsck_journal_release(ctx, journal, 1);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
#if 0
|
2000-08-14 22:25:19 +08:00
|
|
|
#define TEMPLATE "/tmp/ext3.XXXXXX"
|
2000-07-07 12:13:21 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This function attempts to mount and unmount an ext3 filesystem,
|
|
|
|
* which is a cheap way to force the kernel to run the journal and
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
* handle the recovery for us.
|
2000-07-07 12:13:21 +08:00
|
|
|
*/
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
static int recover_ext3_journal_via_mount(e2fsck_t ctx)
|
2000-07-07 12:13:21 +08:00
|
|
|
{
|
2000-08-14 22:25:19 +08:00
|
|
|
ext2_filsys fs = ctx->fs;
|
|
|
|
char *dirlist[] = {"/mnt","/lost+found","/tmp","/root","/boot",0};
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
errcode_t retval, retval2;
|
2000-08-14 22:25:19 +08:00
|
|
|
int count = 0;
|
|
|
|
char template[] = TEMPLATE;
|
|
|
|
struct stat buf;
|
2000-07-07 12:13:21 +08:00
|
|
|
char *tmpdir;
|
|
|
|
|
2000-08-14 22:25:19 +08:00
|
|
|
if (ctx->options & E2F_OPT_READONLY) {
|
|
|
|
printf("%s: won't do journal recovery while read-only\n",
|
|
|
|
ctx->device_name);
|
|
|
|
return EXT2_ET_FILE_RO;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf(_("%s: trying for ext3 kernel journal recovery\n"),
|
|
|
|
ctx->device_name);
|
2000-07-07 12:13:21 +08:00
|
|
|
/*
|
|
|
|
* First try to make a temporary directory. This may fail if
|
|
|
|
* the root partition is still mounted read-only.
|
|
|
|
*/
|
2000-08-14 22:25:19 +08:00
|
|
|
newtemp:
|
2000-07-07 12:13:21 +08:00
|
|
|
tmpdir = mktemp(template);
|
|
|
|
if (tmpdir) {
|
2000-08-14 22:25:19 +08:00
|
|
|
jfs_debug(2, "trying %s as ext3 temp mount point\n", tmpdir);
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
if (mkdir(template, 0700)) {
|
2000-08-14 22:25:19 +08:00
|
|
|
if (errno == EROFS) {
|
|
|
|
tmpdir = NULL;
|
|
|
|
template[0] = '\0';
|
|
|
|
} else if (errno == EEXIST && count++ < 10) {
|
|
|
|
strcpy(template, TEMPLATE);
|
|
|
|
goto newtemp;
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
}
|
|
|
|
return errno;
|
2000-07-07 12:13:21 +08:00
|
|
|
}
|
2000-08-14 22:25:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* OK, creating a temporary directory didn't work.
|
|
|
|
* Let's try a list of possible temporary mountpoints.
|
|
|
|
*/
|
|
|
|
if (!tmpdir) {
|
|
|
|
dev_t rootdev;
|
|
|
|
char **cpp, *dir;
|
|
|
|
|
|
|
|
if (stat("/", &buf))
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
return errno;
|
2000-08-14 22:25:19 +08:00
|
|
|
|
|
|
|
rootdev = buf.st_dev;
|
|
|
|
|
2000-07-07 12:13:21 +08:00
|
|
|
/*
|
2000-08-14 22:25:19 +08:00
|
|
|
* Check that dir is on the same device as root (no other
|
|
|
|
* filesystem is mounted there), and it's a directory.
|
2000-07-07 12:13:21 +08:00
|
|
|
*/
|
2000-08-14 22:25:19 +08:00
|
|
|
for (cpp = dirlist; (dir = *cpp); cpp++)
|
|
|
|
if (stat(dir, &buf) == 0 && buf.st_dev == rootdev &&
|
|
|
|
S_ISDIR(buf.st_mode)) {
|
|
|
|
tmpdir = dir;
|
2000-07-07 12:13:21 +08:00
|
|
|
break;
|
2000-08-14 22:25:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tmpdir) {
|
|
|
|
io_manager io_ptr = fs->io->manager;
|
|
|
|
int blocksize = fs->blocksize;
|
|
|
|
|
|
|
|
jfs_debug(2, "using %s for ext3 mount\n", tmpdir);
|
|
|
|
/* FIXME - need to handle loop devices here */
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
if (mount(ctx->device_name, tmpdir, "ext3", MNT_FL, NULL)) {
|
|
|
|
retval = errno;
|
2000-08-14 22:25:19 +08:00
|
|
|
com_err(ctx->program_name, errno,
|
|
|
|
"when mounting %s", ctx->device_name);
|
|
|
|
if (template[0])
|
|
|
|
rmdir(tmpdir);
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
return retval;
|
2000-07-07 12:13:21 +08:00
|
|
|
}
|
2000-08-14 22:25:19 +08:00
|
|
|
/*
|
|
|
|
* Now that it mounted cleanly, the filesystem will have been
|
|
|
|
* recovered, so we can now unmount it.
|
|
|
|
*/
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
if (umount(tmpdir))
|
2000-07-07 12:13:21 +08:00
|
|
|
return errno;
|
2000-08-14 22:25:19 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove the temporary directory, if it was created.
|
|
|
|
*/
|
|
|
|
if (template[0])
|
|
|
|
rmdir(tmpdir);
|
|
|
|
return 0;
|
2000-07-07 12:13:21 +08:00
|
|
|
}
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int e2fsck_run_ext3_journal(e2fsck_t ctx)
|
|
|
|
{
|
|
|
|
io_manager io_ptr = ctx->fs->io->manager;
|
|
|
|
int blocksize = ctx->fs->blocksize;
|
ChangeLog, journal.c, message.c, problem.c, problem.h, super.c:
journal.c (e2fsck_journal_load): Fix **nasty** bug which caused
e2fsck_check_ext3_journal to smash the journal because
journal->j_transaction_sequence wasn't getting initialized.
journal.c: (recover_ext3_journal, e2fsck_run_ext3_journal): Move call
to e2fsck_clear_recover from recover_ext3_journal to after the
filesystem has been closed and reopened. Otherwise, the superblock in
the filesystem handle will probably be stale, and will overwrite the
newer version of the superblock written by the log recovery.
message.c (expand_inode_expression): Add support for %Iu and %Ig
problem.h (PR_0_CLEAR_ORPHAN_INODE): Add new problem code.
super.c (release_orphan_inodes, release_inode_block,
release_inode_blocks): Update the block group descriptor counts when
freeing the orphan inode. Use PR_0_CLEAR_ORPHAN_INODE to report when
we clear an orphan.
journal.c (e2fsck_run_ext3_journal): Fix a bug where we attempted to
reopen the filesystem using the device name instead of the filesystem
name.
2000-08-21 06:06:31 +08:00
|
|
|
errcode_t retval, recover_retval;
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
|
ChangeLog, journal.c, message.c, problem.c, problem.h, super.c:
journal.c (e2fsck_journal_load): Fix **nasty** bug which caused
e2fsck_check_ext3_journal to smash the journal because
journal->j_transaction_sequence wasn't getting initialized.
journal.c: (recover_ext3_journal, e2fsck_run_ext3_journal): Move call
to e2fsck_clear_recover from recover_ext3_journal to after the
filesystem has been closed and reopened. Otherwise, the superblock in
the filesystem handle will probably be stale, and will overwrite the
newer version of the superblock written by the log recovery.
message.c (expand_inode_expression): Add support for %Iu and %Ig
problem.h (PR_0_CLEAR_ORPHAN_INODE): Add new problem code.
super.c (release_orphan_inodes, release_inode_block,
release_inode_blocks): Update the block group descriptor counts when
freeing the orphan inode. Use PR_0_CLEAR_ORPHAN_INODE to report when
we clear an orphan.
journal.c (e2fsck_run_ext3_journal): Fix a bug where we attempted to
reopen the filesystem using the device name instead of the filesystem
name.
2000-08-21 06:06:31 +08:00
|
|
|
if (ctx->options & E2F_OPT_READONLY) {
|
|
|
|
printf("%s: won't do journal recovery while read-only\n",
|
|
|
|
ctx->device_name);
|
|
|
|
return EXT2_ET_FILE_RO;
|
|
|
|
}
|
|
|
|
|
|
|
|
recover_retval = recover_ext3_journal(ctx);
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Reload the filesystem context to get up-to-date data from disk
|
|
|
|
* because journal recovery will change the filesystem under us.
|
|
|
|
*/
|
|
|
|
ext2fs_close(ctx->fs);
|
ChangeLog, journal.c, message.c, problem.c, problem.h, super.c:
journal.c (e2fsck_journal_load): Fix **nasty** bug which caused
e2fsck_check_ext3_journal to smash the journal because
journal->j_transaction_sequence wasn't getting initialized.
journal.c: (recover_ext3_journal, e2fsck_run_ext3_journal): Move call
to e2fsck_clear_recover from recover_ext3_journal to after the
filesystem has been closed and reopened. Otherwise, the superblock in
the filesystem handle will probably be stale, and will overwrite the
newer version of the superblock written by the log recovery.
message.c (expand_inode_expression): Add support for %Iu and %Ig
problem.h (PR_0_CLEAR_ORPHAN_INODE): Add new problem code.
super.c (release_orphan_inodes, release_inode_block,
release_inode_blocks): Update the block group descriptor counts when
freeing the orphan inode. Use PR_0_CLEAR_ORPHAN_INODE to report when
we clear an orphan.
journal.c (e2fsck_run_ext3_journal): Fix a bug where we attempted to
reopen the filesystem using the device name instead of the filesystem
name.
2000-08-21 06:06:31 +08:00
|
|
|
retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
|
Many files:
Makefile.in: Update the make dependencies
problem.c, problem.h: Add the problem codes:
PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
PR_0_ORPHAN_ILLEGAL_HEAD_INODE, PR_0_ORPHAN_ILLEGAL_INODE,
PR_0_ORPHAN_INODE_INUSE
super.c (release_inode_blocks, release_orphan_inodes,
check_super_block): Add support for clearing orphaned inodes from the
unmounted filesystem.
journal.c (e2fsck_recover_ext3_journal): Remove the last orphan check;
this is now handled in check_super_block --- non-journaled filesystems
can use the orphan list in the future. Also, move the the re-opening
of the filesystem to e2fsck_run_ext3_journal().
debugfs.c:
debugfs.c (finish_range): Make sure the pager FILE pointer to use.
configure, configure.in, ChangeLog:
configure.in (JFS_DEBUG): Add support for --enable-jfs-debug
2000-08-18 23:08:37 +08:00
|
|
|
ctx->superblock, blocksize, io_ptr,
|
|
|
|
&ctx->fs);
|
|
|
|
|
|
|
|
if (retval) {
|
|
|
|
com_err(ctx->program_name, retval,
|
|
|
|
_("while trying to re-open %s"),
|
|
|
|
ctx->device_name);
|
|
|
|
exit(FSCK_ERROR);
|
|
|
|
}
|
|
|
|
ctx->fs->priv_data = ctx;
|
2000-07-07 12:13:21 +08:00
|
|
|
|
ChangeLog, journal.c, message.c, problem.c, problem.h, super.c:
journal.c (e2fsck_journal_load): Fix **nasty** bug which caused
e2fsck_check_ext3_journal to smash the journal because
journal->j_transaction_sequence wasn't getting initialized.
journal.c: (recover_ext3_journal, e2fsck_run_ext3_journal): Move call
to e2fsck_clear_recover from recover_ext3_journal to after the
filesystem has been closed and reopened. Otherwise, the superblock in
the filesystem handle will probably be stale, and will overwrite the
newer version of the superblock written by the log recovery.
message.c (expand_inode_expression): Add support for %Iu and %Ig
problem.h (PR_0_CLEAR_ORPHAN_INODE): Add new problem code.
super.c (release_orphan_inodes, release_inode_block,
release_inode_blocks): Update the block group descriptor counts when
freeing the orphan inode. Use PR_0_CLEAR_ORPHAN_INODE to report when
we clear an orphan.
journal.c (e2fsck_run_ext3_journal): Fix a bug where we attempted to
reopen the filesystem using the device name instead of the filesystem
name.
2000-08-21 06:06:31 +08:00
|
|
|
/* Set the superblock flags */
|
|
|
|
e2fsck_clear_recover(ctx, recover_retval);
|
|
|
|
return recover_retval;
|
2000-07-07 12:13:21 +08:00
|
|
|
}
|