This patch enables injecting sit entry. print_raw_sit_entry_info() is
added to show values of the sit entry.

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

The members could be injected in cp contains:
 * vblocks: sit entry vblocks
 * valid_map: sit entry valid_map
 * mtime: sit entry mtime

Reviewed-by: Chao Yu <c...@kernel.org>
Signed-off-by: Sheng Yong <shengy...@oppo.com>
---
 fsck/inject.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++
 fsck/inject.h |   2 +
 fsck/main.c   |   1 +
 3 files changed, 136 insertions(+)

diff --git a/fsck/inject.c b/fsck/inject.c
index b6f5c59..5799353 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -22,6 +22,27 @@ static void print_raw_nat_entry_info(struct f2fs_nat_entry 
*ne)
        DISP_u32(ne, block_addr);
 }
 
+static void print_raw_sit_entry_info(struct f2fs_sit_entry *se)
+{
+       int i;
+
+       if (!c.dbg_lv)
+               return;
+
+       DISP_u16(se, vblocks);
+       if (c.layout)
+               printf("%-30s ", "valid_map:");
+       else
+               printf("%-30s\t\t[", "valid_map");
+       for (i = 0; i < SIT_VBLOCK_MAP_SIZE; i++)
+               printf("%02x", se->valid_map[i]);
+       if (c.layout)
+               printf("\n");
+       else
+               printf("]\n");
+       DISP_u64(se, mtime);
+}
+
 void inject_usage(void)
 {
        MSG(0, "\nUsage: inject.f2fs [options] device\n");
@@ -33,9 +54,11 @@ void inject_usage(void)
        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, "  --blk <blkaddr> which blkaddr 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, "  --sit <0|1|2> --mb <name> --blk <blk> [--idx <index>] --val 
<value> inject sit entry\n");
        MSG(0, "  --dry-run do not really inject\n");
 
        exit(1);
@@ -84,6 +107,19 @@ static void inject_nat_usage(void)
        MSG(0, "  block_addr: inject nat entry block_addr\n");
 }
 
+static void inject_sit_usage(void)
+{
+       MSG(0, "inject.f2fs --sit <0|1|2> --mb <name> --blk <blk> [--idx 
<index>] --val <value> inject sit entry\n");
+       MSG(0, "[sit]:\n");
+       MSG(0, "  0: auto select the current sit pack\n");
+       MSG(0, "  1: select the first sit pack\n");
+       MSG(0, "  2: select the second sit pack\n");
+       MSG(0, "[mb]:\n");
+       MSG(0, "  vblocks: inject sit entry vblocks\n");
+       MSG(0, "  valid_map: inject sit entry valid_map\n");
+       MSG(0, "  mtime: inject sit entry mtime\n");
+}
+
 int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
 {
        int o = 0;
@@ -100,6 +136,8 @@ int inject_parse_options(int argc, char *argv[], struct 
inject_option *opt)
                {"cp", required_argument, 0, 7},
                {"nat", required_argument, 0, 8},
                {"nid", required_argument, 0, 9},
+               {"sit", required_argument, 0, 10},
+               {"blk", required_argument, 0, 11},
                {0, 0, 0, 0}
        };
 
@@ -165,6 +203,21 @@ int inject_parse_options(int argc, char *argv[], struct 
inject_option *opt)
                                return -ERANGE;
                        MSG(0, "Info: inject nid %u : 0x%x\n", opt->nid, 
opt->nid);
                        break;
+               case 10:
+                       if (!is_digits(optarg))
+                               return EWRONG_OPT;
+                       opt->sit = atoi(optarg);
+                       if (opt->sit < 0 || opt->sit > 2)
+                               return -ERANGE;
+                       MSG(0, "Info: inject sit pack %s\n", pack[opt->sit]);
+                       break;
+               case 11:
+                       opt->blk = strtol(optarg, &endptr, 0);
+                       if (opt->blk == LONG_MAX || opt->blk == LONG_MIN ||
+                           *endptr != '\0')
+                               return -ERANGE;
+                       MSG(0, "Info: inject blkaddr %u : 0x%x\n", opt->blk, 
opt->blk);
+                       break;
                case 'd':
                        if (optarg[0] == '-' || !is_digits(optarg))
                                return EWRONG_OPT;
@@ -185,6 +238,9 @@ int inject_parse_options(int argc, char *argv[], struct 
inject_option *opt)
                        } else if (opt->nat >= 0) {
                                inject_nat_usage();
                                exit(0);
+                       } else if (opt->sit >= 0) {
+                               inject_sit_usage();
+                               exit(0);
                        }
                        return EUNKNOWN_OPT;
                }
@@ -435,6 +491,81 @@ static int inject_nat(struct f2fs_sb_info *sbi, struct 
inject_option *opt)
        return ret;
 }
 
+static int inject_sit(struct f2fs_sb_info *sbi, struct inject_option *opt)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       struct f2fs_sit_block *sit_blk;
+       struct f2fs_sit_entry *sit;
+       unsigned int segno, offs;
+       bool is_set;
+
+       if (!f2fs_is_valid_blkaddr(sbi, opt->blk, DATA_GENERIC)) {
+               ERR_MSG("Invalid blkaddr 0x%x (valid range [0x%x:0x%lx])\n",
+                       opt->blk, SM_I(sbi)->main_blkaddr,
+                       (unsigned 
long)le64_to_cpu(F2FS_RAW_SUPER(sbi)->block_count));
+               return -EINVAL;
+       }
+
+       sit_blk = calloc(F2FS_BLKSIZE, 1);
+       ASSERT(sit_blk);
+
+       segno = GET_SEGNO(sbi, opt->blk);
+       /* change SIT version bitmap temporarily to select specified pack */
+       is_set = f2fs_test_bit(segno, sit_i->sit_bitmap);
+       if (opt->sit == 0) {
+               opt->sit = is_set ? 2 : 1;
+       } else {
+               if (opt->sit == 1)
+                       f2fs_clear_bit(segno, sit_i->sit_bitmap);
+               else
+                       f2fs_set_bit(segno, sit_i->sit_bitmap);
+       }
+       get_current_sit_page(sbi, segno, sit_blk);
+       offs = SIT_ENTRY_OFFSET(sit_i, segno);
+       sit = &sit_blk->entries[offs];
+
+       if (!strcmp(opt->mb, "vblocks")) {
+               MSG(0, "Info: inject sit entry vblocks of block 0x%x "
+                   "in pack %d: %u -> %u\n", opt->blk, opt->sit,
+                   le16_to_cpu(sit->vblocks), (u16)opt->val);
+               sit->vblocks = cpu_to_le16((u16)opt->val);
+       } else if (!strcmp(opt->mb, "valid_map")) {
+               if (opt->idx == -1) {
+                       MSG(0, "Info: auto idx = %u\n", offs);
+                       opt->idx = offs;
+               }
+               if (opt->idx >= SIT_VBLOCK_MAP_SIZE) {
+                       ERR_MSG("invalid idx %u of valid_map[]\n", opt->idx);
+                       free(sit_blk);
+                       return -ERANGE;
+               }
+               MSG(0, "Info: inject sit entry valid_map[%d] of block 0x%x "
+                   "in pack %d: 0x%02x -> 0x%02x\n", opt->idx, opt->blk,
+                   opt->sit, sit->valid_map[opt->idx], (u8)opt->val);
+               sit->valid_map[opt->idx] = (u8)opt->val;
+       } else if (!strcmp(opt->mb, "mtime")) {
+               MSG(0, "Info: inject sit entry mtime of block 0x%x "
+                   "in pack %d: %lu -> %lu\n", opt->blk, opt->sit,
+                   le64_to_cpu(sit->mtime), (u64)opt->val);
+               sit->mtime = cpu_to_le64((u64)opt->val);
+       } else {
+               ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
+               free(sit_blk);
+               return -EINVAL;
+       }
+       print_raw_sit_entry_info(sit);
+
+       rewrite_current_sit_page(sbi, segno, sit_blk);
+       /* restore SIT version bitmap */
+       if (is_set)
+               f2fs_set_bit(segno, sit_i->sit_bitmap);
+       else
+               f2fs_clear_bit(segno, sit_i->sit_bitmap);
+
+       free(sit_blk);
+       return 0;
+}
+
 int do_inject(struct f2fs_sb_info *sbi)
 {
        struct inject_option *opt = (struct inject_option *)c.private;
@@ -446,6 +577,8 @@ int do_inject(struct f2fs_sb_info *sbi)
                ret = inject_cp(sbi, opt);
        else if (opt->nat >= 0)
                ret = inject_nat(sbi, opt);
+       else if (opt->sit >= 0)
+               ret = inject_sit(sbi, opt);
 
        return ret;
 }
diff --git a/fsck/inject.h b/fsck/inject.h
index db45fb9..ece4915 100644
--- a/fsck/inject.h
+++ b/fsck/inject.h
@@ -25,9 +25,11 @@ struct inject_option {
        long long val;          /* new value */
        char *str;              /* new string */
        nid_t nid;
+       block_t blk;
        int sb;                 /* which sb */
        int cp;                 /* which cp */
        int nat;                /* which nat pack */
+       int sit;                /* which sit pack */
 };
 
 void inject_usage(void);
diff --git a/fsck/main.c b/fsck/main.c
index 8527199..bfdb5ba 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -826,6 +826,7 @@ void f2fs_parse_options(int argc, char *argv[])
                        .sb = -1,
                        .cp = -1,
                        .nat = -1,
+                       .sit = -1,
                        .idx = -1,
                        .nid = -1,
                };
-- 
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