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

Reply via email to