|
|
0ab26d |
From 5862f45c314aaf97ce098add06c42b5d592dc984 Mon Sep 17 00:00:00 2001
|
|
|
0ab26d |
From: Theodore Ts'o <tytso@mit.edu>
|
|
|
0ab26d |
Date: Thu, 13 Dec 2018 00:53:16 -0500
|
|
|
0ab26d |
Subject: [PATCH 2/4] debugfs: fix set_inode_field so it can set the checksum
|
|
|
0ab26d |
field
|
|
|
0ab26d |
|
|
|
0ab26d |
Previously, setting the inode field was a no-op, since the library
|
|
|
0ab26d |
function ext2fs_write_inode_full() would override whatever value was
|
|
|
0ab26d |
set by debugfs. Use the new ext2fs_write_inode2() interface so we can
|
|
|
0ab26d |
in fact set the checksum to a potentially wrong value. Also, ignore
|
|
|
0ab26d |
the inode checksum failures if we are setting the checksum, and if the
|
|
|
0ab26d |
checksum value is "calc", set the inode checksum to the correct value.
|
|
|
0ab26d |
|
|
|
0ab26d |
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
|
|
|
0ab26d |
---
|
|
|
0ab26d |
debugfs/debugfs.c | 12 +++----
|
|
|
0ab26d |
debugfs/debugfs.h | 8 ++---
|
|
|
0ab26d |
debugfs/set_fields.c | 84 +++++++++++++++++++++++++++++++++++++++-----
|
|
|
0ab26d |
debugfs/util.c | 17 +++++----
|
|
|
0ab26d |
4 files changed, 94 insertions(+), 27 deletions(-)
|
|
|
0ab26d |
|
|
|
0ab26d |
diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
|
|
|
0ab26d |
index faae12da..06a93270 100644
|
|
|
0ab26d |
--- a/debugfs/debugfs.c
|
|
|
0ab26d |
+++ b/debugfs/debugfs.c
|
|
|
0ab26d |
@@ -985,8 +985,8 @@ void do_stat(int argc, char *argv[])
|
|
|
0ab26d |
return;
|
|
|
0ab26d |
}
|
|
|
0ab26d |
|
|
|
0ab26d |
- if (debugfs_read_inode_full(inode, inode_buf, argv[0],
|
|
|
0ab26d |
- EXT2_INODE_SIZE(current_fs->super))) {
|
|
|
0ab26d |
+ if (debugfs_read_inode2(inode, inode_buf, argv[0],
|
|
|
0ab26d |
+ EXT2_INODE_SIZE(current_fs->super), 0)) {
|
|
|
0ab26d |
free(inode_buf);
|
|
|
0ab26d |
return;
|
|
|
0ab26d |
}
|
|
|
0ab26d |
@@ -1608,12 +1608,12 @@ void do_copy_inode(int argc, char *argv[])
|
|
|
0ab26d |
if (!dest_ino)
|
|
|
0ab26d |
return;
|
|
|
0ab26d |
|
|
|
0ab26d |
- if (debugfs_read_inode_full(src_ino, (struct ext2_inode *) buf,
|
|
|
0ab26d |
- argv[0], sizeof(buf)))
|
|
|
0ab26d |
+ if (debugfs_read_inode2(src_ino, (struct ext2_inode *) buf,
|
|
|
0ab26d |
+ argv[0], sizeof(buf), 0))
|
|
|
0ab26d |
return;
|
|
|
0ab26d |
|
|
|
0ab26d |
- if (debugfs_write_inode_full(dest_ino, (struct ext2_inode *) buf,
|
|
|
0ab26d |
- argv[0], sizeof(buf)))
|
|
|
0ab26d |
+ if (debugfs_write_inode2(dest_ino, (struct ext2_inode *) buf,
|
|
|
0ab26d |
+ argv[0], sizeof(buf), 0))
|
|
|
0ab26d |
return;
|
|
|
0ab26d |
}
|
|
|
0ab26d |
|
|
|
0ab26d |
diff --git a/debugfs/debugfs.h b/debugfs/debugfs.h
|
|
|
0ab26d |
index 93f036de..97fdde7e 100644
|
|
|
0ab26d |
--- a/debugfs/debugfs.h
|
|
|
0ab26d |
+++ b/debugfs/debugfs.h
|
|
|
0ab26d |
@@ -54,12 +54,12 @@ extern int common_block_args_process(int argc, char *argv[],
|
|
|
0ab26d |
blk64_t *block, blk64_t *count);
|
|
|
0ab26d |
extern int debugfs_read_inode(ext2_ino_t ino, struct ext2_inode * inode,
|
|
|
0ab26d |
const char *cmd);
|
|
|
0ab26d |
-extern int debugfs_read_inode_full(ext2_ino_t ino, struct ext2_inode * inode,
|
|
|
0ab26d |
- const char *cmd, int bufsize);
|
|
|
0ab26d |
+extern int debugfs_read_inode2(ext2_ino_t ino, struct ext2_inode * inode,
|
|
|
0ab26d |
+ const char *cmd, int bufsize, int flags);
|
|
|
0ab26d |
extern int debugfs_write_inode(ext2_ino_t ino, struct ext2_inode * inode,
|
|
|
0ab26d |
const char *cmd);
|
|
|
0ab26d |
-extern int debugfs_write_inode_full(ext2_ino_t ino, struct ext2_inode * inode,
|
|
|
0ab26d |
- const char *cmd, int bufsize);
|
|
|
0ab26d |
+extern int debugfs_write_inode2(ext2_ino_t ino, struct ext2_inode * inode,
|
|
|
0ab26d |
+ const char *cmd, int bufsize, int flags);
|
|
|
0ab26d |
extern int debugfs_write_new_inode(ext2_ino_t ino, struct ext2_inode * inode,
|
|
|
0ab26d |
const char *cmd);
|
|
|
0ab26d |
extern int ext2_file_type(unsigned int mode);
|
|
|
0ab26d |
diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c
|
|
|
0ab26d |
index 3cdf617c..4f033249 100644
|
|
|
0ab26d |
--- a/debugfs/set_fields.c
|
|
|
0ab26d |
+++ b/debugfs/set_fields.c
|
|
|
0ab26d |
@@ -53,6 +53,7 @@ static int array_idx;
|
|
|
0ab26d |
|
|
|
0ab26d |
#define FLAG_ARRAY 0x0001
|
|
|
0ab26d |
#define FLAG_ALIAS 0x0002 /* Data intersects with other field */
|
|
|
0ab26d |
+#define FLAG_CSUM 0x0004
|
|
|
0ab26d |
|
|
|
0ab26d |
struct field_set_info {
|
|
|
0ab26d |
const char *name;
|
|
|
0ab26d |
@@ -72,6 +73,8 @@ static errcode_t parse_hashalg(struct field_set_info *info, char *field, char *a
|
|
|
0ab26d |
static errcode_t parse_time(struct field_set_info *info, char *field, char *arg);
|
|
|
0ab26d |
static errcode_t parse_bmap(struct field_set_info *info, char *field, char *arg);
|
|
|
0ab26d |
static errcode_t parse_gd_csum(struct field_set_info *info, char *field, char *arg);
|
|
|
0ab26d |
+static errcode_t parse_inode_csum(struct field_set_info *info, char *field,
|
|
|
0ab26d |
+ char *arg);
|
|
|
0ab26d |
static errcode_t parse_mmp_clear(struct field_set_info *info, char *field,
|
|
|
0ab26d |
char *arg);
|
|
|
0ab26d |
|
|
|
0ab26d |
@@ -218,7 +221,7 @@ static struct field_set_info inode_fields[] = {
|
|
|
0ab26d |
{ "frag", &set_inode.osd2.hurd2.h_i_frag, NULL, 1, parse_uint, FLAG_ALIAS },
|
|
|
0ab26d |
{ "fsize", &set_inode.osd2.hurd2.h_i_fsize, NULL, 1, parse_uint },
|
|
|
0ab26d |
{ "checksum", &set_inode.osd2.linux2.l_i_checksum_lo,
|
|
|
0ab26d |
- &set_inode.i_checksum_hi, 2, parse_uint },
|
|
|
0ab26d |
+ &set_inode.i_checksum_hi, 2, parse_inode_csum, FLAG_CSUM },
|
|
|
0ab26d |
{ "author", &set_inode.osd2.hurd2.h_i_author, NULL,
|
|
|
0ab26d |
4, parse_uint, FLAG_ALIAS },
|
|
|
0ab26d |
{ "extra_isize", &set_inode.i_extra_isize, NULL,
|
|
|
0ab26d |
@@ -665,6 +668,68 @@ static errcode_t parse_gd_csum(struct field_set_info *info, char *field,
|
|
|
0ab26d |
return parse_uint(info, field, arg);
|
|
|
0ab26d |
}
|
|
|
0ab26d |
|
|
|
0ab26d |
+static errcode_t parse_inode_csum(struct field_set_info *info, char *field,
|
|
|
0ab26d |
+ char *arg)
|
|
|
0ab26d |
+{
|
|
|
0ab26d |
+ errcode_t retval = 0;
|
|
|
0ab26d |
+ __u32 crc;
|
|
|
0ab26d |
+ int is_large_inode = 0;
|
|
|
0ab26d |
+ struct ext2_inode_large *tmp_inode;
|
|
|
0ab26d |
+
|
|
|
0ab26d |
+ if (strcmp(arg, "calc") == 0) {
|
|
|
0ab26d |
+ size_t sz = EXT2_INODE_SIZE(current_fs->super);
|
|
|
0ab26d |
+ struct ext2_inode_large *tmp_inode = NULL;
|
|
|
0ab26d |
+
|
|
|
0ab26d |
+ retval = ext2fs_get_mem(sz, &tmp_inode);
|
|
|
0ab26d |
+ if (retval)
|
|
|
0ab26d |
+ goto out;
|
|
|
0ab26d |
+
|
|
|
0ab26d |
+ retval = ext2fs_read_inode_full(current_fs, set_ino,
|
|
|
0ab26d |
+ (struct ext2_inode *) tmp_inode,
|
|
|
0ab26d |
+ sz);
|
|
|
0ab26d |
+ if (retval)
|
|
|
0ab26d |
+ goto out;
|
|
|
0ab26d |
+
|
|
|
0ab26d |
+#ifdef WORDS_BIGENDIAN
|
|
|
0ab26d |
+ ext2fs_swap_inode_full(current_fs, tmp_inode,
|
|
|
0ab26d |
+ tmp_inode, 1, sz);
|
|
|
0ab26d |
+#endif
|
|
|
0ab26d |
+
|
|
|
0ab26d |
+ if (sz > EXT2_GOOD_OLD_INODE_SIZE)
|
|
|
0ab26d |
+ is_large_inode = 1;
|
|
|
0ab26d |
+
|
|
|
0ab26d |
+ retval = ext2fs_inode_csum_set(current_fs, set_ino,
|
|
|
0ab26d |
+ tmp_inode);
|
|
|
0ab26d |
+ if (retval)
|
|
|
0ab26d |
+ goto out;
|
|
|
0ab26d |
+#ifdef WORDS_BIGENDIAN
|
|
|
0ab26d |
+ crc = set_inode.i_checksum_lo =
|
|
|
0ab26d |
+ ext2fs_swab16(tmp_inode->i_checksum_lo);
|
|
|
0ab26d |
+
|
|
|
0ab26d |
+#else
|
|
|
0ab26d |
+ crc = set_inode.i_checksum_lo = tmp_inode->i_checksum_lo;
|
|
|
0ab26d |
+#endif
|
|
|
0ab26d |
+ if (is_large_inode &&
|
|
|
0ab26d |
+ set_inode.i_extra_isize >=
|
|
|
0ab26d |
+ (offsetof(struct ext2_inode_large,
|
|
|
0ab26d |
+ i_checksum_hi) -
|
|
|
0ab26d |
+ EXT2_GOOD_OLD_INODE_SIZE)) {
|
|
|
0ab26d |
+#ifdef WORDS_BIGENDIAN
|
|
|
0ab26d |
+ set_inode.i_checksum_lo =
|
|
|
0ab26d |
+ ext2fs_swab16(tmp_inode->i_checksum_lo);
|
|
|
0ab26d |
+#else
|
|
|
0ab26d |
+ set_inode.i_checksum_hi = tmp_inode->i_checksum_hi;
|
|
|
0ab26d |
+#endif
|
|
|
0ab26d |
+ crc |= ((__u32)set_inode.i_checksum_hi) << 16;
|
|
|
0ab26d |
+ }
|
|
|
0ab26d |
+ printf("Checksum set to 0x%08x\n", crc);
|
|
|
0ab26d |
+ out:
|
|
|
0ab26d |
+ ext2fs_free_mem(&tmp_inode);
|
|
|
0ab26d |
+ return retval;
|
|
|
0ab26d |
+ }
|
|
|
0ab26d |
+ return parse_uint(info, field, arg);
|
|
|
0ab26d |
+}
|
|
|
0ab26d |
+
|
|
|
0ab26d |
static void print_possible_fields(struct field_set_info *fields)
|
|
|
0ab26d |
{
|
|
|
0ab26d |
struct field_set_info *ss;
|
|
|
0ab26d |
@@ -775,16 +840,19 @@ void do_set_inode(int argc, char *argv[])
|
|
|
0ab26d |
if (!set_ino)
|
|
|
0ab26d |
return;
|
|
|
0ab26d |
|
|
|
0ab26d |
- if (debugfs_read_inode_full(set_ino,
|
|
|
0ab26d |
- (struct ext2_inode *) &set_inode, argv[1],
|
|
|
0ab26d |
- sizeof(set_inode)))
|
|
|
0ab26d |
+ if (debugfs_read_inode2(set_ino,
|
|
|
0ab26d |
+ (struct ext2_inode *) &set_inode, argv[1],
|
|
|
0ab26d |
+ sizeof(set_inode),
|
|
|
0ab26d |
+ (ss->flags & FLAG_CSUM) ?
|
|
|
0ab26d |
+ READ_INODE_NOCSUM : 0))
|
|
|
0ab26d |
return;
|
|
|
0ab26d |
|
|
|
0ab26d |
if (ss->func(ss, argv[2], argv[3]) == 0) {
|
|
|
0ab26d |
- if (debugfs_write_inode_full(set_ino,
|
|
|
0ab26d |
- (struct ext2_inode *) &set_inode,
|
|
|
0ab26d |
- argv[1], sizeof(set_inode)))
|
|
|
0ab26d |
- return;
|
|
|
0ab26d |
+ debugfs_write_inode2(set_ino,
|
|
|
0ab26d |
+ (struct ext2_inode *) &set_inode,
|
|
|
0ab26d |
+ argv[1], sizeof(set_inode),
|
|
|
0ab26d |
+ (ss->flags & FLAG_CSUM) ?
|
|
|
0ab26d |
+ WRITE_INODE_NOCSUM : 0);
|
|
|
0ab26d |
}
|
|
|
0ab26d |
}
|
|
|
0ab26d |
|
|
|
0ab26d |
diff --git a/debugfs/util.c b/debugfs/util.c
|
|
|
0ab26d |
index 452de749..759bb392 100644
|
|
|
0ab26d |
--- a/debugfs/util.c
|
|
|
0ab26d |
+++ b/debugfs/util.c
|
|
|
0ab26d |
@@ -420,12 +420,12 @@ int common_block_args_process(int argc, char *argv[],
|
|
|
0ab26d |
return 0;
|
|
|
0ab26d |
}
|
|
|
0ab26d |
|
|
|
0ab26d |
-int debugfs_read_inode_full(ext2_ino_t ino, struct ext2_inode * inode,
|
|
|
0ab26d |
- const char *cmd, int bufsize)
|
|
|
0ab26d |
+int debugfs_read_inode2(ext2_ino_t ino, struct ext2_inode * inode,
|
|
|
0ab26d |
+ const char *cmd, int bufsize, int flags)
|
|
|
0ab26d |
{
|
|
|
0ab26d |
int retval;
|
|
|
0ab26d |
|
|
|
0ab26d |
- retval = ext2fs_read_inode_full(current_fs, ino, inode, bufsize);
|
|
|
0ab26d |
+ retval = ext2fs_read_inode2(current_fs, ino, inode, bufsize, flags);
|
|
|
0ab26d |
if (retval) {
|
|
|
0ab26d |
com_err(cmd, retval, "while reading inode %u", ino);
|
|
|
0ab26d |
return 1;
|
|
|
0ab26d |
@@ -446,15 +446,14 @@ int debugfs_read_inode(ext2_ino_t ino, struct ext2_inode * inode,
|
|
|
0ab26d |
return 0;
|
|
|
0ab26d |
}
|
|
|
0ab26d |
|
|
|
0ab26d |
-int debugfs_write_inode_full(ext2_ino_t ino,
|
|
|
0ab26d |
- struct ext2_inode *inode,
|
|
|
0ab26d |
- const char *cmd,
|
|
|
0ab26d |
- int bufsize)
|
|
|
0ab26d |
+int debugfs_write_inode2(ext2_ino_t ino,
|
|
|
0ab26d |
+ struct ext2_inode *inode,
|
|
|
0ab26d |
+ const char *cmd,
|
|
|
0ab26d |
+ int bufsize, int flags)
|
|
|
0ab26d |
{
|
|
|
0ab26d |
int retval;
|
|
|
0ab26d |
|
|
|
0ab26d |
- retval = ext2fs_write_inode_full(current_fs, ino,
|
|
|
0ab26d |
- inode, bufsize);
|
|
|
0ab26d |
+ retval = ext2fs_write_inode2(current_fs, ino, inode, bufsize, flags);
|
|
|
0ab26d |
if (retval) {
|
|
|
0ab26d |
com_err(cmd, retval, "while writing inode %u", ino);
|
|
|
0ab26d |
return 1;
|
|
|
0ab26d |
--
|
|
|
0ab26d |
2.20.1
|
|
|
0ab26d |
|