+2004-07-28 Theodore Ts'o <tytso@mit.edu>
+
+ * debugfs.c, debugfs.8.in: Add new option -d which allows the
+ system administrator to specify data source of a
+ filesystem being opened via an e2image file.
+
2004-04-11 Theodore Ts'o <tytso@mit.edu>
* util.c (open_pager): Use DEBUGFS_PAGER in preference to PAGER
.SH SYNOPSIS
.B debugfs
[
+.B \-Vwci
+]
+[
.B \-b
blocksize
]
request
]
[
-.B \-V
-]
-[
-[
-.B \-w
-]
-[
-.B \-c
-]
-[
-.B \-i
+.B \-d
+data_source_device
]
[
device
]
-]
.SH DESCRIPTION
The
.B debugfs
.B debugfs
may fail in interesting ways if commands such as
.IR ls ", " dump ", "
-etc. are tried.
+etc. are tried without specifying the
+.I data_source_device
+using the
+.I \-d
+option.
.B debugfs
is a debugging tool. It has rough edges!
.TP
+.I -d data_source_device
+Used with the
+.I \-i
+option, specifies that
+.I data_source_device
+should be used when reading blocks not found in the ext2 image file.
+This includes data, directory, and indirect blocks.
+.TP
.I -b blocksize
Forces the use of the given block size for the file system, rather than
detecting the correct block size as normal.
ext2_ino_t root, cwd;
static void open_filesystem(char *device, int open_flags, blk_t superblock,
- blk_t blocksize, int catastrophic)
+ blk_t blocksize, int catastrophic,
+ char *data_filename)
{
int retval;
+ io_channel data_io = 0;
if (superblock != 0 && blocksize == 0) {
com_err(device, 0, "if you specify the superblock, you must also specify the block size");
return;
}
+ if (data_filename) {
+ if ((open_flags & EXT2_FLAG_IMAGE_FILE) == 0) {
+ com_err(device, 0,
+ "The -d option is only valid when reading an e2image file");
+ current_fs = NULL;
+ return;
+ }
+ retval = unix_io_manager->open(data_filename, 0, &data_io);
+ if (retval) {
+ com_err(data_filename, 0, "while opening data source");
+ current_fs = NULL;
+ return;
+ }
+ }
+
if (catastrophic && (open_flags & EXT2_FLAG_RW)) {
com_err(device, 0,
"opening read-only because of catastrophic mode");
goto errout;
}
}
+
+ if (data_io) {
+ retval = ext2fs_set_data_io(current_fs, data_io);
+ if (retval) {
+ com_err(device, retval,
+ "while setting data source");
+ goto errout;
+ }
+ }
+
root = cwd = EXT2_ROOT_INO;
return;
int catastrophic = 0;
blk_t superblock = 0;
blk_t blocksize = 0;
- int open_flags = 0;
+ int open_flags = 0;
+ char *data_filename;
reset_getopt();
- while ((c = getopt (argc, argv, "iwfcb:s:")) != EOF) {
+ while ((c = getopt (argc, argv, "iwfcb:s:d:")) != EOF) {
switch (c) {
case 'i':
open_flags |= EXT2_FLAG_IMAGE_FILE;
case 'c':
catastrophic = 1;
break;
+ case 'd':
+ data_filename = optarg;
+ break;
case 'b':
blocksize = parse_ulong(optarg, argv[0],
"block size", &err);
if (check_fs_not_open(argv[0]))
return;
open_filesystem(argv[optind], open_flags,
- superblock, blocksize, catastrophic);
+ superblock, blocksize, catastrophic,
+ data_filename);
}
void do_lcd(int argc, char **argv)
blk_t superblock = 0;
blk_t blocksize = 0;
int catastrophic = 0;
+ char *data_filename = 0;
initialize_ext2_error_table();
fprintf (stderr, "debugfs %s (%s)\n", E2FSPROGS_VERSION,
E2FSPROGS_DATE);
- while ((c = getopt (argc, argv, "iwcR:f:b:s:V")) != EOF) {
+ while ((c = getopt (argc, argv, "iwcR:f:b:s:Vd:")) != EOF) {
switch (c) {
case 'R':
request = optarg;
case 'f':
cmd_file = optarg;
break;
+ case 'd':
+ data_filename = optarg;
+ break;
case 'i':
open_flags |= EXT2_FLAG_IMAGE_FILE;
break;
}
if (optind < argc)
open_filesystem(argv[optind], open_flags,
- superblock, blocksize, catastrophic);
+ superblock, blocksize, catastrophic,
+ data_filename);
sci_idx = ss_create_invocation("debugfs", "0.0", (char *) NULL,
&debug_cmds, &retval);
+2004-07-28 Theodore Ts'o <tytso@mit.edu>
+
+ * rw_bitmaps.c (read_bitmaps), block.c (block_iterate_ind,
+ block_iterate_dind, block_iterate_tind), inode.c
+ (ext2fs_read_inode): If EXT2_FLAG_IMAGE_FILE is set, so
+ read the metadata from fs->image_io instead of fs->io.
+
+ * initialize.c (ext2fs_initialize), openfs.c (ext2fs_open):
+ Initialize fs->image_io to be the same as fs->io.
+
+ * ext2_err.et.in (EXT2_ET_NOT_IMAGE_FILE): Add new error code.
+
+ * openfs.c (ext2fs_get_data_io, ext2fs_set_data_io,
+ ext2fs_rewrite_to_io): New functions that allow
+ applications to manipulate fs->image_io and fs->io safely.
+
+ * freefs.c (ext2fs_free): If fs->image_io is different fs->io,
+ then call io_channel_close on fs->image_io.
+
+ * ext2fs.h: Add image_io element to the ext2_filsys data
+ structure. Add ext2fs_get_data_io() ext2fs_set_data_io(),
+ and ext2fs_rewrite_to_io() prototypes.
+
2004-05-26 Theodore Ts'o <tytso@mit.edu>
* closefs.c (ext2fs_flush): Make sure the master superblock is
ret |= BLOCK_ERROR;
return ret;
}
- if (ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) {
+ if ((ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) &&
+ (ctx->fs->io != ctx->fs->image_io)) {
ctx->errcode = 0;
memset(ctx->ind_buf, 0, ctx->fs->blocksize);
} else
ret |= BLOCK_ERROR;
return ret;
}
- if (ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) {
+ if ((ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) &&
+ (ctx->fs->io != ctx->fs->image_io)) {
ctx->errcode = 0;
memset(ctx->dind_buf, 0, ctx->fs->blocksize);
} else
ret |= BLOCK_ERROR;
return ret;
}
- if (ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) {
+ if ((ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) &&
+ (ctx->fs->io != ctx->fs->image_io)) {
ctx->errcode = 0;
memset(ctx->tind_buf, 0, ctx->fs->blocksize);
} else
ec EXT2_ET_TOO_MANY_INODES,
"Cannot create filesystem with requested number of inodes"
+ec EXT2_ET_NOT_IMAGE_FILE,
+ "E2image snapshot not in use"
+
end
* Inode cache
*/
struct ext2_inode_cache *icache;
+ io_channel image_io;
};
#if EXT2_FLAT_INCLUDES
ext2_filsys *ret_fs);
extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block,
dgrp_t i);
+errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io);
+errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io);
+errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io);
/* get_pathname.c */
extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
{
if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS))
return;
+ if (fs->image_io != fs->io) {
+ io_channel_close(fs->image_io);
+ }
if (fs->io) {
io_channel_close(fs->io);
}
retval = manager->open(name, IO_FLAG_RW, &fs->io);
if (retval)
goto cleanup;
+ fs->image_io = fs->io;
fs->io->app_data = fs;
retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
if (retval)
errcode_t retval;
int clen, i, inodes_per_block;
unsigned int length;
+ io_channel io;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
block_nr += (ino - 1) / inodes_per_block;
offset = ((ino - 1) % inodes_per_block) *
EXT2_INODE_SIZE(fs->super);
+ io = fs->image_io;
} else {
group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
return EXT2_ET_MISSING_INODE_TABLE;
block_nr = fs->group_desc[(unsigned)group].bg_inode_table +
block;
+ io = fs->io;
}
if (block_nr != fs->icache->buffer_blk) {
- retval = io_channel_read_blk(fs->io, block_nr, 1,
+ retval = io_channel_read_blk(io, block_nr, 1,
fs->icache->buffer);
if (retval)
return retval;
memcpy((char *) inode, ptr, clen);
length -= clen;
- retval = io_channel_read_blk(fs->io, block_nr+1, 1,
+ retval = io_channel_read_blk(io, block_nr+1, 1,
fs->icache->buffer);
if (retval) {
fs->icache->buffer_blk = 0;
&fs->io);
if (retval)
goto cleanup;
+ fs->image_io = fs->io;
fs->io->app_data = fs;
retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
if (retval)
return retval;
}
+/*
+ * Set/get the filesystem data I/O channel.
+ *
+ * These functions are only valid if EXT2_FLAG_IMAGE_FILE is true.
+ */
+errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io)
+{
+ if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
+ return EXT2_ET_NOT_IMAGE_FILE;
+ if (old_io) {
+ *old_io = (fs->image_io == fs->io) ? 0 : fs->io;
+ }
+ return 0;
+}
+
+errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io)
+{
+ if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
+ return EXT2_ET_NOT_IMAGE_FILE;
+ fs->io = new_io ? new_io : fs->image_io;
+ return 0;
+}
+
+errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io)
+{
+ if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
+ return EXT2_ET_NOT_IMAGE_FILE;
+ fs->io = fs->image_io = new_io;
+ fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_RW |
+ EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
+ fs->flags &= ~EXT2_FLAG_IMAGE_FILE;
+ return 0;
+}
if (inode_bitmap) {
blk = (fs->image_header->offset_inodemap /
fs->blocksize);
- retval = io_channel_read_blk(fs->io, blk,
+ retval = io_channel_read_blk(fs->image_io, blk,
-(inode_nbytes * fs->group_desc_count),
inode_bitmap);
if (retval)
if (block_bitmap) {
blk = (fs->image_header->offset_blockmap /
fs->blocksize);
- retval = io_channel_read_blk(fs->io, blk,
+ retval = io_channel_read_blk(fs->image_io, blk,
-(block_nbytes * fs->group_desc_count),
block_bitmap);
if (retval)