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