On 6/10/25 20:37, Sheng Yong wrote:
> From: Sheng Yong <[email protected]>
>
> 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 <[email protected]>
> ---
> 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel