From: Greg Kroah-Hartman Date: Mon, 6 Jun 2022 11:40:04 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v5.10.121~123 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=436fadaf00768b6162aa8d4469a6aab3deb1b0f0;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: f2fs-fix-deadloop-in-foreground-gc.patch --- diff --git a/queue-4.19/f2fs-fix-deadloop-in-foreground-gc.patch b/queue-4.19/f2fs-fix-deadloop-in-foreground-gc.patch new file mode 100644 index 00000000000..29e3113eecd --- /dev/null +++ b/queue-4.19/f2fs-fix-deadloop-in-foreground-gc.patch @@ -0,0 +1,92 @@ +From cfd66bb715fd11fde3338d0660cffa1396adc27d Mon Sep 17 00:00:00 2001 +From: Chao Yu +Date: Wed, 4 May 2022 14:09:22 +0800 +Subject: f2fs: fix deadloop in foreground GC + +From: Chao Yu + +commit cfd66bb715fd11fde3338d0660cffa1396adc27d upstream. + +As Yanming reported in bugzilla: + +https://bugzilla.kernel.org/show_bug.cgi?id=215914 + +The root cause is: in a very small sized image, it's very easy to +exceed threshold of foreground GC, if we calculate free space and +dirty data based on section granularity, in corner case, +has_not_enough_free_secs() will always return true, result in +deadloop in f2fs_gc(). + +So this patch refactors has_not_enough_free_secs() as below to fix +this issue: +1. calculate needed space based on block granularity, and separate +all blocks to two parts, section part, and block part, comparing +section part to free section, and comparing block part to free space +in openned log. +2. account F2FS_DIRTY_NODES, F2FS_DIRTY_IMETA and F2FS_DIRTY_DENTS +as node block consumer; +3. account F2FS_DIRTY_DENTS as data block consumer; + +Cc: stable@vger.kernel.org +Reported-by: Ming Yan +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/segment.h | 32 ++++++++++++++++++++------------ + 1 file changed, 20 insertions(+), 12 deletions(-) + +--- a/fs/f2fs/segment.h ++++ b/fs/f2fs/segment.h +@@ -534,11 +534,10 @@ static inline int reserved_sections(stru + return GET_SEC_FROM_SEG(sbi, (unsigned int)reserved_segments(sbi)); + } + +-static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi) ++static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi, ++ unsigned int node_blocks, unsigned int dent_blocks) + { +- unsigned int node_blocks = get_pages(sbi, F2FS_DIRTY_NODES) + +- get_pages(sbi, F2FS_DIRTY_DENTS); +- unsigned int dent_blocks = get_pages(sbi, F2FS_DIRTY_DENTS); ++ + unsigned int segno, left_blocks; + int i; + +@@ -564,19 +563,28 @@ static inline bool has_curseg_enough_spa + static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, + int freed, int needed) + { +- int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES); +- int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS); +- int imeta_secs = get_blocktype_secs(sbi, F2FS_DIRTY_IMETA); ++ unsigned int total_node_blocks = get_pages(sbi, F2FS_DIRTY_NODES) + ++ get_pages(sbi, F2FS_DIRTY_DENTS) + ++ get_pages(sbi, F2FS_DIRTY_IMETA); ++ unsigned int total_dent_blocks = get_pages(sbi, F2FS_DIRTY_DENTS); ++ unsigned int node_secs = total_node_blocks / BLKS_PER_SEC(sbi); ++ unsigned int dent_secs = total_dent_blocks / BLKS_PER_SEC(sbi); ++ unsigned int node_blocks = total_node_blocks % BLKS_PER_SEC(sbi); ++ unsigned int dent_blocks = total_dent_blocks % BLKS_PER_SEC(sbi); ++ unsigned int free, need_lower, need_upper; + + if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) + return false; + +- if (free_sections(sbi) + freed == reserved_sections(sbi) + needed && +- has_curseg_enough_space(sbi)) ++ free = free_sections(sbi) + freed; ++ need_lower = node_secs + dent_secs + reserved_sections(sbi) + needed; ++ need_upper = need_lower + (node_blocks ? 1 : 0) + (dent_blocks ? 1 : 0); ++ ++ if (free > need_upper) + return false; +- return (free_sections(sbi) + freed) <= +- (node_secs + 2 * dent_secs + imeta_secs + +- reserved_sections(sbi) + needed); ++ else if (free <= need_lower) ++ return true; ++ return !has_curseg_enough_space(sbi, node_blocks, dent_blocks); + } + + static inline bool excess_prefree_segs(struct f2fs_sb_info *sbi) diff --git a/queue-4.19/series b/queue-4.19/series index 133bc504257..af8b588ed9c 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -140,3 +140,4 @@ dmaengine-stm32-mdma-remove-gisr1-register.patch iommu-amd-increase-timeout-waiting-for-ga-log-enable.patch perf-c2c-use-stdio-interface-if-slang-is-not-support.patch perf-jevents-fix-event-syntax-error-caused-by-extsel.patch +f2fs-fix-deadloop-in-foreground-gc.patch