@@ -74,6 +74,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 +103,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 +198,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;
@@ -205,6 +227,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}
};
@@ -280,6 +303,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;
@@ -309,6 +336,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;
}
@@ -879,6 +909,122 @@ out:
return ret;
}
+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;
+ int ofs;
+ int i, slot;
+ struct f2fs_dir_entry *dent = NULL;
+ nid_t pino;
+ int ret;
+
+ node_blk = malloc(F2FS_BLKSIZE);
+ ASSERT(node_blk != NULL);
+
+ /* child */
+ get_node_info(sbi, opt->nid, &ni);
+ ret = dev_read_block(node_blk, ni.blk_addr);
+ ASSERT(ret >= 0);
+ inode = &node_blk->i;
+ pino = le32_to_cpu(inode->i_pino);
+
+ /* parent */
+ get_node_info(sbi, pino, &ni);
+ ret = dev_read_block(node_blk, ni.blk_addr);
+ ASSERT(ret >= 0);
+ inode = &node_blk->i;
+
+ /* locate dentry */
+ ofs = get_extra_isize(node_blk);
+ 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;
+
+ for (slot = 0; slot < d.max; slot++) {
+ dent = &d.dentry[slot];
+ if (dent->ino == opt->nid && dent->hash_code != 0)
+ break;
+ dent = NULL;
+ }
+ } else {
+ dent_blk = malloc(F2FS_BLKSIZE);
+ ASSERT(dent_blk != NULL);
+
+ for (i = ofs; i < DEF_ADDRS_PER_INODE; i++) {
+ addr = le32_to_cpu(inode->i_addr[i]);
+ if (addr == NULL_ADDR || addr == COMPRESS_ADDR || addr == NEW_ADDR)
+ continue;
+
+ ret = dev_read_block(dent_blk, addr);
+ ASSERT(ret >= 0);
+
+ make_dentry_ptr(&d, node_blk, dent_blk, 1);
+ buf = dent_blk;
+ for (slot = 0; slot < d.max; slot++) {
+ dent = &d.dentry[slot];
+ if (dent->ino == opt->nid && dent->hash_code != 0)
+ break;
+ dent = NULL;
+ }
+ if (dent != NULL)
+ break;
+ }
+ }
+
+ if (dent == NULL) {
+ 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;
@@ -896,6 +1042,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;
}
@@ -32,6 +32,7 @@ struct inject_option {
int sit; /* which sit pack */
bool ssa;
bool node;
+ bool dent;
};
void inject_usage(void);
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 | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++ fsck/inject.h | 1 + 2 files changed, 149 insertions(+)