f2fs: check zone type before sending async reset zone command
The commit25f9080576
("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:25f9080576
("f2fs: add async reset zone command support") Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
025b3602b5
commit
3cb88bc159
@ -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);
|
||||
|
@ -1260,8 +1260,16 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
if (f2fs_sb_has_blkzoned(sbi) && bdev_is_zoned(bdev)) {
|
||||
__submit_zone_reset_cmd(sbi, dc, flag, wait_list, issued);
|
||||
return 0;
|
||||
int devi = f2fs_bdev_index(sbi, bdev);
|
||||
|
||||
if (devi < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (f2fs_blkz_is_seq(sbi, devi, dc->di.start)) {
|
||||
__submit_zone_reset_cmd(sbi, dc, flag,
|
||||
wait_list, issued);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1787,15 +1795,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) {
|
||||
|
Loading…
Reference in New Issue
Block a user