linux-f2fs-devel.lists.sourceforge.net archive mirror
 help / color / mirror / Atom feed
* [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections
@ 2025-08-20 12:42 Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 01/13] fsck.f2fs: do not finish/reset zone if dry-run is true Sheng Yong
                   ` (13 more replies)
  0 siblings, 14 replies; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

Hi, all,

Since we have not yet determined how to check the test result properly,
I split patchset v2 into two parts on Chao's suggestion. This is the
first part which contains some fixes/cleanups for f2fs-tools, and adds
new injections for inject.f2fs.

Changes from last version are also updated in individual patch.

v3: * split original patchset into two parts
    * update manual
    * refactor inject sit/nat in journal
    * fix memleak
v2: * add some fix and cleanup
    * remove img.tar.gz from testcases
    * add testcases for injection
    * cleanup helpers script and simplify filter.sed and expected.in
    https://lore.kernel.org/linux-f2fs-devel/20250610123743.667183-1-shengyong1@xiaomi.com/
v1: https://lore.kernel.org/linux-f2fs-devel/20241029120956.4186731-1-shengyong@oppo.com/

Sheng Yong (13):
  fsck.f2fs: do not finish/reset zone if dry-run is true
  f2fs-tools: add option N to answer no for all questions
  f2fs-tools: cleanup {nid|segno}_in_journal
  fsck.f2fs: fix invalidate checkpoint
  dump.f2fs: print more info
  f2fs-tools: add and export lookup_sit_in_journal
  inject.f2fs: fix injecting sit/nat in journal
  inject.f2fs: fix injection on zoned device
  inject.f2fs: fix and cleanup parsing numeric options
  inject.f2fs: add members in inject_cp
  inject.f2fs: add member `feature' in inject_sb
  inject.f2fs: add members in inject_node
  inject.f2fs: add member `filename' in inject_dentry

 fsck/dump.c         |  15 +-
 fsck/f2fs.h         |  12 +-
 fsck/fsck.c         |   2 +-
 fsck/fsck.h         |   4 +-
 fsck/inject.c       | 515 ++++++++++++++++++++++++++++++++++++--------
 fsck/inject.h       |   1 +
 fsck/main.c         |  14 +-
 fsck/mount.c        |  61 ++++--
 include/f2fs_fs.h   |   1 +
 lib/libf2fs_zoned.c |   6 +-
 man/dump.f2fs.8     |   3 +
 man/fsck.f2fs.8     |   3 +
 man/inject.f2fs.8   |  43 +++-
 13 files changed, 552 insertions(+), 128 deletions(-)

-- 
2.43.0



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

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH v3 01/13] fsck.f2fs: do not finish/reset zone if dry-run is true
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
@ 2025-08-20 12:42 ` Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 02/13] f2fs-tools: add option N to answer no for all questions Sheng Yong
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

From: Sheng Yong <shengyong1@xiaomi.com>

Signed-off-by: Sheng Yong <shengyong1@xiaomi.com>
---
 lib/libf2fs_zoned.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/libf2fs_zoned.c b/lib/libf2fs_zoned.c
index 6730bba0da82..92791a768807 100644
--- a/lib/libf2fs_zoned.c
+++ b/lib/libf2fs_zoned.c
@@ -429,7 +429,7 @@ int f2fs_reset_zone(int i, void *blkzone)
 	struct blk_zone_range range;
 	int ret;
 
-	if (!blk_zone_seq(blkz) || blk_zone_empty(blkz))
+	if (!blk_zone_seq(blkz) || blk_zone_empty(blkz) || c.dry_run)
 		return 0;
 
 	/* Non empty sequential zone: reset */
@@ -484,7 +484,7 @@ int f2fs_reset_zones(int j)
 		blkz = (struct blk_zone *)(rep + 1);
 		for (i = 0; i < rep->nr_zones && sector < total_sectors; i++) {
 			if (blk_zone_seq(blkz) &&
-			    !blk_zone_empty(blkz)) {
+			    !blk_zone_empty(blkz) && !c.dry_run) {
 				/* Non empty sequential zone: reset */
 				range.sector = blk_zone_sector(blkz);
 				range.nr_sectors = blk_zone_length(blkz);
@@ -513,7 +513,7 @@ int f2fs_finish_zone(int i, void *blkzone)
 	struct blk_zone_range range;
 	int ret;
 
-	if (!blk_zone_seq(blkz) || !blk_zone_open(blkz))
+	if (!blk_zone_seq(blkz) || !blk_zone_open(blkz) || c.dry_run)
 		return 0;
 
 	/* Non empty sequential zone: finish */
-- 
2.43.0



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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH v3 02/13] f2fs-tools: add option N to answer no for all questions
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 01/13] fsck.f2fs: do not finish/reset zone if dry-run is true Sheng Yong
@ 2025-08-20 12:42 ` Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 03/13] f2fs-tools: cleanup {nid|segno}_in_journal Sheng Yong
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

From: Sheng Yong <shengyong1@xiaomi.com>

In some scenario, such as autotest, it is not expected to answer
question from fsck or dump. To simply answer no to all these questions,
this patch adds an option `N' to do that.

Signed-off-by: Sheng Yong <shengyong1@xiaomi.com>
---
v3: update manual
---
 fsck/dump.c       |  3 +++
 fsck/fsck.c       |  2 +-
 fsck/main.c       | 14 +++++++++++---
 include/f2fs_fs.h |  1 +
 man/dump.f2fs.8   |  3 +++
 man/fsck.f2fs.8   |  3 +++
 6 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/fsck/dump.c b/fsck/dump.c
index 66d6c791ae09..10df7e593bfe 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -681,6 +681,9 @@ static int dump_filesystem(struct f2fs_sb_info *sbi, struct node_info *ni,
 	if (c.show_file_map)
 		return dump_inode_blk(sbi, ni->ino, node_blk);
 
+	if (c.answer_no)
+		return 0;
+
 	printf("Do you want to dump this %s into %s/? [Y/N] ",
 			S_ISDIR(imode) ? "folder" : "file",
 			base_path);
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 4c36dc1d0451..0b53c67e3b8a 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -3848,7 +3848,7 @@ int fsck_verify(struct f2fs_sb_info *sbi)
 	}
 
 #ifndef WITH_ANDROID
-	if (nr_unref_nid && !c.ro) {
+	if (nr_unref_nid && !c.ro && !c.answer_no) {
 		char ans[255] = {0};
 		int res;
 
diff --git a/fsck/main.c b/fsck/main.c
index 324629ea531b..d034dc39218c 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -86,6 +86,7 @@ void fsck_usage()
 	MSG(0, "  -t show directory tree\n");
 	MSG(0, "  -q preserve quota limits\n");
 	MSG(0, "  -y fix all the time\n");
+	MSG(0, "  -N answer \"No\" for all questions\n");
 	MSG(0, "  -V print the version number and exit\n");
 	MSG(0, "  --dry-run do not really fix corruptions\n");
 	MSG(0, "  --no-kernel-check skips detecting kernel change\n");
@@ -114,6 +115,7 @@ void dump_usage()
 	MSG(0, "  -f do not prompt before dumping\n");
 	MSG(0, "  -H support write hint\n");
 	MSG(0, "  -y alias for -f\n");
+	MSG(0, "  -N answer \"No\" for all questions\n");
 	MSG(0, "  -o dump inodes to the given path\n");
 	MSG(0, "  -P preserve mode/owner/group for dumped inode\n");
 	MSG(0, "  -L Preserves symlinks. Otherwise symlinks are dumped as regular files.\n");
@@ -266,7 +268,7 @@ void f2fs_parse_options(int argc, char *argv[])
 	}
 
 	if (!strcmp("fsck.f2fs", prog)) {
-		const char *option_string = ":aC:c:m:Md:fg:HlO:p:q:StyV";
+		const char *option_string = ":aC:c:m:Md:fg:HlO:p:q:StyNV";
 		int opt = 0, val;
 		char *token;
 		struct option long_opt[] = {
@@ -399,6 +401,9 @@ void f2fs_parse_options(int argc, char *argv[])
 				c.force = 1;
 				MSG(0, "Info: Force to fix corruption\n");
 				break;
+			case 'N':
+				c.answer_no = true;
+				break;
 			case 'q':
 				c.preserve_limits = atoi(optarg);
 				MSG(0, "Info: Preserve quota limits = %d\n",
@@ -452,7 +457,7 @@ void f2fs_parse_options(int argc, char *argv[])
 		}
 	} else if (!strcmp("dump.f2fs", prog)) {
 #ifdef WITH_DUMP
-		const char *option_string = "d:fi:I:n:LMo:Prs:Sa:b:Vy";
+		const char *option_string = "d:fi:I:n:LMo:Prs:Sa:b:VyN";
 		static struct dump_option dump_opt = {
 			.nid = 0,	/* default root ino */
 			.start_nat = -1,
@@ -530,6 +535,9 @@ void f2fs_parse_options(int argc, char *argv[])
 			case 'f':
 				c.force = 1;
 				break;
+			case 'N':
+				c.answer_no = true;
+				break;
 			case 'r':
 				dump_opt.use_root_nid = 1;
 				break;
@@ -1372,7 +1380,7 @@ fsck_again:
 
 	f2fs_do_umount(sbi);
 
-	if (c.func == FSCK && c.bug_on) {
+	if (c.func == FSCK && c.bug_on && !c.answer_no) {
 		if (!c.ro && c.fix_on == 0 && c.auto_fix == 0 && !c.dry_run) {
 			char ans[255] = {0};
 retry:
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index 1686b9a29d4c..be2e85376c16 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -1595,6 +1595,7 @@ struct f2fs_configuration {
 	int whint;
 	int aliased_devices;
 	uint32_t aliased_segments;
+	bool answer_no;
 
 	/* mkfs parameters */
 	int fake_seed;
diff --git a/man/dump.f2fs.8 b/man/dump.f2fs.8
index 4035d57ad6e1..975aa9c091a1 100644
--- a/man/dump.f2fs.8
+++ b/man/dump.f2fs.8
@@ -96,6 +96,9 @@ Specify a block address to retrieve its metadata information.
 Specify the level of debugging options.
 The default number is 0, which shows basic debugging messages.
 .TP
+.BI \-N
+Answer "No" for all questsions.
+.TP
 .SH AUTHOR
 Initial checking code was written by Byoung Geun Kim <bgbg.kim@samsung.com>.
 .SH AVAILABILITY
diff --git a/man/fsck.f2fs.8 b/man/fsck.f2fs.8
index c20c43144897..e3e3b04bb5b0 100644
--- a/man/fsck.f2fs.8
+++ b/man/fsck.f2fs.8
@@ -67,6 +67,9 @@ Enable to show every directory entries in the partition.
 Specify the level of debugging options.
 The default number is 0, which shows basic debugging messages.
 .TP
+.BI \-N
+Answer "No" for all questsions.
+.TP
 .BI \--nolinear-lookup
 Tune linear lookup fallback, must specify an argument, 0: enable linear lookup, 1: disable linear lookup. For android case, it will disable linear lookup by default.
 .TP
-- 
2.43.0



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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH v3 03/13] f2fs-tools: cleanup {nid|segno}_in_journal
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 01/13] fsck.f2fs: do not finish/reset zone if dry-run is true Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 02/13] f2fs-tools: add option N to answer no for all questions Sheng Yong
@ 2025-08-20 12:42 ` Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 04/13] fsck.f2fs: fix invalidate checkpoint Sheng Yong
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

From: Sheng Yong <shengyong1@xiaomi.com>

Signed-off-by: Sheng Yong <shengyong1@xiaomi.com>
---
 fsck/f2fs.h  |  4 ++--
 fsck/mount.c | 14 +++++++-------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index 187e73cf9aec..4c6c0c48b9ee 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -504,9 +504,9 @@ struct fsync_inode_entry {
 #define sits_in_cursum(jnl)             (le16_to_cpu(jnl->n_sits))
 
 #define nat_in_journal(jnl, i)          (jnl->nat_j.entries[i].ne)
-#define nid_in_journal(jnl, i)          (jnl->nat_j.entries[i].nid)
+#define nid_in_journal(jnl, i)          (le32_to_cpu(jnl->nat_j.entries[i].nid))
 #define sit_in_journal(jnl, i)          (jnl->sit_j.entries[i].se)
-#define segno_in_journal(jnl, i)        (jnl->sit_j.entries[i].segno)
+#define segno_in_journal(jnl, i)        (le32_to_cpu(jnl->sit_j.entries[i].segno))
 
 #define SIT_ENTRY_OFFSET(sit_i, segno)                                  \
 	((segno) % sit_i->sents_per_block)
diff --git a/fsck/mount.c b/fsck/mount.c
index 5399f16c6bf0..1fe2b110942b 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -1694,7 +1694,7 @@ static int f2fs_early_init_nid_bitmap(struct f2fs_sb_info *sbi)
 			continue;
 		}
 
-		nid = le32_to_cpu(nid_in_journal(journal, i));
+		nid = nid_in_journal(journal, i);
 		if (!IS_VALID_NID(sbi, nid)) {
 			MSG(0, "\tError: f2fs_init_nid_bitmap: nid(%u) is invalid!!!\n", nid);
 			journal->n_nats = cpu_to_le16(i);
@@ -2573,7 +2573,7 @@ void update_nat_blkaddr(struct f2fs_sb_info *sbi, nid_t ino,
 	int ret, i;
 
 	for (i = 0; i < nats_in_cursum(journal); i++) {
-		if (le32_to_cpu(nid_in_journal(journal, i)) == nid) {
+		if (nid_in_journal(journal, i) == nid) {
 			entry = &nat_in_journal(journal, i);
 			entry->block_addr = cpu_to_le32(newaddr);
 			if (ino)
@@ -2677,7 +2677,7 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
 	}
 
 	for (i = 0; i < sits_in_cursum(journal); i++) {
-		segno = le32_to_cpu(segno_in_journal(journal, i));
+		segno = segno_in_journal(journal, i);
 
 		if (segno >= MAIN_SEGS(sbi)) {
 			MSG(0, "\tError: build_sit_entries: segno(%u) is invalid!!!\n", segno);
@@ -2883,7 +2883,7 @@ next:
 		return i;
 	}
 
-	nid = le32_to_cpu(nid_in_journal(journal, i));
+	nid = nid_in_journal(journal, i);
 
 	entry_off = nid % NAT_ENTRY_PER_BLOCK;
 	block_addr = current_nat_addr(sbi, nid, NULL);
@@ -3282,7 +3282,7 @@ int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid,
 	int i = 0;
 
 	for (i = 0; i < nats_in_cursum(journal); i++) {
-		if (le32_to_cpu(nid_in_journal(journal, i)) == nid) {
+		if (nid_in_journal(journal, i) == nid) {
 			memcpy(raw_nat, &nat_in_journal(journal, i),
 						sizeof(struct f2fs_nat_entry));
 			DBG(3, "==> Found nid [0x%x] in nat cache\n", nid);
@@ -3307,7 +3307,7 @@ void nullify_nat_entry(struct f2fs_sb_info *sbi, u32 nid)
 
 	/* check in journal */
 	for (i = 0; i < nats_in_cursum(journal); i++) {
-		if (le32_to_cpu(nid_in_journal(journal, i)) == nid) {
+		if (nid_in_journal(journal, i) == nid) {
 			memset(&nat_in_journal(journal, i), 0,
 					sizeof(struct f2fs_nat_entry));
 			FIX_MSG("Remove nid [0x%x] in nat journal", nid);
@@ -3611,7 +3611,7 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
 	/* Traverse nat journal, update the corresponding entries */
 	for (i = 0; i < nats_in_cursum(journal); i++) {
 		struct f2fs_nat_entry raw_nat;
-		nid = le32_to_cpu(nid_in_journal(journal, i));
+		nid = nid_in_journal(journal, i);
 		ni.nid = nid;
 
 		DBG(3, "==> Found nid [0x%x] in nat cache, update it\n", nid);
-- 
2.43.0



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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH v3 04/13] fsck.f2fs: fix invalidate checkpoint
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
                   ` (2 preceding siblings ...)
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 03/13] f2fs-tools: cleanup {nid|segno}_in_journal Sheng Yong
@ 2025-08-20 12:42 ` Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 05/13] dump.f2fs: print more info Sheng Yong
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

From: Sheng Yong <shengyong1@xiaomi.com>

If one cp is invalidate, set CP_FSCK_FLAG to allow fsck_verify() to
fixing cp at the end of check.

Signed-off-by: Sheng Yong <shengyong1@xiaomi.com>
---
 fsck/f2fs.h  |  6 ++++++
 fsck/mount.c | 11 ++++++++---
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index 4c6c0c48b9ee..a4888a817284 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -346,6 +346,12 @@ static inline __u64 cur_cp_crc(struct f2fs_checkpoint *cp)
 	return le32_to_cpu(*((__le32 *)((unsigned char *)cp + crc_offset)));
 }
 
+static inline void set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
+{
+	unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
+	cp->ckpt_flags = cpu_to_le32(ckpt_flags | f);
+}
+
 static inline bool is_set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
 {
 	unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
diff --git a/fsck/mount.c b/fsck/mount.c
index 1fe2b110942b..c671811941ad 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -1359,8 +1359,11 @@ void *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr,
 		return NULL;
 
 	cp = (struct f2fs_checkpoint *)cp_page_1;
-	if (get_cp(cp_pack_total_block_count) > sbi->blocks_per_seg)
+	if (get_cp(cp_pack_total_block_count) > sbi->blocks_per_seg) {
+		MSG(0, "\tInvalid CP pack block count: %u\n",
+		    get_cp(cp_pack_total_block_count));
 		goto invalid_cp1;
+	}
 
 	pre_version = get_cp(checkpoint_ver);
 
@@ -1424,14 +1427,16 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
 			sbi->cur_cp = 1;
 			version = cp1_version;
 		}
-	} else if (cp1) {
+	} else if (cp1) { // cp2 is invalidate
 		cur_page = cp1;
 		sbi->cur_cp = 1;
 		version = cp1_version;
-	} else if (cp2) {
+		set_ckpt_flags(cp1, CP_FSCK_FLAG);
+	} else if (cp2) { // cp1 is invalidate
 		cur_page = cp2;
 		sbi->cur_cp = 2;
 		version = cp2_version;
+		set_ckpt_flags(cp2, CP_FSCK_FLAG);
 	} else
 		goto fail_no_cp;
 
-- 
2.43.0



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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH v3 05/13] dump.f2fs: print more info
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
                   ` (3 preceding siblings ...)
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 04/13] fsck.f2fs: fix invalidate checkpoint Sheng Yong
@ 2025-08-20 12:42 ` Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 06/13] f2fs-tools: add and export lookup_sit_in_journal Sheng Yong
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

From: Sheng Yong <shengyong1@xiaomi.com>

dump.f2fs shows more info:
 * nat entry version
 * sit entry mtime

Signed-off-by: Sheng Yong <shengyong1@xiaomi.com>
---
 fsck/dump.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/fsck/dump.c b/fsck/dump.c
index 10df7e593bfe..21de2acf80b5 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -70,10 +70,10 @@ void nat_dump(struct f2fs_sb_info *sbi, nid_t start_nat, nid_t end_nat)
 			ASSERT(ret >= 0);
 			if (ni.blk_addr != 0x0) {
 				len = snprintf(buf, BUF_SZ,
-					"nid:%5u\tino:%5u\toffset:%5u"
+					"nid:%5u\tino:%5u\tver:%3d\toffset:%5u"
 					"\tblkaddr:%10u\tpack:%d"
 					"\tcp_ver:0x%" PRIx64 "\n",
-					ni.nid, ni.ino,
+					ni.nid, ni.ino, ni.version,
 					le32_to_cpu(footer->flag) >> OFFSET_BIT_SHIFT,
 					ni.blk_addr, pack,
 					le64_to_cpu(footer->cp_ver));
@@ -91,10 +91,10 @@ void nat_dump(struct f2fs_sb_info *sbi, nid_t start_nat, nid_t end_nat)
 			ret = dev_read_block(node_block, ni.blk_addr);
 			ASSERT(ret >= 0);
 			len = snprintf(buf, BUF_SZ,
-				"nid:%5u\tino:%5u\toffset:%5u"
+				"nid:%5u\tino:%5u\tver:%3d\toffset:%5u"
 				"\tblkaddr:%10u\tpack:%d"
 				"\tcp_ver:0x%" PRIx64 "\n",
-				ni.nid, ni.ino,
+				ni.nid, ni.ino, ni.version,
 				le32_to_cpu(footer->flag) >> OFFSET_BIT_SHIFT,
 				ni.blk_addr, pack,
 				le64_to_cpu(footer->cp_ver));
@@ -135,8 +135,10 @@ void sit_dump(struct f2fs_sb_info *sbi, unsigned int start_sit,
 		offset = SIT_BLOCK_OFFSET(sit_i, segno);
 		memset(buf, 0, BUF_SZ);
 		snprintf(buf, BUF_SZ,
-		"\nsegno:%8u\tvblocks:%3u\tseg_type:%d\tsit_pack:%d\n\n",
+		"\nsegno:%8u\tvblocks:%3u\tseg_type:%d\tmtime:%llu\t"
+		"sit_pack:%d\n\n",
 			segno, se->valid_blocks, se->type,
+			(unsigned long long)se->mtime,
 			f2fs_test_bit(offset, sit_i->sit_bitmap) ? 2 : 1);
 
 		ret = write(fd, buf, strlen(buf));
-- 
2.43.0



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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH v3 06/13] f2fs-tools: add and export lookup_sit_in_journal
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
                   ` (4 preceding siblings ...)
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 05/13] dump.f2fs: print more info Sheng Yong
@ 2025-08-20 12:42 ` Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 07/13] inject.f2fs: fix injecting sit/nat in journal Sheng Yong
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

From: Sheng Yong <shengyong1@xiaomi.com>

Add lookup_sit_in_journal() which is similar to lookup_nat_in_journal()
to get the raw sit entry from journal if exist.

Signed-off-by: Sheng Yong <shengyong1@xiaomi.com>
---
 fsck/f2fs.h  |  2 ++
 fsck/mount.c | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index a4888a817284..60e3a2ebb0ee 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -613,6 +613,8 @@ static inline int inline_xattr_size(struct f2fs_inode *inode)
 }
 
 extern int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, struct f2fs_nat_entry *ne);
+extern int lookup_sit_in_journal(struct f2fs_sb_info *sbi, unsigned int segno,
+				 struct f2fs_sit_entry *raw_sit);
 #define IS_SUM_NODE_SEG(sum)		(F2FS_SUMMARY_BLOCK_FOOTER(sum)->entry_type == SUM_TYPE_NODE)
 #define IS_SUM_DATA_SEG(sum)		(F2FS_SUMMARY_BLOCK_FOOTER(sum)->entry_type == SUM_TYPE_DATA)
 
diff --git a/fsck/mount.c b/fsck/mount.c
index c671811941ad..f9f780d4aff6 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -3297,6 +3297,24 @@ int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid,
 	return -1;
 }
 
+int lookup_sit_in_journal(struct f2fs_sb_info *sbi, unsigned int segno,
+					struct f2fs_sit_entry *raw_sit)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
+	struct f2fs_journal *journal = F2FS_SUMMARY_BLOCK_JOURNAL(curseg->sum_blk);
+	int i;
+
+	for (i = 0; i < sits_in_cursum(journal); i++) {
+		if (segno_in_journal(journal, i) == segno) {
+			memcpy(raw_sit, &sit_in_journal(journal, i),
+						sizeof(struct f2fs_sit_entry));
+			DBG(3, "==> Found sit [0x%x] in sit cache\n", segno);
+			return i;
+		}
+	}
+	return -1;
+}
+
 void nullify_nat_entry(struct f2fs_sb_info *sbi, u32 nid)
 {
 	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
-- 
2.43.0



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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH v3 07/13] inject.f2fs: fix injecting sit/nat in journal
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
                   ` (5 preceding siblings ...)
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 06/13] f2fs-tools: add and export lookup_sit_in_journal Sheng Yong
@ 2025-08-20 12:42 ` Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 08/13] inject.f2fs: fix injection on zoned device Sheng Yong
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

From: Sheng Yong <shengyong1@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 <shengyong1@xiaomi.com>
---
v3: * add helper get_raw_{nat|sit}() to get nat/sit entry and return
      its position (journal/pack1/pack2)
    * show entry's position correctly
    * add helper rewrite_raw_{nat|sit}() to write nat/sit entry back
      to its original position
---
 fsck/inject.c | 257 ++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 195 insertions(+), 62 deletions(-)

diff --git a/fsck/inject.c b/fsck/inject.c
index b291d9dbc096..aae3db0c6524 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -10,9 +10,22 @@
  */
 
 #include <getopt.h>
+#include "f2fs.h"
 #include "node.h"
 #include "inject.h"
 
+/* localtion of a sit/nat entry */
+enum entry_pos {
+	ENT_IN_JOURNAL,
+	ENT_IN_PACK1,
+	ENT_IN_PACK2
+};
+
+/* format of printing entry position */
+#define PRENTPOS "%s %d"
+#define show_entry_pos(pack) (pack) == ENT_IN_JOURNAL ? "journal" : "pack", \
+			     (pack) == ENT_IN_JOURNAL ? 0 : (pack)
+
 static void print_raw_nat_entry_info(struct f2fs_nat_entry *ne)
 {
 	if (!c.dbg_lv)
@@ -534,16 +547,92 @@ out:
 	return ret;
 }
 
-static int inject_nat(struct f2fs_sb_info *sbi, struct inject_option *opt)
+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 block_t get_nat_addr(struct f2fs_sb_info *sbi, int nat_pack,
+			    nid_t nid, enum entry_pos *pack)
 {
 	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	block_t blkaddr;
+	unsigned int blkoff;
+
+	blkoff = NAT_BLOCK_OFFSET(nid);
+	blkaddr = nm_i->nat_blkaddr + (blkoff << 1) +
+			(blkoff & (sbi->blocks_per_seg - 1));
+	if (nat_pack == 0) // select valid nat pack
+		nat_pack = f2fs_test_bit(blkoff, nm_i->nat_bitmap) ?
+				ENT_IN_PACK2 : ENT_IN_PACK1;
+	if (nat_pack == ENT_IN_PACK2)
+		blkaddr += sbi->blocks_per_seg;
+	if (pack)
+		*pack = nat_pack;
+	return blkaddr;
+}
+
+static struct f2fs_nat_entry *get_raw_nat(struct f2fs_sb_info *sbi,
+					  struct inject_option *opt,
+					  struct f2fs_nat_block *nat_blk,
+					  enum entry_pos *pack)
+{
+	block_t blkaddr;
+	unsigned int offs;
+
+	if (lookup_nat_in_journal(sbi, opt->nid, &nat_blk->entries[0]) >= 0) {
+		offs = 0;
+		*pack = ENT_IN_JOURNAL;
+	} else {
+		blkaddr = get_nat_addr(sbi, opt->nat, opt->nid, pack);
+		ASSERT(dev_read_block(nat_blk, blkaddr) >= 0);
+		offs = opt->nid % NAT_ENTRY_PER_BLOCK;
+	}
+
+	return &nat_blk->entries[offs];
+}
+
+static void rewrite_raw_nat(struct f2fs_sb_info *sbi,
+			    struct inject_option *opt,
+			    struct f2fs_nat_block *nat_blk,
+			    enum entry_pos pack)
+{
+	block_t blkaddr;
+
+	if (pack == ENT_IN_JOURNAL) {
+		rewrite_nat_in_journal(sbi, opt->nid, &nat_blk->entries[0]);
+	} else {
+		blkaddr = get_nat_addr(sbi, opt->nat, opt->nid, NULL);
+		ASSERT(dev_write_block(nat_blk, blkaddr, WRITE_LIFE_NONE) >= 0);
+	}
+}
+
+static int inject_nat(struct f2fs_sb_info *sbi, struct inject_option *opt)
+{
 	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;
+	enum entry_pos pack;
 
 	if (!IS_VALID_NID(sbi, opt->nid)) {
 		ERR_MSG("Invalid nid %u range [%u:%"PRIu64"]\n", opt->nid, 0,
@@ -556,38 +645,24 @@ 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;
-	} 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];
+	ne = get_raw_nat(sbi, opt, nat_blk, &pack);
 
 	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 "PRENTPOS": %d -> %d\n", opt->nid,
+		    show_entry_pos(pack),
 		    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 "PRENTPOS": %d -> %d\n", opt->nid,
+		    show_entry_pos(pack),
 		    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 "PRENTPOS": 0x%x -> 0x%x\n", opt->nid,
+		    show_entry_pos(pack),
 		    le32_to_cpu(ne->block_addr), (block_t)opt->val);
 		ne->block_addr = cpu_to_le32((block_t)opt->val);
 	} else {
@@ -597,25 +672,99 @@ 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);
+	rewrite_raw_nat(sbi, opt, nat_blk, pack);
 
 	free(nat_blk);
-	return ret;
+	return 0;
 }
 
-static int inject_sit(struct f2fs_sb_info *sbi, struct inject_option *opt)
+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 block_t get_sit_addr(struct f2fs_sb_info *sbi, int sit_pack,
+			    unsigned int segno, enum entry_pos *pack)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	unsigned int blkaddr, offs;
+
+	offs = SIT_BLOCK_OFFSET(sit_i, segno);
+	blkaddr = sit_i->sit_base_addr + offs;
+	if (sit_pack == 0) // select valid sit pack
+		sit_pack = f2fs_test_bit(offs, sit_i->sit_bitmap) ?
+				ENT_IN_PACK2 : ENT_IN_PACK1;
+	if (sit_pack == ENT_IN_PACK2)
+		blkaddr += sit_i->sit_blocks;
+	if (pack)
+		*pack = sit_pack;
+	return blkaddr;
+}
+
+static struct f2fs_sit_entry *get_raw_sit(struct f2fs_sb_info *sbi,
+					  struct inject_option *opt,
+					  struct f2fs_sit_block *sit_blk,
+					  enum entry_pos *pack)
 {
 	struct sit_info *sit_i = SIT_I(sbi);
+	unsigned int segno, offs;
+	block_t blkaddr;
+
+	segno = GET_SEGNO(sbi, opt->blk);
+	if (lookup_sit_in_journal(sbi, segno, &sit_blk->entries[0]) >= 0) {
+		offs = 0;
+		*pack = ENT_IN_JOURNAL;
+	} else {
+		blkaddr = get_sit_addr(sbi, opt->sit, segno, pack);
+		ASSERT(dev_read_block(sit_blk, blkaddr) >= 0);
+		offs = SIT_ENTRY_OFFSET(sit_i, segno);
+	}
+
+	return &sit_blk->entries[offs];
+}
+
+static void rewrite_raw_sit(struct f2fs_sb_info *sbi,
+			    struct inject_option *opt,
+			    struct f2fs_sit_block *sit_blk,
+			    enum entry_pos pack)
+{
+	unsigned int segno;
+	block_t blkaddr;
+
+	segno = GET_SEGNO(sbi, opt->blk);
+	if (pack == ENT_IN_JOURNAL) {
+		rewrite_sit_in_journal(sbi, segno, &sit_blk->entries[0]);
+	} else {
+		blkaddr = get_sit_addr(sbi, opt->sit, segno, NULL);
+		ASSERT(dev_write_block(sit_blk, blkaddr, WRITE_LIFE_NONE) >= 0);
+	}
+}
+
+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;
+	enum entry_pos pack;
 
 	if (!f2fs_is_valid_blkaddr(sbi, opt->blk, DATA_GENERIC)) {
 		ERR_MSG("Invalid blkaddr 0x%x (valid range [0x%x:0x%lx])\n",
@@ -627,30 +776,18 @@ static int inject_sit(struct f2fs_sb_info *sbi, struct inject_option *opt)
 	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];
+	sit = get_raw_sit(sbi, opt, sit_blk, &pack);
 
 	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 "PRENTPOS": %u -> %u\n", opt->blk,
+		    show_entry_pos(pack),
 		    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);
@@ -658,8 +795,9 @@ 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 "PRENTPOS": 0x%02x -> 0x%02x\n", opt->idx, opt->blk,
+		    show_entry_pos(pack),
+		    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 "
@@ -673,12 +811,7 @@ 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);
+	rewrite_raw_sit(sbi, opt, sit_blk, pack);
 
 	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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH v3 08/13] inject.f2fs: fix injection on zoned device
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
                   ` (6 preceding siblings ...)
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 07/13] inject.f2fs: fix injecting sit/nat in journal Sheng Yong
@ 2025-08-20 12:42 ` Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 09/13] inject.f2fs: fix and cleanup parsing numeric options Sheng Yong
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

From: Sheng Yong <shengyong1@xiaomi.com>

Because node and data blocks are updated out of place on zoned device,
sit_area_bitmap and main_area_bitmap are required to record which
blocks are allocated, sit should be flushed to reflect changes in
block address, and checkpoint should be rewritten to update cursegs.

Signed-off-by: Sheng Yong <shengyong1@xiaomi.com>
---
 fsck/inject.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/fsck/inject.c b/fsck/inject.c
index aae3db0c6524..674881043a76 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -1227,6 +1227,9 @@ int do_inject(struct f2fs_sb_info *sbi)
 	struct inject_option *opt = (struct inject_option *)c.private;
 	int ret = -EINVAL;
 
+	if (c.zoned_model == F2FS_ZONED_HM)
+		fsck_init(sbi);
+
 	if (opt->sb >= 0)
 		ret = inject_sb(sbi, opt);
 	else if (opt->cp >= 0)
@@ -1242,5 +1245,15 @@ int do_inject(struct f2fs_sb_info *sbi)
 	else if (opt->dent)
 		ret = inject_dentry(sbi, opt);
 
+	if (c.zoned_model == F2FS_ZONED_HM) {
+		if (!ret && (opt->node || opt->dent)) {
+			write_curseg_info(sbi);
+			flush_journal_entries(sbi);
+			flush_sit_entries(sbi);
+			write_checkpoint(sbi);
+		}
+		fsck_free(sbi);
+	}
+
 	return ret;
 }
-- 
2.43.0



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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH v3 09/13] inject.f2fs: fix and cleanup parsing numeric options
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
                   ` (7 preceding siblings ...)
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 08/13] inject.f2fs: fix injection on zoned device Sheng Yong
@ 2025-08-20 12:42 ` Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 10/13] inject.f2fs: add members in inject_cp Sheng Yong
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

From: Sheng Yong <shengyong1@xiaomi.com>

This patch fixes:
  * parsing hex optarg of --idx option
  * converting -1 to 0xff...ff of --val option
and do a little cleanup of converting string to a long integer.

Signed-off-by: Sheng Yong <shengyong1@xiaomi.com>
---
 fsck/inject.c | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/fsck/inject.c b/fsck/inject.c
index 674881043a76..5ca105b60f8e 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -249,8 +249,9 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
 
 	while ((o = getopt_long(argc, argv, option_string,
 				long_opt, NULL)) != EOF) {
-		long nid, blk;
+		long long val;
 
+		errno = 0;
 		switch (o) {
 		case 1:
 			c.dry_run = 1;
@@ -261,18 +262,19 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
 			MSG(0, "Info: inject member %s\n", optarg);
 			break;
 		case 3:
-			if (!is_digits(optarg))
-				return EWRONG_OPT;
-			opt->idx = atoi(optarg);
-			MSG(0, "Info: inject slot index %d\n", opt->idx);
+			val = strtoll(optarg, &endptr, 0);
+			if (errno != 0 || val >= UINT_MAX || val < 0 ||
+			    *endptr != '\0')
+				return -ERANGE;
+			opt->idx = (unsigned int)val;
+			MSG(0, "Info: inject slot index %u\n", opt->idx);
 			break;
 		case 4:
-			opt->val = strtoll(optarg, &endptr, 0);
-			if (opt->val == LLONG_MAX || opt->val == LLONG_MIN ||
-			    *endptr != '\0')
+			opt->val = strtoull(optarg, &endptr, 0);
+			if (errno != 0 || *endptr != '\0')
 				return -ERANGE;
 			MSG(0, "Info: inject value %lld : 0x%llx\n", opt->val,
-			    (unsigned long long)opt->val);
+			    opt->val);
 			break;
 		case 5:
 			opt->str = strdup(optarg);
@@ -305,11 +307,11 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
 			MSG(0, "Info: inject nat pack %s\n", pack[opt->nat]);
 			break;
 		case 9:
-			nid = strtol(optarg, &endptr, 0);
-			if (nid >= UINT_MAX || nid < 0 ||
+			val = strtoll(optarg, &endptr, 0);
+			if (errno != 0 || val >= UINT_MAX || val < 0 ||
 			    *endptr != '\0')
 				return -ERANGE;
-			opt->nid = nid;
+			opt->nid = (nid_t)val;
 			MSG(0, "Info: inject nid %u : 0x%x\n", opt->nid, opt->nid);
 			break;
 		case 10:
@@ -321,11 +323,11 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
 			MSG(0, "Info: inject sit pack %s\n", pack[opt->sit]);
 			break;
 		case 11:
-			blk = strtol(optarg, &endptr, 0);
-			if (blk >= UINT_MAX || blk < 0 ||
+			val = strtoll(optarg, &endptr, 0);
+			if (errno != 0 || val >= UINT_MAX || val < 0 ||
 			    *endptr != '\0')
 				return -ERANGE;
-			opt->blk = blk;
+			opt->blk = (block_t)val;
 			MSG(0, "Info: inject blkaddr %u : 0x%x\n", opt->blk, opt->blk);
 			break;
 		case 12:
-- 
2.43.0



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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH v3 10/13] inject.f2fs: add members in inject_cp
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
                   ` (8 preceding siblings ...)
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 09/13] inject.f2fs: fix and cleanup parsing numeric options Sheng Yong
@ 2025-08-20 12:42 ` Sheng Yong
  2025-08-23  8:28   ` Chao Yu via Linux-f2fs-devel
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 11/13] inject.f2fs: add member `feature' in inject_sb Sheng Yong
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

From: Sheng Yong <shengyong1@xiaomi.com>

The following members are added to inject more fields in cp:

* next_blkaddr: inject fsync dnodes

  An error is returned if no fsync dnode is found.
  Furthermore, the injection is not supported on a zoned device. This
  is because fsync dnodes must remains at the end of current warm node
  segment, any dnode change causes all previous dnodes in the chain to
  be updated out-of-place, and there may not have enough space left in
  the curseg. To simplify the injection, it returns an error on the
  zoned device.
  An example of dnode chain shows:
    [inject_cp: 608] [   0] blkaddr:0x1204
    [inject_cp: 608] [   1] blkaddr:0x1205
    [inject_cp: 608] [   2] blkaddr:0x1206
    [inject_cp: 608] [   3] blkaddr:0x1207
    [inject_cp: 608] [   4] blkaddr:0x1208
    [inject_cp: 608] [   5] blkaddr:0x1209
    [inject_cp: 608] [   6] blkaddr:0x120a
    [inject_cp: 608] [   7] blkaddr:0x120b
    [inject_cp: 608] [   8] blkaddr:0x120c
    [inject_cp: 608] [   9] blkaddr:0x120d
  where `0' indicates next free blkaddr of warm node curseg, thus
  start blkaddr + next_blkoff of warm node curseg, which cannot be
  injected. `1~9` indicate next_blkaddr in node_footer of dnodes in
  the chain, which can be injected.

* alloc_type: inject curseg's alloc type
* crc: inject cp's checksum
* elapsed_time: inject cp's mount elapsed time

Signed-off-by: Sheng Yong <shengyong1@xiaomi.com>
---
v3: * update commit message to show dnode chain and the injectable range
    * free(node) before return
---
 fsck/fsck.h       |  4 ++-
 fsck/inject.c     | 86 ++++++++++++++++++++++++++++++++++++++++++++++-
 fsck/mount.c      | 18 +++++-----
 man/inject.f2fs.8 | 11 +++++-
 4 files changed, 108 insertions(+), 11 deletions(-)

diff --git a/fsck/fsck.h b/fsck/fsck.h
index 40cb6d9a6417..05daa2de9531 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -223,6 +223,8 @@ extern int f2fs_ra_meta_pages(struct f2fs_sb_info *, block_t, int, int);
 extern int f2fs_do_mount(struct f2fs_sb_info *);
 extern void f2fs_do_umount(struct f2fs_sb_info *);
 extern int f2fs_sparse_initialize_meta(struct f2fs_sb_info *);
+extern int f2fs_find_fsync_inode(struct f2fs_sb_info *, struct list_head *);
+extern void f2fs_destroy_fsync_dnodes(struct list_head *);
 
 extern void flush_journal_entries(struct f2fs_sb_info *);
 extern void update_curseg_info(struct f2fs_sb_info *, int);
@@ -239,7 +241,7 @@ extern void duplicate_checkpoint(struct f2fs_sb_info *);
 extern void write_checkpoint(struct f2fs_sb_info *);
 extern void write_checkpoints(struct f2fs_sb_info *);
 extern void write_raw_cp_blocks(struct f2fs_sb_info *sbi,
-			struct f2fs_checkpoint *cp, int which);
+			struct f2fs_checkpoint *cp, int which, bool update_crc);
 extern void update_superblock(struct f2fs_super_block *, int);
 extern void update_data_blkaddr(struct f2fs_sb_info *, nid_t, u16, block_t,
 			struct f2fs_node *);
diff --git a/fsck/inject.c b/fsck/inject.c
index 5ca105b60f8e..272a4a64dc05 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -151,6 +151,10 @@ static void inject_cp_usage(void)
 	MSG(0, "  cur_node_blkoff: inject cur_node_blkoff array selected by --idx <index>\n");
 	MSG(0, "  cur_data_segno: inject cur_data_segno array selected by --idx <index>\n");
 	MSG(0, "  cur_data_blkoff: inject cur_data_blkoff array selected by --idx <index>\n");
+	MSG(0, "  alloc_type: inject alloc_type array selected by --idx <index>\n");
+	MSG(0, "  next_blkaddr: inject next_blkaddr of fsync dnodes selected by --idx <index>\n");
+	MSG(0, "  crc: inject crc checksum\n");
+	MSG(0, "  elapsed_time: inject elapsed_time\n");
 }
 
 static void inject_nat_usage(void)
@@ -456,6 +460,7 @@ out:
 static int inject_cp(struct f2fs_sb_info *sbi, struct inject_option *opt)
 {
 	struct f2fs_checkpoint *cp, *cur_cp = F2FS_CKPT(sbi);
+	bool update_crc = true;
 	char *buf = NULL;
 	int ret = 0;
 
@@ -534,6 +539,85 @@ static int inject_cp(struct f2fs_sb_info *sbi, struct inject_option *opt)
 		    opt->idx, opt->cp, get_cp(cur_data_blkoff[opt->idx]),
 		    (u16)opt->val);
 		set_cp(cur_data_blkoff[opt->idx], (u16)opt->val);
+	} else if (!strcmp(opt->mb, "alloc_type")) {
+		if (opt->idx >= MAX_ACTIVE_LOGS) {
+			ERR_MSG("invalid index %u of cp->alloc_type[]\n",
+				opt->idx);
+			ret = -EINVAL;
+			goto out;
+		}
+		MSG(0, "Info: inject alloc_type[%d] of cp %d: 0x%x -> 0x%x\n",
+		    opt->idx, opt->cp, cp->alloc_type[opt->idx],
+		    (unsigned char)opt->val);
+		cp->alloc_type[opt->idx] = (unsigned char)opt->val;
+	} else if (!strcmp(opt->mb, "next_blkaddr")) {
+		struct fsync_inode_entry *entry;
+		struct list_head inode_list = LIST_HEAD_INIT(inode_list);
+		struct f2fs_node *node;
+		block_t blkaddr;
+		int i = 0;
+
+		if (c.zoned_model == F2FS_ZONED_HM) {
+			ERR_MSG("inject fsync dnodes not supported in "
+				"zoned device\n");
+			ret = -EOPNOTSUPP;
+			goto out;
+		}
+
+		if (!need_fsync_data_record(sbi)) {
+			ERR_MSG("no need to recover fsync dnodes\n");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		ret = f2fs_find_fsync_inode(sbi, &inode_list);
+		if (ret) {
+			ERR_MSG("failed to find fsync inodes: %d\n", ret);
+			goto out;
+		}
+
+		list_for_each_entry(entry, &inode_list, list) {
+			if (i == opt->idx)
+				blkaddr = entry->blkaddr;
+			DBG(0, "[%4d] blkaddr:0x%x\n", i++, entry->blkaddr);
+		}
+
+		f2fs_destroy_fsync_dnodes(&inode_list);
+
+		if (opt->idx == 0 || opt->idx >= i) {
+			ERR_MSG("invalid index %u of fsync dnodes range [1, %u]\n",
+				opt->idx, i);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		MSG(0, "Info: inject next_blkaddr[%d] of cp %d: 0x%x -> 0x%x\n",
+		    opt->idx, opt->cp, blkaddr, (u32)opt->val);
+
+		node = malloc(F2FS_BLKSIZE);
+		ASSERT(node);
+		ret = dev_read_block(node, blkaddr);
+		ASSERT(ret >= 0);
+		F2FS_NODE_FOOTER(node)->next_blkaddr = cpu_to_le32((u32)opt->val);
+		if (IS_INODE(node))
+			ret = update_inode(sbi, node, &blkaddr);
+		else
+			ret = update_block(sbi, node, &blkaddr, NULL);
+		free(node);
+		ASSERT(ret >= 0);
+		goto out;
+	} else if (!strcmp(opt->mb, "crc")) {
+		__le32 *crc = (__le32 *)((unsigned char *)cp +
+						get_cp(checksum_offset));
+
+		MSG(0, "Info: inject crc of cp %d: 0x%x -> 0x%x\n",
+		    opt->cp, le32_to_cpu(*crc), (u32)opt->val);
+		*crc = cpu_to_le32((u32)opt->val);
+		update_crc = false;
+	} else if (!strcmp(opt->mb, "elapsed_time")) {
+		MSG(0, "Info: inject elapsed_time of cp %d: %llu -> %"PRIu64"\n",
+		    opt->cp, get_cp(elapsed_time), (u64)opt->val);
+		set_cp(elapsed_time, (u64)opt->val);
 	} else {
 		ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
 		ret = -EINVAL;
@@ -541,7 +625,7 @@ static int inject_cp(struct f2fs_sb_info *sbi, struct inject_option *opt)
 	}
 
 	print_ckpt_info(sbi);
-	write_raw_cp_blocks(sbi, cp, opt->cp);
+	write_raw_cp_blocks(sbi, cp, opt->cp, update_crc);
 
 out:
 	free(buf);
diff --git a/fsck/mount.c b/fsck/mount.c
index f9f780d4aff6..f03fa2d6861a 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -3510,17 +3510,19 @@ void write_checkpoints(struct f2fs_sb_info *sbi)
 	write_checkpoint(sbi);
 }
 
-void write_raw_cp_blocks(struct f2fs_sb_info *sbi,
-			 struct f2fs_checkpoint *cp, int which)
+void write_raw_cp_blocks(struct f2fs_sb_info *sbi, struct f2fs_checkpoint *cp,
+			 int which, bool update_crc)
 {
 	struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
 	uint32_t crc;
 	block_t cp_blkaddr;
 	int ret;
 
-	crc = f2fs_checkpoint_chksum(cp);
-	*((__le32 *)((unsigned char *)cp + get_cp(checksum_offset))) =
+	if (update_crc) {
+		crc = f2fs_checkpoint_chksum(cp);
+		*((__le32 *)((unsigned char *)cp + get_cp(checksum_offset))) =
 							cpu_to_le32(crc);
+	}
 
 	cp_blkaddr = get_sb(cp_blkaddr);
 	if (which == 2)
@@ -3754,7 +3756,7 @@ static void del_fsync_inode(struct fsync_inode_entry *entry)
 	free(entry);
 }
 
-static void destroy_fsync_dnodes(struct list_head *head)
+void f2fs_destroy_fsync_dnodes(struct list_head *head)
 {
 	struct fsync_inode_entry *entry, *tmp;
 
@@ -3860,7 +3862,7 @@ static int sanity_check_node_chain(struct f2fs_sb_info *sbi,
 	return 0;
 }
 
-static int find_fsync_inode(struct f2fs_sb_info *sbi, struct list_head *head)
+int f2fs_find_fsync_inode(struct f2fs_sb_info *sbi, struct list_head *head)
 {
 	struct curseg_info *curseg;
 	struct f2fs_node *node_blk, *node_blk_fast;
@@ -4056,7 +4058,7 @@ static int record_fsync_data(struct f2fs_sb_info *sbi)
 	if (!need_fsync_data_record(sbi))
 		return 0;
 
-	ret = find_fsync_inode(sbi, &inode_list);
+	ret = f2fs_find_fsync_inode(sbi, &inode_list);
 	if (ret)
 		goto out;
 
@@ -4071,7 +4073,7 @@ static int record_fsync_data(struct f2fs_sb_info *sbi)
 
 	ret = traverse_dnodes(sbi, &inode_list);
 out:
-	destroy_fsync_dnodes(&inode_list);
+	f2fs_destroy_fsync_dnodes(&inode_list);
 	return ret;
 }
 
diff --git a/man/inject.f2fs.8 b/man/inject.f2fs.8
index 65ac658a129b..0e7cd5065a15 100644
--- a/man/inject.f2fs.8
+++ b/man/inject.f2fs.8
@@ -45,7 +45,7 @@ The available \fImb\fP of \fIsb\fP are:
 .RS 1.2i
 .TP
 .BI magic
-magic numbe.
+magic number.
 .TP
 .BI s_stop_reason
 s_stop_reason array.
@@ -79,6 +79,15 @@ cur_data_segno array.
 .TP
 .BI cur_data_blkoff
 cur_data_blkoff array.
+.TP
+.BI next_blkaddr
+fsync dnodes.
+.TP
+.BI crc
+crc checksum.
+.TP
+.BI elapsed_time
+elapsed mount time.
 .RE
 .TP
 .BI \-\-nat " 0 or 1 or 2"
-- 
2.43.0



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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH v3 11/13] inject.f2fs: add member `feature' in inject_sb
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
                   ` (9 preceding siblings ...)
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 10/13] inject.f2fs: add members in inject_cp Sheng Yong
@ 2025-08-20 12:42 ` Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 12/13] inject.f2fs: add members in inject_node Sheng Yong
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

From: Sheng Yong <shengyong1@xiaomi.com>

This patch adds a new member `feature' in inject_sb to inject features.

Signed-off-by: Sheng Yong <shengyong1@xiaomi.com>
---
 fsck/inject.c     | 5 +++++
 man/inject.f2fs.8 | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/fsck/inject.c b/fsck/inject.c
index 272a4a64dc05..cb348b3ba067 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -134,6 +134,7 @@ static void inject_sb_usage(void)
 	MSG(0, "  magic: inject magic number\n");
 	MSG(0, "  s_stop_reason: inject s_stop_reason array selected by --idx <index>\n");
 	MSG(0, "  s_errors: inject s_errors array selected by --idx <index>\n");
+	MSG(0, "  feature: inject feature\n");
 	MSG(0, "  devs.path: inject path in devs array selected by --idx <index> specified by --str <string>\n");
 }
 
@@ -428,6 +429,10 @@ static int inject_sb(struct f2fs_sb_info *sbi, struct inject_option *opt)
 		MSG(0, "Info: inject s_errors[%d] of sb %d: %x -> %x\n",
 		    opt->idx, opt->sb, sb->s_errors[opt->idx], (u8)opt->val);
 		sb->s_errors[opt->idx] = (u8)opt->val;
+	} else if (!strcmp(opt->mb, "feature")) {
+		MSG(0, "Info: inject feature of sb %d: 0x%x -> 0x%x\n",
+		    opt->sb, get_sb(feature), (u32)opt->val);
+		set_sb(feature, (u32)opt->val);
 	} else if (!strcmp(opt->mb, "devs.path")) {
 		if (opt->idx >= MAX_DEVICES) {
 			ERR_MSG("invalid index %u of sb->devs[]\n", opt->idx);
diff --git a/man/inject.f2fs.8 b/man/inject.f2fs.8
index 0e7cd5065a15..0dcf3a23cff8 100644
--- a/man/inject.f2fs.8
+++ b/man/inject.f2fs.8
@@ -53,6 +53,9 @@ s_stop_reason array.
 .BI s_errors
 s_errors array.
 .TP
+.BI feature
+features.
+.TP
 .BI devs.path
 path in devs array.
 .RE
-- 
2.43.0



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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH v3 12/13] inject.f2fs: add members in inject_node
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
                   ` (10 preceding siblings ...)
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 11/13] inject.f2fs: add member `feature' in inject_sb Sheng Yong
@ 2025-08-20 12:42 ` Sheng Yong
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 13/13] inject.f2fs: add member `filename' in inject_dentry Sheng Yong
  2025-08-23  8:34 ` [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Chao Yu via Linux-f2fs-devel
  13 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

From: Sheng Yong <shengyong1@xiaomi.com>

This patch adds new members in inject_node to inject inode:
 * i_ext.fofs: extent fofs
 * i_ext.blk_addr: extent blk_addr
 * i_ext.len: extent len
 * i_inline_xattr_size: inline xattr size
 * i_compr_blocks: compression blocks

Signed-off-by: Sheng Yong <shengyong1@xiaomi.com>
---
v3: * fix print format
---
 fsck/inject.c     | 28 ++++++++++++++++++++++++++++
 man/inject.f2fs.8 | 17 ++++++++++++++++-
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/fsck/inject.c b/fsck/inject.c
index cb348b3ba067..3c3f37790616 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -211,8 +211,13 @@ static void inject_node_usage(void)
 	MSG(0, "  i_size: inject inode i_size\n");
 	MSG(0, "  i_blocks: inject inode i_blocks\n");
 	MSG(0, "  i_xattr_nid: inject inode i_xattr_nid\n");
+	MSG(0, "  i_ext.fofs: inject inode i_ext.fofs\n");
+	MSG(0, "  i_ext.blk_addr: inject inode i_ext.blk_addr\n");
+	MSG(0, "  i_ext.len: inject inode i_ext.len\n");
 	MSG(0, "  i_extra_isize: inject inode i_extra_isize\n");
+	MSG(0, "  i_inline_xattr_size: inject inode i_inline_xattr_size\n");
 	MSG(0, "  i_inode_checksum: inject inode i_inode_checksum\n");
+	MSG(0, "  i_compr_blocks: inject inode i_compr_blocks\n");
 	MSG(0, "  i_addr: inject inode i_addr array selected by --idx <index>\n");
 	MSG(0, "  i_nid: inject inode i_nid array selected by --idx <index>\n");
 	MSG(0, "  addr: inject {in}direct node nid/addr array selected by --idx <index>\n");
@@ -1023,16 +1028,39 @@ static int inject_inode(struct f2fs_sb_info *sbi, struct f2fs_node *node,
 		MSG(0, "Info: inject inode i_xattr_nid of nid %u: %u -> %u\n",
 		    opt->nid, le32_to_cpu(inode->i_xattr_nid), (u32)opt->val);
 		inode->i_xattr_nid = cpu_to_le32((u32)opt->val);
+	} else if (!strcmp(opt->mb, "i_ext.fofs")) {
+		MSG(0, "Info: inject inode i_ext.fofs of nid %u: %u -> %u\n",
+		    opt->nid, le32_to_cpu(inode->i_ext.fofs), (u32)opt->val);
+		inode->i_ext.fofs = cpu_to_le32((u32)opt->val);
+	} else if (!strcmp(opt->mb, "i_ext.blk_addr")) {
+		MSG(0, "Info: inject inode i_ext.blk_addr of nid %u: "
+		    "0x%x -> 0x%x\n", opt->nid,
+		    le32_to_cpu(inode->i_ext.blk_addr), (u32)opt->val);
+		inode->i_ext.blk_addr = cpu_to_le32((u32)opt->val);
+	} else if (!strcmp(opt->mb, "i_ext.len")) {
+		MSG(0, "Info: inject inode i_ext.len of nid %u: %u -> %u\n",
+		    opt->nid, le32_to_cpu(inode->i_ext.len), (u32)opt->val);
+		inode->i_ext.len = cpu_to_le32((u32)opt->val);
 	} else if (!strcmp(opt->mb, "i_extra_isize")) {
 		/* do not care if F2FS_EXTRA_ATTR is enabled */
 		MSG(0, "Info: inject inode i_extra_isize of nid %u: %d -> %d\n",
 		    opt->nid, le16_to_cpu(inode->i_extra_isize), (u16)opt->val);
 		inode->i_extra_isize = cpu_to_le16((u16)opt->val);
+	} else if (!strcmp(opt->mb, "i_inline_xattr_size")) {
+		MSG(0, "Info: inject inode i_inline_xattr_size of nid %u: "
+		    "%d -> %d\n", opt->nid,
+		    le16_to_cpu(inode->i_inline_xattr_size), (u16)opt->val);
+		inode->i_inline_xattr_size = cpu_to_le16((u16)opt->val);
 	} else if (!strcmp(opt->mb, "i_inode_checksum")) {
 		MSG(0, "Info: inject inode i_inode_checksum of nid %u: "
 		    "0x%x -> 0x%x\n", opt->nid,
 		    le32_to_cpu(inode->i_inode_checksum), (u32)opt->val);
 		inode->i_inode_checksum = cpu_to_le32((u32)opt->val);
+	} else if (!strcmp(opt->mb, "i_compr_blocks")) {
+		MSG(0, "Info: inject inode i_compr_blocks of nid %u: "
+		    "%"PRIu64" -> %"PRIu64"\n", opt->nid,
+		    le64_to_cpu(inode->i_compr_blocks), (u64)opt->val);
+		inode->i_compr_blocks = cpu_to_le64((u64)opt->val);
 	} else if (!strcmp(opt->mb, "i_addr")) {
 		/* do not care if it is inline data */
 		if (opt->idx >= DEF_ADDRS_PER_INODE) {
diff --git a/man/inject.f2fs.8 b/man/inject.f2fs.8
index 0dcf3a23cff8..15f77d076e3c 100644
--- a/man/inject.f2fs.8
+++ b/man/inject.f2fs.8
@@ -145,7 +145,7 @@ summary entry ofs_in_node.
 .RE
 .TP
 .BI \-\-node
-Inject node block specified by \fInid\P.
+Inject node block specified by \fInid\fP.
 The available \fImb\fP of \fInode\fP are:
 .RS 1.2i
 .TP
@@ -185,12 +185,27 @@ inode i_blocks.
 .BI i_xattr_nid
 inode i_xattr_nid.
 .TP
+.BI i_ext.fofs
+inode i_ext.fofs.
+.TP
+.BI i_ext.blk_addr
+inode i_ext.blk_addr.
+.TP
+.BI i_ext.len
+inode i_ext.len.
+.TP
 .BI i_extra_isize
 inode i_extra_isize.
 .TP
+.BI i_inline_xattr_size
+inode i_inline_xattr_size.
+.TP
 .BI i_inode_checksum
 inode i_inode_checksum.
 .TP
+.BI i_compr_blocks
+inode i_compr_blocks.
+.TP
 .BI i_addr
 inode i_addr array specified by \fIidx\fP.
 .TP
-- 
2.43.0



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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [f2fs-dev] [PATCH v3 13/13] inject.f2fs: add member `filename' in inject_dentry
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
                   ` (11 preceding siblings ...)
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 12/13] inject.f2fs: add members in inject_node Sheng Yong
@ 2025-08-20 12:42 ` Sheng Yong
  2025-08-23  8:34 ` [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Chao Yu via Linux-f2fs-devel
  13 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2025-08-20 12:42 UTC (permalink / raw)
  To: jaegeuk, chao; +Cc: shengyong1, linux-f2fs-devel

From: Sheng Yong <shengyong1@xiaomi.com>

This patch adds a new member `filename' in inject_dentry to inject
dentry filename. The dentry is specified by nid option.

Note that '.' and '..' dentries are special, because they are not in the
parent directory of nid. So this patch also adds a new option `--dots'
to inject these two dentries.

Signed-off-by: Sheng Yong <shengyong1@xiaomi.com>
---
 fsck/inject.c     | 94 ++++++++++++++++++++++++++++++++++++++++-------
 fsck/inject.h     |  1 +
 man/inject.f2fs.8 | 12 +++++-
 3 files changed, 92 insertions(+), 15 deletions(-)

diff --git a/fsck/inject.c b/fsck/inject.c
index 3c3f37790616..0e46b1b8f067 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -117,7 +117,7 @@ void inject_usage(void)
 	MSG(0, "  --sit <0|1|2> --mb <name> --blk <blk> [--idx <index>] --val <value> inject sit entry\n");
 	MSG(0, "  --ssa --mb <name> --blk <blk> [--idx <index>] --val <value> inject summary entry\n");
 	MSG(0, "  --node --mb <name> --nid <nid> [--idx <index>] --val <value> inject node\n");
-	MSG(0, "  --dent --mb <name> --nid <ino> [--idx <index>] --val <value> inject ino's dentry\n");
+	MSG(0, "  --dent --mb <name> --nid <ino> [--dots <1|2>] --val/str <value/string> inject ino's dentry\n");
 	MSG(0, "  --dry-run do not really inject\n");
 
 	exit(1);
@@ -225,12 +225,16 @@ static void inject_node_usage(void)
 
 static void inject_dent_usage(void)
 {
-	MSG(0, "inject.f2fs --dent --mb <name> --nid <nid> [--idx <index>] --val <value> inject dentry\n");
+	MSG(0, "inject.f2fs --dent --mb <name> --nid <nid> [--dots <1|2>] --val/str <value/string> inject dentry\n");
+	MSG(0, "[dots]:\n");
+	MSG(0, "  1: inject \".\" in directory which is specified by nid\n");
+	MSG(0, "  2: inject \"..\" in directory which is specified by nid\n");
 	MSG(0, "[mb]:\n");
 	MSG(0, "  d_bitmap: inject dentry block d_bitmap of nid\n");
 	MSG(0, "  d_hash: inject dentry hash\n");
 	MSG(0, "  d_ino: inject dentry ino\n");
 	MSG(0, "  d_ftype: inject dentry ftype\n");
+	MSG(0, "  filename: inject dentry filename, its hash and len are updated implicitly\n");
 }
 
 int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
@@ -254,6 +258,7 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
 		{"ssa", no_argument, 0, 12},
 		{"node", no_argument, 0, 13},
 		{"dent", no_argument, 0, 14},
+		{"dots", required_argument, 0, 15},
 		{0, 0, 0, 0}
 	};
 
@@ -352,6 +357,14 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
 			opt->dent = true;
 			MSG(0, "Info: inject dentry\n");
 			break;
+		case 15:
+			opt->dots = atoi(optarg);
+			if (opt->dots != TYPE_DOT &&
+			    opt->dots != TYPE_DOTDOT)
+				return -ERANGE;
+			MSG(0, "Info: inject %s dentry\n",
+			    opt->dots == TYPE_DOT ? "dot" : "dotdot");
+			break;
 		case 'd':
 			if (optarg[0] == '-' || !is_digits(optarg))
 				return EWRONG_OPT;
@@ -384,6 +397,9 @@ int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
 			} else if (opt->dent) {
 				inject_dent_usage();
 				exit(0);
+			} else {
+				MSG(0, "\tError: Wrong option -%c (%d) %s\n",
+				    o, o, optarg);
 			}
 			return EUNKNOWN_OPT;
 		}
@@ -1202,12 +1218,12 @@ static int find_dir_entry(struct f2fs_dentry_ptr *d, nid_t ino)
 		}
 
 		de = &d->dentry[slot];
-		if (le32_to_cpu(de->ino) == ino && de->hash_code != 0)
-			return slot;
 		if (de->name_len == 0) {
 			slot++;
 			continue;
 		}
+		if (le32_to_cpu(de->ino) == ino)
+			return slot;
 		slot += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
 	}
 
@@ -1220,14 +1236,15 @@ static int inject_dentry(struct f2fs_sb_info *sbi, struct inject_option *opt)
 	struct f2fs_node *node_blk = NULL;
 	struct f2fs_inode *inode;
 	struct f2fs_dentry_ptr d;
-	void *inline_dentry;
+	void *buf = NULL, *inline_dentry;
 	struct f2fs_dentry_block *dent_blk = NULL;
 	block_t addr = 0;
-	void *buf = NULL;
 	struct f2fs_dir_entry *dent = NULL;
 	struct dnode_of_data dn;
 	nid_t pino;
-	int slot = -ENOENT, ret;
+	int slot = -ENOENT, namelen, namecap, ret;
+	unsigned int dentry_hash;
+	char *name;
 
 	node_blk = malloc(F2FS_BLKSIZE);
 	ASSERT(node_blk != NULL);
@@ -1236,12 +1253,25 @@ static int inject_dentry(struct f2fs_sb_info *sbi, struct inject_option *opt)
 	get_node_info(sbi, opt->nid, &ni);
 	ret = dev_read_block(node_blk, ni.blk_addr);
 	ASSERT(ret >= 0);
-	pino = le32_to_cpu(node_blk->i.i_pino);
 
-	/* get parent inode */
-	get_node_info(sbi, pino, &ni);
-	ret = dev_read_block(node_blk, ni.blk_addr);
-	ASSERT(ret >= 0);
+	if (opt->dots) {
+		if (!LINUX_S_ISDIR(le16_to_cpu(node_blk->i.i_mode))) {
+			ERR_MSG("ino %u is not a directory, cannot inject "
+				"its %s\n", opt->nid,
+				opt->dots == TYPE_DOT ? "." : "..");
+			ret = -EINVAL;
+			goto out;
+		}
+		/* pino is itself */
+		pino = opt->nid;
+	} else {
+		pino = le32_to_cpu(node_blk->i.i_pino);
+
+		/* get parent inode */
+		get_node_info(sbi, pino, &ni);
+		ret = dev_read_block(node_blk, ni.blk_addr);
+		ASSERT(ret >= 0);
+	}
 	inode = &node_blk->i;
 
 	/* find child dentry */
@@ -1251,7 +1281,10 @@ static int inject_dentry(struct f2fs_sb_info *sbi, struct inject_option *opt)
 		addr = ni.blk_addr;
 		buf = node_blk;
 
-		slot = find_dir_entry(&d, opt->nid);
+		if (opt->dots == TYPE_DOTDOT)
+			slot = find_dir_entry(&d, le32_to_cpu(node_blk->i.i_pino));
+		else
+			slot = find_dir_entry(&d, opt->nid);
 		if (slot >= 0)
 			dent = &d.dentry[slot];
 	} else {
@@ -1287,7 +1320,10 @@ static int inject_dentry(struct f2fs_sb_info *sbi, struct inject_option *opt)
 			ASSERT(ret >= 0);
 
 			make_dentry_ptr(&d, node_blk, dent_blk, 1);
-			slot = find_dir_entry(&d, opt->nid);
+			if (opt->dots == TYPE_DOTDOT)
+				slot = find_dir_entry(&d, le32_to_cpu(node_blk->i.i_pino));
+			else
+				slot = find_dir_entry(&d, opt->nid);
 			if (slot >= 0) {
 				dent = &d.dentry[slot];
 				buf = dent_blk;
@@ -1321,6 +1357,36 @@ static int inject_dentry(struct f2fs_sb_info *sbi, struct inject_option *opt)
 		    "%d -> %d\n", opt->nid, dent->file_type,
 		    (u8)opt->val);
 		dent->file_type = (u8)opt->val;
+	} else if (!strcmp(opt->mb, "filename")) {
+		if (!opt->str) {
+			ERR_MSG("option str is needed\n");
+			ret = -EINVAL;
+			goto out;
+		}
+		namecap = ALIGN_UP(le16_to_cpu(dent->name_len), F2FS_SLOT_LEN);
+		namelen = strlen(opt->str);
+		if (namelen > namecap || namelen > F2FS_NAME_LEN) {
+			ERR_MSG("option str too long\n");
+			ret = -EINVAL;
+			goto out;
+		}
+		name = (char *)d.filename[slot];
+		MSG(0, "Info: inject dentry filename of nid %u: "
+		    "%.*s -> %s\n", opt->nid, le16_to_cpu(dent->name_len),
+		    name, opt->str);
+		memcpy(name, opt->str, namelen);
+		MSG(0, "Info: inject dentry namelen of nid %u: "
+		    "%d -> %d\n", opt->nid, le16_to_cpu(dent->name_len),
+		    namelen);
+		dent->name_len = cpu_to_le16(namelen);
+		dentry_hash = f2fs_dentry_hash(get_encoding(sbi),
+						IS_CASEFOLDED(inode),
+						(unsigned char *)name,
+						namelen);
+		MSG(0, "Info: inject dentry d_hash of nid %u: "
+		    "0x%x -> 0x%x\n", opt->nid, le32_to_cpu(dent->hash_code),
+		    dentry_hash);
+		dent->hash_code = cpu_to_le32(dentry_hash);
 	} else {
 		ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
 		ret = -EINVAL;
diff --git a/fsck/inject.h b/fsck/inject.h
index 43c21b56a7eb..706a211bc645 100644
--- a/fsck/inject.h
+++ b/fsck/inject.h
@@ -30,6 +30,7 @@ struct inject_option {
 	int cp;			/* which cp */
 	int nat;		/* which nat pack */
 	int sit;		/* which sit pack */
+	int dots;		/* . or .. dentry */
 	bool ssa;
 	bool node;
 	bool dent;
diff --git a/man/inject.f2fs.8 b/man/inject.f2fs.8
index 15f77d076e3c..1fb7328c8c69 100644
--- a/man/inject.f2fs.8
+++ b/man/inject.f2fs.8
@@ -217,7 +217,14 @@ inode i_nid array specified by \fIidx\fP.
 .RE
 .TP
 .BI \-\-dent
-Inject dentry block or dir entry specified \fInid\fP.
+Inject dentry block or dir entry specified by \fInid\fP.
+.RS 1.2i
+.TP
+.BI \-\-dots " 1 or 2"
+The option means the "." or ".." directory entry of \fInid\fP is going to be injected.
+.RE
+.TP
+.BI ""
 The available \fImb\fP of \fIdent\fP are:
 .RS 1.2i
 .TP
@@ -232,6 +239,9 @@ dentry ino.
 .TP
 .BI d_ftype
 dentry ftype.
+.TP
+.BI filename
+dentry filename, and corresponding d_hash and namelen are updated implicitly.
 .RE
 .TP
 .BI \-\-dry\-run
-- 
2.43.0



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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [f2fs-dev] [PATCH v3 10/13] inject.f2fs: add members in inject_cp
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 10/13] inject.f2fs: add members in inject_cp Sheng Yong
@ 2025-08-23  8:28   ` Chao Yu via Linux-f2fs-devel
  0 siblings, 0 replies; 16+ messages in thread
From: Chao Yu via Linux-f2fs-devel @ 2025-08-23  8:28 UTC (permalink / raw)
  To: Sheng Yong, jaegeuk; +Cc: shengyong1, linux-f2fs-devel

On 8/20/2025 8:42 PM, Sheng Yong wrote:
> From: Sheng Yong <shengyong1@xiaomi.com>
> 
> The following members are added to inject more fields in cp:
> 
> * next_blkaddr: inject fsync dnodes
> 
>    An error is returned if no fsync dnode is found.
>    Furthermore, the injection is not supported on a zoned device. This
>    is because fsync dnodes must remains at the end of current warm node
>    segment, any dnode change causes all previous dnodes in the chain to
>    be updated out-of-place, and there may not have enough space left in
>    the curseg. To simplify the injection, it returns an error on the
>    zoned device.
>    An example of dnode chain shows:
>      [inject_cp: 608] [   0] blkaddr:0x1204
>      [inject_cp: 608] [   1] blkaddr:0x1205
>      [inject_cp: 608] [   2] blkaddr:0x1206
>      [inject_cp: 608] [   3] blkaddr:0x1207
>      [inject_cp: 608] [   4] blkaddr:0x1208
>      [inject_cp: 608] [   5] blkaddr:0x1209
>      [inject_cp: 608] [   6] blkaddr:0x120a
>      [inject_cp: 608] [   7] blkaddr:0x120b
>      [inject_cp: 608] [   8] blkaddr:0x120c
>      [inject_cp: 608] [   9] blkaddr:0x120d
>    where `0' indicates next free blkaddr of warm node curseg, thus
>    start blkaddr + next_blkoff of warm node curseg, which cannot be
>    injected. `1~9` indicate next_blkaddr in node_footer of dnodes in
>    the chain, which can be injected.
> 
> * alloc_type: inject curseg's alloc type
> * crc: inject cp's checksum
> * elapsed_time: inject cp's mount elapsed time
> 
> Signed-off-by: Sheng Yong <shengyong1@xiaomi.com>
> ---
> v3: * update commit message to show dnode chain and the injectable range
>      * free(node) before return
> ---
>   fsck/fsck.h       |  4 ++-
>   fsck/inject.c     | 86 ++++++++++++++++++++++++++++++++++++++++++++++-
>   fsck/mount.c      | 18 +++++-----
>   man/inject.f2fs.8 | 11 +++++-
>   4 files changed, 108 insertions(+), 11 deletions(-)
> 
> diff --git a/fsck/fsck.h b/fsck/fsck.h
> index 40cb6d9a6417..05daa2de9531 100644
> --- a/fsck/fsck.h
> +++ b/fsck/fsck.h
> @@ -223,6 +223,8 @@ extern int f2fs_ra_meta_pages(struct f2fs_sb_info *, block_t, int, int);
>   extern int f2fs_do_mount(struct f2fs_sb_info *);
>   extern void f2fs_do_umount(struct f2fs_sb_info *);
>   extern int f2fs_sparse_initialize_meta(struct f2fs_sb_info *);
> +extern int f2fs_find_fsync_inode(struct f2fs_sb_info *, struct list_head *);
> +extern void f2fs_destroy_fsync_dnodes(struct list_head *);
>   
>   extern void flush_journal_entries(struct f2fs_sb_info *);
>   extern void update_curseg_info(struct f2fs_sb_info *, int);
> @@ -239,7 +241,7 @@ extern void duplicate_checkpoint(struct f2fs_sb_info *);
>   extern void write_checkpoint(struct f2fs_sb_info *);
>   extern void write_checkpoints(struct f2fs_sb_info *);
>   extern void write_raw_cp_blocks(struct f2fs_sb_info *sbi,
> -			struct f2fs_checkpoint *cp, int which);
> +			struct f2fs_checkpoint *cp, int which, bool update_crc);
>   extern void update_superblock(struct f2fs_super_block *, int);
>   extern void update_data_blkaddr(struct f2fs_sb_info *, nid_t, u16, block_t,
>   			struct f2fs_node *);
> diff --git a/fsck/inject.c b/fsck/inject.c
> index 5ca105b60f8e..272a4a64dc05 100644
> --- a/fsck/inject.c
> +++ b/fsck/inject.c
> @@ -151,6 +151,10 @@ static void inject_cp_usage(void)
>   	MSG(0, "  cur_node_blkoff: inject cur_node_blkoff array selected by --idx <index>\n");
>   	MSG(0, "  cur_data_segno: inject cur_data_segno array selected by --idx <index>\n");
>   	MSG(0, "  cur_data_blkoff: inject cur_data_blkoff array selected by --idx <index>\n");
> +	MSG(0, "  alloc_type: inject alloc_type array selected by --idx <index>\n");
> +	MSG(0, "  next_blkaddr: inject next_blkaddr of fsync dnodes selected by --idx <index>\n");
> +	MSG(0, "  crc: inject crc checksum\n");
> +	MSG(0, "  elapsed_time: inject elapsed_time\n");
>   }
>   
>   static void inject_nat_usage(void)
> @@ -456,6 +460,7 @@ out:
>   static int inject_cp(struct f2fs_sb_info *sbi, struct inject_option *opt)
>   {
>   	struct f2fs_checkpoint *cp, *cur_cp = F2FS_CKPT(sbi);
> +	bool update_crc = true;
>   	char *buf = NULL;
>   	int ret = 0;
>   
> @@ -534,6 +539,85 @@ static int inject_cp(struct f2fs_sb_info *sbi, struct inject_option *opt)
>   		    opt->idx, opt->cp, get_cp(cur_data_blkoff[opt->idx]),
>   		    (u16)opt->val);
>   		set_cp(cur_data_blkoff[opt->idx], (u16)opt->val);
> +	} else if (!strcmp(opt->mb, "alloc_type")) {
> +		if (opt->idx >= MAX_ACTIVE_LOGS) {
> +			ERR_MSG("invalid index %u of cp->alloc_type[]\n",
> +				opt->idx);
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +		MSG(0, "Info: inject alloc_type[%d] of cp %d: 0x%x -> 0x%x\n",
> +		    opt->idx, opt->cp, cp->alloc_type[opt->idx],
> +		    (unsigned char)opt->val);
> +		cp->alloc_type[opt->idx] = (unsigned char)opt->val;
> +	} else if (!strcmp(opt->mb, "next_blkaddr")) {
> +		struct fsync_inode_entry *entry;
> +		struct list_head inode_list = LIST_HEAD_INIT(inode_list);
> +		struct f2fs_node *node;
> +		block_t blkaddr;
> +		int i = 0;
> +
> +		if (c.zoned_model == F2FS_ZONED_HM) {
> +			ERR_MSG("inject fsync dnodes not supported in "
> +				"zoned device\n");
> +			ret = -EOPNOTSUPP;
> +			goto out;
> +		}
> +
> +		if (!need_fsync_data_record(sbi)) {
> +			ERR_MSG("no need to recover fsync dnodes\n");
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		ret = f2fs_find_fsync_inode(sbi, &inode_list);
> +		if (ret) {
> +			ERR_MSG("failed to find fsync inodes: %d\n", ret);
> +			goto out;
> +		}
> +
> +		list_for_each_entry(entry, &inode_list, list) {
> +			if (i == opt->idx)
> +				blkaddr = entry->blkaddr;
> +			DBG(0, "[%4d] blkaddr:0x%x\n", i++, entry->blkaddr);
> +		}
> +
> +		f2fs_destroy_fsync_dnodes(&inode_list);
> +
> +		if (opt->idx == 0 || opt->idx >= i) {
> +			ERR_MSG("invalid index %u of fsync dnodes range [1, %u]\n",
> +				opt->idx, i);
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		MSG(0, "Info: inject next_blkaddr[%d] of cp %d: 0x%x -> 0x%x\n",
> +		    opt->idx, opt->cp, blkaddr, (u32)opt->val);
> +
> +		node = malloc(F2FS_BLKSIZE);
> +		ASSERT(node);
> +		ret = dev_read_block(node, blkaddr);
> +		ASSERT(ret >= 0);
> +		F2FS_NODE_FOOTER(node)->next_blkaddr = cpu_to_le32((u32)opt->val);
> +		if (IS_INODE(node))
> +			ret = update_inode(sbi, node, &blkaddr);
> +		else
> +			ret = update_block(sbi, node, &blkaddr, NULL);
> +		free(node);
> +		ASSERT(ret >= 0);
> +		goto out;
> +	} else if (!strcmp(opt->mb, "crc")) {
> +		__le32 *crc = (__le32 *)((unsigned char *)cp +
> +						get_cp(checksum_offset));
> +
> +		MSG(0, "Info: inject crc of cp %d: 0x%x -> 0x%x\n",
> +		    opt->cp, le32_to_cpu(*crc), (u32)opt->val);
> +		*crc = cpu_to_le32((u32)opt->val);
> +		update_crc = false;
> +	} else if (!strcmp(opt->mb, "elapsed_time")) {
> +		MSG(0, "Info: inject elapsed_time of cp %d: %llu -> %"PRIu64"\n",
> +		    opt->cp, get_cp(elapsed_time), (u64)opt->val);
> +		set_cp(elapsed_time, (u64)opt->val);
>   	} else {
>   		ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
>   		ret = -EINVAL;
> @@ -541,7 +625,7 @@ static int inject_cp(struct f2fs_sb_info *sbi, struct inject_option *opt)
>   	}
>   
>   	print_ckpt_info(sbi);
> -	write_raw_cp_blocks(sbi, cp, opt->cp);
> +	write_raw_cp_blocks(sbi, cp, opt->cp, update_crc);
>   
>   out:
>   	free(buf);
> diff --git a/fsck/mount.c b/fsck/mount.c
> index f9f780d4aff6..f03fa2d6861a 100644
> --- a/fsck/mount.c
> +++ b/fsck/mount.c
> @@ -3510,17 +3510,19 @@ void write_checkpoints(struct f2fs_sb_info *sbi)
>   	write_checkpoint(sbi);
>   }
>   
> -void write_raw_cp_blocks(struct f2fs_sb_info *sbi,
> -			 struct f2fs_checkpoint *cp, int which)
> +void write_raw_cp_blocks(struct f2fs_sb_info *sbi, struct f2fs_checkpoint *cp,
> +			 int which, bool update_crc)
>   {
>   	struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
>   	uint32_t crc;
>   	block_t cp_blkaddr;
>   	int ret;
>   
> -	crc = f2fs_checkpoint_chksum(cp);
> -	*((__le32 *)((unsigned char *)cp + get_cp(checksum_offset))) =
> +	if (update_crc) {
> +		crc = f2fs_checkpoint_chksum(cp);
> +		*((__le32 *)((unsigned char *)cp + get_cp(checksum_offset))) =
>   							cpu_to_le32(crc);
> +	}
>   
>   	cp_blkaddr = get_sb(cp_blkaddr);
>   	if (which == 2)
> @@ -3754,7 +3756,7 @@ static void del_fsync_inode(struct fsync_inode_entry *entry)
>   	free(entry);
>   }
>   
> -static void destroy_fsync_dnodes(struct list_head *head)
> +void f2fs_destroy_fsync_dnodes(struct list_head *head)
>   {
>   	struct fsync_inode_entry *entry, *tmp;
>   
> @@ -3860,7 +3862,7 @@ static int sanity_check_node_chain(struct f2fs_sb_info *sbi,
>   	return 0;
>   }
>   
> -static int find_fsync_inode(struct f2fs_sb_info *sbi, struct list_head *head)
> +int f2fs_find_fsync_inode(struct f2fs_sb_info *sbi, struct list_head *head)
>   {
>   	struct curseg_info *curseg;
>   	struct f2fs_node *node_blk, *node_blk_fast;
> @@ -4056,7 +4058,7 @@ static int record_fsync_data(struct f2fs_sb_info *sbi)
>   	if (!need_fsync_data_record(sbi))
>   		return 0;
>   
> -	ret = find_fsync_inode(sbi, &inode_list);
> +	ret = f2fs_find_fsync_inode(sbi, &inode_list);
>   	if (ret)
>   		goto out;
>   
> @@ -4071,7 +4073,7 @@ static int record_fsync_data(struct f2fs_sb_info *sbi)
>   
>   	ret = traverse_dnodes(sbi, &inode_list);
>   out:
> -	destroy_fsync_dnodes(&inode_list);
> +	f2fs_destroy_fsync_dnodes(&inode_list);
>   	return ret;
>   }
>   
> diff --git a/man/inject.f2fs.8 b/man/inject.f2fs.8
> index 65ac658a129b..0e7cd5065a15 100644
> --- a/man/inject.f2fs.8
> +++ b/man/inject.f2fs.8
> @@ -45,7 +45,7 @@ The available \fImb\fP of \fIsb\fP are:
>   .RS 1.2i
>   .TP
>   .BI magic
> -magic numbe.
> +magic number.
>   .TP
>   .BI s_stop_reason
>   s_stop_reason array.
> @@ -79,6 +79,15 @@ cur_data_segno array.
>   .TP
>   .BI cur_data_blkoff
>   cur_data_blkoff array.

alloc_type entry.

Thanks,

> +.TP
> +.BI next_blkaddr
> +fsync dnodes.
> +.TP
> +.BI crc
> +crc checksum.
> +.TP
> +.BI elapsed_time
> +elapsed mount time.
>   .RE
>   .TP
>   .BI \-\-nat " 0 or 1 or 2"



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

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections
  2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
                   ` (12 preceding siblings ...)
  2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 13/13] inject.f2fs: add member `filename' in inject_dentry Sheng Yong
@ 2025-08-23  8:34 ` Chao Yu via Linux-f2fs-devel
  13 siblings, 0 replies; 16+ messages in thread
From: Chao Yu via Linux-f2fs-devel @ 2025-08-23  8:34 UTC (permalink / raw)
  To: Sheng Yong, jaegeuk; +Cc: shengyong1, linux-f2fs-devel

On 8/20/2025 8:42 PM, Sheng Yong wrote:
> Hi, all,
> 
> Since we have not yet determined how to check the test result properly,
> I split patchset v2 into two parts on Chao's suggestion. This is the
> first part which contains some fixes/cleanups for f2fs-tools, and adds
> new injections for inject.f2fs.

There is one missed entry in inject.f2fs manual page in 10/13, once you
fixed it, feel free to add:

Reviewed-by: Chao Yu <chao@kernel.org>

Thanks,

> 
> Changes from last version are also updated in individual patch.
> 
> v3: * split original patchset into two parts
>      * update manual
>      * refactor inject sit/nat in journal
>      * fix memleak
> v2: * add some fix and cleanup
>      * remove img.tar.gz from testcases
>      * add testcases for injection
>      * cleanup helpers script and simplify filter.sed and expected.in
>      https://lore.kernel.org/linux-f2fs-devel/20250610123743.667183-1-shengyong1@xiaomi.com/
> v1: https://lore.kernel.org/linux-f2fs-devel/20241029120956.4186731-1-shengyong@oppo.com/
> 
> Sheng Yong (13):
>    fsck.f2fs: do not finish/reset zone if dry-run is true
>    f2fs-tools: add option N to answer no for all questions
>    f2fs-tools: cleanup {nid|segno}_in_journal
>    fsck.f2fs: fix invalidate checkpoint
>    dump.f2fs: print more info
>    f2fs-tools: add and export lookup_sit_in_journal
>    inject.f2fs: fix injecting sit/nat in journal
>    inject.f2fs: fix injection on zoned device
>    inject.f2fs: fix and cleanup parsing numeric options
>    inject.f2fs: add members in inject_cp
>    inject.f2fs: add member `feature' in inject_sb
>    inject.f2fs: add members in inject_node
>    inject.f2fs: add member `filename' in inject_dentry
> 
>   fsck/dump.c         |  15 +-
>   fsck/f2fs.h         |  12 +-
>   fsck/fsck.c         |   2 +-
>   fsck/fsck.h         |   4 +-
>   fsck/inject.c       | 515 ++++++++++++++++++++++++++++++++++++--------
>   fsck/inject.h       |   1 +
>   fsck/main.c         |  14 +-
>   fsck/mount.c        |  61 ++++--
>   include/f2fs_fs.h   |   1 +
>   lib/libf2fs_zoned.c |   6 +-
>   man/dump.f2fs.8     |   3 +
>   man/fsck.f2fs.8     |   3 +
>   man/inject.f2fs.8   |  43 +++-
>   13 files changed, 552 insertions(+), 128 deletions(-)
> 



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

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2025-08-23  8:34 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-20 12:42 [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Sheng Yong
2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 01/13] fsck.f2fs: do not finish/reset zone if dry-run is true Sheng Yong
2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 02/13] f2fs-tools: add option N to answer no for all questions Sheng Yong
2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 03/13] f2fs-tools: cleanup {nid|segno}_in_journal Sheng Yong
2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 04/13] fsck.f2fs: fix invalidate checkpoint Sheng Yong
2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 05/13] dump.f2fs: print more info Sheng Yong
2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 06/13] f2fs-tools: add and export lookup_sit_in_journal Sheng Yong
2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 07/13] inject.f2fs: fix injecting sit/nat in journal Sheng Yong
2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 08/13] inject.f2fs: fix injection on zoned device Sheng Yong
2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 09/13] inject.f2fs: fix and cleanup parsing numeric options Sheng Yong
2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 10/13] inject.f2fs: add members in inject_cp Sheng Yong
2025-08-23  8:28   ` Chao Yu via Linux-f2fs-devel
2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 11/13] inject.f2fs: add member `feature' in inject_sb Sheng Yong
2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 12/13] inject.f2fs: add members in inject_node Sheng Yong
2025-08-20 12:42 ` [f2fs-dev] [PATCH v3 13/13] inject.f2fs: add member `filename' in inject_dentry Sheng Yong
2025-08-23  8:34 ` [f2fs-dev] [PATCH v3 00/13] f2fs-tools & inject.f2fs: bugfix and new injections Chao Yu via Linux-f2fs-devel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).