From: Greg Kroah-Hartman Date: Mon, 6 Jun 2022 11:32:38 +0000 (+0200) Subject: 5.17-stable patches X-Git-Tag: v5.10.121~127 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3f8edb37f639284a36a2f115841ff4b036a992fe;p=thirdparty%2Fkernel%2Fstable-queue.git 5.17-stable patches added patches: f2fs-don-t-need-inode-lock-for-system-hidden-quota.patch f2fs-don-t-use-casefolded-comparison-for-.-and.patch f2fs-fix-deadloop-in-foreground-gc.patch f2fs-fix-fallocate-to-use-file_modified-to-update-permissions-consistently.patch f2fs-fix-to-clear-dirty-inode-in-f2fs_evict_inode.patch f2fs-fix-to-do-sanity-check-for-inline-inode.patch f2fs-fix-to-do-sanity-check-on-total_data_blocks.patch --- diff --git a/queue-5.17/f2fs-don-t-need-inode-lock-for-system-hidden-quota.patch b/queue-5.17/f2fs-don-t-need-inode-lock-for-system-hidden-quota.patch new file mode 100644 index 00000000000..1a8c118170e --- /dev/null +++ b/queue-5.17/f2fs-don-t-need-inode-lock-for-system-hidden-quota.patch @@ -0,0 +1,90 @@ +From 6213f5d4d23c50d393a31dc8e351e63a1fd10dbe Mon Sep 17 00:00:00 2001 +From: Jaegeuk Kim +Date: Thu, 5 May 2022 17:40:25 -0700 +Subject: f2fs: don't need inode lock for system hidden quota + +From: Jaegeuk Kim + +commit 6213f5d4d23c50d393a31dc8e351e63a1fd10dbe upstream. + +Let's avoid false-alarmed lockdep warning. + +[ 58.914674] [T1501146] -> #2 (&sb->s_type->i_mutex_key#20){+.+.}-{3:3}: +[ 58.915975] [T1501146] system_server: down_write+0x7c/0xe0 +[ 58.916738] [T1501146] system_server: f2fs_quota_sync+0x60/0x1a8 +[ 58.917563] [T1501146] system_server: block_operations+0x16c/0x43c +[ 58.918410] [T1501146] system_server: f2fs_write_checkpoint+0x114/0x318 +[ 58.919312] [T1501146] system_server: f2fs_issue_checkpoint+0x178/0x21c +[ 58.920214] [T1501146] system_server: f2fs_sync_fs+0x48/0x6c +[ 58.920999] [T1501146] system_server: f2fs_do_sync_file+0x334/0x738 +[ 58.921862] [T1501146] system_server: f2fs_sync_file+0x30/0x48 +[ 58.922667] [T1501146] system_server: __arm64_sys_fsync+0x84/0xf8 +[ 58.923506] [T1501146] system_server: el0_svc_common.llvm.12821150825140585682+0xd8/0x20c +[ 58.924604] [T1501146] system_server: do_el0_svc+0x28/0xa0 +[ 58.925366] [T1501146] system_server: el0_svc+0x24/0x38 +[ 58.926094] [T1501146] system_server: el0_sync_handler+0x88/0xec +[ 58.926920] [T1501146] system_server: el0_sync+0x1b4/0x1c0 + +[ 58.927681] [T1501146] -> #1 (&sbi->cp_global_sem){+.+.}-{3:3}: +[ 58.928889] [T1501146] system_server: down_write+0x7c/0xe0 +[ 58.929650] [T1501146] system_server: f2fs_write_checkpoint+0xbc/0x318 +[ 58.930541] [T1501146] system_server: f2fs_issue_checkpoint+0x178/0x21c +[ 58.931443] [T1501146] system_server: f2fs_sync_fs+0x48/0x6c +[ 58.932226] [T1501146] system_server: sync_filesystem+0xac/0x130 +[ 58.933053] [T1501146] system_server: generic_shutdown_super+0x38/0x150 +[ 58.933958] [T1501146] system_server: kill_block_super+0x24/0x58 +[ 58.934791] [T1501146] system_server: kill_f2fs_super+0xcc/0x124 +[ 58.935618] [T1501146] system_server: deactivate_locked_super+0x90/0x120 +[ 58.936529] [T1501146] system_server: deactivate_super+0x74/0xac +[ 58.937356] [T1501146] system_server: cleanup_mnt+0x128/0x168 +[ 58.938150] [T1501146] system_server: __cleanup_mnt+0x18/0x28 +[ 58.938944] [T1501146] system_server: task_work_run+0xb8/0x14c +[ 58.939749] [T1501146] system_server: do_notify_resume+0x114/0x1e8 +[ 58.940595] [T1501146] system_server: work_pending+0xc/0x5f0 + +[ 58.941375] [T1501146] -> #0 (&sbi->gc_lock){+.+.}-{3:3}: +[ 58.942519] [T1501146] system_server: __lock_acquire+0x1270/0x2868 +[ 58.943366] [T1501146] system_server: lock_acquire+0x114/0x294 +[ 58.944169] [T1501146] system_server: down_write+0x7c/0xe0 +[ 58.944930] [T1501146] system_server: f2fs_issue_checkpoint+0x13c/0x21c +[ 58.945831] [T1501146] system_server: f2fs_sync_fs+0x48/0x6c +[ 58.946614] [T1501146] system_server: f2fs_do_sync_file+0x334/0x738 +[ 58.947472] [T1501146] system_server: f2fs_ioc_commit_atomic_write+0xc8/0x14c +[ 58.948439] [T1501146] system_server: __f2fs_ioctl+0x674/0x154c +[ 58.949253] [T1501146] system_server: f2fs_ioctl+0x54/0x88 +[ 58.950018] [T1501146] system_server: __arm64_sys_ioctl+0xa8/0x110 +[ 58.950865] [T1501146] system_server: el0_svc_common.llvm.12821150825140585682+0xd8/0x20c +[ 58.951965] [T1501146] system_server: do_el0_svc+0x28/0xa0 +[ 58.952727] [T1501146] system_server: el0_svc+0x24/0x38 +[ 58.953454] [T1501146] system_server: el0_sync_handler+0x88/0xec +[ 58.954279] [T1501146] system_server: el0_sync+0x1b4/0x1c0 + +Cc: stable@vger.kernel.org +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/super.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -2706,7 +2706,8 @@ int f2fs_quota_sync(struct super_block * + if (!sb_has_quota_active(sb, cnt)) + continue; + +- inode_lock(dqopt->files[cnt]); ++ if (!f2fs_sb_has_quota_ino(sbi)) ++ inode_lock(dqopt->files[cnt]); + + /* + * do_quotactl +@@ -2725,7 +2726,8 @@ int f2fs_quota_sync(struct super_block * + up_read(&sbi->quota_sem); + f2fs_unlock_op(sbi); + +- inode_unlock(dqopt->files[cnt]); ++ if (!f2fs_sb_has_quota_ino(sbi)) ++ inode_unlock(dqopt->files[cnt]); + + if (ret) + break; diff --git a/queue-5.17/f2fs-don-t-use-casefolded-comparison-for-.-and.patch b/queue-5.17/f2fs-don-t-use-casefolded-comparison-for-.-and.patch new file mode 100644 index 00000000000..6fb8ba061ae --- /dev/null +++ b/queue-5.17/f2fs-don-t-use-casefolded-comparison-for-.-and.patch @@ -0,0 +1,101 @@ +From b5639bb4313b9d455fc9fc4768d23a5e4ca8cb9d Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Sat, 14 May 2022 10:59:29 -0700 +Subject: f2fs: don't use casefolded comparison for "." and ".." + +From: Eric Biggers + +commit b5639bb4313b9d455fc9fc4768d23a5e4ca8cb9d upstream. + +Tryng to rename a directory that has all following properties fails with +EINVAL and triggers the 'WARN_ON_ONCE(!fscrypt_has_encryption_key(dir))' +in f2fs_match_ci_name(): + + - The directory is casefolded + - The directory is encrypted + - The directory's encryption key is not yet set up + - The parent directory is *not* encrypted + +The problem is incorrect handling of the lookup of ".." to get the +parent reference to update. fscrypt_setup_filename() treats ".." (and +".") specially, as it's never encrypted. It's passed through as-is, and +setting up the directory's key is not attempted. As the name isn't a +no-key name, f2fs treats it as a "normal" name and attempts a casefolded +comparison. That breaks the assumption of the WARN_ON_ONCE() in +f2fs_match_ci_name() which assumes that for encrypted directories, +casefolded comparisons only happen when the directory's key is set up. + +We could just remove this WARN_ON_ONCE(). However, since casefolding is +always a no-op on "." and ".." anyway, let's instead just not casefold +these names. This results in the standard bytewise comparison. + +Fixes: 7ad08a58bf67 ("f2fs: Handle casefolding with Encryption") +Cc: # v5.11+ +Signed-off-by: Eric Biggers +Reviewed-by: Gabriel Krisman Bertazi +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/dir.c | 3 ++- + fs/f2fs/f2fs.h | 10 +++++----- + fs/f2fs/hash.c | 11 ++++++----- + 3 files changed, 13 insertions(+), 11 deletions(-) + +--- a/fs/f2fs/dir.c ++++ b/fs/f2fs/dir.c +@@ -82,7 +82,8 @@ int f2fs_init_casefolded_name(const stru + #if IS_ENABLED(CONFIG_UNICODE) + struct super_block *sb = dir->i_sb; + +- if (IS_CASEFOLDED(dir)) { ++ if (IS_CASEFOLDED(dir) && ++ !is_dot_dotdot(fname->usr_fname->name, fname->usr_fname->len)) { + fname->cf_name.name = f2fs_kmem_cache_alloc(f2fs_cf_name_slab, + GFP_NOFS, false, F2FS_SB(sb)); + if (!fname->cf_name.name) +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -491,11 +491,11 @@ struct f2fs_filename { + #if IS_ENABLED(CONFIG_UNICODE) + /* + * For casefolded directories: the casefolded name, but it's left NULL +- * if the original name is not valid Unicode, if the directory is both +- * casefolded and encrypted and its encryption key is unavailable, or if +- * the filesystem is doing an internal operation where usr_fname is also +- * NULL. In all these cases we fall back to treating the name as an +- * opaque byte sequence. ++ * if the original name is not valid Unicode, if the original name is ++ * "." or "..", if the directory is both casefolded and encrypted and ++ * its encryption key is unavailable, or if the filesystem is doing an ++ * internal operation where usr_fname is also NULL. In all these cases ++ * we fall back to treating the name as an opaque byte sequence. + */ + struct fscrypt_str cf_name; + #endif +--- a/fs/f2fs/hash.c ++++ b/fs/f2fs/hash.c +@@ -91,7 +91,7 @@ static u32 TEA_hash_name(const u8 *p, si + /* + * Compute @fname->hash. For all directories, @fname->disk_name must be set. + * For casefolded directories, @fname->usr_fname must be set, and also +- * @fname->cf_name if the filename is valid Unicode. ++ * @fname->cf_name if the filename is valid Unicode and is not "." or "..". + */ + void f2fs_hash_filename(const struct inode *dir, struct f2fs_filename *fname) + { +@@ -110,10 +110,11 @@ void f2fs_hash_filename(const struct ino + /* + * If the casefolded name is provided, hash it instead of the + * on-disk name. If the casefolded name is *not* provided, that +- * should only be because the name wasn't valid Unicode, so fall +- * back to treating the name as an opaque byte sequence. Note +- * that to handle encrypted directories, the fallback must use +- * usr_fname (plaintext) rather than disk_name (ciphertext). ++ * should only be because the name wasn't valid Unicode or was ++ * "." or "..", so fall back to treating the name as an opaque ++ * byte sequence. Note that to handle encrypted directories, ++ * the fallback must use usr_fname (plaintext) rather than ++ * disk_name (ciphertext). + */ + WARN_ON_ONCE(!fname->usr_fname->name); + if (fname->cf_name.name) { diff --git a/queue-5.17/f2fs-fix-deadloop-in-foreground-gc.patch b/queue-5.17/f2fs-fix-deadloop-in-foreground-gc.patch new file mode 100644 index 00000000000..9ef9392d662 --- /dev/null +++ b/queue-5.17/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 +@@ -572,11 +572,10 @@ static inline int reserved_sections(stru + return GET_SEC_FROM_SEG(sbi, 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; + +@@ -602,19 +601,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 f2fs_is_checkpoint_ready(struct f2fs_sb_info *sbi) diff --git a/queue-5.17/f2fs-fix-fallocate-to-use-file_modified-to-update-permissions-consistently.patch b/queue-5.17/f2fs-fix-fallocate-to-use-file_modified-to-update-permissions-consistently.patch new file mode 100644 index 00000000000..4aedb274af6 --- /dev/null +++ b/queue-5.17/f2fs-fix-fallocate-to-use-file_modified-to-update-permissions-consistently.patch @@ -0,0 +1,44 @@ +From 958ed92922028ec67f504dcdc72bfdfd0f43936a Mon Sep 17 00:00:00 2001 +From: Chao Yu +Date: Tue, 17 May 2022 11:37:23 +0800 +Subject: f2fs: fix fallocate to use file_modified to update permissions consistently + +From: Chao Yu + +commit 958ed92922028ec67f504dcdc72bfdfd0f43936a upstream. + +This patch tries to fix permission consistency issue as all other +mainline filesystems. + +Since the initial introduction of (posix) fallocate back at the turn of +the century, it has been possible to use this syscall to change the +user-visible contents of files. This can happen by extending the file +size during a preallocation, or through any of the newer modes (punch, +zero, collapse, insert range). Because the call can be used to change +file contents, we should treat it like we do any other modification to a +file -- update the mtime, and drop set[ug]id privileges/capabilities. + +The VFS function file_modified() does all this for us if pass it a +locked inode, so let's make fallocate drop permissions correctly. + +Cc: stable@kernel.org +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/file.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -1774,6 +1774,10 @@ static long f2fs_fallocate(struct file * + + inode_lock(inode); + ++ ret = file_modified(file); ++ if (ret) ++ goto out; ++ + if (mode & FALLOC_FL_PUNCH_HOLE) { + if (offset >= inode->i_size) + goto out; diff --git a/queue-5.17/f2fs-fix-to-clear-dirty-inode-in-f2fs_evict_inode.patch b/queue-5.17/f2fs-fix-to-clear-dirty-inode-in-f2fs_evict_inode.patch new file mode 100644 index 00000000000..1dbb616c2e0 --- /dev/null +++ b/queue-5.17/f2fs-fix-to-clear-dirty-inode-in-f2fs_evict_inode.patch @@ -0,0 +1,79 @@ +From f2db71053dc0409fae785096ad19cce4c8a95af7 Mon Sep 17 00:00:00 2001 +From: Chao Yu +Date: Sat, 30 Apr 2022 21:19:24 +0800 +Subject: f2fs: fix to clear dirty inode in f2fs_evict_inode() + +From: Chao Yu + +commit f2db71053dc0409fae785096ad19cce4c8a95af7 upstream. + +As Yanming reported in bugzilla: + +https://bugzilla.kernel.org/show_bug.cgi?id=215904 + +The kernel message is shown below: + +kernel BUG at fs/f2fs/inode.c:825! +Call Trace: + evict+0x282/0x4e0 + __dentry_kill+0x2b2/0x4d0 + shrink_dentry_list+0x17c/0x4f0 + shrink_dcache_parent+0x143/0x1e0 + do_one_tree+0x9/0x30 + shrink_dcache_for_umount+0x51/0x120 + generic_shutdown_super+0x5c/0x3a0 + kill_block_super+0x90/0xd0 + kill_f2fs_super+0x225/0x310 + deactivate_locked_super+0x78/0xc0 + cleanup_mnt+0x2b7/0x480 + task_work_run+0xc8/0x150 + exit_to_user_mode_prepare+0x14a/0x150 + syscall_exit_to_user_mode+0x1d/0x40 + do_syscall_64+0x48/0x90 + +The root cause is: inode node and dnode node share the same nid, +so during f2fs_evict_inode(), dnode node truncation will invalidate +its NAT entry, so when truncating inode node, it fails due to +invalid NAT entry, result in inode is still marked as dirty, fix +this issue by clearing dirty for inode and setting SBI_NEED_FSCK +flag in filesystem. + +output from dump.f2fs: +[print_node_info: 354] Node ID [0xf:15] is inode +i_nid[0] [0x f : 15] + +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/inode.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -796,8 +796,22 @@ retry: + f2fs_lock_op(sbi); + err = f2fs_remove_inode_page(inode); + f2fs_unlock_op(sbi); +- if (err == -ENOENT) ++ if (err == -ENOENT) { + err = 0; ++ ++ /* ++ * in fuzzed image, another node may has the same ++ * block address as inode's, if it was truncated ++ * previously, truncation of inode node will fail. ++ */ ++ if (is_inode_flag_set(inode, FI_DIRTY_INODE)) { ++ f2fs_warn(F2FS_I_SB(inode), ++ "f2fs_evict_inode: inconsistent node id, ino:%lu", ++ inode->i_ino); ++ f2fs_inode_synced(inode); ++ set_sbi_flag(sbi, SBI_NEED_FSCK); ++ } ++ } + } + + /* give more chances, if ENOMEM case */ diff --git a/queue-5.17/f2fs-fix-to-do-sanity-check-for-inline-inode.patch b/queue-5.17/f2fs-fix-to-do-sanity-check-for-inline-inode.patch new file mode 100644 index 00000000000..67ad42ebd49 --- /dev/null +++ b/queue-5.17/f2fs-fix-to-do-sanity-check-for-inline-inode.patch @@ -0,0 +1,114 @@ +From 677a82b44ebf263d4f9a0cfbd576a6ade797a07b Mon Sep 17 00:00:00 2001 +From: Chao Yu +Date: Wed, 18 May 2022 20:28:41 +0800 +Subject: f2fs: fix to do sanity check for inline inode + +From: Chao Yu + +commit 677a82b44ebf263d4f9a0cfbd576a6ade797a07b upstream. + +Yanming reported a kernel bug in Bugzilla kernel [1], which can be +reproduced. The bug message is: + +The kernel message is shown below: + +kernel BUG at fs/inode.c:611! +Call Trace: + evict+0x282/0x4e0 + __dentry_kill+0x2b2/0x4d0 + dput+0x2dd/0x720 + do_renameat2+0x596/0x970 + __x64_sys_rename+0x78/0x90 + do_syscall_64+0x3b/0x90 + +[1] https://bugzilla.kernel.org/show_bug.cgi?id=215895 + +The bug is due to fuzzed inode has both inline_data and encrypted flags. +During f2fs_evict_inode(), as the inode was deleted by rename(), it +will cause inline data conversion due to conflicting flags. The page +cache will be polluted and the panic will be triggered in clear_inode(). + +Try fixing the bug by doing more sanity checks for inline data inode in +sanity_check_inode(). + +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/f2fs.h | 1 + + fs/f2fs/inline.c | 29 ++++++++++++++++++++++++----- + fs/f2fs/inode.c | 3 +-- + 3 files changed, 26 insertions(+), 7 deletions(-) + +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -3955,6 +3955,7 @@ extern struct kmem_cache *f2fs_inode_ent + * inline.c + */ + bool f2fs_may_inline_data(struct inode *inode); ++bool f2fs_sanity_check_inline_data(struct inode *inode); + bool f2fs_may_inline_dentry(struct inode *inode); + void f2fs_do_read_inline_data(struct page *page, struct page *ipage); + void f2fs_truncate_inline_inode(struct inode *inode, +--- a/fs/f2fs/inline.c ++++ b/fs/f2fs/inline.c +@@ -14,21 +14,40 @@ + #include "node.h" + #include + +-bool f2fs_may_inline_data(struct inode *inode) ++static bool support_inline_data(struct inode *inode) + { + if (f2fs_is_atomic_file(inode)) + return false; +- + if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) + return false; +- + if (i_size_read(inode) > MAX_INLINE_DATA(inode)) + return false; ++ return true; ++} ++ ++bool f2fs_may_inline_data(struct inode *inode) ++{ ++ if (!support_inline_data(inode)) ++ return false; ++ ++ return !f2fs_post_read_required(inode); ++} + +- if (f2fs_post_read_required(inode)) ++bool f2fs_sanity_check_inline_data(struct inode *inode) ++{ ++ if (!f2fs_has_inline_data(inode)) + return false; + +- return true; ++ if (!support_inline_data(inode)) ++ return true; ++ ++ /* ++ * used by sanity_check_inode(), when disk layout fields has not ++ * been synchronized to inmem fields. ++ */ ++ return (S_ISREG(inode->i_mode) && ++ (file_is_encrypt(inode) || file_is_verity(inode) || ++ (F2FS_I(inode)->i_flags & F2FS_COMPR_FL))); + } + + bool f2fs_may_inline_dentry(struct inode *inode) +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -276,8 +276,7 @@ static bool sanity_check_inode(struct in + } + } + +- if (f2fs_has_inline_data(inode) && +- (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode))) { ++ if (f2fs_sanity_check_inline_data(inode)) { + set_sbi_flag(sbi, SBI_NEED_FSCK); + f2fs_warn(sbi, "%s: inode (ino=%lx, mode=%u) should not have inline_data, run fsck to fix", + __func__, inode->i_ino, inode->i_mode); diff --git a/queue-5.17/f2fs-fix-to-do-sanity-check-on-total_data_blocks.patch b/queue-5.17/f2fs-fix-to-do-sanity-check-on-total_data_blocks.patch new file mode 100644 index 00000000000..86bf7bc1c59 --- /dev/null +++ b/queue-5.17/f2fs-fix-to-do-sanity-check-on-total_data_blocks.patch @@ -0,0 +1,156 @@ +From 6b8beca0edd32075a769bfe4178ca00c0dcd22a9 Mon Sep 17 00:00:00 2001 +From: Chao Yu +Date: Fri, 6 May 2022 09:33:06 +0800 +Subject: f2fs: fix to do sanity check on total_data_blocks + +From: Chao Yu + +commit 6b8beca0edd32075a769bfe4178ca00c0dcd22a9 upstream. + +As Yanming reported in bugzilla: + +https://bugzilla.kernel.org/show_bug.cgi?id=215916 + +The kernel message is shown below: + +kernel BUG at fs/f2fs/segment.c:2560! +Call Trace: + allocate_segment_by_default+0x228/0x440 + f2fs_allocate_data_block+0x13d1/0x31f0 + do_write_page+0x18d/0x710 + f2fs_outplace_write_data+0x151/0x250 + f2fs_do_write_data_page+0xef9/0x1980 + move_data_page+0x6af/0xbc0 + do_garbage_collect+0x312f/0x46f0 + f2fs_gc+0x6b0/0x3bc0 + f2fs_balance_fs+0x921/0x2260 + f2fs_write_single_data_page+0x16be/0x2370 + f2fs_write_cache_pages+0x428/0xd00 + f2fs_write_data_pages+0x96e/0xd50 + do_writepages+0x168/0x550 + __writeback_single_inode+0x9f/0x870 + writeback_sb_inodes+0x47d/0xb20 + __writeback_inodes_wb+0xb2/0x200 + wb_writeback+0x4bd/0x660 + wb_workfn+0x5f3/0xab0 + process_one_work+0x79f/0x13e0 + worker_thread+0x89/0xf60 + kthread+0x26a/0x300 + ret_from_fork+0x22/0x30 +RIP: 0010:new_curseg+0xe8d/0x15f0 + +The root cause is: ckpt.valid_block_count is inconsistent with SIT table, +stat info indicates filesystem has free blocks, but SIT table indicates +filesystem has no free segment. + +So that during garbage colloection, it triggers panic when LFS allocator +fails to find free segment. + +This patch tries to fix this issue by checking consistency in between +ckpt.valid_block_count and block accounted from SIT. + +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/f2fs.h | 4 ++-- + fs/f2fs/segment.c | 33 ++++++++++++++++++++++----------- + fs/f2fs/segment.h | 1 + + 3 files changed, 25 insertions(+), 13 deletions(-) + +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -1092,8 +1092,8 @@ enum count_type { + */ + #define PAGE_TYPE_OF_BIO(type) ((type) > META ? META : (type)) + enum page_type { +- DATA, +- NODE, ++ DATA = 0, ++ NODE = 1, /* should not change this */ + META, + NR_PAGE_TYPE, + META_FLUSH, +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -4553,7 +4553,7 @@ static int build_sit_entries(struct f2fs + unsigned int i, start, end; + unsigned int readed, start_blk = 0; + int err = 0; +- block_t total_node_blocks = 0; ++ block_t sit_valid_blocks[2] = {0, 0}; + + do { + readed = f2fs_ra_meta_pages(sbi, start_blk, BIO_MAX_VECS, +@@ -4578,8 +4578,8 @@ static int build_sit_entries(struct f2fs + if (err) + return err; + seg_info_from_raw_sit(se, &sit); +- if (IS_NODESEG(se->type)) +- total_node_blocks += se->valid_blocks; ++ ++ sit_valid_blocks[SE_PAGETYPE(se)] += se->valid_blocks; + + if (f2fs_block_unit_discard(sbi)) { + /* build discard map only one time */ +@@ -4619,15 +4619,15 @@ static int build_sit_entries(struct f2fs + sit = sit_in_journal(journal, i); + + old_valid_blocks = se->valid_blocks; +- if (IS_NODESEG(se->type)) +- total_node_blocks -= old_valid_blocks; ++ ++ sit_valid_blocks[SE_PAGETYPE(se)] -= old_valid_blocks; + + err = check_block_count(sbi, start, &sit); + if (err) + break; + seg_info_from_raw_sit(se, &sit); +- if (IS_NODESEG(se->type)) +- total_node_blocks += se->valid_blocks; ++ ++ sit_valid_blocks[SE_PAGETYPE(se)] += se->valid_blocks; + + if (f2fs_block_unit_discard(sbi)) { + if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) { +@@ -4649,13 +4649,24 @@ static int build_sit_entries(struct f2fs + } + up_read(&curseg->journal_rwsem); + +- if (!err && total_node_blocks != valid_node_count(sbi)) { ++ if (err) ++ return err; ++ ++ if (sit_valid_blocks[NODE] != valid_node_count(sbi)) { + f2fs_err(sbi, "SIT is corrupted node# %u vs %u", +- total_node_blocks, valid_node_count(sbi)); +- err = -EFSCORRUPTED; ++ sit_valid_blocks[NODE], valid_node_count(sbi)); ++ return -EFSCORRUPTED; ++ } ++ ++ if (sit_valid_blocks[DATA] + sit_valid_blocks[NODE] > ++ valid_user_blocks(sbi)) { ++ f2fs_err(sbi, "SIT is corrupted data# %u %u vs %u", ++ sit_valid_blocks[DATA], sit_valid_blocks[NODE], ++ valid_user_blocks(sbi)); ++ return -EFSCORRUPTED; + } + +- return err; ++ return 0; + } + + static void init_free_segmap(struct f2fs_sb_info *sbi) +--- a/fs/f2fs/segment.h ++++ b/fs/f2fs/segment.h +@@ -24,6 +24,7 @@ + + #define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA) + #define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE && (t) <= CURSEG_COLD_NODE) ++#define SE_PAGETYPE(se) ((IS_NODESEG((se)->type) ? NODE : DATA)) + + static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi, + unsigned short seg_type) diff --git a/queue-5.17/series b/queue-5.17/series index 3907e5facfb..d74ba791010 100644 --- a/queue-5.17/series +++ b/queue-5.17/series @@ -609,3 +609,10 @@ nfs-convert-gfp_nofs-to-gfp_kernel.patch nfsv4.1-mark-qualified-async-operations-as-moveable-.patch f2fs-fix-to-avoid-f2fs_bug_on-in-dec_valid_node_count.patch f2fs-fix-to-do-sanity-check-on-block-address-in-f2fs_do_zero_range.patch +f2fs-fix-to-clear-dirty-inode-in-f2fs_evict_inode.patch +f2fs-fix-deadloop-in-foreground-gc.patch +f2fs-don-t-need-inode-lock-for-system-hidden-quota.patch +f2fs-fix-to-do-sanity-check-on-total_data_blocks.patch +f2fs-don-t-use-casefolded-comparison-for-.-and.patch +f2fs-fix-fallocate-to-use-file_modified-to-update-permissions-consistently.patch +f2fs-fix-to-do-sanity-check-for-inline-inode.patch