inject.f2fs: introduce inject.f2fs

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>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Sheng Yong 2024-07-04 10:57:32 +08:00 committed by Jaegeuk Kim
parent a9066a4e23
commit b39aa80647
5 changed files with 126 additions and 2 deletions

View File

@ -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

64
fsck/inject.c Normal file
View File

@ -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;
}

28
fsck/inject.h Normal file
View File

@ -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

View File

@ -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;
@ -196,6 +205,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");
}
@ -818,6 +829,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) {
@ -1238,6 +1261,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");

View File

@ -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 {