diff mbox series

[f2fs-dev] f2fs: check zone type before sending async reset zone command

Message ID 20230804091556.2372567-1-shinichiro.kawasaki@wdc.com (mailing list archive)
State New
Headers show
Series [f2fs-dev] f2fs: check zone type before sending async reset zone command | expand

Commit Message

Shinichiro Kawasaki Aug. 4, 2023, 9:15 a.m. UTC
The commit 25f9080576b9 ("f2fs: add async reset zone command support")
introduced "async reset zone commands" by calling
__submit_zone_reset_cmd() in async discard operations. However,
__submit_zone_reset_cmd() is called regardless of zone type of discard
target zone. When devices have conventional zones, zone reset commands
are sent to the conventional zones and cause I/O errors.

Avoid the I/O errors by checking that the discard target zone type is
sequential write required. If not, handle the discard operation in same
manner as non-zoned, regular block devices. For that purpose, add a new
helper function f2fs_bdev_index() which gets index of the zone reset
target device.

Fixes: 25f9080576b9 ("f2fs: add async reset zone command support")
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
---
 fs/f2fs/f2fs.h    | 16 ++++++++++++++++
 fs/f2fs/segment.c | 35 +++++++++++++++++++++++++----------
 2 files changed, 41 insertions(+), 10 deletions(-)

Comments

Chao Yu Aug. 7, 2023, 2:34 a.m. UTC | #1
On 2023/8/4 17:15, Shin'ichiro Kawasaki via Linux-f2fs-devel wrote:
> The commit 25f9080576b9 ("f2fs: add async reset zone command support")
> introduced "async reset zone commands" by calling
> __submit_zone_reset_cmd() in async discard operations. However,
> __submit_zone_reset_cmd() is called regardless of zone type of discard
> target zone. When devices have conventional zones, zone reset commands
> are sent to the conventional zones and cause I/O errors.
> 
> Avoid the I/O errors by checking that the discard target zone type is
> sequential write required. If not, handle the discard operation in same
> manner as non-zoned, regular block devices. For that purpose, add a new
> helper function f2fs_bdev_index() which gets index of the zone reset
> target device.
> 
> Fixes: 25f9080576b9 ("f2fs: add async reset zone command support")
> Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>

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

Thanks,
diff mbox series

Patch

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index c7cb2177b252..73fbc9c5f5b3 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -4423,6 +4423,22 @@  static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi,
 }
 #endif
 
+static inline int f2fs_bdev_index(struct f2fs_sb_info *sbi,
+				  struct block_device *bdev)
+{
+	int i;
+
+	if (!f2fs_is_multi_device(sbi))
+		return 0;
+
+	for (i = 0; i < sbi->s_ndevs; i++)
+		if (FDEV(i).bdev == bdev)
+			return i;
+
+	WARN_ON(1);
+	return -1;
+}
+
 static inline bool f2fs_hw_should_discard(struct f2fs_sb_info *sbi)
 {
 	return f2fs_sb_has_blkzoned(sbi);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 0457d620011f..668cf709927f 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -1257,7 +1257,13 @@  static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
 		return 0;
 
 #ifdef CONFIG_BLK_DEV_ZONED
-	if (f2fs_sb_has_blkzoned(sbi) && bdev_is_zoned(bdev)) {
+	int devi = f2fs_bdev_index(sbi, bdev);
+
+	if (devi < 0)
+		return -EINVAL;
+
+	if (f2fs_sb_has_blkzoned(sbi) && bdev_is_zoned(bdev) &&
+		f2fs_blkz_is_seq(sbi, devi, dc->di.start)) {
 		__submit_zone_reset_cmd(sbi, dc, flag, wait_list, issued);
 		return 0;
 	}
@@ -1785,15 +1791,24 @@  static void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr)
 	dc = __lookup_discard_cmd(sbi, blkaddr);
 #ifdef CONFIG_BLK_DEV_ZONED
 	if (dc && f2fs_sb_has_blkzoned(sbi) && bdev_is_zoned(dc->bdev)) {
-		/* force submit zone reset */
-		if (dc->state == D_PREP)
-			__submit_zone_reset_cmd(sbi, dc, REQ_SYNC,
-						&dcc->wait_list, NULL);
-		dc->ref++;
-		mutex_unlock(&dcc->cmd_lock);
-		/* wait zone reset */
-		__wait_one_discard_bio(sbi, dc);
-		return;
+		int devi = f2fs_bdev_index(sbi, dc->bdev);
+
+		if (devi < 0) {
+			mutex_unlock(&dcc->cmd_lock);
+			return;
+		}
+
+		if (f2fs_blkz_is_seq(sbi, devi, dc->di.start)) {
+			/* force submit zone reset */
+			if (dc->state == D_PREP)
+				__submit_zone_reset_cmd(sbi, dc, REQ_SYNC,
+							&dcc->wait_list, NULL);
+			dc->ref++;
+			mutex_unlock(&dcc->cmd_lock);
+			/* wait zone reset */
+			__wait_one_discard_bio(sbi, dc);
+			return;
+		}
 	}
 #endif
 	if (dc) {