diff mbox series

[f2fs-dev,RFC,v2,02/10] inject.f2fs: introduce inject.f2fs

Message ID 20240628013140.2444209-3-shengyong@oppo.com (mailing list archive)
State New
Headers show
Series f2fs-tools: introduce inject.f2fs | expand

Commit Message

Sheng Yong June 28, 2024, 1:31 a.m. UTC
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.

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 mbox series

Patch

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 9bda412..f093ca7 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;
 
@@ -190,6 +199,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");
 }
@@ -804,6 +815,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) {
@@ -1224,6 +1247,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 {