On 6/10/25 20:37, Sheng Yong wrote: > From: Sheng Yong <shengyo...@xiaomi.com> > > Previously when injecting sit/nat entry, we only inject SIT/NAT pack. > If the valid target is in journal, the injection has no effect. So we > have to check whether the valid target is in journal, and inject the > target at its valid position. > > Signed-off-by: Sheng Yong <shengyo...@xiaomi.com> > --- > fsck/inject.c | 181 ++++++++++++++++++++++++++++++++++++-------------- > 1 file changed, 132 insertions(+), 49 deletions(-) > > diff --git a/fsck/inject.c b/fsck/inject.c > index bd6ab8480972..b3228621de48 100644 > --- a/fsck/inject.c > +++ b/fsck/inject.c > @@ -10,6 +10,7 @@ > */ > > #include <getopt.h> > +#include "f2fs.h" > #include "node.h" > #include "inject.h" > > @@ -533,6 +534,31 @@ out: > return ret; > } > > +static void rewrite_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, > + struct f2fs_nat_entry *nat) > +{ > + struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); > + struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); > + struct f2fs_journal *journal = > F2FS_SUMMARY_BLOCK_JOURNAL(curseg->sum_blk); > + block_t blkaddr; > + int ret, i; > + > + for (i = 0; i < nats_in_cursum(journal); i++) { > + if (nid_in_journal(journal, i) == nid) { > + memcpy(&nat_in_journal(journal, i), nat, sizeof(*nat)); > + break; > + } > + } > + > + if (is_set_ckpt_flags(cp, CP_UMOUNT_FLAG)) > + blkaddr = sum_blk_addr(sbi, NR_CURSEG_TYPE, CURSEG_HOT_DATA); > + else > + blkaddr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, > CURSEG_HOT_DATA); > + > + ret = dev_write_block(curseg->sum_blk, blkaddr, WRITE_LIFE_NONE); > + ASSERT(ret >= 0); > +} > + > static int inject_nat(struct f2fs_sb_info *sbi, struct inject_option *opt) > { > struct f2fs_nm_info *nm_i = NM_I(sbi); > @@ -541,7 +567,7 @@ static int inject_nat(struct f2fs_sb_info *sbi, struct > inject_option *opt) > struct f2fs_nat_entry *ne; > block_t blk_addr; > unsigned int offs; > - bool is_set; > + bool is_set, in_journal = false; > int ret; > > if (!IS_VALID_NID(sbi, opt->nid)) { > @@ -555,38 +581,49 @@ static int inject_nat(struct f2fs_sb_info *sbi, struct > inject_option *opt) > 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; > + if (lookup_nat_in_journal(sbi, opt->nid, &nat_blk->entries[0]) >= 0) {
Yong, If we found an existed nat entry in journal, what about getting log_type from return value of lookup_nat_in_journal, and then call rewrite_nat_in_journal(, log_type) to rewrite nat entry to original position? > + offs = 0; > + in_journal = true; > } else { > - if (opt->nat == 1) > - f2fs_clear_bit(opt->nid, nm_i->nat_bitmap); > - else > - f2fs_set_bit(opt->nid, nm_i->nat_bitmap); > + /* > + * read nat entry from NAT area, 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; > } > - > - 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, > + "in %s %d: %d -> %d\n", opt->nid, > + in_journal ? "journal" : "pack", > + in_journal ? 0 : 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, > + "in %s %d: %d -> %d\n", opt->nid, > + in_journal ? "journal" : "pack", > + in_journal ? 0 : 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, > + "in %s %d: 0x%x -> 0x%x\n", opt->nid, > + in_journal ? "journal" : "pack", > + in_journal ? 0 : opt->nat, > le32_to_cpu(ne->block_addr), (block_t)opt->val); > ne->block_addr = cpu_to_le32((block_t)opt->val); > } else { > @@ -596,16 +633,45 @@ static int inject_nat(struct f2fs_sb_info *sbi, struct > inject_option *opt) > } > print_raw_nat_entry_info(ne); > > - ret = dev_write_block(nat_blk, blk_addr, WRITE_LIFE_NONE); > - 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); > + if (in_journal) { > + rewrite_nat_in_journal(sbi, opt->nid, ne); > + } else { > + ret = dev_write_block(nat_blk, blk_addr, WRITE_LIFE_NONE); > + 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; > + return 0; > +} > + > +static void rewrite_sit_in_journal(struct f2fs_sb_info *sbi, unsigned int > segno, > + struct f2fs_sit_entry *sit) > +{ > + struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); > + struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); > + struct f2fs_journal *journal = > F2FS_SUMMARY_BLOCK_JOURNAL(curseg->sum_blk); > + block_t blkaddr; > + int ret, i; > + > + for (i = 0; i < sits_in_cursum(journal); i++) { > + if (segno_in_journal(journal, i) == segno) { > + memcpy(&sit_in_journal(journal, i), sit, sizeof(*sit)); > + break; > + } > + } > + > + if (is_set_ckpt_flags(cp, CP_UMOUNT_FLAG)) > + blkaddr = sum_blk_addr(sbi, NR_CURSEG_TYPE, CURSEG_COLD_DATA); > + else > + blkaddr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, > CURSEG_COLD_DATA); > + > + ret = dev_write_block(curseg->sum_blk, blkaddr, WRITE_LIFE_NONE); > + ASSERT(ret >= 0); > } > > static int inject_sit(struct f2fs_sb_info *sbi, struct inject_option *opt) > @@ -614,7 +680,7 @@ static int inject_sit(struct f2fs_sb_info *sbi, struct > inject_option *opt) > struct f2fs_sit_block *sit_blk; > struct f2fs_sit_entry *sit; > unsigned int segno, offs; > - bool is_set; > + bool is_set, in_journal = false; > > if (!f2fs_is_valid_blkaddr(sbi, opt->blk, DATA_GENERIC)) { > ERR_MSG("Invalid blkaddr 0x%x (valid range [0x%x:0x%lx])\n", > @@ -627,29 +693,39 @@ static int inject_sit(struct f2fs_sb_info *sbi, struct > inject_option *opt) > 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; > + if (lookup_sit_in_journal(sbi, segno, &sit_blk->entries[0]) >= 0) { Ditto, Thanks, > + offs = 0; > + in_journal = true; > } else { > - if (opt->sit == 1) > - f2fs_clear_bit(segno, sit_i->sit_bitmap); > - else > - f2fs_set_bit(segno, sit_i->sit_bitmap); > + /* > + * read sit entry from SIT area, 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); > } > - 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, > + "in %s %d: %u -> %u\n", opt->blk, > + in_journal ? "journal" : "pack", > + in_journal ? 0 : 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; > + opt->idx = OFFSET_IN_SEG(sbi, opt->blk); > + MSG(0, "Info: auto idx = %u\n", opt->idx); > } > if (opt->idx >= SIT_VBLOCK_MAP_SIZE) { > ERR_MSG("invalid idx %u of valid_map[]\n", opt->idx); > @@ -657,8 +733,10 @@ static int inject_sit(struct f2fs_sb_info *sbi, struct > inject_option *opt) > 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); > + "in %s %d: 0x%02x -> 0x%02x\n", opt->idx, opt->blk, > + in_journal ? "journal" : "pack", > + in_journal ? 0 : 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 " > @@ -672,12 +750,17 @@ static int inject_sit(struct f2fs_sb_info *sbi, struct > inject_option *opt) > } > 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); > + if (in_journal) { > + rewrite_sit_in_journal(sbi, segno, sit); > + } else { > + 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; _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel