This patch enables injecting nat entry. print_raw_nat_entry_info() is
added to show values of the nat entry.

The meanings of options are:
 * nat: means nat entry is injected, its argument chooses which nat pack
        to be injected, where 0 means the current valid nat is choosen
        automatically.
 * nid: is the nid of the nat entry

The members could be injected in cp contains:
 * version: nat entry version
 * ino: nat entry ino
 * block_addr: nat entry block_addr

Signed-off-by: Sheng Yong <shengy...@oppo.com>
---
 fsck/inject.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++
 fsck/inject.h |   2 +
 fsck/main.c   |   2 +
 3 files changed, 123 insertions(+)

diff --git a/fsck/inject.c b/fsck/inject.c
index e7ec329..c2deaba 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -12,6 +12,16 @@
 #include <getopt.h>
 #include "inject.h"
 
+static void print_raw_nat_entry_info(struct f2fs_nat_entry *ne)
+{
+       if (!c.dbg_lv)
+               return;
+
+       DISP_u8(ne, version);
+       DISP_u32(ne, ino);
+       DISP_u32(ne, block_addr);
+}
+
 void inject_usage(void)
 {
        MSG(0, "\nUsage: inject.f2fs [options] device\n");
@@ -22,8 +32,10 @@ void inject_usage(void)
        MSG(0, "  --val <new value> new value to set\n");
        MSG(0, "  --str <new string> new string to set\n");
        MSG(0, "  --idx <slot index> which slot is injected in an array\n");
+       MSG(0, "  --nid <nid> which nid is injected\n");
        MSG(0, "  --sb <0|1|2> --mb <name> [--idx <index>] --val/str 
<value/string> inject superblock\n");
        MSG(0, "  --cp <0|1|2> --mb <name> [--idx <index>] --val <value> inject 
checkpoint\n");
+       MSG(0, "  --nat <0|1|2> --mb <name> --nid <nid> --val <value> inject 
nat entry\n");
        MSG(0, "  --dry-run do not really inject\n");
 
        exit(1);
@@ -59,6 +71,19 @@ static void inject_cp_usage(void)
        MSG(0, "  cur_data_blkoff: inject cur_data_blkoff array selected by 
--idx <index>\n");
 }
 
+static void inject_nat_usage(void)
+{
+       MSG(0, "inject.f2fs --nat <0|1|2> --mb <name> --nid <nid> --val <value> 
inject nat entry\n");
+       MSG(0, "[nat]:\n");
+       MSG(0, "  0: auto select the current nat pack\n");
+       MSG(0, "  1: select the first nat pack\n");
+       MSG(0, "  2: select the second nat pack\n");
+       MSG(0, "[mb]:\n");
+       MSG(0, "  version: inject nat entry version\n");
+       MSG(0, "  ino: inject nat entry ino\n");
+       MSG(0, "  block_addr: inject nat entry block_addr\n");
+}
+
 int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
 {
        int o = 0;
@@ -72,6 +97,8 @@ int inject_parse_options(int argc, char *argv[], struct 
inject_option *opt)
                {"str", required_argument, 0, 5},
                {"sb", required_argument, 0, 6},
                {"cp", required_argument, 0, 7},
+               {"nat", required_argument, 0, 8},
+               {"nid", required_argument, 0, 9},
                {0, 0, 0, 0}
        };
 
@@ -115,6 +142,18 @@ int inject_parse_options(int argc, char *argv[], struct 
inject_option *opt)
                                return -ERANGE;
                        MSG(0, "Info: inject cp pack %s\n", pack[opt->cp]);
                        break;
+               case 8:
+                       opt->nat = atoi(optarg);
+                       if (opt->nat < 0 || opt->nat > 2)
+                               return -ERANGE;
+                       MSG(0, "Info: inject nat pack %s\n", pack[opt->nat]);
+                       break;
+               case 9:
+                       opt->nid = strtol(optarg, NULL, 0);
+                       if (opt->nid == ULONG_MAX || opt->nid == LONG_MIN)
+                               return -ERANGE;
+                       MSG(0, "Info: inject nid %u : 0x%x\n", opt->nid, 
opt->nid);
+                       break;
                case 'd':
                        if (optarg[0] == '-' || !is_digits(optarg))
                                return EWRONG_OPT;
@@ -132,6 +171,9 @@ int inject_parse_options(int argc, char *argv[], struct 
inject_option *opt)
                        } else if (opt->cp >= 0) {
                                inject_cp_usage();
                                exit(0);
+                       } else if (opt->nat >= 0) {
+                               inject_nat_usage();
+                               exit(0);
                        }
                        return EUNKNOWN_OPT;
                }
@@ -306,6 +348,81 @@ out:
        return ret;
 }
 
+static int inject_nat(struct f2fs_sb_info *sbi, struct inject_option *opt)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
+       struct f2fs_nat_block *nat_blk;
+       struct f2fs_nat_entry *ne;
+       block_t blk_addr;
+       unsigned int offs;
+       bool is_set;
+       int ret;
+
+       if (!IS_VALID_NID(sbi, opt->nid)) {
+               ERR_MSG("Invalid nid %u range [%u:%lu]\n", opt->nid, 0,
+                       NAT_ENTRY_PER_BLOCK *
+                       ((get_sb(segment_count_nat) << 1) <<
+                        sbi->log_blocks_per_seg));
+               return -EINVAL;
+       }
+
+       nat_blk = calloc(F2FS_BLKSIZE, 1);
+       ASSERT(nat_blk);
+
+       /* change NAT version bitmap temporarily to select specified pack */
+       is_set = f2fs_test_bit(opt->nid, nm_i->nat_bitmap);
+       if (opt->nat == 0) {
+               opt->nat = is_set ? 2 : 1;
+       } else {
+               if (opt->nat == 1)
+                       f2fs_clear_bit(opt->nid, nm_i->nat_bitmap);
+               else
+                       f2fs_set_bit(opt->nid, nm_i->nat_bitmap);
+       }
+
+       blk_addr = current_nat_addr(sbi, opt->nid, NULL);
+
+       ret = dev_read_block(nat_blk, blk_addr);
+       ASSERT(ret >= 0);
+
+       offs = opt->nid % NAT_ENTRY_PER_BLOCK;
+       ne = &nat_blk->entries[offs];
+
+       if (!strcmp(opt->mb, "version")) {
+               MSG(0, "Info: inject nat entry version of nid %u "
+                   "in pack %d: %d -> %d\n", opt->nid, opt->nat,
+                   ne->version, (u8)opt->val);
+               ne->version = (u8)opt->val;
+       } else if (!strcmp(opt->mb, "ino")) {
+               MSG(0, "Info: inject nat entry ino of nid %u "
+                   "in pack %d: %d -> %d\n", opt->nid, opt->nat,
+                   le32_to_cpu(ne->ino), (nid_t)opt->val);
+               ne->ino = cpu_to_le32((nid_t)opt->val);
+       } else if (!strcmp(opt->mb, "block_addr")) {
+               MSG(0, "Info: inject nat entry block_addr of nid %u "
+                   "in pack %d: 0x%x -> 0x%x\n", opt->nid, opt->nat,
+                   le32_to_cpu(ne->block_addr), (block_t)opt->val);
+               ne->block_addr = cpu_to_le32((block_t)opt->val);
+       } else {
+               ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
+               free(nat_blk);
+               return -EINVAL;
+       }
+       print_raw_nat_entry_info(ne);
+
+       ret = dev_write_block(nat_blk, blk_addr);
+       ASSERT(ret >= 0);
+       /* restore NAT version bitmap */
+       if (is_set)
+               f2fs_set_bit(opt->nid, nm_i->nat_bitmap);
+       else
+               f2fs_clear_bit(opt->nid, nm_i->nat_bitmap);
+
+       free(nat_blk);
+       return ret;
+}
+
 int do_inject(struct f2fs_sb_info *sbi)
 {
        struct inject_option *opt = (struct inject_option *)c.private;
@@ -315,6 +432,8 @@ int do_inject(struct f2fs_sb_info *sbi)
                ret = inject_sb(sbi, opt);
        else if (opt->cp >= 0)
                ret = inject_cp(sbi, opt);
+       else if (opt->nat >= 0)
+               ret = inject_nat(sbi, opt);
 
        return ret;
 }
diff --git a/fsck/inject.h b/fsck/inject.h
index 907309f..db45fb9 100644
--- a/fsck/inject.h
+++ b/fsck/inject.h
@@ -24,8 +24,10 @@ struct inject_option {
        unsigned int idx;       /* slot index */
        long long val;          /* new value */
        char *str;              /* new string */
+       nid_t nid;
        int sb;                 /* which sb */
        int cp;                 /* which cp */
+       int nat;                /* which nat pack */
 };
 
 void inject_usage(void);
diff --git a/fsck/main.c b/fsck/main.c
index 0318873..3ab49a4 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -820,7 +820,9 @@ void f2fs_parse_options(int argc, char *argv[])
                static struct inject_option inject_opt = {
                        .sb = -1,
                        .cp = -1,
+                       .nat = -1,
                        .idx = -1,
+                       .nid = -1,
                };
 
                err = inject_parse_options(argc, argv, &inject_opt);
-- 
2.40.1



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to