[PATCH v2] f2fs: sync pending discards before reserving device alias

Wenjie Qi posted 1 patch 4 weeks, 1 day ago
There is a newer version of this series
fs/f2fs/segment.c | 10 ++++++++++
1 file changed, 10 insertions(+)
[PATCH v2] f2fs: sync pending discards before reserving device alias
Posted by Wenjie Qi 4 weeks, 1 day ago
A released device-alias range can accumulate pending discard
commands. The reserve path later makes the same range valid again
through f2fs_reserve_device_alias().

If pending discards in that range are not synchronized first, the
discard thread can still submit them and hit __check_sit_bitmap().

Handle the synchronization under sit_i->sentry_lock by moving the
range wait into f2fs_reserve_device_alias().

Fixes: eae3faf210bd ("f2fs: support dynamic reserve/release for device aliasing")
Cc: stable@vger.kernel.org
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
---
v2:
- move the discard wait under sit_i->sentry_lock in
  f2fs_reserve_device_alias()

  kernel BUG at fs/f2fs/segment.c:1228!
  Oops: invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN PTI
  CPU: 1 UID: 0 PID: 79 Comm: f2fs_discard-25
  RIP: 0010:__check_sit_bitmap+0x2e1/0x4e0
  Call Trace:
   __submit_discard_cmd+0x921/0x1140
   __issue_discard_cmd+0x524/0x12f0
   issue_discard_thread+0x686/0xe20

 fs/f2fs/segment.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 1e7e745be71..50d49ba3e11 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -1916,6 +1916,15 @@ static void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr)
 		__wait_one_discard_bio(sbi, dc);
 }
 
+static void f2fs_wait_discard_bios(struct f2fs_sb_info *sbi, block_t blkaddr,
+				   unsigned int len)
+{
+	block_t end = blkaddr + len;
+
+	while (blkaddr < end)
+		f2fs_wait_discard_bio(sbi, blkaddr++);
+}
+
 void f2fs_stop_discard_thread(struct f2fs_sb_info *sbi)
 {
 	struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
@@ -2684,6 +2693,7 @@ void f2fs_reserve_device_alias(struct f2fs_sb_info *sbi, block_t addr,
 	seg_num = GET_SEGNO(sbi, addr_end) - segno + 1;
 
 	down_write(&sit_i->sentry_lock);
+	f2fs_wait_discard_bios(sbi, addr, len);
 
 	if (seg_num == 1)
 		cnt = len;
-- 
2.43.0