* [f2fs-dev] [RCF PATCH v3 01/10] f2fs-tools: export is_digits
2024-07-04 2:57 [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
@ 2024-07-04 2:57 ` Sheng Yong via Linux-f2fs-devel
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 02/10] inject.f2fs: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
` (10 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Sheng Yong via Linux-f2fs-devel @ 2024-07-04 2:57 UTC (permalink / raw)
To: chao, jaegeuk; +Cc: linux-f2fs-devel
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Sheng Yong <shengyong@oppo.com>
---
fsck/fsck.h | 3 +++
fsck/main.c | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 6cac926..4ca75b3 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -353,4 +353,7 @@ int update_inode(struct f2fs_sb_info *sbi, struct f2fs_node *inode,
int flush_nat_journal_entries(struct f2fs_sb_info *sbi);
int flush_sit_journal_entries(struct f2fs_sb_info *sbi);
+/* main.c */
+int is_digits(char *optarg);
+
#endif /* _FSCK_H_ */
diff --git a/fsck/main.c b/fsck/main.c
index c13e287..c8469cd 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -171,7 +171,7 @@ void label_usage()
exit(1);
}
-static int is_digits(char *optarg)
+int is_digits(char *optarg)
{
unsigned int i;
--
2.40.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 19+ messages in thread* [f2fs-dev] [RCF PATCH v3 02/10] inject.f2fs: introduce inject.f2fs
2024-07-04 2:57 [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 01/10] f2fs-tools: export is_digits Sheng Yong via Linux-f2fs-devel
@ 2024-07-04 2:57 ` Sheng Yong via Linux-f2fs-devel
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 03/10] inject.f2fs: add sb injection Sheng Yong via Linux-f2fs-devel
` (9 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Sheng Yong via Linux-f2fs-devel @ 2024-07-04 2:57 UTC (permalink / raw)
To: chao, jaegeuk; +Cc: linux-f2fs-devel
This patch introduces a new tool inject.f2fs to modify metadata or data
(directory entry) of f2fs image offline flexibly.
With inject.f2fs, it is easier to generate a corrupted f2fs image, which
can help verify fsck or reproduce userspace behaviors of some a fault.
If option `--dry-run' is used, nothing really gets changed, and that
could be used to get the value of a specified field.
The following patches enable injecting each part of f2fs.
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Sheng Yong <shengyong@oppo.com>
---
fsck/Makefile.am | 5 ++--
fsck/inject.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++
fsck/inject.h | 28 +++++++++++++++++++++
fsck/main.c | 29 +++++++++++++++++++++
include/f2fs_fs.h | 2 ++
5 files changed, 126 insertions(+), 2 deletions(-)
create mode 100644 fsck/inject.c
create mode 100644 fsck/inject.h
diff --git a/fsck/Makefile.am b/fsck/Makefile.am
index 40d31b8..48402ab 100644
--- a/fsck/Makefile.am
+++ b/fsck/Makefile.am
@@ -4,11 +4,12 @@ AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include
AM_CFLAGS = -Wall -D_FILE_OFFSET_BITS=64
sbin_PROGRAMS = fsck.f2fs
noinst_HEADERS = common.h dict.h dqblk_v2.h f2fs.h fsck.h node.h quotaio.h \
- quotaio_tree.h quotaio_v2.h xattr.h compress.h
+ quotaio_tree.h quotaio_v2.h xattr.h compress.h inject.h
include_HEADERS = $(top_srcdir)/include/quota.h
fsck_f2fs_SOURCES = main.c fsck.c dump.c mount.c defrag.c resize.c \
node.c segment.c dir.c sload.c xattr.c compress.c \
- dict.c mkquota.c quotaio.c quotaio_tree.c quotaio_v2.c
+ dict.c mkquota.c quotaio.c quotaio_tree.c quotaio_v2.c \
+ inject.c
fsck_f2fs_LDADD = ${libselinux_LIBS} ${libuuid_LIBS} \
${liblzo2_LIBS} ${liblz4_LIBS} ${libwinpthread_LIBS} \
$(top_builddir)/lib/libf2fs.la
diff --git a/fsck/inject.c b/fsck/inject.c
new file mode 100644
index 0000000..f6fd346
--- /dev/null
+++ b/fsck/inject.c
@@ -0,0 +1,64 @@
+/**
+ * inject.c
+ *
+ * Copyright (c) 2024 OPPO Mobile Comm Corp., Ltd.
+ * http://www.oppo.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <getopt.h>
+#include "inject.h"
+
+void inject_usage(void)
+{
+ MSG(0, "\nUsage: inject.f2fs [options] device\n");
+ MSG(0, "[options]:\n");
+ MSG(0, " -d debug level [default:0]\n");
+ MSG(0, " -V print the version number and exit\n");
+ MSG(0, " --dry-run do not really inject\n");
+
+ exit(1);
+}
+
+int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
+{
+ int o = 0;
+ const char *option_string = "d:V";
+ struct option long_opt[] = {
+ {"dry-run", no_argument, 0, 1},
+ {0, 0, 0, 0}
+ };
+
+ while ((o = getopt_long(argc, argv, option_string,
+ long_opt, NULL)) != EOF) {
+ switch (o) {
+ case 1:
+ c.dry_run = 1;
+ MSG(0, "Info: Dry run\n");
+ break;
+ case 'd':
+ if (optarg[0] == '-' || !is_digits(optarg))
+ return EWRONG_OPT;
+ c.dbg_lv = atoi(optarg);
+ MSG(0, "Info: Debug level = %d\n", c.dbg_lv);
+ break;
+ case 'V':
+ show_version("inject.f2fs");
+ exit(0);
+ default:
+ return EUNKNOWN_OPT;
+ }
+ }
+
+ return 0;
+}
+
+int do_inject(struct f2fs_sb_info *sbi)
+{
+ int ret = -EINVAL;
+
+ return ret;
+}
diff --git a/fsck/inject.h b/fsck/inject.h
new file mode 100644
index 0000000..62543c1
--- /dev/null
+++ b/fsck/inject.h
@@ -0,0 +1,28 @@
+/**
+ * inject.h
+ *
+ * Copyright (c) 2024 OPPO Mobile Comm Corp., Ltd.
+ * http://www.oppo.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _INJECT_H_
+#define _INJECT_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <limits.h>
+
+#include "f2fs_fs.h"
+#include "fsck.h"
+
+struct inject_option {
+};
+
+void inject_usage(void);
+int inject_parse_options(int argc, char *argv[], struct inject_option *inject_opt);
+int do_inject(struct f2fs_sb_info *sbi);
+#endif
diff --git a/fsck/main.c b/fsck/main.c
index c8469cd..eca09aa 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -29,6 +29,15 @@
#include <stdbool.h>
#include "quotaio.h"
#include "compress.h"
+#ifdef WITH_INJECT
+#include "inject.h"
+#else
+static void inject_usage(void)
+{
+ MSG(0, "\ninject.f2fs not supported\n");
+ exit(1);
+}
+#endif
struct f2fs_fsck gfsck;
@@ -195,6 +204,8 @@ static void error_out(char *prog)
sload_usage();
else if (!strcmp("f2fslabel", prog))
label_usage();
+ else if (!strcmp("inject.f2fs", prog))
+ inject_usage();
else
MSG(0, "\nWrong program.\n");
}
@@ -809,6 +820,18 @@ void f2fs_parse_options(int argc, char *argv[])
c.vol_label = NULL;
}
#endif /* WITH_LABEL */
+ } else if (!strcmp("inject.f2fs", prog)) {
+#ifdef WITH_INJECT
+ static struct inject_option inject_opt;
+
+ err = inject_parse_options(argc, argv, &inject_opt);
+ if (err < 0) {
+ err = EWRONG_OPT;
+ }
+
+ c.func = INJECT;
+ c.private = &inject_opt;
+#endif /* WITH_INJECT */
}
if (err == NOERROR) {
@@ -1229,6 +1252,12 @@ fsck_again:
if (do_label(sbi))
goto out_err;
break;
+#endif
+#ifdef WITH_INJECT
+ case INJECT:
+ if (do_inject(sbi))
+ goto out_err;
+ break;
#endif
default:
ERR_MSG("Wrong program name\n");
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index 870a6e4..3a5d146 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -45,6 +45,7 @@
#define WITH_RESIZE
#define WITH_SLOAD
#define WITH_LABEL
+#define WITH_INJECT
#endif
#include <inttypes.h>
@@ -427,6 +428,7 @@ enum f2fs_config_func {
RESIZE,
SLOAD,
LABEL,
+ INJECT,
};
enum default_set {
--
2.40.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 19+ messages in thread* [f2fs-dev] [RCF PATCH v3 03/10] inject.f2fs: add sb injection
2024-07-04 2:57 [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 01/10] f2fs-tools: export is_digits Sheng Yong via Linux-f2fs-devel
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 02/10] inject.f2fs: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
@ 2024-07-04 2:57 ` Sheng Yong via Linux-f2fs-devel
2024-07-04 3:39 ` Chao Yu
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 04/10] inject.f2fs: add cp injection Sheng Yong via Linux-f2fs-devel
` (8 subsequent siblings)
11 siblings, 1 reply; 19+ messages in thread
From: Sheng Yong via Linux-f2fs-devel @ 2024-07-04 2:57 UTC (permalink / raw)
To: chao, jaegeuk; +Cc: linux-f2fs-devel
This patch enables injecting super block.
The meanings of options are:
* sb: means sb is injected, its argument chooses which sb pack to be
injected, where 0 means the current valid sb is choosen
automatically.
* mb: indicates which member in sb is injected, its argument is the
member name.
* idx: is used when the mb is an array, its argument is the index of
the array.
* val: is the new value to be set when the type of mb is a number.
* str: is the new value to be set when the type of mb is a string.
The members could be injected in sb contains:
* magic: magic number
* s_stop_reason: s_stop_reason array
* s_errors: s_errors array
* devs.path: path in devs array
Signed-off-by: Sheng Yong <shengyong@oppo.com>
---
fsck/inject.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++-
fsck/inject.h | 5 ++
fsck/main.c | 5 +-
fsck/mount.c | 4 +-
4 files changed, 150 insertions(+), 4 deletions(-)
diff --git a/fsck/inject.c b/fsck/inject.c
index f6fd346..f29e746 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -18,17 +18,43 @@ void inject_usage(void)
MSG(0, "[options]:\n");
MSG(0, " -d debug level [default:0]\n");
MSG(0, " -V print the version number and exit\n");
+ MSG(0, " --mb <member name> which member is injected in a struct\n");
+ MSG(0, " --val <new value> new value to set\n");
+ MSG(0, " --str <new string> new string to set\n");
+ MSG(0, " --idx <slot index> which slot is injected in an array\n");
+ MSG(0, " --sb <0|1|2> --mb <name> [--idx <index>] --val/str <value/string> inject superblock\n");
MSG(0, " --dry-run do not really inject\n");
exit(1);
}
+static void inject_sb_usage(void)
+{
+ MSG(0, "inject.f2fs --sb <0|1|2> --mb <name> [--idx <index>] --val/str <value/string>\n");
+ MSG(0, "[sb]:\n");
+ MSG(0, " 0: auto select the first super block\n");
+ MSG(0, " 1: select the first super block\n");
+ MSG(0, " 2: select the second super block\n");
+ MSG(0, "[mb]:\n");
+ MSG(0, " magic: inject magic number\n");
+ MSG(0, " s_stop_reason: inject s_stop_reason array selected by --idx <index>\n");
+ MSG(0, " s_errors: inject s_errors array selected by --idx <index>\n");
+ MSG(0, " devs.path: inject path in devs array selected by --idx <index> specified by --str <string>\n");
+}
+
int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
{
int o = 0;
- const char *option_string = "d:V";
+ const char *pack[] = {"auto", "1", "2"};
+ const char *option_string = "d:Vh";
+ char *endptr;
struct option long_opt[] = {
{"dry-run", no_argument, 0, 1},
+ {"mb", required_argument, 0, 2},
+ {"idx", required_argument, 0, 3},
+ {"val", required_argument, 0, 4},
+ {"str", required_argument, 0, 5},
+ {"sb", required_argument, 0, 6},
{0, 0, 0, 0}
};
@@ -39,6 +65,38 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
c.dry_run = 1;
MSG(0, "Info: Dry run\n");
break;
+ case 2:
+ opt->mb = optarg;
+ MSG(0, "Info: inject member %s\n", optarg);
+ break;
+ case 3:
+ if (!is_digits(optarg))
+ return EWRONG_OPT;
+ opt->idx = atoi(optarg);
+ MSG(0, "Info: inject slot index %d\n", opt->idx);
+ break;
+ case 4:
+ opt->val = strtoll(optarg, &endptr, 0);
+ if (opt->val == LLONG_MAX || opt->val == LLONG_MIN ||
+ *endptr != '\0')
+ return -ERANGE;
+ MSG(0, "Info: inject value %lld : 0x%llx\n", opt->val,
+ (unsigned long long)opt->val);
+ break;
+ case 5:
+ opt->str = strdup(optarg);
+ if (!opt->str)
+ return -ENOMEM;
+ MSG(0, "Info: inject string %s\n", opt->str);
+ break;
+ case 6:
+ if (!is_digits(optarg))
+ return EWRONG_OPT;
+ opt->sb = atoi(optarg);
+ if (opt->sb < 0 || opt->sb > 2)
+ return -ERANGE;
+ MSG(0, "Info: inject sb %s\n", pack[opt->sb]);
+ break;
case 'd':
if (optarg[0] == '-' || !is_digits(optarg))
return EWRONG_OPT;
@@ -48,7 +106,12 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
case 'V':
show_version("inject.f2fs");
exit(0);
+ case 'h':
default:
+ if (opt->sb >= 0) {
+ inject_sb_usage();
+ exit(0);
+ }
return EUNKNOWN_OPT;
}
}
@@ -56,9 +119,84 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
return 0;
}
+static int inject_sb(struct f2fs_sb_info *sbi, struct inject_option *opt)
+{
+ struct f2fs_super_block *sb;
+ char *buf;
+ int ret;
+
+ buf = calloc(1, F2FS_BLKSIZE);
+ ASSERT(buf != NULL);
+
+ if (opt->sb == 0)
+ opt->sb = 1;
+
+ ret = dev_read_block(buf, opt->sb == 1 ? SB0_ADDR : SB1_ADDR);
+ ASSERT(ret >= 0);
+
+ sb = (struct f2fs_super_block *)(buf + F2FS_SUPER_OFFSET);
+
+ if (!strcmp(opt->mb, "magic")) {
+ MSG(0, "Info: inject magic of sb %d: 0x%x -> 0x%x\n",
+ opt->sb, get_sb(magic), (u32)opt->val);
+ set_sb(magic, (u32)opt->val);
+ } else if (!strcmp(opt->mb, "s_stop_reason")) {
+ if (opt->idx >= MAX_STOP_REASON) {
+ ERR_MSG("invalid index %u of sb->s_stop_reason[]\n",
+ opt->idx);
+ ret = -EINVAL;
+ goto out;
+ }
+ MSG(0, "Info: inject s_stop_reason[%d] of sb %d: %d -> %d\n",
+ opt->idx, opt->sb, sb->s_stop_reason[opt->idx],
+ (u8)opt->val);
+ sb->s_stop_reason[opt->idx] = (u8)opt->val;
+ } else if (!strcmp(opt->mb, "s_errors")) {
+ if (opt->idx >= MAX_F2FS_ERRORS) {
+ ERR_MSG("invalid index %u of sb->s_errors[]\n",
+ opt->idx);
+ ret = -EINVAL;
+ goto out;
+ }
+ MSG(0, "Info: inject s_errors[%d] of sb %d: %x -> %x\n",
+ opt->idx, opt->sb, sb->s_errors[opt->idx], (u8)opt->val);
+ sb->s_errors[opt->idx] = (u8)opt->val;
+ } else if (!strcmp(opt->mb, "devs.path")) {
+ if (opt->idx >= MAX_DEVICES) {
+ ERR_MSG("invalid index %u of sb->devs[]\n", opt->idx);
+ ret = -EINVAL;
+ goto out;
+ }
+ if (strlen(opt->str) >= MAX_PATH_LEN) {
+ ERR_MSG("invalid length of option str\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ MSG(0, "Info: inject devs[%d].path of sb %d: %s -> %s\n",
+ opt->idx, opt->sb, (char *)sb->devs[opt->idx].path, opt->str);
+ strcpy((char *)sb->devs[opt->idx].path, opt->str);
+ } else {
+ ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ print_raw_sb_info(sb);
+ update_superblock(sb, SB_MASK((u32)opt->sb - 1));
+
+out:
+ free(buf);
+ free(opt->str);
+ return ret;
+}
+
int do_inject(struct f2fs_sb_info *sbi)
{
+ struct inject_option *opt = (struct inject_option *)c.private;
int ret = -EINVAL;
+ if (opt->sb >= 0)
+ ret = inject_sb(sbi, opt);
+
return ret;
}
diff --git a/fsck/inject.h b/fsck/inject.h
index 62543c1..c7d0e33 100644
--- a/fsck/inject.h
+++ b/fsck/inject.h
@@ -20,6 +20,11 @@
#include "fsck.h"
struct inject_option {
+ const char *mb; /* member name */
+ unsigned int idx; /* slot index */
+ long long val; /* new value */
+ char *str; /* new string */
+ int sb; /* which sb */
};
void inject_usage(void);
diff --git a/fsck/main.c b/fsck/main.c
index eca09aa..40edf35 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -822,7 +822,10 @@ void f2fs_parse_options(int argc, char *argv[])
#endif /* WITH_LABEL */
} else if (!strcmp("inject.f2fs", prog)) {
#ifdef WITH_INJECT
- static struct inject_option inject_opt;
+ static struct inject_option inject_opt = {
+ .sb = -1,
+ .idx = -1,
+ };
err = inject_parse_options(argc, argv, &inject_opt);
if (err < 0) {
diff --git a/fsck/mount.c b/fsck/mount.c
index 8524335..77e3919 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -1212,7 +1212,7 @@ int init_sb_info(struct f2fs_sb_info *sbi)
c.devices[i].path = strdup((char *)sb->devs[i].path);
if (get_device_info(i))
ASSERT(0);
- } else {
+ } else if (c.func != INJECT) {
ASSERT(!strcmp((char *)sb->devs[i].path,
(char *)c.devices[i].path));
}
@@ -4018,7 +4018,7 @@ int f2fs_do_mount(struct f2fs_sb_info *sbi)
}
cp = F2FS_CKPT(sbi);
- if (c.func != FSCK && c.func != DUMP &&
+ if (c.func != FSCK && c.func != DUMP && c.func != INJECT &&
!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG)) {
ERR_MSG("Mount unclean image to replay log first\n");
return -1;
--
2.40.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [f2fs-dev] [RCF PATCH v3 03/10] inject.f2fs: add sb injection
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 03/10] inject.f2fs: add sb injection Sheng Yong via Linux-f2fs-devel
@ 2024-07-04 3:39 ` Chao Yu
0 siblings, 0 replies; 19+ messages in thread
From: Chao Yu @ 2024-07-04 3:39 UTC (permalink / raw)
To: Sheng Yong, jaegeuk; +Cc: linux-f2fs-devel
On 2024/7/4 10:57, Sheng Yong wrote:
> This patch enables injecting super block.
>
> The meanings of options are:
> * sb: means sb is injected, its argument chooses which sb pack to be
> injected, where 0 means the current valid sb is choosen
> automatically.
> * mb: indicates which member in sb is injected, its argument is the
> member name.
> * idx: is used when the mb is an array, its argument is the index of
> the array.
> * val: is the new value to be set when the type of mb is a number.
> * str: is the new value to be set when the type of mb is a string.
>
> The members could be injected in sb contains:
> * magic: magic number
> * s_stop_reason: s_stop_reason array
> * s_errors: s_errors array
> * devs.path: path in devs array
>
> Signed-off-by: Sheng Yong <shengyong@oppo.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Thanks,
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 19+ messages in thread
* [f2fs-dev] [RCF PATCH v3 04/10] inject.f2fs: add cp injection
2024-07-04 2:57 [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
` (2 preceding siblings ...)
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 03/10] inject.f2fs: add sb injection Sheng Yong via Linux-f2fs-devel
@ 2024-07-04 2:57 ` Sheng Yong via Linux-f2fs-devel
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 05/10] inject.f2fs: add nat injection Sheng Yong via Linux-f2fs-devel
` (7 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Sheng Yong via Linux-f2fs-devel @ 2024-07-04 2:57 UTC (permalink / raw)
To: chao, jaegeuk; +Cc: linux-f2fs-devel
This patch enables injecting checkpoint. To archive this, a helper
write_raw_cp_blocks() is added to write the first and last blocks
of a specific cp. And print_ckpt_info() is exported to show new
checkpoint info.
The meanings of options are:
* cp: means cp is injected, its argument chooses which cp pack to be
injected, where 0 means the current valid cp is choosen
automatically.
The members could be injected in cp contains:
* checkpoint_ver: checkpoint version
* ckpt_flags: checkpoint flags
* cur_node_segno: cur_node_segno array
* cur_node_blkoff: cur_node_blkoff array
* cur_data_segno: cur_data_segno array
* cur_data_blkoff: cur_data_blkoff array
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Sheng Yong <shengyong@oppo.com>
---
fsck/fsck.h | 3 ++
fsck/inject.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++
fsck/inject.h | 1 +
fsck/main.c | 1 +
fsck/mount.c | 26 +++++++++++
5 files changed, 158 insertions(+)
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 4ca75b3..02986ef 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -236,12 +236,15 @@ extern int find_next_free_block(struct f2fs_sb_info *, u64 *, int, int, bool);
extern void duplicate_checkpoint(struct f2fs_sb_info *);
extern void write_checkpoint(struct f2fs_sb_info *);
extern void write_checkpoints(struct f2fs_sb_info *);
+extern void write_raw_cp_blocks(struct f2fs_sb_info *sbi,
+ struct f2fs_checkpoint *cp, int which);
extern void update_superblock(struct f2fs_super_block *, int);
extern void update_data_blkaddr(struct f2fs_sb_info *, nid_t, u16, block_t,
struct f2fs_node *);
extern void update_nat_blkaddr(struct f2fs_sb_info *, nid_t, nid_t, block_t);
extern void print_raw_sb_info(struct f2fs_super_block *);
+extern void print_ckpt_info(struct f2fs_sb_info *);
extern bool is_checkpoint_stop(struct f2fs_super_block *, bool);
extern bool is_inconsistent_error(struct f2fs_super_block *);
extern pgoff_t current_nat_addr(struct f2fs_sb_info *, nid_t, int *);
diff --git a/fsck/inject.c b/fsck/inject.c
index f29e746..da4356d 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -23,6 +23,7 @@ void inject_usage(void)
MSG(0, " --str <new string> new string to set\n");
MSG(0, " --idx <slot index> which slot is injected in an array\n");
MSG(0, " --sb <0|1|2> --mb <name> [--idx <index>] --val/str <value/string> inject superblock\n");
+ MSG(0, " --cp <0|1|2> --mb <name> [--idx <index>] --val <value> inject checkpoint\n");
MSG(0, " --dry-run do not really inject\n");
exit(1);
@@ -42,6 +43,22 @@ static void inject_sb_usage(void)
MSG(0, " devs.path: inject path in devs array selected by --idx <index> specified by --str <string>\n");
}
+static void inject_cp_usage(void)
+{
+ MSG(0, "inject.f2fs --cp <0|1|2> --mb <name> [--idx <index>] --val <value> inject checkpoint\n");
+ MSG(0, "[cp]:\n");
+ MSG(0, " 0: auto select the current cp pack\n");
+ MSG(0, " 1: select the first cp pack\n");
+ MSG(0, " 2: select the second cp pack\n");
+ MSG(0, "[mb]:\n");
+ MSG(0, " checkpoint_ver: inject checkpoint_ver\n");
+ MSG(0, " ckpt_flags: inject ckpt_flags\n");
+ MSG(0, " cur_node_segno: inject cur_node_segno array selected by --idx <index>\n");
+ MSG(0, " cur_node_blkoff: inject cur_node_blkoff array selected by --idx <index>\n");
+ MSG(0, " cur_data_segno: inject cur_data_segno array selected by --idx <index>\n");
+ MSG(0, " cur_data_blkoff: inject cur_data_blkoff array selected by --idx <index>\n");
+}
+
int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
{
int o = 0;
@@ -55,6 +72,7 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
{"val", required_argument, 0, 4},
{"str", required_argument, 0, 5},
{"sb", required_argument, 0, 6},
+ {"cp", required_argument, 0, 7},
{0, 0, 0, 0}
};
@@ -97,6 +115,14 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
return -ERANGE;
MSG(0, "Info: inject sb %s\n", pack[opt->sb]);
break;
+ case 7:
+ if (!is_digits(optarg))
+ return EWRONG_OPT;
+ opt->cp = atoi(optarg);
+ if (opt->cp < 0 || opt->cp > 2)
+ return -ERANGE;
+ MSG(0, "Info: inject cp pack %s\n", pack[opt->cp]);
+ break;
case 'd':
if (optarg[0] == '-' || !is_digits(optarg))
return EWRONG_OPT;
@@ -111,6 +137,9 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
if (opt->sb >= 0) {
inject_sb_usage();
exit(0);
+ } else if (opt->cp >= 0) {
+ inject_cp_usage();
+ exit(0);
}
return EUNKNOWN_OPT;
}
@@ -190,6 +219,102 @@ out:
return ret;
}
+static int inject_cp(struct f2fs_sb_info *sbi, struct inject_option *opt)
+{
+ struct f2fs_checkpoint *cp, *cur_cp = F2FS_CKPT(sbi);
+ char *buf = NULL;
+ int ret = 0;
+
+ if (opt->cp == 0)
+ opt->cp = sbi->cur_cp;
+
+ if (opt->cp != sbi->cur_cp) {
+ struct f2fs_super_block *sb = sbi->raw_super;
+ block_t cp_addr;
+
+ buf = calloc(1, F2FS_BLKSIZE);
+ ASSERT(buf != NULL);
+
+ cp_addr = get_sb(cp_blkaddr);
+ if (opt->cp == 2)
+ cp_addr += 1 << get_sb(log_blocks_per_seg);
+ ret = dev_read_block(buf, cp_addr);
+ ASSERT(ret >= 0);
+
+ cp = (struct f2fs_checkpoint *)buf;
+ sbi->ckpt = cp;
+ sbi->cur_cp = opt->cp;
+ } else {
+ cp = cur_cp;
+ }
+
+ if (!strcmp(opt->mb, "checkpoint_ver")) {
+ MSG(0, "Info: inject checkpoint_ver of cp %d: 0x%llx -> 0x%lx\n",
+ opt->cp, get_cp(checkpoint_ver), (u64)opt->val);
+ set_cp(checkpoint_ver, (u64)opt->val);
+ } else if (!strcmp(opt->mb, "ckpt_flags")) {
+ MSG(0, "Info: inject ckpt_flags of cp %d: 0x%x -> 0x%x\n",
+ opt->cp, get_cp(ckpt_flags), (u32)opt->val);
+ set_cp(ckpt_flags, (u32)opt->val);
+ } else if (!strcmp(opt->mb, "cur_node_segno")) {
+ if (opt->idx >= MAX_ACTIVE_NODE_LOGS) {
+ ERR_MSG("invalid index %u of cp->cur_node_segno[]\n",
+ opt->idx);
+ ret = -EINVAL;
+ goto out;
+ }
+ MSG(0, "Info: inject cur_node_segno[%d] of cp %d: 0x%x -> 0x%x\n",
+ opt->idx, opt->cp, get_cp(cur_node_segno[opt->idx]),
+ (u32)opt->val);
+ set_cp(cur_node_segno[opt->idx], (u32)opt->val);
+ } else if (!strcmp(opt->mb, "cur_node_blkoff")) {
+ if (opt->idx >= MAX_ACTIVE_NODE_LOGS) {
+ ERR_MSG("invalid index %u of cp->cur_node_blkoff[]\n",
+ opt->idx);
+ ret = -EINVAL;
+ goto out;
+ }
+ MSG(0, "Info: inject cur_node_blkoff[%d] of cp %d: 0x%x -> 0x%x\n",
+ opt->idx, opt->cp, get_cp(cur_node_blkoff[opt->idx]),
+ (u16)opt->val);
+ set_cp(cur_node_blkoff[opt->idx], (u16)opt->val);
+ } else if (!strcmp(opt->mb, "cur_data_segno")) {
+ if (opt->idx >= MAX_ACTIVE_DATA_LOGS) {
+ ERR_MSG("invalid index %u of cp->cur_data_segno[]\n",
+ opt->idx);
+ ret = -EINVAL;
+ goto out;
+ }
+ MSG(0, "Info: inject cur_data_segno[%d] of cp %d: 0x%x -> 0x%x\n",
+ opt->idx, opt->cp, get_cp(cur_data_segno[opt->idx]),
+ (u32)opt->val);
+ set_cp(cur_data_segno[opt->idx], (u32)opt->val);
+ } else if (!strcmp(opt->mb, "cur_data_blkoff")) {
+ if (opt->idx >= MAX_ACTIVE_DATA_LOGS) {
+ ERR_MSG("invalid index %u of cp->cur_data_blkoff[]\n",
+ opt->idx);
+ ret = -EINVAL;
+ goto out;
+ }
+ MSG(0, "Info: inject cur_data_blkoff[%d] of cp %d: 0x%x -> 0x%x\n",
+ opt->idx, opt->cp, get_cp(cur_data_blkoff[opt->idx]),
+ (u16)opt->val);
+ set_cp(cur_data_blkoff[opt->idx], (u16)opt->val);
+ } else {
+ ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ print_ckpt_info(sbi);
+ write_raw_cp_blocks(sbi, cp, opt->cp);
+
+out:
+ free(buf);
+ sbi->ckpt = cur_cp;
+ return ret;
+}
+
int do_inject(struct f2fs_sb_info *sbi)
{
struct inject_option *opt = (struct inject_option *)c.private;
@@ -197,6 +322,8 @@ int do_inject(struct f2fs_sb_info *sbi)
if (opt->sb >= 0)
ret = inject_sb(sbi, opt);
+ else if (opt->cp >= 0)
+ ret = inject_cp(sbi, opt);
return ret;
}
diff --git a/fsck/inject.h b/fsck/inject.h
index c7d0e33..907309f 100644
--- a/fsck/inject.h
+++ b/fsck/inject.h
@@ -25,6 +25,7 @@ struct inject_option {
long long val; /* new value */
char *str; /* new string */
int sb; /* which sb */
+ int cp; /* which cp */
};
void inject_usage(void);
diff --git a/fsck/main.c b/fsck/main.c
index 40edf35..da58f0c 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -824,6 +824,7 @@ void f2fs_parse_options(int argc, char *argv[])
#ifdef WITH_INJECT
static struct inject_option inject_opt = {
.sb = -1,
+ .cp = -1,
.idx = -1,
};
diff --git a/fsck/mount.c b/fsck/mount.c
index 77e3919..77b6144 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -3426,6 +3426,32 @@ void write_checkpoints(struct f2fs_sb_info *sbi)
write_checkpoint(sbi);
}
+void write_raw_cp_blocks(struct f2fs_sb_info *sbi,
+ struct f2fs_checkpoint *cp, int which)
+{
+ struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
+ uint32_t crc;
+ block_t cp_blkaddr;
+ int ret;
+
+ crc = f2fs_checkpoint_chksum(cp);
+ *((__le32 *)((unsigned char *)cp + get_cp(checksum_offset))) =
+ cpu_to_le32(crc);
+
+ cp_blkaddr = get_sb(cp_blkaddr);
+ if (which == 2)
+ cp_blkaddr += 1 << get_sb(log_blocks_per_seg);
+
+ /* write the first cp block in this CP pack */
+ ret = dev_write_block(cp, cp_blkaddr);
+ ASSERT(ret >= 0);
+
+ /* write the second cp block in this CP pack */
+ cp_blkaddr += get_cp(cp_pack_total_block_count) - 1;
+ ret = dev_write_block(cp, cp_blkaddr);
+ ASSERT(ret >= 0);
+}
+
void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
{
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
--
2.40.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 19+ messages in thread* [f2fs-dev] [RCF PATCH v3 05/10] inject.f2fs: add nat injection
2024-07-04 2:57 [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
` (3 preceding siblings ...)
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 04/10] inject.f2fs: add cp injection Sheng Yong via Linux-f2fs-devel
@ 2024-07-04 2:57 ` Sheng Yong via Linux-f2fs-devel
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 06/10] inject.f2fs: add sit injection Sheng Yong via Linux-f2fs-devel
` (6 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Sheng Yong via Linux-f2fs-devel @ 2024-07-04 2:57 UTC (permalink / raw)
To: chao, jaegeuk; +Cc: linux-f2fs-devel
This patch enables injecting nat entry. print_raw_nat_entry_info() is
added to show values of the nat entry.
The meanings of options are:
* nat: means nat entry is injected, its argument chooses which nat pack
to be injected, where 0 means the current valid nat is choosen
automatically.
* nid: is the nid of the nat entry
The members could be injected in cp contains:
* version: nat entry version
* ino: nat entry ino
* block_addr: nat entry block_addr
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Sheng Yong <shengyong@oppo.com>
---
fsck/inject.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++
fsck/inject.h | 2 +
fsck/main.c | 2 +
3 files changed, 126 insertions(+)
diff --git a/fsck/inject.c b/fsck/inject.c
index da4356d..b6f5c59 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -12,6 +12,16 @@
#include <getopt.h>
#include "inject.h"
+static void print_raw_nat_entry_info(struct f2fs_nat_entry *ne)
+{
+ if (!c.dbg_lv)
+ return;
+
+ DISP_u8(ne, version);
+ DISP_u32(ne, ino);
+ DISP_u32(ne, block_addr);
+}
+
void inject_usage(void)
{
MSG(0, "\nUsage: inject.f2fs [options] device\n");
@@ -22,8 +32,10 @@ void inject_usage(void)
MSG(0, " --val <new value> new value to set\n");
MSG(0, " --str <new string> new string to set\n");
MSG(0, " --idx <slot index> which slot is injected in an array\n");
+ MSG(0, " --nid <nid> which nid is injected\n");
MSG(0, " --sb <0|1|2> --mb <name> [--idx <index>] --val/str <value/string> inject superblock\n");
MSG(0, " --cp <0|1|2> --mb <name> [--idx <index>] --val <value> inject checkpoint\n");
+ MSG(0, " --nat <0|1|2> --mb <name> --nid <nid> --val <value> inject nat entry\n");
MSG(0, " --dry-run do not really inject\n");
exit(1);
@@ -59,6 +71,19 @@ static void inject_cp_usage(void)
MSG(0, " cur_data_blkoff: inject cur_data_blkoff array selected by --idx <index>\n");
}
+static void inject_nat_usage(void)
+{
+ MSG(0, "inject.f2fs --nat <0|1|2> --mb <name> --nid <nid> --val <value> inject nat entry\n");
+ MSG(0, "[nat]:\n");
+ MSG(0, " 0: auto select the current nat pack\n");
+ MSG(0, " 1: select the first nat pack\n");
+ MSG(0, " 2: select the second nat pack\n");
+ MSG(0, "[mb]:\n");
+ MSG(0, " version: inject nat entry version\n");
+ MSG(0, " ino: inject nat entry ino\n");
+ MSG(0, " block_addr: inject nat entry block_addr\n");
+}
+
int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
{
int o = 0;
@@ -73,6 +98,8 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
{"str", required_argument, 0, 5},
{"sb", required_argument, 0, 6},
{"cp", required_argument, 0, 7},
+ {"nat", required_argument, 0, 8},
+ {"nid", required_argument, 0, 9},
{0, 0, 0, 0}
};
@@ -123,6 +150,21 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
return -ERANGE;
MSG(0, "Info: inject cp pack %s\n", pack[opt->cp]);
break;
+ case 8:
+ if (!is_digits(optarg))
+ return EWRONG_OPT;
+ opt->nat = atoi(optarg);
+ if (opt->nat < 0 || opt->nat > 2)
+ return -ERANGE;
+ MSG(0, "Info: inject nat pack %s\n", pack[opt->nat]);
+ break;
+ case 9:
+ opt->nid = strtol(optarg, &endptr, 0);
+ if (opt->nid == LONG_MAX || opt->nid == LONG_MIN ||
+ *endptr != '\0')
+ return -ERANGE;
+ MSG(0, "Info: inject nid %u : 0x%x\n", opt->nid, opt->nid);
+ break;
case 'd':
if (optarg[0] == '-' || !is_digits(optarg))
return EWRONG_OPT;
@@ -140,6 +182,9 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
} else if (opt->cp >= 0) {
inject_cp_usage();
exit(0);
+ } else if (opt->nat >= 0) {
+ inject_nat_usage();
+ exit(0);
}
return EUNKNOWN_OPT;
}
@@ -315,6 +360,81 @@ out:
return ret;
}
+static int inject_nat(struct f2fs_sb_info *sbi, struct inject_option *opt)
+{
+ struct f2fs_nm_info *nm_i = NM_I(sbi);
+ struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
+ struct f2fs_nat_block *nat_blk;
+ struct f2fs_nat_entry *ne;
+ block_t blk_addr;
+ unsigned int offs;
+ bool is_set;
+ int ret;
+
+ if (!IS_VALID_NID(sbi, opt->nid)) {
+ ERR_MSG("Invalid nid %u range [%u:%lu]\n", opt->nid, 0,
+ NAT_ENTRY_PER_BLOCK *
+ ((get_sb(segment_count_nat) << 1) <<
+ sbi->log_blocks_per_seg));
+ return -EINVAL;
+ }
+
+ nat_blk = calloc(F2FS_BLKSIZE, 1);
+ ASSERT(nat_blk);
+
+ /* change NAT version bitmap temporarily to select specified pack */
+ is_set = f2fs_test_bit(opt->nid, nm_i->nat_bitmap);
+ if (opt->nat == 0) {
+ opt->nat = is_set ? 2 : 1;
+ } else {
+ if (opt->nat == 1)
+ f2fs_clear_bit(opt->nid, nm_i->nat_bitmap);
+ else
+ f2fs_set_bit(opt->nid, nm_i->nat_bitmap);
+ }
+
+ blk_addr = current_nat_addr(sbi, opt->nid, NULL);
+
+ ret = dev_read_block(nat_blk, blk_addr);
+ ASSERT(ret >= 0);
+
+ offs = opt->nid % NAT_ENTRY_PER_BLOCK;
+ ne = &nat_blk->entries[offs];
+
+ if (!strcmp(opt->mb, "version")) {
+ MSG(0, "Info: inject nat entry version of nid %u "
+ "in pack %d: %d -> %d\n", opt->nid, opt->nat,
+ ne->version, (u8)opt->val);
+ ne->version = (u8)opt->val;
+ } else if (!strcmp(opt->mb, "ino")) {
+ MSG(0, "Info: inject nat entry ino of nid %u "
+ "in pack %d: %d -> %d\n", opt->nid, opt->nat,
+ le32_to_cpu(ne->ino), (nid_t)opt->val);
+ ne->ino = cpu_to_le32((nid_t)opt->val);
+ } else if (!strcmp(opt->mb, "block_addr")) {
+ MSG(0, "Info: inject nat entry block_addr of nid %u "
+ "in pack %d: 0x%x -> 0x%x\n", opt->nid, opt->nat,
+ le32_to_cpu(ne->block_addr), (block_t)opt->val);
+ ne->block_addr = cpu_to_le32((block_t)opt->val);
+ } else {
+ ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
+ free(nat_blk);
+ return -EINVAL;
+ }
+ print_raw_nat_entry_info(ne);
+
+ ret = dev_write_block(nat_blk, blk_addr);
+ ASSERT(ret >= 0);
+ /* restore NAT version bitmap */
+ if (is_set)
+ f2fs_set_bit(opt->nid, nm_i->nat_bitmap);
+ else
+ f2fs_clear_bit(opt->nid, nm_i->nat_bitmap);
+
+ free(nat_blk);
+ return ret;
+}
+
int do_inject(struct f2fs_sb_info *sbi)
{
struct inject_option *opt = (struct inject_option *)c.private;
@@ -324,6 +444,8 @@ int do_inject(struct f2fs_sb_info *sbi)
ret = inject_sb(sbi, opt);
else if (opt->cp >= 0)
ret = inject_cp(sbi, opt);
+ else if (opt->nat >= 0)
+ ret = inject_nat(sbi, opt);
return ret;
}
diff --git a/fsck/inject.h b/fsck/inject.h
index 907309f..db45fb9 100644
--- a/fsck/inject.h
+++ b/fsck/inject.h
@@ -24,8 +24,10 @@ struct inject_option {
unsigned int idx; /* slot index */
long long val; /* new value */
char *str; /* new string */
+ nid_t nid;
int sb; /* which sb */
int cp; /* which cp */
+ int nat; /* which nat pack */
};
void inject_usage(void);
diff --git a/fsck/main.c b/fsck/main.c
index da58f0c..8527199 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -825,7 +825,9 @@ void f2fs_parse_options(int argc, char *argv[])
static struct inject_option inject_opt = {
.sb = -1,
.cp = -1,
+ .nat = -1,
.idx = -1,
+ .nid = -1,
};
err = inject_parse_options(argc, argv, &inject_opt);
--
2.40.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 19+ messages in thread* [f2fs-dev] [RCF PATCH v3 06/10] inject.f2fs: add sit injection
2024-07-04 2:57 [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
` (4 preceding siblings ...)
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 05/10] inject.f2fs: add nat injection Sheng Yong via Linux-f2fs-devel
@ 2024-07-04 2:57 ` Sheng Yong via Linux-f2fs-devel
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 07/10] inject.f2fs: add ssa injection Sheng Yong via Linux-f2fs-devel
` (5 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Sheng Yong via Linux-f2fs-devel @ 2024-07-04 2:57 UTC (permalink / raw)
To: chao, jaegeuk; +Cc: linux-f2fs-devel
This patch enables injecting sit entry. print_raw_sit_entry_info() is
added to show values of the sit entry.
The meanings of options are:
* sit: means sit entry is injected, its argument chooses which sit pack
to be injected, where 0 means the current valid sit is choosen
automatically.
* blk: is the block address of the sit entry.
The members could be injected in cp contains:
* vblocks: sit entry vblocks
* valid_map: sit entry valid_map
* mtime: sit entry mtime
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Sheng Yong <shengyong@oppo.com>
---
fsck/inject.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++
fsck/inject.h | 2 +
fsck/main.c | 1 +
3 files changed, 136 insertions(+)
diff --git a/fsck/inject.c b/fsck/inject.c
index b6f5c59..5799353 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -22,6 +22,27 @@ static void print_raw_nat_entry_info(struct f2fs_nat_entry *ne)
DISP_u32(ne, block_addr);
}
+static void print_raw_sit_entry_info(struct f2fs_sit_entry *se)
+{
+ int i;
+
+ if (!c.dbg_lv)
+ return;
+
+ DISP_u16(se, vblocks);
+ if (c.layout)
+ printf("%-30s ", "valid_map:");
+ else
+ printf("%-30s\t\t[", "valid_map");
+ for (i = 0; i < SIT_VBLOCK_MAP_SIZE; i++)
+ printf("%02x", se->valid_map[i]);
+ if (c.layout)
+ printf("\n");
+ else
+ printf("]\n");
+ DISP_u64(se, mtime);
+}
+
void inject_usage(void)
{
MSG(0, "\nUsage: inject.f2fs [options] device\n");
@@ -33,9 +54,11 @@ void inject_usage(void)
MSG(0, " --str <new string> new string to set\n");
MSG(0, " --idx <slot index> which slot is injected in an array\n");
MSG(0, " --nid <nid> which nid is injected\n");
+ MSG(0, " --blk <blkaddr> which blkaddr is injected\n");
MSG(0, " --sb <0|1|2> --mb <name> [--idx <index>] --val/str <value/string> inject superblock\n");
MSG(0, " --cp <0|1|2> --mb <name> [--idx <index>] --val <value> inject checkpoint\n");
MSG(0, " --nat <0|1|2> --mb <name> --nid <nid> --val <value> inject nat entry\n");
+ MSG(0, " --sit <0|1|2> --mb <name> --blk <blk> [--idx <index>] --val <value> inject sit entry\n");
MSG(0, " --dry-run do not really inject\n");
exit(1);
@@ -84,6 +107,19 @@ static void inject_nat_usage(void)
MSG(0, " block_addr: inject nat entry block_addr\n");
}
+static void inject_sit_usage(void)
+{
+ MSG(0, "inject.f2fs --sit <0|1|2> --mb <name> --blk <blk> [--idx <index>] --val <value> inject sit entry\n");
+ MSG(0, "[sit]:\n");
+ MSG(0, " 0: auto select the current sit pack\n");
+ MSG(0, " 1: select the first sit pack\n");
+ MSG(0, " 2: select the second sit pack\n");
+ MSG(0, "[mb]:\n");
+ MSG(0, " vblocks: inject sit entry vblocks\n");
+ MSG(0, " valid_map: inject sit entry valid_map\n");
+ MSG(0, " mtime: inject sit entry mtime\n");
+}
+
int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
{
int o = 0;
@@ -100,6 +136,8 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
{"cp", required_argument, 0, 7},
{"nat", required_argument, 0, 8},
{"nid", required_argument, 0, 9},
+ {"sit", required_argument, 0, 10},
+ {"blk", required_argument, 0, 11},
{0, 0, 0, 0}
};
@@ -165,6 +203,21 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
return -ERANGE;
MSG(0, "Info: inject nid %u : 0x%x\n", opt->nid, opt->nid);
break;
+ case 10:
+ if (!is_digits(optarg))
+ return EWRONG_OPT;
+ opt->sit = atoi(optarg);
+ if (opt->sit < 0 || opt->sit > 2)
+ return -ERANGE;
+ MSG(0, "Info: inject sit pack %s\n", pack[opt->sit]);
+ break;
+ case 11:
+ opt->blk = strtol(optarg, &endptr, 0);
+ if (opt->blk == LONG_MAX || opt->blk == LONG_MIN ||
+ *endptr != '\0')
+ return -ERANGE;
+ MSG(0, "Info: inject blkaddr %u : 0x%x\n", opt->blk, opt->blk);
+ break;
case 'd':
if (optarg[0] == '-' || !is_digits(optarg))
return EWRONG_OPT;
@@ -185,6 +238,9 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
} else if (opt->nat >= 0) {
inject_nat_usage();
exit(0);
+ } else if (opt->sit >= 0) {
+ inject_sit_usage();
+ exit(0);
}
return EUNKNOWN_OPT;
}
@@ -435,6 +491,81 @@ static int inject_nat(struct f2fs_sb_info *sbi, struct inject_option *opt)
return ret;
}
+static int inject_sit(struct f2fs_sb_info *sbi, struct inject_option *opt)
+{
+ struct sit_info *sit_i = SIT_I(sbi);
+ struct f2fs_sit_block *sit_blk;
+ struct f2fs_sit_entry *sit;
+ unsigned int segno, offs;
+ bool is_set;
+
+ if (!f2fs_is_valid_blkaddr(sbi, opt->blk, DATA_GENERIC)) {
+ ERR_MSG("Invalid blkaddr 0x%x (valid range [0x%x:0x%lx])\n",
+ opt->blk, SM_I(sbi)->main_blkaddr,
+ (unsigned long)le64_to_cpu(F2FS_RAW_SUPER(sbi)->block_count));
+ return -EINVAL;
+ }
+
+ sit_blk = calloc(F2FS_BLKSIZE, 1);
+ ASSERT(sit_blk);
+
+ segno = GET_SEGNO(sbi, opt->blk);
+ /* change SIT version bitmap temporarily to select specified pack */
+ is_set = f2fs_test_bit(segno, sit_i->sit_bitmap);
+ if (opt->sit == 0) {
+ opt->sit = is_set ? 2 : 1;
+ } else {
+ if (opt->sit == 1)
+ f2fs_clear_bit(segno, sit_i->sit_bitmap);
+ else
+ f2fs_set_bit(segno, sit_i->sit_bitmap);
+ }
+ get_current_sit_page(sbi, segno, sit_blk);
+ offs = SIT_ENTRY_OFFSET(sit_i, segno);
+ sit = &sit_blk->entries[offs];
+
+ if (!strcmp(opt->mb, "vblocks")) {
+ MSG(0, "Info: inject sit entry vblocks of block 0x%x "
+ "in pack %d: %u -> %u\n", opt->blk, opt->sit,
+ le16_to_cpu(sit->vblocks), (u16)opt->val);
+ sit->vblocks = cpu_to_le16((u16)opt->val);
+ } else if (!strcmp(opt->mb, "valid_map")) {
+ if (opt->idx == -1) {
+ MSG(0, "Info: auto idx = %u\n", offs);
+ opt->idx = offs;
+ }
+ if (opt->idx >= SIT_VBLOCK_MAP_SIZE) {
+ ERR_MSG("invalid idx %u of valid_map[]\n", opt->idx);
+ free(sit_blk);
+ return -ERANGE;
+ }
+ MSG(0, "Info: inject sit entry valid_map[%d] of block 0x%x "
+ "in pack %d: 0x%02x -> 0x%02x\n", opt->idx, opt->blk,
+ opt->sit, sit->valid_map[opt->idx], (u8)opt->val);
+ sit->valid_map[opt->idx] = (u8)opt->val;
+ } else if (!strcmp(opt->mb, "mtime")) {
+ MSG(0, "Info: inject sit entry mtime of block 0x%x "
+ "in pack %d: %lu -> %lu\n", opt->blk, opt->sit,
+ le64_to_cpu(sit->mtime), (u64)opt->val);
+ sit->mtime = cpu_to_le64((u64)opt->val);
+ } else {
+ ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
+ free(sit_blk);
+ return -EINVAL;
+ }
+ print_raw_sit_entry_info(sit);
+
+ rewrite_current_sit_page(sbi, segno, sit_blk);
+ /* restore SIT version bitmap */
+ if (is_set)
+ f2fs_set_bit(segno, sit_i->sit_bitmap);
+ else
+ f2fs_clear_bit(segno, sit_i->sit_bitmap);
+
+ free(sit_blk);
+ return 0;
+}
+
int do_inject(struct f2fs_sb_info *sbi)
{
struct inject_option *opt = (struct inject_option *)c.private;
@@ -446,6 +577,8 @@ int do_inject(struct f2fs_sb_info *sbi)
ret = inject_cp(sbi, opt);
else if (opt->nat >= 0)
ret = inject_nat(sbi, opt);
+ else if (opt->sit >= 0)
+ ret = inject_sit(sbi, opt);
return ret;
}
diff --git a/fsck/inject.h b/fsck/inject.h
index db45fb9..ece4915 100644
--- a/fsck/inject.h
+++ b/fsck/inject.h
@@ -25,9 +25,11 @@ struct inject_option {
long long val; /* new value */
char *str; /* new string */
nid_t nid;
+ block_t blk;
int sb; /* which sb */
int cp; /* which cp */
int nat; /* which nat pack */
+ int sit; /* which sit pack */
};
void inject_usage(void);
diff --git a/fsck/main.c b/fsck/main.c
index 8527199..bfdb5ba 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -826,6 +826,7 @@ void f2fs_parse_options(int argc, char *argv[])
.sb = -1,
.cp = -1,
.nat = -1,
+ .sit = -1,
.idx = -1,
.nid = -1,
};
--
2.40.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 19+ messages in thread* [f2fs-dev] [RCF PATCH v3 07/10] inject.f2fs: add ssa injection
2024-07-04 2:57 [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
` (5 preceding siblings ...)
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 06/10] inject.f2fs: add sit injection Sheng Yong via Linux-f2fs-devel
@ 2024-07-04 2:57 ` Sheng Yong via Linux-f2fs-devel
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 08/10] inject.f2fs: add node injection Sheng Yong via Linux-f2fs-devel
` (4 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Sheng Yong via Linux-f2fs-devel @ 2024-07-04 2:57 UTC (permalink / raw)
To: chao, jaegeuk; +Cc: linux-f2fs-devel
This patch enables injecting summary block or summary entry.
print_raw_sum_entry_info() and print_sum_footer_info() are added to show
values of the ssa entry and summary footer.
The meanings of options are:
* ssa: means ssa entry is injected.
The members could be injected in cp contains:
* entry_type: summary block footer entry_type
* check_sum: summary block footer check_sum
* nid: summary entry nid
* version: summary entry version
* ofs_in_node: summary entry ofs_in_node
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Sheng Yong <shengyong@oppo.com>
---
fsck/inject.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++
fsck/inject.h | 1 +
2 files changed, 124 insertions(+)
diff --git a/fsck/inject.c b/fsck/inject.c
index 5799353..d6f8774 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -43,6 +43,25 @@ static void print_raw_sit_entry_info(struct f2fs_sit_entry *se)
DISP_u64(se, mtime);
}
+static void print_raw_sum_entry_info(struct f2fs_summary *sum)
+{
+ if (!c.dbg_lv)
+ return;
+
+ DISP_u32(sum, nid);
+ DISP_u8(sum, version);
+ DISP_u16(sum, ofs_in_node);
+}
+
+static void print_sum_footer_info(struct summary_footer *footer)
+{
+ if (!c.dbg_lv)
+ return;
+
+ DISP_u8(footer, entry_type);
+ DISP_u32(footer, check_sum);
+}
+
void inject_usage(void)
{
MSG(0, "\nUsage: inject.f2fs [options] device\n");
@@ -59,6 +78,7 @@ void inject_usage(void)
MSG(0, " --cp <0|1|2> --mb <name> [--idx <index>] --val <value> inject checkpoint\n");
MSG(0, " --nat <0|1|2> --mb <name> --nid <nid> --val <value> inject nat entry\n");
MSG(0, " --sit <0|1|2> --mb <name> --blk <blk> [--idx <index>] --val <value> inject sit entry\n");
+ MSG(0, " --ssa --mb <name> --blk <blk> [--idx <index>] --val <value> inject summary entry\n");
MSG(0, " --dry-run do not really inject\n");
exit(1);
@@ -120,6 +140,17 @@ static void inject_sit_usage(void)
MSG(0, " mtime: inject sit entry mtime\n");
}
+static void inject_ssa_usage(void)
+{
+ MSG(0, "inject.f2fs --ssa --mb <name> --blk <blk> [--idx <index>] --val <value> inject summary entry\n");
+ MSG(0, "[mb]:\n");
+ MSG(0, " entry_type: inject summary block footer entry_type\n");
+ MSG(0, " check_sum: inject summary block footer check_sum\n");
+ MSG(0, " nid: inject summary entry nid selected by --idx <index\n");
+ MSG(0, " version: inject summary entry version selected by --idx <index\n");
+ MSG(0, " ofs_in_node: inject summary entry ofs_in_node selected by --idx <index\n");
+}
+
int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
{
int o = 0;
@@ -138,6 +169,7 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
{"nid", required_argument, 0, 9},
{"sit", required_argument, 0, 10},
{"blk", required_argument, 0, 11},
+ {"ssa", no_argument, 0, 12},
{0, 0, 0, 0}
};
@@ -218,6 +250,10 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
return -ERANGE;
MSG(0, "Info: inject blkaddr %u : 0x%x\n", opt->blk, opt->blk);
break;
+ case 12:
+ opt->ssa = true;
+ MSG(0, "Info: inject ssa\n");
+ break;
case 'd':
if (optarg[0] == '-' || !is_digits(optarg))
return EWRONG_OPT;
@@ -241,6 +277,9 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
} else if (opt->sit >= 0) {
inject_sit_usage();
exit(0);
+ } else if (opt->ssa) {
+ inject_ssa_usage();
+ exit(0);
}
return EUNKNOWN_OPT;
}
@@ -566,6 +605,88 @@ static int inject_sit(struct f2fs_sb_info *sbi, struct inject_option *opt)
return 0;
}
+static int inject_ssa(struct f2fs_sb_info *sbi, struct inject_option *opt)
+{
+ struct f2fs_summary_block *sum_blk;
+ struct summary_footer *footer;
+ struct f2fs_summary *sum;
+ u32 segno, offset;
+ block_t ssa_blkaddr;
+ int type;
+ int ret;
+
+ if (!f2fs_is_valid_blkaddr(sbi, opt->blk, DATA_GENERIC)) {
+ ERR_MSG("Invalid blkaddr %#x (valid range [%#x:%#lx])\n",
+ opt->blk, SM_I(sbi)->main_blkaddr,
+ (unsigned long)le64_to_cpu(F2FS_RAW_SUPER(sbi)->block_count));
+ return -ERANGE;
+ }
+
+ segno = GET_SEGNO(sbi, opt->blk);
+ offset = OFFSET_IN_SEG(sbi, opt->blk);
+
+ sum_blk = get_sum_block(sbi, segno, &type);
+ sum = &sum_blk->entries[offset];
+ footer = F2FS_SUMMARY_BLOCK_FOOTER(sum_blk);
+
+ if (!strcmp(opt->mb, "entry_type")) {
+ MSG(0, "Info: inject summary block footer entry_type of "
+ "block 0x%x: %d -> %d\n", opt->blk, footer->entry_type,
+ (unsigned char)opt->val);
+ footer->entry_type = (unsigned char)opt->val;
+ } else if (!strcmp(opt->mb, "check_sum")) {
+ MSG(0, "Info: inject summary block footer check_sum of "
+ "block 0x%x: 0x%x -> 0x%x\n", opt->blk,
+ le32_to_cpu(footer->check_sum), (u32)opt->val);
+ footer->check_sum = cpu_to_le32((u32)opt->val);
+ } else {
+ if (opt->idx == -1) {
+ MSG(0, "Info: auto idx = %u\n", offset);
+ opt->idx = offset;
+ }
+ if (opt->idx >= ENTRIES_IN_SUM) {
+ ERR_MSG("invalid idx %u of entries[]\n", opt->idx);
+ ret = -EINVAL;
+ goto out;
+ }
+ sum = &sum_blk->entries[opt->idx];
+ if (!strcmp(opt->mb, "nid")) {
+ MSG(0, "Info: inject summary entry nid of "
+ "block 0x%x: 0x%x -> 0x%x\n", opt->blk,
+ le32_to_cpu(sum->nid), (u32)opt->val);
+ sum->nid = cpu_to_le32((u32)opt->val);
+ } else if (!strcmp(opt->mb, "version")) {
+ MSG(0, "Info: inject summary entry version of "
+ "block 0x%x: %d -> %d\n", opt->blk,
+ sum->version, (u8)opt->val);
+ sum->version = (u8)opt->val;
+ } else if (!strcmp(opt->mb, "ofs_in_node")) {
+ MSG(0, "Info: inject summary entry ofs_in_node of "
+ "block 0x%x: %d -> %d\n", opt->blk,
+ sum->ofs_in_node, (u16)opt->val);
+ sum->ofs_in_node = cpu_to_le16((u16)opt->val);
+ } else {
+ ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ print_raw_sum_entry_info(sum);
+ }
+
+ print_sum_footer_info(footer);
+
+ ssa_blkaddr = GET_SUM_BLKADDR(sbi, segno);
+ ret = dev_write_block(sum_blk, ssa_blkaddr);
+ ASSERT(ret >= 0);
+
+out:
+ if (type == SEG_TYPE_NODE || type == SEG_TYPE_DATA ||
+ type == SEG_TYPE_MAX)
+ free(sum_blk);
+ return ret;
+}
+
int do_inject(struct f2fs_sb_info *sbi)
{
struct inject_option *opt = (struct inject_option *)c.private;
@@ -579,6 +700,8 @@ int do_inject(struct f2fs_sb_info *sbi)
ret = inject_nat(sbi, opt);
else if (opt->sit >= 0)
ret = inject_sit(sbi, opt);
+ else if (opt->ssa)
+ ret = inject_ssa(sbi, opt);
return ret;
}
diff --git a/fsck/inject.h b/fsck/inject.h
index ece4915..c828f3f 100644
--- a/fsck/inject.h
+++ b/fsck/inject.h
@@ -30,6 +30,7 @@ struct inject_option {
int cp; /* which cp */
int nat; /* which nat pack */
int sit; /* which sit pack */
+ bool ssa;
};
void inject_usage(void);
--
2.40.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 19+ messages in thread* [f2fs-dev] [RCF PATCH v3 08/10] inject.f2fs: add node injection
2024-07-04 2:57 [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
` (6 preceding siblings ...)
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 07/10] inject.f2fs: add ssa injection Sheng Yong via Linux-f2fs-devel
@ 2024-07-04 2:57 ` Sheng Yong via Linux-f2fs-devel
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 09/10] inject.f2fs: add dentry injection Sheng Yong via Linux-f2fs-devel
` (3 subsequent siblings)
11 siblings, 0 replies; 19+ messages in thread
From: Sheng Yong via Linux-f2fs-devel @ 2024-07-04 2:57 UTC (permalink / raw)
To: chao, jaegeuk; +Cc: linux-f2fs-devel
This patch enables injecting node block. print_node_footer_info() is
added to show values of node footer.
The meanings of options are:
* node: means node is injected.
The members could be injected in cp contains:
* nid: node footer nid
* ino: node footer ino
* flag: node footer flag
* cp_ver: node footer cp_ver
* next_blkaddr: node footer next_blkaddr
* i_mode: inode i_mode
* i_advise: inode i_advise
* i_inline: inode i_inline
* i_links: inode i_links
* i_size: inode i_size
* i_blocks: inode i_blocks
* i_extra_isize: inode i_extra_isize
* i_inode_checksum: inode i_inode_checksum
* i_addr: inode i_addr array
* i_nid: inode i_nid array
* addr: {in}direct node nid/addr array
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Sheng Yong <shengyong@oppo.com>
---
fsck/inject.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++
fsck/inject.h | 1 +
2 files changed, 214 insertions(+)
diff --git a/fsck/inject.c b/fsck/inject.c
index d6f8774..2a21dae 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -62,6 +62,18 @@ static void print_sum_footer_info(struct summary_footer *footer)
DISP_u32(footer, check_sum);
}
+static void print_node_footer_info(struct node_footer *footer)
+{
+ if (!c.dbg_lv)
+ return;
+
+ DISP_u32(footer, nid);
+ DISP_u32(footer, ino);
+ DISP_u32(footer, flag);
+ DISP_u64(footer, cp_ver);
+ DISP_u32(footer, next_blkaddr);
+}
+
void inject_usage(void)
{
MSG(0, "\nUsage: inject.f2fs [options] device\n");
@@ -79,6 +91,7 @@ void inject_usage(void)
MSG(0, " --nat <0|1|2> --mb <name> --nid <nid> --val <value> inject nat entry\n");
MSG(0, " --sit <0|1|2> --mb <name> --blk <blk> [--idx <index>] --val <value> inject sit entry\n");
MSG(0, " --ssa --mb <name> --blk <blk> [--idx <index>] --val <value> inject summary entry\n");
+ MSG(0, " --node --mb <name> --nid <nid> [--idx <index>] --val <value> inject node\n");
MSG(0, " --dry-run do not really inject\n");
exit(1);
@@ -151,6 +164,28 @@ static void inject_ssa_usage(void)
MSG(0, " ofs_in_node: inject summary entry ofs_in_node selected by --idx <index\n");
}
+static void inject_node_usage(void)
+{
+ MSG(0, "inject.f2fs --node --mb <name> --nid <nid> [--idx <index>] --val <value> inject node\n");
+ MSG(0, "[mb]:\n");
+ MSG(0, " nid: inject node footer nid\n");
+ MSG(0, " ino: inject node footer ino\n");
+ MSG(0, " flag: inject node footer flag\n");
+ MSG(0, " cp_ver: inject node footer cp_ver\n");
+ MSG(0, " next_blkaddr: inject node footer next_blkaddr\n");
+ MSG(0, " i_mode: inject inode i_mode\n");
+ MSG(0, " i_advise: inject inode i_advise\n");
+ MSG(0, " i_inline: inject inode i_inline\n");
+ MSG(0, " i_links: inject inode i_links\n");
+ MSG(0, " i_size: inject inode i_size\n");
+ MSG(0, " i_blocks: inject inode i_blocks\n");
+ MSG(0, " i_extra_isize: inject inode i_extra_isize\n");
+ MSG(0, " i_inode_checksum: inject inode i_inode_checksum\n");
+ MSG(0, " i_addr: inject inode i_addr array selected by --idx <index>\n");
+ MSG(0, " i_nid: inject inode i_nid array selected by --idx <index>\n");
+ MSG(0, " addr: inject {in}direct node nid/addr array selected by --idx <index>\n");
+}
+
int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
{
int o = 0;
@@ -170,6 +205,7 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
{"sit", required_argument, 0, 10},
{"blk", required_argument, 0, 11},
{"ssa", no_argument, 0, 12},
+ {"node", no_argument, 0, 13},
{0, 0, 0, 0}
};
@@ -254,6 +290,10 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
opt->ssa = true;
MSG(0, "Info: inject ssa\n");
break;
+ case 13:
+ opt->node = true;
+ MSG(0, "Info: inject node\n");
+ break;
case 'd':
if (optarg[0] == '-' || !is_digits(optarg))
return EWRONG_OPT;
@@ -280,6 +320,9 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
} else if (opt->ssa) {
inject_ssa_usage();
exit(0);
+ } else if (opt->node) {
+ inject_node_usage();
+ exit(0);
}
return EUNKNOWN_OPT;
}
@@ -687,6 +730,174 @@ out:
return ret;
}
+static int inject_inode(struct f2fs_sb_info *sbi, struct f2fs_node *node,
+ struct inject_option *opt)
+{
+ struct f2fs_inode *inode = &node->i;
+
+ if (!strcmp(opt->mb, "i_mode")) {
+ MSG(0, "Info: inject inode i_mode of nid %u: 0x%x -> 0x%x\n",
+ opt->nid, le16_to_cpu(inode->i_mode), (u16)opt->val);
+ inode->i_mode = cpu_to_le16((u16)opt->val);
+ } else if (!strcmp(opt->mb, "i_advise")) {
+ MSG(0, "Info: inject inode i_advise of nid %u: 0x%x -> 0x%x\n",
+ opt->nid, inode->i_advise, (u8)opt->val);
+ inode->i_advise = (u8)opt->val;
+ } else if (!strcmp(opt->mb, "i_inline")) {
+ MSG(0, "Info: inject inode i_inline of nid %u: 0x%x -> 0x%x\n",
+ opt->nid, inode->i_inline, (u8)opt->val);
+ inode->i_inline = (u8)opt->val;
+ } else if (!strcmp(opt->mb, "i_links")) {
+ MSG(0, "Info: inject inode i_links of nid %u: %u -> %u\n",
+ opt->nid, le32_to_cpu(inode->i_links), (u32)opt->val);
+ inode->i_links = cpu_to_le32((u32)opt->val);
+ } else if (!strcmp(opt->mb, "i_size")) {
+ MSG(0, "Info: inject inode i_size of nid %u: %lu -> %lu\n",
+ opt->nid, le64_to_cpu(inode->i_size), (u64)opt->val);
+ inode->i_size = cpu_to_le64((u64)opt->val);
+ } else if (!strcmp(opt->mb, "i_blocks")) {
+ MSG(0, "Info: inject inode i_blocks of nid %u: %lu -> %lu\n",
+ opt->nid, le64_to_cpu(inode->i_blocks), (u64)opt->val);
+ inode->i_blocks = cpu_to_le64((u64)opt->val);
+ } else if (!strcmp(opt->mb, "i_extra_isize")) {
+ /* do not care if F2FS_EXTRA_ATTR is enabled */
+ MSG(0, "Info: inject inode i_extra_isize of nid %u: %d -> %d\n",
+ opt->nid, le16_to_cpu(inode->i_extra_isize), (u16)opt->val);
+ inode->i_extra_isize = cpu_to_le16((u16)opt->val);
+ } else if (!strcmp(opt->mb, "i_inode_checksum")) {
+ MSG(0, "Info: inject inode i_inode_checksum of nid %u: "
+ "0x%x -> 0x%x\n", opt->nid,
+ le32_to_cpu(inode->i_inode_checksum), (u32)opt->val);
+ inode->i_inode_checksum = cpu_to_le32((u32)opt->val);
+ } else if (!strcmp(opt->mb, "i_addr")) {
+ /* do not care if it is inline data */
+ if (opt->idx >= DEF_ADDRS_PER_INODE) {
+ ERR_MSG("invalid index %u of i_addr[]\n", opt->idx);
+ return -EINVAL;
+ }
+ MSG(0, "Info: inject inode i_addr[%d] of nid %u: "
+ "0x%x -> 0x%x\n", opt->idx, opt->nid,
+ le32_to_cpu(inode->i_addr[opt->idx]), (u32)opt->val);
+ inode->i_addr[opt->idx] = cpu_to_le32((block_t)opt->val);
+ } else if (!strcmp(opt->mb, "i_nid")) {
+ if (opt->idx >= 5) {
+ ERR_MSG("invalid index %u of i_nid[]\n", opt->idx);
+ return -EINVAL;
+ }
+ MSG(0, "Info: inject inode i_nid[%d] of nid %u: "
+ "0x%x -> 0x%x\n", opt->idx, opt->nid,
+ le32_to_cpu(F2FS_INODE_I_NID(inode, opt->idx)),
+ (u32)opt->val);
+ F2FS_INODE_I_NID(inode, opt->idx) = cpu_to_le32((nid_t)opt->val);
+ } else {
+ ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
+ return -EINVAL;
+ }
+
+ if (c.dbg_lv > 0)
+ print_node_info(sbi, node, 1);
+
+ return 0;
+}
+
+static int inject_index_node(struct f2fs_sb_info *sbi, struct f2fs_node *node,
+ struct inject_option *opt)
+{
+ struct direct_node *dn = &node->dn;
+
+ if (strcmp(opt->mb, "addr")) {
+ ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
+ return -EINVAL;
+ }
+
+ if (opt->idx >= DEF_ADDRS_PER_BLOCK) {
+ ERR_MSG("invalid index %u of nid/addr[]\n", opt->idx);
+ return -EINVAL;
+ }
+
+ MSG(0, "Info: inject node nid/addr[%d] of nid %u: 0x%x -> 0x%x\n",
+ opt->idx, opt->nid, le32_to_cpu(dn->addr[opt->idx]),
+ (block_t)opt->val);
+ dn->addr[opt->idx] = cpu_to_le32((block_t)opt->val);
+
+ if (c.dbg_lv > 0)
+ print_node_info(sbi, node, 1);
+
+ return 0;
+}
+
+static int inject_node(struct f2fs_sb_info *sbi, struct inject_option *opt)
+{
+ struct f2fs_super_block *sb = sbi->raw_super;
+ struct node_info ni;
+ struct f2fs_node *node_blk;
+ struct node_footer *footer;
+ int ret;
+
+ if (!IS_VALID_NID(sbi, opt->nid)) {
+ ERR_MSG("Invalid nid %u range [%u:%lu]\n", opt->nid, 0,
+ NAT_ENTRY_PER_BLOCK *
+ ((get_sb(segment_count_nat) << 1) <<
+ sbi->log_blocks_per_seg));
+ return -EINVAL;
+ }
+
+ node_blk = calloc(F2FS_BLKSIZE, 1);
+ ASSERT(node_blk);
+
+ get_node_info(sbi, opt->nid, &ni);
+ ret = dev_read_block(node_blk, ni.blk_addr);
+ ASSERT(ret >= 0);
+ footer = F2FS_NODE_FOOTER(node_blk);
+
+ if (!strcmp(opt->mb, "nid")) {
+ MSG(0, "Info: inject node footer nid of nid %u: %u -> %u\n",
+ opt->nid, le32_to_cpu(footer->nid), (u32)opt->val);
+ footer->nid = cpu_to_le32((u32)opt->val);
+ } else if (!strcmp(opt->mb, "ino")) {
+ MSG(0, "Info: inject node footer ino of nid %u: %u -> %u\n",
+ opt->nid, le32_to_cpu(footer->ino), (u32)opt->val);
+ footer->ino = cpu_to_le32((u32)opt->val);
+ } else if (!strcmp(opt->mb, "flag")) {
+ MSG(0, "Info: inject node footer flag of nid %u: "
+ "0x%x -> 0x%x\n", opt->nid, le32_to_cpu(footer->flag),
+ (u32)opt->val);
+ footer->flag = cpu_to_le32((u32)opt->val);
+ } else if (!strcmp(opt->mb, "cp_ver")) {
+ MSG(0, "Info: inject node footer cp_ver of nid %u: "
+ "0x%lx -> 0x%lx\n", opt->nid, le64_to_cpu(footer->cp_ver),
+ (u64)opt->val);
+ footer->cp_ver = cpu_to_le64((u64)opt->val);
+ } else if (!strcmp(opt->mb, "next_blkaddr")) {
+ MSG(0, "Info: inject node footer next_blkaddr of nid %u: "
+ "0x%x -> 0x%x\n", opt->nid,
+ le32_to_cpu(footer->next_blkaddr), (u32)opt->val);
+ footer->next_blkaddr = cpu_to_le32((u32)opt->val);
+ } else if (ni.nid == ni.ino) {
+ ret = inject_inode(sbi, node_blk, opt);
+ } else {
+ ret = inject_index_node(sbi, node_blk, opt);
+ }
+ if (ret)
+ goto out;
+
+ print_node_footer_info(footer);
+
+ /*
+ * if i_inode_checksum is injected, should call update_block() to
+ * avoid recalculate inode checksum
+ */
+ if (ni.nid == ni.ino && strcmp(opt->mb, "i_inode_checksum"))
+ ret = update_inode(sbi, node_blk, &ni.blk_addr);
+ else
+ ret = update_block(sbi, node_blk, &ni.blk_addr, NULL);
+ ASSERT(ret >= 0);
+
+out:
+ free(node_blk);
+ return ret;
+}
+
int do_inject(struct f2fs_sb_info *sbi)
{
struct inject_option *opt = (struct inject_option *)c.private;
@@ -702,6 +913,8 @@ int do_inject(struct f2fs_sb_info *sbi)
ret = inject_sit(sbi, opt);
else if (opt->ssa)
ret = inject_ssa(sbi, opt);
+ else if (opt->node)
+ ret = inject_node(sbi, opt);
return ret;
}
diff --git a/fsck/inject.h b/fsck/inject.h
index c828f3f..9b14c31 100644
--- a/fsck/inject.h
+++ b/fsck/inject.h
@@ -31,6 +31,7 @@ struct inject_option {
int nat; /* which nat pack */
int sit; /* which sit pack */
bool ssa;
+ bool node;
};
void inject_usage(void);
--
2.40.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 19+ messages in thread* [f2fs-dev] [RCF PATCH v3 09/10] inject.f2fs: add dentry injection
2024-07-04 2:57 [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
` (7 preceding siblings ...)
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 08/10] inject.f2fs: add node injection Sheng Yong via Linux-f2fs-devel
@ 2024-07-04 2:57 ` Sheng Yong via Linux-f2fs-devel
2024-07-04 3:43 ` Chao Yu
2024-09-03 10:14 ` Sheng Yong via Linux-f2fs-devel
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 10/10] man: add inject.f2fs man page Sheng Yong via Linux-f2fs-devel
` (2 subsequent siblings)
11 siblings, 2 replies; 19+ messages in thread
From: Sheng Yong via Linux-f2fs-devel @ 2024-07-04 2:57 UTC (permalink / raw)
To: chao, jaegeuk; +Cc: linux-f2fs-devel
This patch enables injecting dentry block or dir entry.
print_raw_dentry_info() is added to show values of node footer.
The meanings of options are:
* dent: means dentry is injected.
The members could be injected in cp contains:
* d_bitmap: dentry block d_bitmap of nid
* d_hash: dentry hash
* d_ino: dentry ino
* d_ftype: dentry ftype
Signed-off-by: Sheng Yong <shengyong@oppo.com>
---
fsck/inject.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++
fsck/inject.h | 1 +
2 files changed, 185 insertions(+)
diff --git a/fsck/inject.c b/fsck/inject.c
index 2a21dae..a7d2a2c 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -10,6 +10,7 @@
*/
#include <getopt.h>
+#include "node.h"
#include "inject.h"
static void print_raw_nat_entry_info(struct f2fs_nat_entry *ne)
@@ -74,6 +75,17 @@ static void print_node_footer_info(struct node_footer *footer)
DISP_u32(footer, next_blkaddr);
}
+static void print_raw_dentry_info(struct f2fs_dir_entry *dentry)
+{
+ if (!c.dbg_lv)
+ return;
+
+ DISP_u32(dentry, hash_code);
+ DISP_u32(dentry, ino);
+ DISP_u16(dentry, name_len);
+ DISP_u8(dentry, file_type);
+}
+
void inject_usage(void)
{
MSG(0, "\nUsage: inject.f2fs [options] device\n");
@@ -92,6 +104,7 @@ void inject_usage(void)
MSG(0, " --sit <0|1|2> --mb <name> --blk <blk> [--idx <index>] --val <value> inject sit entry\n");
MSG(0, " --ssa --mb <name> --blk <blk> [--idx <index>] --val <value> inject summary entry\n");
MSG(0, " --node --mb <name> --nid <nid> [--idx <index>] --val <value> inject node\n");
+ MSG(0, " --dent --mb <name> --nid <ino> [--idx <index>] --val <value> inject ino's dentry\n");
MSG(0, " --dry-run do not really inject\n");
exit(1);
@@ -186,6 +199,16 @@ static void inject_node_usage(void)
MSG(0, " addr: inject {in}direct node nid/addr array selected by --idx <index>\n");
}
+static void inject_dent_usage(void)
+{
+ MSG(0, "inject.f2fs --dent --mb <name> --nid <nid> [--idx <index>] --val <value> inject dentry\n");
+ MSG(0, "[mb]:\n");
+ MSG(0, " d_bitmap: inject dentry block d_bitmap of nid\n");
+ MSG(0, " d_hash: inject dentry hash\n");
+ MSG(0, " d_ino: inject dentry ino\n");
+ MSG(0, " d_ftype: inject dentry ftype\n");
+}
+
int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
{
int o = 0;
@@ -206,6 +229,7 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
{"blk", required_argument, 0, 11},
{"ssa", no_argument, 0, 12},
{"node", no_argument, 0, 13},
+ {"dent", no_argument, 0, 14},
{0, 0, 0, 0}
};
@@ -294,6 +318,10 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
opt->node = true;
MSG(0, "Info: inject node\n");
break;
+ case 14:
+ opt->dent = true;
+ MSG(0, "Info: inject dentry\n");
+ break;
case 'd':
if (optarg[0] == '-' || !is_digits(optarg))
return EWRONG_OPT;
@@ -323,6 +351,9 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
} else if (opt->node) {
inject_node_usage();
exit(0);
+ } else if (opt->dent) {
+ inject_dent_usage();
+ exit(0);
}
return EUNKNOWN_OPT;
}
@@ -898,6 +929,157 @@ out:
return ret;
}
+static int find_dir_entry(struct f2fs_dentry_ptr *d, nid_t ino)
+{
+ struct f2fs_dir_entry *de;
+ int slot = 0;
+
+ while (slot < d->max) {
+ if (!test_bit_le(slot, d->bitmap)) {
+ slot++;
+ continue;
+ }
+
+ de = &d->dentry[slot];
+ if (le32_to_cpu(de->ino) == ino && de->hash_code != 0)
+ return slot;
+ if (de->name_len == 0) {
+ slot++;
+ continue;
+ }
+ slot += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
+ }
+
+ return -ENOENT;
+}
+
+static int inject_dentry(struct f2fs_sb_info *sbi, struct inject_option *opt)
+{
+ struct node_info ni;
+ struct f2fs_node *node_blk = NULL;
+ struct f2fs_inode *inode;
+ struct f2fs_dentry_ptr d;
+ void *inline_dentry;
+ struct f2fs_dentry_block *dent_blk = NULL;
+ block_t addr = 0;
+ void *buf = NULL;
+ struct f2fs_dir_entry *dent = NULL;
+ struct dnode_of_data dn;
+ nid_t pino;
+ int slot = -ENOENT, ret;
+
+ node_blk = malloc(F2FS_BLKSIZE);
+ ASSERT(node_blk != NULL);
+
+ /* get child inode */
+ get_node_info(sbi, opt->nid, &ni);
+ ret = dev_read_block(node_blk, ni.blk_addr);
+ ASSERT(ret >= 0);
+ pino = le32_to_cpu(node_blk->i.i_pino);
+
+ /* get parent inode */
+ get_node_info(sbi, pino, &ni);
+ ret = dev_read_block(node_blk, ni.blk_addr);
+ ASSERT(ret >= 0);
+ inode = &node_blk->i;
+
+ /* find child dentry */
+ if (inode->i_inline & F2FS_INLINE_DENTRY) {
+ inline_dentry = inline_data_addr(node_blk);
+ make_dentry_ptr(&d, node_blk, inline_dentry, 2);
+ addr = ni.blk_addr;
+ buf = node_blk;
+
+ slot = find_dir_entry(&d, opt->nid);
+ if (slot >= 0)
+ dent = &d.dentry[slot];
+ } else {
+ unsigned int level, dirlevel, nbucket;
+ unsigned long i, end;
+
+ level = le32_to_cpu(inode->i_current_depth);
+ dirlevel = le32_to_cpu(inode->i_dir_level);
+ nbucket = dir_buckets(level, dirlevel);
+ end = dir_block_index(level, dirlevel, nbucket) +
+ bucket_blocks(level);
+
+ dent_blk = malloc(F2FS_BLKSIZE);
+ ASSERT(dent_blk != NULL);
+
+ for (i = 0; i < end; i++) {
+ memset(&dn, 0, sizeof(dn));
+ set_new_dnode(&dn, node_blk, NULL, pino);
+ ret = get_dnode_of_data(sbi, &dn, i, LOOKUP_NODE);
+ if (ret < 0)
+ break;
+ addr = dn.data_blkaddr;
+ if (dn.inode_blk != dn.node_blk)
+ free(dn.node_blk);
+ if (addr == NULL_ADDR || addr == NEW_ADDR)
+ continue;
+ if (!f2fs_is_valid_blkaddr(sbi, addr, DATA_GENERIC)) {
+ MSG(0, "invalid blkaddr 0x%x at offset %lu\n",
+ addr, i);
+ continue;
+ }
+ ret = dev_read_block(dent_blk, addr);
+ ASSERT(ret >= 0);
+
+ make_dentry_ptr(&d, node_blk, dent_blk, 1);
+ slot = find_dir_entry(&d, opt->nid);
+ if (slot >= 0) {
+ dent = &d.dentry[slot];
+ buf = dent_blk;
+ break;
+ }
+ }
+ }
+
+ if (slot < 0) {
+ ERR_MSG("dentry of ino %u not found\n", opt->nid);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ if (!strcmp(opt->mb, "d_bitmap")) {
+ MSG(0, "Info: inject dentry bitmap of nid %u: 1 -> 0\n",
+ opt->nid);
+ test_and_clear_bit_le(slot, d.bitmap);
+ } else if (!strcmp(opt->mb, "d_hash")) {
+ MSG(0, "Info: inject dentry d_hash of nid %u: "
+ "0x%x -> 0x%x\n", opt->nid, le32_to_cpu(dent->hash_code),
+ (u32)opt->val);
+ dent->hash_code = cpu_to_le32((u32)opt->val);
+ } else if (!strcmp(opt->mb, "d_ino")) {
+ MSG(0, "Info: inject dentry d_ino of nid %u: "
+ "%u -> %u\n", opt->nid, le32_to_cpu(dent->ino),
+ (nid_t)opt->val);
+ dent->ino = cpu_to_le32((nid_t)opt->val);
+ } else if (!strcmp(opt->mb, "d_ftype")) {
+ MSG(0, "Info: inject dentry d_type of nid %u: "
+ "%d -> %d\n", opt->nid, dent->file_type,
+ (u8)opt->val);
+ dent->file_type = (u8)opt->val;
+ } else {
+ ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ print_raw_dentry_info(dent);
+
+ if (inode->i_inline & F2FS_INLINE_DENTRY)
+ ret = update_inode(sbi, buf, &addr);
+ else
+ ret = update_block(sbi, buf, &addr, NULL);
+ ASSERT(ret >= 0);
+
+out:
+ free(node_blk);
+ free(dent_blk);
+ return ret;
+}
+
int do_inject(struct f2fs_sb_info *sbi)
{
struct inject_option *opt = (struct inject_option *)c.private;
@@ -915,6 +1097,8 @@ int do_inject(struct f2fs_sb_info *sbi)
ret = inject_ssa(sbi, opt);
else if (opt->node)
ret = inject_node(sbi, opt);
+ else if (opt->dent)
+ ret = inject_dentry(sbi, opt);
return ret;
}
diff --git a/fsck/inject.h b/fsck/inject.h
index 9b14c31..43c21b5 100644
--- a/fsck/inject.h
+++ b/fsck/inject.h
@@ -32,6 +32,7 @@ struct inject_option {
int sit; /* which sit pack */
bool ssa;
bool node;
+ bool dent;
};
void inject_usage(void);
--
2.40.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [f2fs-dev] [RCF PATCH v3 09/10] inject.f2fs: add dentry injection
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 09/10] inject.f2fs: add dentry injection Sheng Yong via Linux-f2fs-devel
@ 2024-07-04 3:43 ` Chao Yu
2024-09-03 10:14 ` Sheng Yong via Linux-f2fs-devel
1 sibling, 0 replies; 19+ messages in thread
From: Chao Yu @ 2024-07-04 3:43 UTC (permalink / raw)
To: Sheng Yong, jaegeuk; +Cc: linux-f2fs-devel
On 2024/7/4 10:57, Sheng Yong wrote:
> This patch enables injecting dentry block or dir entry.
> print_raw_dentry_info() is added to show values of node footer.
>
> The meanings of options are:
> * dent: means dentry is injected.
>
> The members could be injected in cp contains:
> * d_bitmap: dentry block d_bitmap of nid
> * d_hash: dentry hash
> * d_ino: dentry ino
> * d_ftype: dentry ftype
>
> Signed-off-by: Sheng Yong <shengyong@oppo.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Thanks,
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [f2fs-dev] [RCF PATCH v3 09/10] inject.f2fs: add dentry injection
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 09/10] inject.f2fs: add dentry injection Sheng Yong via Linux-f2fs-devel
2024-07-04 3:43 ` Chao Yu
@ 2024-09-03 10:14 ` Sheng Yong via Linux-f2fs-devel
2024-09-03 21:28 ` Jaegeuk Kim via Linux-f2fs-devel
1 sibling, 1 reply; 19+ messages in thread
From: Sheng Yong via Linux-f2fs-devel @ 2024-09-03 10:14 UTC (permalink / raw)
To: chao, jaegeuk; +Cc: linux-f2fs-devel
Hi, Jaegeuk,
I noticed that this commit is not queued in either dev or master branch.
Do you have any comments on this commit :-)
thanks,
shengyong
On 2024/7/4 10:57, Sheng Yong wrote:
> This patch enables injecting dentry block or dir entry.
> print_raw_dentry_info() is added to show values of node footer.
>
> The meanings of options are:
> * dent: means dentry is injected.
>
> The members could be injected in cp contains:
> * d_bitmap: dentry block d_bitmap of nid
> * d_hash: dentry hash
> * d_ino: dentry ino
> * d_ftype: dentry ftype
>
> Signed-off-by: Sheng Yong <shengyong@oppo.com>
> ---
> fsck/inject.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++
> fsck/inject.h | 1 +
> 2 files changed, 185 insertions(+)
>
> diff --git a/fsck/inject.c b/fsck/inject.c
> index 2a21dae..a7d2a2c 100644
> --- a/fsck/inject.c
> +++ b/fsck/inject.c
> @@ -10,6 +10,7 @@
> */
>
> #include <getopt.h>
> +#include "node.h"
> #include "inject.h"
>
> static void print_raw_nat_entry_info(struct f2fs_nat_entry *ne)
> @@ -74,6 +75,17 @@ static void print_node_footer_info(struct node_footer *footer)
> DISP_u32(footer, next_blkaddr);
> }
>
> +static void print_raw_dentry_info(struct f2fs_dir_entry *dentry)
> +{
> + if (!c.dbg_lv)
> + return;
> +
> + DISP_u32(dentry, hash_code);
> + DISP_u32(dentry, ino);
> + DISP_u16(dentry, name_len);
> + DISP_u8(dentry, file_type);
> +}
> +
> void inject_usage(void)
> {
> MSG(0, "\nUsage: inject.f2fs [options] device\n");
> @@ -92,6 +104,7 @@ void inject_usage(void)
> MSG(0, " --sit <0|1|2> --mb <name> --blk <blk> [--idx <index>] --val <value> inject sit entry\n");
> MSG(0, " --ssa --mb <name> --blk <blk> [--idx <index>] --val <value> inject summary entry\n");
> MSG(0, " --node --mb <name> --nid <nid> [--idx <index>] --val <value> inject node\n");
> + MSG(0, " --dent --mb <name> --nid <ino> [--idx <index>] --val <value> inject ino's dentry\n");
> MSG(0, " --dry-run do not really inject\n");
>
> exit(1);
> @@ -186,6 +199,16 @@ static void inject_node_usage(void)
> MSG(0, " addr: inject {in}direct node nid/addr array selected by --idx <index>\n");
> }
>
> +static void inject_dent_usage(void)
> +{
> + MSG(0, "inject.f2fs --dent --mb <name> --nid <nid> [--idx <index>] --val <value> inject dentry\n");
> + MSG(0, "[mb]:\n");
> + MSG(0, " d_bitmap: inject dentry block d_bitmap of nid\n");
> + MSG(0, " d_hash: inject dentry hash\n");
> + MSG(0, " d_ino: inject dentry ino\n");
> + MSG(0, " d_ftype: inject dentry ftype\n");
> +}
> +
> int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
> {
> int o = 0;
> @@ -206,6 +229,7 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
> {"blk", required_argument, 0, 11},
> {"ssa", no_argument, 0, 12},
> {"node", no_argument, 0, 13},
> + {"dent", no_argument, 0, 14},
> {0, 0, 0, 0}
> };
>
> @@ -294,6 +318,10 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
> opt->node = true;
> MSG(0, "Info: inject node\n");
> break;
> + case 14:
> + opt->dent = true;
> + MSG(0, "Info: inject dentry\n");
> + break;
> case 'd':
> if (optarg[0] == '-' || !is_digits(optarg))
> return EWRONG_OPT;
> @@ -323,6 +351,9 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
> } else if (opt->node) {
> inject_node_usage();
> exit(0);
> + } else if (opt->dent) {
> + inject_dent_usage();
> + exit(0);
> }
> return EUNKNOWN_OPT;
> }
> @@ -898,6 +929,157 @@ out:
> return ret;
> }
>
> +static int find_dir_entry(struct f2fs_dentry_ptr *d, nid_t ino)
> +{
> + struct f2fs_dir_entry *de;
> + int slot = 0;
> +
> + while (slot < d->max) {
> + if (!test_bit_le(slot, d->bitmap)) {
> + slot++;
> + continue;
> + }
> +
> + de = &d->dentry[slot];
> + if (le32_to_cpu(de->ino) == ino && de->hash_code != 0)
> + return slot;
> + if (de->name_len == 0) {
> + slot++;
> + continue;
> + }
> + slot += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
> + }
> +
> + return -ENOENT;
> +}
> +
> +static int inject_dentry(struct f2fs_sb_info *sbi, struct inject_option *opt)
> +{
> + struct node_info ni;
> + struct f2fs_node *node_blk = NULL;
> + struct f2fs_inode *inode;
> + struct f2fs_dentry_ptr d;
> + void *inline_dentry;
> + struct f2fs_dentry_block *dent_blk = NULL;
> + block_t addr = 0;
> + void *buf = NULL;
> + struct f2fs_dir_entry *dent = NULL;
> + struct dnode_of_data dn;
> + nid_t pino;
> + int slot = -ENOENT, ret;
> +
> + node_blk = malloc(F2FS_BLKSIZE);
> + ASSERT(node_blk != NULL);
> +
> + /* get child inode */
> + get_node_info(sbi, opt->nid, &ni);
> + ret = dev_read_block(node_blk, ni.blk_addr);
> + ASSERT(ret >= 0);
> + pino = le32_to_cpu(node_blk->i.i_pino);
> +
> + /* get parent inode */
> + get_node_info(sbi, pino, &ni);
> + ret = dev_read_block(node_blk, ni.blk_addr);
> + ASSERT(ret >= 0);
> + inode = &node_blk->i;
> +
> + /* find child dentry */
> + if (inode->i_inline & F2FS_INLINE_DENTRY) {
> + inline_dentry = inline_data_addr(node_blk);
> + make_dentry_ptr(&d, node_blk, inline_dentry, 2);
> + addr = ni.blk_addr;
> + buf = node_blk;
> +
> + slot = find_dir_entry(&d, opt->nid);
> + if (slot >= 0)
> + dent = &d.dentry[slot];
> + } else {
> + unsigned int level, dirlevel, nbucket;
> + unsigned long i, end;
> +
> + level = le32_to_cpu(inode->i_current_depth);
> + dirlevel = le32_to_cpu(inode->i_dir_level);
> + nbucket = dir_buckets(level, dirlevel);
> + end = dir_block_index(level, dirlevel, nbucket) +
> + bucket_blocks(level);
> +
> + dent_blk = malloc(F2FS_BLKSIZE);
> + ASSERT(dent_blk != NULL);
> +
> + for (i = 0; i < end; i++) {
> + memset(&dn, 0, sizeof(dn));
> + set_new_dnode(&dn, node_blk, NULL, pino);
> + ret = get_dnode_of_data(sbi, &dn, i, LOOKUP_NODE);
> + if (ret < 0)
> + break;
> + addr = dn.data_blkaddr;
> + if (dn.inode_blk != dn.node_blk)
> + free(dn.node_blk);
> + if (addr == NULL_ADDR || addr == NEW_ADDR)
> + continue;
> + if (!f2fs_is_valid_blkaddr(sbi, addr, DATA_GENERIC)) {
> + MSG(0, "invalid blkaddr 0x%x at offset %lu\n",
> + addr, i);
> + continue;
> + }
> + ret = dev_read_block(dent_blk, addr);
> + ASSERT(ret >= 0);
> +
> + make_dentry_ptr(&d, node_blk, dent_blk, 1);
> + slot = find_dir_entry(&d, opt->nid);
> + if (slot >= 0) {
> + dent = &d.dentry[slot];
> + buf = dent_blk;
> + break;
> + }
> + }
> + }
> +
> + if (slot < 0) {
> + ERR_MSG("dentry of ino %u not found\n", opt->nid);
> + ret = -ENOENT;
> + goto out;
> + }
> +
> + if (!strcmp(opt->mb, "d_bitmap")) {
> + MSG(0, "Info: inject dentry bitmap of nid %u: 1 -> 0\n",
> + opt->nid);
> + test_and_clear_bit_le(slot, d.bitmap);
> + } else if (!strcmp(opt->mb, "d_hash")) {
> + MSG(0, "Info: inject dentry d_hash of nid %u: "
> + "0x%x -> 0x%x\n", opt->nid, le32_to_cpu(dent->hash_code),
> + (u32)opt->val);
> + dent->hash_code = cpu_to_le32((u32)opt->val);
> + } else if (!strcmp(opt->mb, "d_ino")) {
> + MSG(0, "Info: inject dentry d_ino of nid %u: "
> + "%u -> %u\n", opt->nid, le32_to_cpu(dent->ino),
> + (nid_t)opt->val);
> + dent->ino = cpu_to_le32((nid_t)opt->val);
> + } else if (!strcmp(opt->mb, "d_ftype")) {
> + MSG(0, "Info: inject dentry d_type of nid %u: "
> + "%d -> %d\n", opt->nid, dent->file_type,
> + (u8)opt->val);
> + dent->file_type = (u8)opt->val;
> + } else {
> + ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + print_raw_dentry_info(dent);
> +
> + if (inode->i_inline & F2FS_INLINE_DENTRY)
> + ret = update_inode(sbi, buf, &addr);
> + else
> + ret = update_block(sbi, buf, &addr, NULL);
> + ASSERT(ret >= 0);
> +
> +out:
> + free(node_blk);
> + free(dent_blk);
> + return ret;
> +}
> +
> int do_inject(struct f2fs_sb_info *sbi)
> {
> struct inject_option *opt = (struct inject_option *)c.private;
> @@ -915,6 +1097,8 @@ int do_inject(struct f2fs_sb_info *sbi)
> ret = inject_ssa(sbi, opt);
> else if (opt->node)
> ret = inject_node(sbi, opt);
> + else if (opt->dent)
> + ret = inject_dentry(sbi, opt);
>
> return ret;
> }
> diff --git a/fsck/inject.h b/fsck/inject.h
> index 9b14c31..43c21b5 100644
> --- a/fsck/inject.h
> +++ b/fsck/inject.h
> @@ -32,6 +32,7 @@ struct inject_option {
> int sit; /* which sit pack */
> bool ssa;
> bool node;
> + bool dent;
> };
>
> void inject_usage(void);
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [f2fs-dev] [RCF PATCH v3 09/10] inject.f2fs: add dentry injection
2024-09-03 10:14 ` Sheng Yong via Linux-f2fs-devel
@ 2024-09-03 21:28 ` Jaegeuk Kim via Linux-f2fs-devel
0 siblings, 0 replies; 19+ messages in thread
From: Jaegeuk Kim via Linux-f2fs-devel @ 2024-09-03 21:28 UTC (permalink / raw)
To: Sheng Yong; +Cc: linux-f2fs-devel
On 09/03, Sheng Yong wrote:
> Hi, Jaegeuk,
>
> I noticed that this commit is not queued in either dev or master branch.
> Do you have any comments on this commit :-)
Thanks, I missed. Let me queue in the branches. :)
>
> thanks,
> shengyong
>
> On 2024/7/4 10:57, Sheng Yong wrote:
> > This patch enables injecting dentry block or dir entry.
> > print_raw_dentry_info() is added to show values of node footer.
> >
> > The meanings of options are:
> > * dent: means dentry is injected.
> >
> > The members could be injected in cp contains:
> > * d_bitmap: dentry block d_bitmap of nid
> > * d_hash: dentry hash
> > * d_ino: dentry ino
> > * d_ftype: dentry ftype
> >
> > Signed-off-by: Sheng Yong <shengyong@oppo.com>
> > ---
> > fsck/inject.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++
> > fsck/inject.h | 1 +
> > 2 files changed, 185 insertions(+)
> >
> > diff --git a/fsck/inject.c b/fsck/inject.c
> > index 2a21dae..a7d2a2c 100644
> > --- a/fsck/inject.c
> > +++ b/fsck/inject.c
> > @@ -10,6 +10,7 @@
> > */
> > #include <getopt.h>
> > +#include "node.h"
> > #include "inject.h"
> > static void print_raw_nat_entry_info(struct f2fs_nat_entry *ne)
> > @@ -74,6 +75,17 @@ static void print_node_footer_info(struct node_footer *footer)
> > DISP_u32(footer, next_blkaddr);
> > }
> > +static void print_raw_dentry_info(struct f2fs_dir_entry *dentry)
> > +{
> > + if (!c.dbg_lv)
> > + return;
> > +
> > + DISP_u32(dentry, hash_code);
> > + DISP_u32(dentry, ino);
> > + DISP_u16(dentry, name_len);
> > + DISP_u8(dentry, file_type);
> > +}
> > +
> > void inject_usage(void)
> > {
> > MSG(0, "\nUsage: inject.f2fs [options] device\n");
> > @@ -92,6 +104,7 @@ void inject_usage(void)
> > MSG(0, " --sit <0|1|2> --mb <name> --blk <blk> [--idx <index>] --val <value> inject sit entry\n");
> > MSG(0, " --ssa --mb <name> --blk <blk> [--idx <index>] --val <value> inject summary entry\n");
> > MSG(0, " --node --mb <name> --nid <nid> [--idx <index>] --val <value> inject node\n");
> > + MSG(0, " --dent --mb <name> --nid <ino> [--idx <index>] --val <value> inject ino's dentry\n");
> > MSG(0, " --dry-run do not really inject\n");
> > exit(1);
> > @@ -186,6 +199,16 @@ static void inject_node_usage(void)
> > MSG(0, " addr: inject {in}direct node nid/addr array selected by --idx <index>\n");
> > }
> > +static void inject_dent_usage(void)
> > +{
> > + MSG(0, "inject.f2fs --dent --mb <name> --nid <nid> [--idx <index>] --val <value> inject dentry\n");
> > + MSG(0, "[mb]:\n");
> > + MSG(0, " d_bitmap: inject dentry block d_bitmap of nid\n");
> > + MSG(0, " d_hash: inject dentry hash\n");
> > + MSG(0, " d_ino: inject dentry ino\n");
> > + MSG(0, " d_ftype: inject dentry ftype\n");
> > +}
> > +
> > int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
> > {
> > int o = 0;
> > @@ -206,6 +229,7 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
> > {"blk", required_argument, 0, 11},
> > {"ssa", no_argument, 0, 12},
> > {"node", no_argument, 0, 13},
> > + {"dent", no_argument, 0, 14},
> > {0, 0, 0, 0}
> > };
> > @@ -294,6 +318,10 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
> > opt->node = true;
> > MSG(0, "Info: inject node\n");
> > break;
> > + case 14:
> > + opt->dent = true;
> > + MSG(0, "Info: inject dentry\n");
> > + break;
> > case 'd':
> > if (optarg[0] == '-' || !is_digits(optarg))
> > return EWRONG_OPT;
> > @@ -323,6 +351,9 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
> > } else if (opt->node) {
> > inject_node_usage();
> > exit(0);
> > + } else if (opt->dent) {
> > + inject_dent_usage();
> > + exit(0);
> > }
> > return EUNKNOWN_OPT;
> > }
> > @@ -898,6 +929,157 @@ out:
> > return ret;
> > }
> > +static int find_dir_entry(struct f2fs_dentry_ptr *d, nid_t ino)
> > +{
> > + struct f2fs_dir_entry *de;
> > + int slot = 0;
> > +
> > + while (slot < d->max) {
> > + if (!test_bit_le(slot, d->bitmap)) {
> > + slot++;
> > + continue;
> > + }
> > +
> > + de = &d->dentry[slot];
> > + if (le32_to_cpu(de->ino) == ino && de->hash_code != 0)
> > + return slot;
> > + if (de->name_len == 0) {
> > + slot++;
> > + continue;
> > + }
> > + slot += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
> > + }
> > +
> > + return -ENOENT;
> > +}
> > +
> > +static int inject_dentry(struct f2fs_sb_info *sbi, struct inject_option *opt)
> > +{
> > + struct node_info ni;
> > + struct f2fs_node *node_blk = NULL;
> > + struct f2fs_inode *inode;
> > + struct f2fs_dentry_ptr d;
> > + void *inline_dentry;
> > + struct f2fs_dentry_block *dent_blk = NULL;
> > + block_t addr = 0;
> > + void *buf = NULL;
> > + struct f2fs_dir_entry *dent = NULL;
> > + struct dnode_of_data dn;
> > + nid_t pino;
> > + int slot = -ENOENT, ret;
> > +
> > + node_blk = malloc(F2FS_BLKSIZE);
> > + ASSERT(node_blk != NULL);
> > +
> > + /* get child inode */
> > + get_node_info(sbi, opt->nid, &ni);
> > + ret = dev_read_block(node_blk, ni.blk_addr);
> > + ASSERT(ret >= 0);
> > + pino = le32_to_cpu(node_blk->i.i_pino);
> > +
> > + /* get parent inode */
> > + get_node_info(sbi, pino, &ni);
> > + ret = dev_read_block(node_blk, ni.blk_addr);
> > + ASSERT(ret >= 0);
> > + inode = &node_blk->i;
> > +
> > + /* find child dentry */
> > + if (inode->i_inline & F2FS_INLINE_DENTRY) {
> > + inline_dentry = inline_data_addr(node_blk);
> > + make_dentry_ptr(&d, node_blk, inline_dentry, 2);
> > + addr = ni.blk_addr;
> > + buf = node_blk;
> > +
> > + slot = find_dir_entry(&d, opt->nid);
> > + if (slot >= 0)
> > + dent = &d.dentry[slot];
> > + } else {
> > + unsigned int level, dirlevel, nbucket;
> > + unsigned long i, end;
> > +
> > + level = le32_to_cpu(inode->i_current_depth);
> > + dirlevel = le32_to_cpu(inode->i_dir_level);
> > + nbucket = dir_buckets(level, dirlevel);
> > + end = dir_block_index(level, dirlevel, nbucket) +
> > + bucket_blocks(level);
> > +
> > + dent_blk = malloc(F2FS_BLKSIZE);
> > + ASSERT(dent_blk != NULL);
> > +
> > + for (i = 0; i < end; i++) {
> > + memset(&dn, 0, sizeof(dn));
> > + set_new_dnode(&dn, node_blk, NULL, pino);
> > + ret = get_dnode_of_data(sbi, &dn, i, LOOKUP_NODE);
> > + if (ret < 0)
> > + break;
> > + addr = dn.data_blkaddr;
> > + if (dn.inode_blk != dn.node_blk)
> > + free(dn.node_blk);
> > + if (addr == NULL_ADDR || addr == NEW_ADDR)
> > + continue;
> > + if (!f2fs_is_valid_blkaddr(sbi, addr, DATA_GENERIC)) {
> > + MSG(0, "invalid blkaddr 0x%x at offset %lu\n",
> > + addr, i);
> > + continue;
> > + }
> > + ret = dev_read_block(dent_blk, addr);
> > + ASSERT(ret >= 0);
> > +
> > + make_dentry_ptr(&d, node_blk, dent_blk, 1);
> > + slot = find_dir_entry(&d, opt->nid);
> > + if (slot >= 0) {
> > + dent = &d.dentry[slot];
> > + buf = dent_blk;
> > + break;
> > + }
> > + }
> > + }
> > +
> > + if (slot < 0) {
> > + ERR_MSG("dentry of ino %u not found\n", opt->nid);
> > + ret = -ENOENT;
> > + goto out;
> > + }
> > +
> > + if (!strcmp(opt->mb, "d_bitmap")) {
> > + MSG(0, "Info: inject dentry bitmap of nid %u: 1 -> 0\n",
> > + opt->nid);
> > + test_and_clear_bit_le(slot, d.bitmap);
> > + } else if (!strcmp(opt->mb, "d_hash")) {
> > + MSG(0, "Info: inject dentry d_hash of nid %u: "
> > + "0x%x -> 0x%x\n", opt->nid, le32_to_cpu(dent->hash_code),
> > + (u32)opt->val);
> > + dent->hash_code = cpu_to_le32((u32)opt->val);
> > + } else if (!strcmp(opt->mb, "d_ino")) {
> > + MSG(0, "Info: inject dentry d_ino of nid %u: "
> > + "%u -> %u\n", opt->nid, le32_to_cpu(dent->ino),
> > + (nid_t)opt->val);
> > + dent->ino = cpu_to_le32((nid_t)opt->val);
> > + } else if (!strcmp(opt->mb, "d_ftype")) {
> > + MSG(0, "Info: inject dentry d_type of nid %u: "
> > + "%d -> %d\n", opt->nid, dent->file_type,
> > + (u8)opt->val);
> > + dent->file_type = (u8)opt->val;
> > + } else {
> > + ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
> > + ret = -EINVAL;
> > + goto out;
> > + }
> > +
> > + print_raw_dentry_info(dent);
> > +
> > + if (inode->i_inline & F2FS_INLINE_DENTRY)
> > + ret = update_inode(sbi, buf, &addr);
> > + else
> > + ret = update_block(sbi, buf, &addr, NULL);
> > + ASSERT(ret >= 0);
> > +
> > +out:
> > + free(node_blk);
> > + free(dent_blk);
> > + return ret;
> > +}
> > +
> > int do_inject(struct f2fs_sb_info *sbi)
> > {
> > struct inject_option *opt = (struct inject_option *)c.private;
> > @@ -915,6 +1097,8 @@ int do_inject(struct f2fs_sb_info *sbi)
> > ret = inject_ssa(sbi, opt);
> > else if (opt->node)
> > ret = inject_node(sbi, opt);
> > + else if (opt->dent)
> > + ret = inject_dentry(sbi, opt);
> > return ret;
> > }
> > diff --git a/fsck/inject.h b/fsck/inject.h
> > index 9b14c31..43c21b5 100644
> > --- a/fsck/inject.h
> > +++ b/fsck/inject.h
> > @@ -32,6 +32,7 @@ struct inject_option {
> > int sit; /* which sit pack */
> > bool ssa;
> > bool node;
> > + bool dent;
> > };
> > void inject_usage(void);
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 19+ messages in thread
* [f2fs-dev] [RCF PATCH v3 10/10] man: add inject.f2fs man page
2024-07-04 2:57 [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
` (8 preceding siblings ...)
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 09/10] inject.f2fs: add dentry injection Sheng Yong via Linux-f2fs-devel
@ 2024-07-04 2:57 ` Sheng Yong via Linux-f2fs-devel
2024-07-04 3:26 ` [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Chao Yu
2024-07-10 22:57 ` Jaegeuk Kim
11 siblings, 0 replies; 19+ messages in thread
From: Sheng Yong via Linux-f2fs-devel @ 2024-07-04 2:57 UTC (permalink / raw)
To: chao, jaegeuk; +Cc: linux-f2fs-devel
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Sheng Yong <shengyong@oppo.com>
---
man/Makefile.am | 2 +-
man/inject.f2fs.8 | 225 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 226 insertions(+), 1 deletion(-)
create mode 100644 man/inject.f2fs.8
diff --git a/man/Makefile.am b/man/Makefile.am
index 9363b82..b78344a 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -1,3 +1,3 @@
## Makefile.am
-dist_man_MANS = mkfs.f2fs.8 fsck.f2fs.8 dump.f2fs.8 defrag.f2fs.8 resize.f2fs.8 sload.f2fs.8 f2fs_io.8 f2fslabel.8
+dist_man_MANS = mkfs.f2fs.8 fsck.f2fs.8 dump.f2fs.8 defrag.f2fs.8 resize.f2fs.8 sload.f2fs.8 f2fs_io.8 f2fslabel.8 inject.f2fs.8
diff --git a/man/inject.f2fs.8 b/man/inject.f2fs.8
new file mode 100644
index 0000000..01d58ef
--- /dev/null
+++ b/man/inject.f2fs.8
@@ -0,0 +1,225 @@
+.\" Copyright (c) 2024 OPPO Mobile Comm Corp., Ltd.
+.\"
+.TH INJECT.F2FS 8
+.SH NAME
+inject.f2fs \- inject a Linux F2FS file system
+.SH SYNOPSIS
+.B inject.f2fs
+[
+.I options
+]
+.I device
+.SH DESCRIPTION
+.B inject.f2fs
+is used to modify metadata or data (directory entry) of f2fs file system
+image offline flexibly.
+.SH OPTIONS
+.TP
+.BI \-d " debug level [default:0]"
+Specify the level of debugging options.
+.TP
+.BI \-V
+Print the version number and exit.
+.TP
+.BI \-\-mb " member name"
+Specify the member name in a struct that is injected.
+.TP
+.BI \-\-val " new value"
+New value to set if \fImb\fP is a number.
+.TP
+.BI \-\-str " new string"
+New string to set if \fImb\fP is a string.
+.TP
+.BI \-\-idx " slot index"
+Specify which slot is injected if \fImb\fP is an array.
+.TP
+.BI \-\-nid " nid"
+Specify which nid is injected.
+.TP
+.BI \-\-blk " blkaddr"
+Specify which blkaddr is injected.
+.TP
+.BI \-\-sb " 0 or 1 or 2"
+Inject super block, its argument means which sb pack is injected, where 0 choses the current valid sb automatically.
+The available \fImb\fP of \fIsb\fP are:
+.RS 1.2i
+.TP
+.BI magic
+magic numbe.
+.TP
+.BI s_stop_reason
+s_stop_reason array.
+.TP
+.BI s_errors
+s_errors array.
+.TP
+.BI devs.path
+path in devs array.
+.RE
+.TP
+.BI \-\-cp " 0 or 1 or 2"
+Inject checkpoint, its argument means which cp pack is injected, where 0 choses the current valid cp automatically.
+The available \fImb\fP of \fIcp\fP are:
+.RS 1.2i
+.TP
+.BI checkpoint_ver
+checkpoint version.
+.TP
+.BI ckpt_flags
+checkpoint flags.
+.TP
+.BI cur_node_segno
+cur_node_segno array.
+.TP
+.BI cur_node_blkoff
+cur_node_blkoff array.
+.TP
+.BI cur_data_segno
+cur_data_segno array.
+.TP
+.BI cur_data_blkoff
+cur_data_blkoff array.
+.RE
+.TP
+.BI \-\-nat " 0 or 1 or 2"
+Inject nat entry specified by \fInid\fP, its argument means which nat pack is injected, where 0 choses the current valid nat automatically.
+The available \fImb\fP of \fInat\fP are:
+.RS 1.2i
+.TP
+.BI version
+nat entry version.
+.TP
+.BI ino
+nat entry ino.
+.TP
+.BI block_addr
+nat entry block_addr.
+.RE
+.TP
+.BI \-\-sit " 0 or 1 or 2"
+Inject sit entry specified by \fIblk\fP, its argument means which sit pack is injected, where 0 choses the current valid sit automatically.
+The available \fImb\fP of \fIsit\fP are:
+.RS 1.2i
+.TP
+.BI vblocks
+sit entry vblocks.
+.TP
+.BI valid_map
+sit entry valid_map.
+.TP
+.BI mtime
+sit entry mtime.
+.RE
+.TP
+.BI \-\-ssa
+Inject summary block or summary entry specified by \fIblk\fP.
+The available \fImb\fP of \fIssa\fP are:
+.RS 1.2i
+.TP
+.BI entry_type
+summary block footer entry_type.
+.TP
+.BI check_sum
+summary block footer check_sum.
+.TP
+.BI nid
+summary entry nid.
+.TP
+.BI version
+summary entry version.
+.TP
+.BI ofs_in_node
+summary entry ofs_in_node.
+.RE
+.TP
+.BI \-\-node
+Inject node block specified by \fInid\P.
+The available \fImb\fP of \fInode\fP are:
+.RS 1.2i
+.TP
+.BI nid
+node footer nid.
+.TP
+.BI ino
+node footer ino.
+.TP
+.BI flag
+node footer flag.
+.TP
+.BI cp_ver
+node footer cp_ver.
+.TP
+.BI next_blkaddr
+node footer next_blkaddr.
+.TP
+.BI i_mode
+inode i_mode.
+.TP
+.BI i_advise
+inode i_advise.
+.TP
+.BI i_inline
+inode i_inline.
+.TP
+.BI i_links
+inode i_links.
+.TP
+.BI i_size
+inode i_size.
+.TP
+.BI i_blocks
+inode i_blocks.
+.TP
+.BI i_extra_isize
+inode i_extra_isize.
+.TP
+.BI i_inode_checksum
+inode i_inode_checksum.
+.TP
+.BI i_addr
+inode i_addr array specified by \fIidx\fP.
+.TP
+.BI i_nid
+inode i_nid array specified by \fIidx\fP.
+.TP
+.BI addr
+{in}direct node nid/addr array specified by \fIidx\fP.
+.RE
+.TP
+.BI \-\-dent
+Inject dentry block or dir entry specified \fInid\fP.
+The available \fImb\fP of \fIdent\fP are:
+.RS 1.2i
+.TP
+.BI d_bitmap
+dentry block d_bitmap.
+.TP
+.BI d_hash
+dentry hash.
+.TP
+.BI d_ino
+dentry ino.
+.TP
+.BI d_ftype
+dentry ftype.
+.RE
+.TP
+.BI \-\-dry\-run
+Do not really inject.
+
+.PP
+.SH AUTHOR
+This version of
+.B inject.f2fs
+has been written by Sheng Yong <shengyong@oppo.com>.
+.SH AVAILABILITY
+.B inject.f2fs
+is available from git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git.
+.SH "SEE ALSO"
+.BR mkfs.f2fs(8),
+.BR fsck.f2fs(8),
+.BR dump.f2fs(8),
+.BR defrag.f2fs(8),
+.BR resize.f2fs(8),
+.BR sload.f2fs(8),
+.BR defrag.f2fs(8).
--
2.40.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs
2024-07-04 2:57 [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
` (9 preceding siblings ...)
2024-07-04 2:57 ` [f2fs-dev] [RCF PATCH v3 10/10] man: add inject.f2fs man page Sheng Yong via Linux-f2fs-devel
@ 2024-07-04 3:26 ` Chao Yu
2024-07-10 22:57 ` Jaegeuk Kim
11 siblings, 0 replies; 19+ messages in thread
From: Chao Yu @ 2024-07-04 3:26 UTC (permalink / raw)
To: Sheng Yong, jaegeuk; +Cc: linux-f2fs-devel
On 2024/7/4 10:57, Sheng Yong wrote:
> This patchset introduces a new tool inject.f2fs to modify metadata or
> data (directory entry) of f2fs image offline flexibly.
>
> With inject.f2fs, it is easier to generate a corrupted f2fs image, which
> can help verify fsck or reproduce userspace behaviors of some a fault.
> If option `--dry-run' is used, nothing really gets changed, and that
> could be used to get the value of a specified field.
>
> inject.f2fs allows injecting some members in sb, cp, nat, sit, ssa, node
> and dentry for now. The available members of each part can be listed by
> executing command like:
> inject.f2fs --sb 0 --help
>
> [...]
> [mb]:
> magic: inject magic number
> s_stop_reason: inject s_stop_reason array selected by --idx <index>
> s_errors: inject s_errors array selected by --idx <index>
> devs.path: inject path in devs array selected by --idx <index> specified by --str <string>
>
> More injection fields are still work-in-progress. The TODO list includes:
> * sb: features
> * cp: fsync dnodes
> * inode: extent, extra attrs, xattr
> * data: fsverify?
> * other fields which is needed to verify fsck
What about including todo list into manual?
>
> v3:
> * patch 3, fix error handling of inject sb->devs.path
> * patch 3, do not ASSERT devs.path when inject is executed
> * patch 3, allow inject to execute if image is umounted unclean
> * patch 9, check whether blkaddr is valid before reading dentry block
> * add is_digits and strtol entptr check when parsing numeric options
>
> v2:
> * change print format of s_errors
> * add write_raw_cp_blocks to write the first & last cp blocks directly
> to avoid updating ckpt_flags by write_checkpoint
> * call update_block if i_inode_checksum is injected to avoid updating
> i_inode_checksum by update_inode
> * go through all dentry blocks to find the target dir entry
>
> Examples:
>
> Inject sb's magic
> =================
> inject.f2fs --sb 0 --mb magic --val 0x12345 $DEV
>
> Info: inject sb auto
> Info: inject member magic
> Info: inject value 74565 : 0x12345
> [...]
> Info: inject magic of sb 1: 0xf2f52010 -> 0x12345
> [update_superblock: 890] Info: Done to update superblock
>
> Inject cp's cur_data_segno
> ==========================
> inject.f2fs --cp 0 --mb cur_data_segno --idx 1 --val 0x12345 $DEV
>
> Info: inject cp pack auto
> Info: inject member cur_data_segno
> Info: inject slot index 1
> Info: inject value 74565 : 0x12345
> [...]
> Info: inject cur_data_segno[1] of cp 1: 0x4 -> 0x12345
> Info: write_checkpoint() cur_cp:1
>
> Inject nat's ino
> ================
> inject.f2fs --nat 0 --mb ino --nid $INO --val 0x12345 $DEV
>
> Info: inject nat pack auto
> Info: inject nid 4 : 0x4
> Info: inject member ino
> Info: inject value 74565 : 0x12345
> [...]
> Info: inject nat entry ino of nid 4 in pack 1: 4 -> 74565
>
> Inject ssa's nid
> ================
> inject.f2fs --ssa --blk $BLK --mb nid --val 0x12345 $DEV
>
> Info: inject ssa
> Info: inject blkaddr 7511 : 0x1d57
> Info: inject member nid
> Info: inject value 74565 : 0x12345
> [...]
> Info: auto idx = 343
> Info: inject summary entry nid of block 0x1d57: 0x4 -> 0x12345
>
> Inject inode's i_addr
> =====================
> inject.f2fs --node --nid $INO --mb i_addr --idx 100 --val 0x12345 $DEV
>
> Info: inject node
> Info: inject nid 4 : 0x4
> Info: inject member i_addr
> Info: inject slot index 100
> Info: inject value 74565 : 0x12345
> [...]
> Info: inject inode i_addr[100] of nid 4: 0x20864 -> 0x12345
>
> Inject inode's dentry hash
> ==========================
> inject.f2fs --dent --nid $INO --mb d_hash --val 0x12345 $DEV
>
> Info: inject dentry
> Info: inject nid 4 : 0x4
> Info: inject member d_hash
> Info: inject value 74565 : 0x12345
> [..]
> Info: inject dentry d_hash of nid 4: 0xc77b804e -> 0x12345
Ditto, better to include examples in manual, since it's a little bit
complicated to use inject.f2fs.
Thanks,
>
> Sheng Yong (10):
> f2fs-tools: export is_digits
> inject.f2fs: introduce inject.f2fs
> inject.f2fs: add sb injection
> inject.f2fs: add cp injection
> inject.f2fs: add nat injection
> inject.f2fs: add sit injection
> inject.f2fs: add ssa injection
> inject.f2fs: add node injection
> inject.f2fs: add dentry injection
> man: add inject.f2fs man page
>
> fsck/Makefile.am | 5 +-
> fsck/fsck.h | 6 +
> fsck/inject.c | 1104 +++++++++++++++++++++++++++++++++++++++++++++
> fsck/inject.h | 41 ++
> fsck/main.c | 38 +-
> fsck/mount.c | 30 +-
> include/f2fs_fs.h | 2 +
> man/Makefile.am | 2 +-
> man/inject.f2fs.8 | 225 +++++++++
> 9 files changed, 1447 insertions(+), 6 deletions(-)
> create mode 100644 fsck/inject.c
> create mode 100644 fsck/inject.h
> create mode 100644 man/inject.f2fs.8
>
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs
2024-07-04 2:57 [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Sheng Yong via Linux-f2fs-devel
` (10 preceding siblings ...)
2024-07-04 3:26 ` [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs Chao Yu
@ 2024-07-10 22:57 ` Jaegeuk Kim
2024-07-10 23:04 ` Jaegeuk Kim
11 siblings, 1 reply; 19+ messages in thread
From: Jaegeuk Kim @ 2024-07-10 22:57 UTC (permalink / raw)
To: Sheng Yong; +Cc: linux-f2fs-devel
Hi Sheng,
Can we have a list of tests to check the expected behavior of given
inject.f2fs followed by fsck.f2fs?
Thanks,
On 07/04, Sheng Yong wrote:
> This patchset introduces a new tool inject.f2fs to modify metadata or
> data (directory entry) of f2fs image offline flexibly.
>
> With inject.f2fs, it is easier to generate a corrupted f2fs image, which
> can help verify fsck or reproduce userspace behaviors of some a fault.
> If option `--dry-run' is used, nothing really gets changed, and that
> could be used to get the value of a specified field.
>
> inject.f2fs allows injecting some members in sb, cp, nat, sit, ssa, node
> and dentry for now. The available members of each part can be listed by
> executing command like:
> inject.f2fs --sb 0 --help
>
> [...]
> [mb]:
> magic: inject magic number
> s_stop_reason: inject s_stop_reason array selected by --idx <index>
> s_errors: inject s_errors array selected by --idx <index>
> devs.path: inject path in devs array selected by --idx <index> specified by --str <string>
>
> More injection fields are still work-in-progress. The TODO list includes:
> * sb: features
> * cp: fsync dnodes
> * inode: extent, extra attrs, xattr
> * data: fsverify?
> * other fields which is needed to verify fsck
>
> v3:
> * patch 3, fix error handling of inject sb->devs.path
> * patch 3, do not ASSERT devs.path when inject is executed
> * patch 3, allow inject to execute if image is umounted unclean
> * patch 9, check whether blkaddr is valid before reading dentry block
> * add is_digits and strtol entptr check when parsing numeric options
>
> v2:
> * change print format of s_errors
> * add write_raw_cp_blocks to write the first & last cp blocks directly
> to avoid updating ckpt_flags by write_checkpoint
> * call update_block if i_inode_checksum is injected to avoid updating
> i_inode_checksum by update_inode
> * go through all dentry blocks to find the target dir entry
>
> Examples:
>
> Inject sb's magic
> =================
> inject.f2fs --sb 0 --mb magic --val 0x12345 $DEV
>
> Info: inject sb auto
> Info: inject member magic
> Info: inject value 74565 : 0x12345
> [...]
> Info: inject magic of sb 1: 0xf2f52010 -> 0x12345
> [update_superblock: 890] Info: Done to update superblock
>
> Inject cp's cur_data_segno
> ==========================
> inject.f2fs --cp 0 --mb cur_data_segno --idx 1 --val 0x12345 $DEV
>
> Info: inject cp pack auto
> Info: inject member cur_data_segno
> Info: inject slot index 1
> Info: inject value 74565 : 0x12345
> [...]
> Info: inject cur_data_segno[1] of cp 1: 0x4 -> 0x12345
> Info: write_checkpoint() cur_cp:1
>
> Inject nat's ino
> ================
> inject.f2fs --nat 0 --mb ino --nid $INO --val 0x12345 $DEV
>
> Info: inject nat pack auto
> Info: inject nid 4 : 0x4
> Info: inject member ino
> Info: inject value 74565 : 0x12345
> [...]
> Info: inject nat entry ino of nid 4 in pack 1: 4 -> 74565
>
> Inject ssa's nid
> ================
> inject.f2fs --ssa --blk $BLK --mb nid --val 0x12345 $DEV
>
> Info: inject ssa
> Info: inject blkaddr 7511 : 0x1d57
> Info: inject member nid
> Info: inject value 74565 : 0x12345
> [...]
> Info: auto idx = 343
> Info: inject summary entry nid of block 0x1d57: 0x4 -> 0x12345
>
> Inject inode's i_addr
> =====================
> inject.f2fs --node --nid $INO --mb i_addr --idx 100 --val 0x12345 $DEV
>
> Info: inject node
> Info: inject nid 4 : 0x4
> Info: inject member i_addr
> Info: inject slot index 100
> Info: inject value 74565 : 0x12345
> [...]
> Info: inject inode i_addr[100] of nid 4: 0x20864 -> 0x12345
>
> Inject inode's dentry hash
> ==========================
> inject.f2fs --dent --nid $INO --mb d_hash --val 0x12345 $DEV
>
> Info: inject dentry
> Info: inject nid 4 : 0x4
> Info: inject member d_hash
> Info: inject value 74565 : 0x12345
> [..]
> Info: inject dentry d_hash of nid 4: 0xc77b804e -> 0x12345
>
> Sheng Yong (10):
> f2fs-tools: export is_digits
> inject.f2fs: introduce inject.f2fs
> inject.f2fs: add sb injection
> inject.f2fs: add cp injection
> inject.f2fs: add nat injection
> inject.f2fs: add sit injection
> inject.f2fs: add ssa injection
> inject.f2fs: add node injection
> inject.f2fs: add dentry injection
> man: add inject.f2fs man page
>
> fsck/Makefile.am | 5 +-
> fsck/fsck.h | 6 +
> fsck/inject.c | 1104 +++++++++++++++++++++++++++++++++++++++++++++
> fsck/inject.h | 41 ++
> fsck/main.c | 38 +-
> fsck/mount.c | 30 +-
> include/f2fs_fs.h | 2 +
> man/Makefile.am | 2 +-
> man/inject.f2fs.8 | 225 +++++++++
> 9 files changed, 1447 insertions(+), 6 deletions(-)
> create mode 100644 fsck/inject.c
> create mode 100644 fsck/inject.h
> create mode 100644 man/inject.f2fs.8
>
> --
> 2.40.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs
2024-07-10 22:57 ` Jaegeuk Kim
@ 2024-07-10 23:04 ` Jaegeuk Kim
2024-07-11 1:25 ` Sheng Yong via Linux-f2fs-devel
0 siblings, 1 reply; 19+ messages in thread
From: Jaegeuk Kim @ 2024-07-10 23:04 UTC (permalink / raw)
To: Sheng Yong; +Cc: linux-f2fs-devel
On 07/10, Jaegeuk Kim wrote:
> Hi Sheng,
>
> Can we have a list of tests to check the expected behavior of given
> inject.f2fs followed by fsck.f2fs?
And we need this.
https://lore.kernel.org/linux-f2fs-devel/20240710230319.33025-1-jaegeuk@kernel.org/T/#u
>
> Thanks,
>
> On 07/04, Sheng Yong wrote:
> > This patchset introduces a new tool inject.f2fs to modify metadata or
> > data (directory entry) of f2fs image offline flexibly.
> >
> > With inject.f2fs, it is easier to generate a corrupted f2fs image, which
> > can help verify fsck or reproduce userspace behaviors of some a fault.
> > If option `--dry-run' is used, nothing really gets changed, and that
> > could be used to get the value of a specified field.
> >
> > inject.f2fs allows injecting some members in sb, cp, nat, sit, ssa, node
> > and dentry for now. The available members of each part can be listed by
> > executing command like:
> > inject.f2fs --sb 0 --help
> >
> > [...]
> > [mb]:
> > magic: inject magic number
> > s_stop_reason: inject s_stop_reason array selected by --idx <index>
> > s_errors: inject s_errors array selected by --idx <index>
> > devs.path: inject path in devs array selected by --idx <index> specified by --str <string>
> >
> > More injection fields are still work-in-progress. The TODO list includes:
> > * sb: features
> > * cp: fsync dnodes
> > * inode: extent, extra attrs, xattr
> > * data: fsverify?
> > * other fields which is needed to verify fsck
> >
> > v3:
> > * patch 3, fix error handling of inject sb->devs.path
> > * patch 3, do not ASSERT devs.path when inject is executed
> > * patch 3, allow inject to execute if image is umounted unclean
> > * patch 9, check whether blkaddr is valid before reading dentry block
> > * add is_digits and strtol entptr check when parsing numeric options
> >
> > v2:
> > * change print format of s_errors
> > * add write_raw_cp_blocks to write the first & last cp blocks directly
> > to avoid updating ckpt_flags by write_checkpoint
> > * call update_block if i_inode_checksum is injected to avoid updating
> > i_inode_checksum by update_inode
> > * go through all dentry blocks to find the target dir entry
> >
> > Examples:
> >
> > Inject sb's magic
> > =================
> > inject.f2fs --sb 0 --mb magic --val 0x12345 $DEV
> >
> > Info: inject sb auto
> > Info: inject member magic
> > Info: inject value 74565 : 0x12345
> > [...]
> > Info: inject magic of sb 1: 0xf2f52010 -> 0x12345
> > [update_superblock: 890] Info: Done to update superblock
> >
> > Inject cp's cur_data_segno
> > ==========================
> > inject.f2fs --cp 0 --mb cur_data_segno --idx 1 --val 0x12345 $DEV
> >
> > Info: inject cp pack auto
> > Info: inject member cur_data_segno
> > Info: inject slot index 1
> > Info: inject value 74565 : 0x12345
> > [...]
> > Info: inject cur_data_segno[1] of cp 1: 0x4 -> 0x12345
> > Info: write_checkpoint() cur_cp:1
> >
> > Inject nat's ino
> > ================
> > inject.f2fs --nat 0 --mb ino --nid $INO --val 0x12345 $DEV
> >
> > Info: inject nat pack auto
> > Info: inject nid 4 : 0x4
> > Info: inject member ino
> > Info: inject value 74565 : 0x12345
> > [...]
> > Info: inject nat entry ino of nid 4 in pack 1: 4 -> 74565
> >
> > Inject ssa's nid
> > ================
> > inject.f2fs --ssa --blk $BLK --mb nid --val 0x12345 $DEV
> >
> > Info: inject ssa
> > Info: inject blkaddr 7511 : 0x1d57
> > Info: inject member nid
> > Info: inject value 74565 : 0x12345
> > [...]
> > Info: auto idx = 343
> > Info: inject summary entry nid of block 0x1d57: 0x4 -> 0x12345
> >
> > Inject inode's i_addr
> > =====================
> > inject.f2fs --node --nid $INO --mb i_addr --idx 100 --val 0x12345 $DEV
> >
> > Info: inject node
> > Info: inject nid 4 : 0x4
> > Info: inject member i_addr
> > Info: inject slot index 100
> > Info: inject value 74565 : 0x12345
> > [...]
> > Info: inject inode i_addr[100] of nid 4: 0x20864 -> 0x12345
> >
> > Inject inode's dentry hash
> > ==========================
> > inject.f2fs --dent --nid $INO --mb d_hash --val 0x12345 $DEV
> >
> > Info: inject dentry
> > Info: inject nid 4 : 0x4
> > Info: inject member d_hash
> > Info: inject value 74565 : 0x12345
> > [..]
> > Info: inject dentry d_hash of nid 4: 0xc77b804e -> 0x12345
> >
> > Sheng Yong (10):
> > f2fs-tools: export is_digits
> > inject.f2fs: introduce inject.f2fs
> > inject.f2fs: add sb injection
> > inject.f2fs: add cp injection
> > inject.f2fs: add nat injection
> > inject.f2fs: add sit injection
> > inject.f2fs: add ssa injection
> > inject.f2fs: add node injection
> > inject.f2fs: add dentry injection
> > man: add inject.f2fs man page
> >
> > fsck/Makefile.am | 5 +-
> > fsck/fsck.h | 6 +
> > fsck/inject.c | 1104 +++++++++++++++++++++++++++++++++++++++++++++
> > fsck/inject.h | 41 ++
> > fsck/main.c | 38 +-
> > fsck/mount.c | 30 +-
> > include/f2fs_fs.h | 2 +
> > man/Makefile.am | 2 +-
> > man/inject.f2fs.8 | 225 +++++++++
> > 9 files changed, 1447 insertions(+), 6 deletions(-)
> > create mode 100644 fsck/inject.c
> > create mode 100644 fsck/inject.h
> > create mode 100644 man/inject.f2fs.8
> >
> > --
> > 2.40.1
>
>
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [f2fs-dev] [RCF PATCH v3 00/10] f2fs-tools: introduce inject.f2fs
2024-07-10 23:04 ` Jaegeuk Kim
@ 2024-07-11 1:25 ` Sheng Yong via Linux-f2fs-devel
0 siblings, 0 replies; 19+ messages in thread
From: Sheng Yong via Linux-f2fs-devel @ 2024-07-11 1:25 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: linux-f2fs-devel
On 2024/7/11 7:04, Jaegeuk Kim wrote:
> On 07/10, Jaegeuk Kim wrote:
>> Hi Sheng,
>>
>> Can we have a list of tests to check the expected behavior of given
>> inject.f2fs followed by fsck.f2fs?
Hi, Jaegeuk,
Yes, I'm working on the testcases of fsck.f2fs and inject.f2fs. The basic
idea is:
1. creates an image by mkfs, and prepare some files for injection
2. inject faults into the image
3. fsck fixes the image
4. compare the output with the expected output (which is filtered to remove
information that changes frequently, like line number or block address).
Some testcases may requiremounting the image again to check file states.
For some complex testcases where there is no simple way to create the scenario,
we have to prepare the image file (with injected faults) in advance.
>
> And we need this.
>
> https://lore.kernel.org/linux-f2fs-devel/20240710230319.33025-1-jaegeuk@kernel.org/T/#u
>
Thanks for the fix.
Thanks,
shengyong
>>
>> Thanks,
>>
>> On 07/04, Sheng Yong wrote:
>>> This patchset introduces a new tool inject.f2fs to modify metadata or
>>> data (directory entry) of f2fs image offline flexibly.
>>>
>>> With inject.f2fs, it is easier to generate a corrupted f2fs image, which
>>> can help verify fsck or reproduce userspace behaviors of some a fault.
>>> If option `--dry-run' is used, nothing really gets changed, and that
>>> could be used to get the value of a specified field.
>>>
>>> inject.f2fs allows injecting some members in sb, cp, nat, sit, ssa, node
>>> and dentry for now. The available members of each part can be listed by
>>> executing command like:
>>> inject.f2fs --sb 0 --help
>>>
>>> [...]
>>> [mb]:
>>> magic: inject magic number
>>> s_stop_reason: inject s_stop_reason array selected by --idx <index>
>>> s_errors: inject s_errors array selected by --idx <index>
>>> devs.path: inject path in devs array selected by --idx <index> specified by --str <string>
>>>
>>> More injection fields are still work-in-progress. The TODO list includes:
>>> * sb: features
>>> * cp: fsync dnodes
>>> * inode: extent, extra attrs, xattr
>>> * data: fsverify?
>>> * other fields which is needed to verify fsck
>>>
>>> v3:
>>> * patch 3, fix error handling of inject sb->devs.path
>>> * patch 3, do not ASSERT devs.path when inject is executed
>>> * patch 3, allow inject to execute if image is umounted unclean
>>> * patch 9, check whether blkaddr is valid before reading dentry block
>>> * add is_digits and strtol entptr check when parsing numeric options
>>>
>>> v2:
>>> * change print format of s_errors
>>> * add write_raw_cp_blocks to write the first & last cp blocks directly
>>> to avoid updating ckpt_flags by write_checkpoint
>>> * call update_block if i_inode_checksum is injected to avoid updating
>>> i_inode_checksum by update_inode
>>> * go through all dentry blocks to find the target dir entry
>>>
>>> Examples:
>>>
>>> Inject sb's magic
>>> =================
>>> inject.f2fs --sb 0 --mb magic --val 0x12345 $DEV
>>>
>>> Info: inject sb auto
>>> Info: inject member magic
>>> Info: inject value 74565 : 0x12345
>>> [...]
>>> Info: inject magic of sb 1: 0xf2f52010 -> 0x12345
>>> [update_superblock: 890] Info: Done to update superblock
>>>
>>> Inject cp's cur_data_segno
>>> ==========================
>>> inject.f2fs --cp 0 --mb cur_data_segno --idx 1 --val 0x12345 $DEV
>>>
>>> Info: inject cp pack auto
>>> Info: inject member cur_data_segno
>>> Info: inject slot index 1
>>> Info: inject value 74565 : 0x12345
>>> [...]
>>> Info: inject cur_data_segno[1] of cp 1: 0x4 -> 0x12345
>>> Info: write_checkpoint() cur_cp:1
>>>
>>> Inject nat's ino
>>> ================
>>> inject.f2fs --nat 0 --mb ino --nid $INO --val 0x12345 $DEV
>>>
>>> Info: inject nat pack auto
>>> Info: inject nid 4 : 0x4
>>> Info: inject member ino
>>> Info: inject value 74565 : 0x12345
>>> [...]
>>> Info: inject nat entry ino of nid 4 in pack 1: 4 -> 74565
>>>
>>> Inject ssa's nid
>>> ================
>>> inject.f2fs --ssa --blk $BLK --mb nid --val 0x12345 $DEV
>>>
>>> Info: inject ssa
>>> Info: inject blkaddr 7511 : 0x1d57
>>> Info: inject member nid
>>> Info: inject value 74565 : 0x12345
>>> [...]
>>> Info: auto idx = 343
>>> Info: inject summary entry nid of block 0x1d57: 0x4 -> 0x12345
>>>
>>> Inject inode's i_addr
>>> =====================
>>> inject.f2fs --node --nid $INO --mb i_addr --idx 100 --val 0x12345 $DEV
>>>
>>> Info: inject node
>>> Info: inject nid 4 : 0x4
>>> Info: inject member i_addr
>>> Info: inject slot index 100
>>> Info: inject value 74565 : 0x12345
>>> [...]
>>> Info: inject inode i_addr[100] of nid 4: 0x20864 -> 0x12345
>>>
>>> Inject inode's dentry hash
>>> ==========================
>>> inject.f2fs --dent --nid $INO --mb d_hash --val 0x12345 $DEV
>>>
>>> Info: inject dentry
>>> Info: inject nid 4 : 0x4
>>> Info: inject member d_hash
>>> Info: inject value 74565 : 0x12345
>>> [..]
>>> Info: inject dentry d_hash of nid 4: 0xc77b804e -> 0x12345
>>>
>>> Sheng Yong (10):
>>> f2fs-tools: export is_digits
>>> inject.f2fs: introduce inject.f2fs
>>> inject.f2fs: add sb injection
>>> inject.f2fs: add cp injection
>>> inject.f2fs: add nat injection
>>> inject.f2fs: add sit injection
>>> inject.f2fs: add ssa injection
>>> inject.f2fs: add node injection
>>> inject.f2fs: add dentry injection
>>> man: add inject.f2fs man page
>>>
>>> fsck/Makefile.am | 5 +-
>>> fsck/fsck.h | 6 +
>>> fsck/inject.c | 1104 +++++++++++++++++++++++++++++++++++++++++++++
>>> fsck/inject.h | 41 ++
>>> fsck/main.c | 38 +-
>>> fsck/mount.c | 30 +-
>>> include/f2fs_fs.h | 2 +
>>> man/Makefile.am | 2 +-
>>> man/inject.f2fs.8 | 225 +++++++++
>>> 9 files changed, 1447 insertions(+), 6 deletions(-)
>>> create mode 100644 fsck/inject.c
>>> create mode 100644 fsck/inject.h
>>> create mode 100644 man/inject.f2fs.8
>>>
>>> --
>>> 2.40.1
>>
>>
>> _______________________________________________
>> Linux-f2fs-devel mailing list
>> Linux-f2fs-devel@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 19+ messages in thread