+2003-08-21 Theodore Ts'o <tytso@mit.edu>
+
+ * debugfs.8.in: Fully document the logdump command in the debugfs
+ man page.
+
+ * logdump.c (do_logdump): Add -s option which will use the journal
+ inode information in the superblock.
+
2003-07-25 Theodore Ts'o <tytso@mit.edu>
* Release of E2fsprogs 1.34
.IR filespec .
Note this does not adjust the inode reference counts.
.TP
-.I logdump [-ac] [-b<block>] [-i<inode>] [-f<journal_file>] [output_file]
-Dump the contents of the ext3 journal.
+.I logdump [-acs] [-b<block>] [-i<filespec>] [-f<journal_file>] [output_file]
+Dump the contents of the ext3 journal. By default, the journal inode as
+specified in the superblock. However, this can be overridden with the
+.I \-i
+option, which uses an inode specifier to specify the journal to be
+used. A file containing journal data can be specified using the
+.I \-f
+option. Finally, the
+.I \-s
+option utilizes the backup information in the superblock to locate the
+journal.
+.IP
+The
+.I \-a
+option causes the
+.I logdump
+program to print the contents of all of the descriptor blocks.
+The
+.I \-b
+option causes
+.I logdump
+to print all journal records that are refer to the specified block.
+The
+.I \-c
+option will print out the contents of all of the data blocks selected by
+the
+.I \-a
+and
+.I \-b
+options.
.TP
.I ls [-l] [-d] filespec
Print a listing of the files in the directory
char *inode_spec = NULL;
char *journal_fn = NULL;
int journal_fd = 0;
+ int use_sb = 0;
ext2_ino_t journal_inum;
struct ext2_inode journal_inode;
ext2_file_t journal_file;
inode_to_dump = -1;
reset_getopt();
- while ((c = getopt (argc, argv, "ab:ci:f:")) != EOF) {
+ while ((c = getopt (argc, argv, "ab:ci:f:s")) != EOF) {
switch (c) {
case 'a':
dump_all++;
inode_spec = optarg;
dump_descriptors = 0;
break;
+ case 's':
+ use_sb++;
+ break;
default:
com_err(argv[0], 0, logdump_usage);
return;
journal_source.where = JOURNAL_IS_EXTERNAL;
journal_source.fd = journal_fd;
} else if ((journal_inum = es->s_journal_inum)) {
- if (debugfs_read_inode(journal_inum, &journal_inode, argv[0]))
- return;
-
- retval = ext2fs_file_open(current_fs, journal_inum,
- 0, &journal_file);
+ if (use_sb) {
+ if (es->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS) {
+ com_err(argv[0], 0,
+ "no journal backup in super block\n");
+ return;
+ }
+ memset(&journal_inode, 0, sizeof(struct ext2_inode));
+ memcpy(&journal_inode.i_block[0], es->s_jnl_blocks,
+ EXT2_N_BLOCKS*4);
+ journal_inode.i_size = es->s_jnl_blocks[16];
+ journal_inode.i_links_count = 1;
+ journal_inode.i_mode = LINUX_S_IFREG | 0600;
+ } else {
+ if (debugfs_read_inode(journal_inum, &journal_inode,
+ argv[0]))
+ return;
+ }
+
+ retval = ext2fs_file_open2(current_fs, journal_inum,
+ &journal_inode, 0, &journal_file);
if (retval) {
com_err(argv[0], retval, "while opening ext2 file");
return;
+2003-08-20 Theodore Ts'o <tytso@mit.edu>
+
+ * journal.c (e2fsck_move_ext3_journal): If the superblock's backup
+ journal information is not set, copy the journal inode
+ information to the superblock.
+ (e2fsck_get_journal): If the journal inode is corrupted,
+ synthesize one from the backup information in the
+ superblock.
+
+ * problem.c, problem.h (PR_0_BACKUP_JNL): Add new problem code
+ which is used when we make a backup of the journal inode.
+
2003-08-19 Theodore Ts'o <tytso@mit.edu>
* e2fsck.h, unix.c (PRS, e2fsck_clear_progbar,
errcode_t retval = 0;
io_manager io_ptr = 0;
unsigned long start = 0;
+ blk_t blk;
int ext_journal = 0;
+ int tried_backup_jnl = 0;
+ int i;
clear_problem_context(&pctx);
if ((retval = ext2fs_read_inode(ctx->fs,
sb->s_journal_inum,
- &j_inode->i_ext2)))
- goto errout;
+ &j_inode->i_ext2))) {
+ try_backup_journal:
+ if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
+ tried_backup_jnl)
+ goto errout;
+ memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
+ memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
+ EXT2_N_BLOCKS*4);
+ j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
+ j_inode->i_ext2.i_links_count = 1;
+ j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
+ tried_backup_jnl++;
+ }
if (!j_inode->i_ext2.i_links_count ||
!LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
retval = EXT2_ET_NO_JOURNAL;
- goto errout;
+ goto try_backup_journal;
}
if (j_inode->i_ext2.i_size / journal->j_blocksize <
JFS_MIN_JOURNAL_BLOCKS) {
retval = EXT2_ET_JOURNAL_TOO_SMALL;
- goto errout;
+ goto try_backup_journal;
+ }
+ for (i=0; i < EXT2_N_BLOCKS; i++) {
+ blk = j_inode->i_ext2.i_block[i];
+ if (!blk) {
+ if (i < EXT2_NDIR_BLOCKS) {
+ retval = EXT2_ET_JOURNAL_TOO_SMALL;
+ goto try_backup_journal;
+ }
+ continue;
+ }
+ if (blk < sb->s_first_data_block ||
+ blk >= sb->s_blocks_count) {
+ retval = EXT2_ET_BAD_BLOCK_NUM;
+ goto try_backup_journal;
+ }
}
-
journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
#ifdef USE_INODE_IO
- retval = ext2fs_inode_io_intern(ctx->fs, sb->s_journal_inum,
- &journal_name);
+ retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
+ &j_inode->i_ext2,
+ &journal_name);
if (retval)
goto errout;
case JFS_SUPERBLOCK_V2:
journal->j_format_version = 2;
if (ntohl(jsb->s_nr_users) > 1 &&
- (ctx->fs->io == ctx->journal_io))
+ uuid_is_null(ctx->fs->super->s_journal_uuid))
clear_v2_journal_fields(journal);
if (ntohl(jsb->s_nr_users) > 1) {
fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
const char * const * cpp;
int group, mount_flags;
+ clear_problem_context(&pctx);
+
/*
* If the filesystem is opened read-only, or there is no
- * journal, or the journal is already in the hidden inode,
- * then do nothing.
+ * journal, then do nothing.
*/
if ((ctx->options & E2F_OPT_READONLY) ||
(sb->s_journal_inum == 0) ||
- (sb->s_journal_inum == EXT2_JOURNAL_INO) ||
!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
return;
/*
+ * Read in the journal inode
+ */
+ if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
+ return;
+
+ /*
+ * If it's necessary to backup the journal inode, do so.
+ */
+ if ((sb->s_jnl_backup_type == 0) ||
+ ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
+ memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
+ if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
+ memcpy(sb->s_jnl_blocks, inode.i_block,
+ EXT2_N_BLOCKS*4);
+ sb->s_jnl_blocks[16] = inode.i_size;
+ sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
+ ext2fs_mark_super_dirty(fs);
+ }
+ }
+
+ /*
+ * If the journal is already the hidden inode, then do nothing
+ */
+ if (sb->s_journal_inum == EXT2_JOURNAL_INO)
+ return;
+
+ /*
+ * The journal inode had better have only one link and not be readable.
+ */
+ if (inode.i_links_count != 1)
+ return;
+
+ /*
* If the filesystem is mounted, or we can't tell whether
* or not it's mounted, do nothing.
*/
if (*cpp == 0)
return;
- /*
- * The inode had better have only one link and not be readable.
- */
- if (ext2fs_read_inode(fs, ino, &inode) != 0)
- return;
- if (inode.i_links_count != 1)
- return;
-
/* We need the inode bitmap to be loaded */
retval = ext2fs_read_bitmaps(fs);
if (retval)
return;
- clear_problem_context(&pctx);
pctx.str = *cpp;
if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
return;
"Clearing fields beyond the V1 @j @S...\n\n"),
PROMPT_NONE, 0 },
+ /* Backup journal inode blocks */
+ { PR_0_BACKUP_JNL,
+ N_("Backing up @j @i @b information.\n\n"),
+ PROMPT_NONE, 0 },
+
/* Pass 1 errors */
/* Pass 1: Checking inodes, blocks, and sizes */
/* Run journal anyway by default */
#define PR_0_JOURNAL_RUN_DEFAULT 0x00002C
+/* Backup journal inode blocks */
+#define PR_0_BACKUP_JNL 0x00002D
+
/*
* Pass 1 errors
*/
+2003-08-20 Theodore Ts'o <tytso@mit.edu>
+
+ * ls.c (list_super2): Display the journal backup type.
+
2003-07-25 Theodore Ts'o <tytso@mit.edu>
* Release of E2fsprogs 1.34
if (!e2p_is_null_uuid(sb->s_hash_seed))
fprintf(f, "Directory Hash Seed: %s\n",
e2p_uuid2str(sb->s_hash_seed));
+ if (sb->s_jnl_backup_type) {
+ fprintf(f, "Journal backup: ");
+ switch (sb->s_jnl_backup_type) {
+ case 1:
+ fprintf(f, "inode blocks\n");
+ break;
+ default:
+ fprintf(f, "type %u\n", sb->s_jnl_backup_type);
+ }
+ }
}
void list_super (struct ext2_super_block * s)
+2003-08-20 Theodore Ts'o <tytso@mit.edu>
+
+ * inode_io.c (ext2fs_inode_io_intern2), ext2fs.h: Add new function
+ allows the caller to pass in the inode data structure.
+
+ * fileio.c (ext2fs_file_open2), ext2fs.h: Add new function which
+ allows the caller to pass in the inode to be used in the
+ file I/O.
+
+ * ext2_fs.h: Add a backup of the location of the journal inode
+ blocks to the superblock.
+
+ * mkjournal.c (write_journal_inode): Save the location of the
+ journal inode to the backup location in the superblock.
+
2003-08-01 Philipp Thomas <pthomas@suse.de>
* alloc.c, badblocks.c, bb_inode.c, bitmaps.c, block.c, bmap.c,
__u32 s_last_orphan; /* start of list of inodes to delete */
__u32 s_hash_seed[4]; /* HTREE hash seed */
__u8 s_def_hash_version; /* Default hash version to use */
- __u8 s_reserved_char_pad;
+ __u8 s_jnl_backup_type; /* Default type of journal backup */
__u16 s_reserved_word_pad;
__u32 s_default_mount_opts;
__u32 s_first_meta_bg; /* First metablock group */
__u32 s_mkfs_time; /* When the filesystem was created */
- __u32 s_reserved[189]; /* Padding to the end of the block */
+ __u32 s_jnl_blocks[16]; /* Backup of the journal inode */
+ __u32 s_reserved[173]; /* Padding to the end of the block */
};
/*
#define EXT2_GOOD_OLD_INODE_SIZE 128
/*
+ * Journal inode backup types
+ */
+#define EXT3_JNL_BACKUP_BLOCKS 1
+
+/*
* Feature set definitions
*/
int adjust, __u32 *newcount);
/* fileio.c */
+extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode *inode,
+ int flags, ext2_file_t *ret);
extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
int flags, ext2_file_t *ret);
extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file);
extern io_manager inode_io_manager;
extern errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
char **name);
+extern errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode *inode,
+ char **name);
/* ismounted.c */
extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
#define BMAP_BUFFER (file->buf + fs->blocksize)
-errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
- int flags, ext2_file_t *ret)
+errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode *inode,
+ int flags, ext2_file_t *ret)
{
ext2_file_t file;
errcode_t retval;
file->ino = ino;
file->flags = flags & EXT2_FILE_MASK;
- retval = ext2fs_read_inode(fs, ino, &file->inode);
- if (retval)
- goto fail;
+ if (inode) {
+ memcpy(&file->inode, inode, sizeof(struct ext2_inode));
+ } else {
+ retval = ext2fs_read_inode(fs, ino, &file->inode);
+ if (retval)
+ goto fail;
+ }
retval = ext2fs_get_mem(fs->blocksize * 3, &file->buf);
if (retval)
return retval;
}
+errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
+ int flags, ext2_file_t *ret)
+{
+ return ext2fs_file_open2(fs, ino, NULL, flags, ret);
+}
+
/*
* This function returns the filesystem handle of a file from the structure
*/
*/
if (!file->physblock) {
retval = ext2fs_bmap(fs, file->ino, &file->inode,
- BMAP_BUFFER, BMAP_ALLOC,
+ BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0,
file->blockno, &file->physblock);
if (retval)
return retval;
file->inode.i_size = size;
file->inode.i_size_high = 0;
- retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
- if (retval)
- return retval;
+ if (file->ino) {
+ retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
+ if (retval)
+ return retval;
+ }
/*
* XXX truncate inode if necessary
ext2_file_t file;
ext2_filsys fs;
ext2_ino_t ino;
+ struct ext2_inode inode;
int flags;
struct inode_private_data *next;
};
+#define CHANNEL_HAS_INODE 0x8000
+
static struct inode_private_data *top_intern;
static int ino_unique = 0;
io_manager inode_io_manager = &struct_inode_manager;
-errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
- char **name)
+errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode *inode,
+ char **name)
{
struct inode_private_data *data;
errcode_t retval;
data->fs = fs;
data->ino = ino;
data->flags = 0;
+ if (inode) {
+ memcpy(&data->inode, inode, sizeof(struct ext2_inode));
+ data->flags |= CHANNEL_HAS_INODE;
+ }
data->next = top_intern;
top_intern = data;
*name = data->name;
return 0;
}
+errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
+ char **name)
+{
+ return ext2fs_inode_io_intern2(fs, ino, NULL, name);
+}
+
static errcode_t inode_open(const char *name, int flags, io_channel *channel)
{
io->refcount = 1;
open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
- retval = ext2fs_file_open(data->fs, data->ino, open_flags,
- &data->file);
+ retval = ext2fs_file_open2(data->fs, data->ino,
+ (data->flags & CHANNEL_HAS_INODE) ?
+ &data->inode : 0, open_flags,
+ &data->file);
if (retval)
goto cleanup;
goto errout;
retval = 0;
+ memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
+ fs->super->s_jnl_blocks[16] = inode.i_size;
+ fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
+ ext2fs_mark_super_dirty(fs);
+
errout:
ext2fs_free_mem(&buf);
return retval;
+2003-08-20 Theodore Ts'o <tytso@mit.edu>
+
+ * f_bad_local_jnl, f_badorphan, f_h_badroot, f_h_reindex,
+ f_special_ea: Update tests to reflect that e2fsck will
+ backup the journal inode.
+
+ * f_journal: Change test to include a backed up journal location
+ in the superblock, and then corrupt the inode table so the
+ journal inode is trashed. Make sure e2fsck can recover
+ from it.
+
2003-08-01 Theodore Ts'o <tytso@mit.edu>
* f_salveage_dir: Remove HTREE flag from the test image's
Found invalid V2 journal superblock fields (from V1 journal).
Clearing fields beyond the V1 journal superblock...
+Backing up journal inode block information.
+
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/256 files (0.0% non-contiguous), 1080/8192 blocks
-Exit status is 0
+Exit status is 1
Clearing orphaned inode 32 (uid=0, gid=0, mode=040700, size=1024)
Clearing orphaned inode 67 (uid=0, gid=0, mode=040700, size=1024)
Clearing orphaned inode 55 (uid=0, gid=0, mode=040700, size=1024)
+Backing up journal inode block information.
+
Pass 1: Checking inodes, blocks, and sizes
Inodes that were part of a corrupted orphan linked list found. Fix? yes
+Backing up journal inode block information.
+
Pass 1: Checking inodes, blocks, and sizes
HTREE directory inode 13345 has an invalid root node.
Clear HTree index? yes
+Backing up journal inode block information.
+
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Problem in HTREE directory inode 16001: node (1) has bad max hash
Clearing orphaned inode 55 (uid=0, gid=0, mode=0100600, size=4096)
Clearing orphaned inode 24 (uid=0, gid=0, mode=0100600, size=4096)
Clearing orphaned inode 59 (uid=0, gid=0, mode=0100600, size=4096)
+Backing up journal inode block information.
+
Moving journal from /journal to hidden inode.
Pass 1: Checking inodes, blocks, and sizes
-recover journal
+recover journal from corrupted inode table
+Backing up journal inode block information.
+
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 17/1024 files (0.0% non-contiguous), 1180/4096 blocks
Exit status is 1