Skip to content

Commit 00034f4

Browse files
chaseyupundiramit
authored andcommitted
UPSTREAM: f2fs: fix potential panic during fstrim
As Ju Hyung Park reported: "When 'fstrim' is called for manual trim, a BUG() can be triggered randomly with this patch. I'm seeing this issue on both x86 Desktop and arm64 Android phone. On x86 Desktop, this was caused during Ubuntu boot-up. I have a cronjob installed which calls 'fstrim -v /' during boot. On arm64 Android, this was caused during GC looping with 1ms gc_min_sleep_time & gc_max_sleep_time." Root cause of this issue is that f2fs_wait_discard_bios can only be used by f2fs_put_super, because during put_super there must be no other referrers, so it can ignore discard entry's reference count when removing the entry, otherwise in other caller we will hit bug_on in __remove_discard_cmd as there may be other issuer added reference count in discard entry. Thread A Thread B - issue_discard_thread - f2fs_ioc_fitrim - f2fs_trim_fs - f2fs_wait_discard_bios - __issue_discard_cmd - __submit_discard_cmd - __wait_discard_cmd - dc->ref++ - __wait_one_discard_bio - __wait_discard_cmd - __remove_discard_cmd - f2fs_bug_on(sbi, dc->ref) Change-Id: I8fb5c8215e6222ae853e7781218d5084e1f11166 Fixes: 969d1b180d987c2be02de890d0fff0f66a0e80de Reported-by: Ju Hyung Park <qkrwngud825@gmail.com> Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> (cherry picked from commit 638164a2718f337ea224b747cf5977ef143166a4)
1 parent 1bd8cd4 commit 00034f4

3 files changed

Lines changed: 5 additions & 5 deletions

File tree

fs/f2fs/f2fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2606,7 +2606,7 @@ void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr);
26062606
bool is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr);
26072607
void refresh_sit_entry(struct f2fs_sb_info *sbi, block_t old, block_t new);
26082608
void stop_discard_thread(struct f2fs_sb_info *sbi);
2609-
void f2fs_wait_discard_bios(struct f2fs_sb_info *sbi);
2609+
void f2fs_wait_discard_bios(struct f2fs_sb_info *sbi, bool umount);
26102610
void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc);
26112611
void release_discard_addrs(struct f2fs_sb_info *sbi);
26122612
int npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);

fs/f2fs/segment.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,11 +1290,11 @@ void stop_discard_thread(struct f2fs_sb_info *sbi)
12901290
}
12911291

12921292
/* This comes from f2fs_put_super and f2fs_trim_fs */
1293-
void f2fs_wait_discard_bios(struct f2fs_sb_info *sbi)
1293+
void f2fs_wait_discard_bios(struct f2fs_sb_info *sbi, bool umount)
12941294
{
12951295
__issue_discard_cmd(sbi, false);
12961296
__drop_discard_cmd(sbi);
1297-
__wait_discard_cmd(sbi, false);
1297+
__wait_discard_cmd(sbi, !umount);
12981298
}
12991299

13001300
static void mark_discard_range_all(struct f2fs_sb_info *sbi)
@@ -2324,7 +2324,7 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
23242324
}
23252325
/* It's time to issue all the filed discards */
23262326
mark_discard_range_all(sbi);
2327-
f2fs_wait_discard_bios(sbi);
2327+
f2fs_wait_discard_bios(sbi, false);
23282328
out:
23292329
range->len = F2FS_BLK_TO_BYTES(cpc.trimmed);
23302330
return err;

fs/f2fs/super.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ static void f2fs_put_super(struct super_block *sb)
801801
}
802802

803803
/* be sure to wait for any on-going discard commands */
804-
f2fs_wait_discard_bios(sbi);
804+
f2fs_wait_discard_bios(sbi, true);
805805

806806
if (f2fs_discard_en(sbi) && !sbi->discard_blks) {
807807
struct cp_control cpc = {

0 commit comments

Comments
 (0)