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) {
+               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) {
+               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;
-- 
2.43.0



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

Reply via email to