Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

f2fs: fix to freeze GC and discard threads quickly

Suspend can fail if kernel threads do not freeze for a while.
f2fs_gc and f2fs_discard threads can perform long-running operations
that prevent them from reaching a freeze point in a timely manner.

This patch adds explicit freezing checks in the following locations:
1. f2fs_gc: Added a check at the 'retry' label to exit the loop quickly
if freezing is requested, especially during heavy GC rounds.
2. __issue_discard_cmd: Added a 'suspended' flag to break both inner and
outer loops during discard command issuance if freezing is detected
after at least one command has been issued.
3. __issue_discard_cmd_orderly: Added a similar check for orderly discard
to ensure responsiveness.

These checks ensure that the threads release locks safely and enter the
frozen state.

Signed-off-by: Daeho Jeong <daehojeong@google.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

authored by

Daeho Jeong and committed by
Jaegeuk Kim
02d91398 7b9161a6

+21 -1
+10
fs/f2fs/gc.c
··· 1895 1895 sbi->next_victim_seg[gc_type] = 1896 1896 (cur_segno + 1 < sec_end_segno) ? 1897 1897 cur_segno + 1 : NULL_SEGNO; 1898 + 1899 + if (unlikely(freezing(current))) { 1900 + folio_put_refs(sum_folio, 2); 1901 + goto stop; 1902 + } 1898 1903 } 1899 1904 next_block: 1900 1905 folio_put_refs(sum_folio, 2); 1901 1906 segno = block_end_segno; 1902 1907 } 1903 1908 1909 + stop: 1904 1910 if (submitted) 1905 1911 f2fs_submit_merged_write(sbi, data_type); 1906 1912 ··· 1980 1974 goto stop; 1981 1975 } 1982 1976 retry: 1977 + if (unlikely(freezing(current))) { 1978 + ret = 0; 1979 + goto stop; 1980 + } 1983 1981 ret = __get_victim(sbi, &segno, gc_type, gc_control->one_time); 1984 1982 if (ret) { 1985 1983 /* allow to search victim from sections has pinned data */
+11 -1
fs/f2fs/segment.c
··· 1606 1606 if (dc->state != D_PREP) 1607 1607 goto next; 1608 1608 1609 + if (*issued > 0 && unlikely(freezing(current))) 1610 + break; 1611 + 1609 1612 if (dpolicy->io_aware && !is_idle(sbi, DISCARD_TIME)) { 1610 1613 io_interrupted = true; 1611 1614 break; ··· 1648 1645 struct blk_plug plug; 1649 1646 int i, issued; 1650 1647 bool io_interrupted = false; 1648 + bool suspended = false; 1651 1649 1652 1650 if (dpolicy->timeout) 1653 1651 f2fs_update_time(sbi, UMOUNT_DISCARD_TIMEOUT); ··· 1679 1675 list_for_each_entry_safe(dc, tmp, pend_list, list) { 1680 1676 f2fs_bug_on(sbi, dc->state != D_PREP); 1681 1677 1678 + if (issued > 0 && unlikely(freezing(current))) { 1679 + suspended = true; 1680 + break; 1681 + } 1682 + 1682 1683 if (dpolicy->timeout && 1683 1684 f2fs_time_over(sbi, UMOUNT_DISCARD_TIMEOUT)) 1684 1685 break; ··· 1703 1694 next: 1704 1695 mutex_unlock(&dcc->cmd_lock); 1705 1696 1706 - if (issued >= dpolicy->max_requests || io_interrupted) 1697 + if (issued >= dpolicy->max_requests || io_interrupted || 1698 + suspended) 1707 1699 break; 1708 1700 } 1709 1701