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 <shengy...@oppo.com> --- fsck/inject.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++ fsck/inject.h | 1 + 2 files changed, 149 insertions(+) diff --git a/fsck/inject.c b/fsck/inject.c index 20ae87c..3d26b25 100644 --- a/fsck/inject.c +++ b/fsck/inject.c @@ -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; } 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