From 55b5300571b77af8e448f1e9e31771454ac324d0 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 21 Apr 2025 07:19:45 -0400 Subject: [PATCH] Fixes for 6.1 Signed-off-by: Sasha Levin --- ...d-missing-selections-of-config_crc32.patch | 179 ++++++++++++++++++ ..._fhandle_hash-to-common-include-file.patch | 92 +++++++++ ..._count-directly-if-fail-to-queue-dl_.patch | 75 ++++++++ queue-6.1/series | 3 + 4 files changed, 349 insertions(+) create mode 100644 queue-6.1/nfs-add-missing-selections-of-config_crc32.patch create mode 100644 queue-6.1/nfs-move-nfs_fhandle_hash-to-common-include-file.patch create mode 100644 queue-6.1/nfsd-decrease-sc_count-directly-if-fail-to-queue-dl_.patch diff --git a/queue-6.1/nfs-add-missing-selections-of-config_crc32.patch b/queue-6.1/nfs-add-missing-selections-of-config_crc32.patch new file mode 100644 index 0000000000..e964866d9b --- /dev/null +++ b/queue-6.1/nfs-add-missing-selections-of-config_crc32.patch @@ -0,0 +1,179 @@ +From 6cbe99b0c33fa23d66d8f07de6aea128fde6a15f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 15:02:21 -0700 +Subject: nfs: add missing selections of CONFIG_CRC32 + +From: Eric Biggers + +[ Upstream commit cd35b6cb46649750b7dbd0df0e2d767415d8917b ] + +nfs.ko, nfsd.ko, and lockd.ko all use crc32_le(), which is available +only when CONFIG_CRC32 is enabled. But the only NFS kconfig option that +selected CONFIG_CRC32 was CONFIG_NFS_DEBUG, which is client-specific and +did not actually guard the use of crc32_le() even on the client. + +The code worked around this bug by only actually calling crc32_le() when +CONFIG_CRC32 is built-in, instead hard-coding '0' in other cases. This +avoided randconfig build errors, and in real kernels the fallback code +was unlikely to be reached since CONFIG_CRC32 is 'default y'. But, this +really needs to just be done properly, especially now that I'm planning +to update CONFIG_CRC32 to not be 'default y'. + +Therefore, make CONFIG_NFS_FS, CONFIG_NFSD, and CONFIG_LOCKD select +CONFIG_CRC32. Then remove the fallback code that becomes unnecessary, +as well as the selection of CONFIG_CRC32 from CONFIG_NFS_DEBUG. + +Fixes: 1264a2f053a3 ("NFS: refactor code for calculating the crc32 hash of a filehandle") +Signed-off-by: Eric Biggers +Acked-by: Anna Schumaker +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/Kconfig | 1 + + fs/nfs/Kconfig | 2 +- + fs/nfs/internal.h | 7 ------- + fs/nfs/nfs4session.h | 4 ---- + fs/nfsd/Kconfig | 1 + + fs/nfsd/nfsfh.h | 7 ------- + include/linux/nfs.h | 7 ------- + 7 files changed, 3 insertions(+), 26 deletions(-) + +diff --git a/fs/Kconfig b/fs/Kconfig +index 703a1cea0fc09..7104e3eb38eb4 100644 +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -347,6 +347,7 @@ config GRACE_PERIOD + config LOCKD + tristate + depends on FILE_LOCKING ++ select CRC32 + select GRACE_PERIOD + + config LOCKD_V4 +diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig +index 14a72224b6571..899e25e9b4eb5 100644 +--- a/fs/nfs/Kconfig ++++ b/fs/nfs/Kconfig +@@ -2,6 +2,7 @@ + config NFS_FS + tristate "NFS client support" + depends on INET && FILE_LOCKING && MULTIUSER ++ select CRC32 + select LOCKD + select SUNRPC + select NFS_ACL_SUPPORT if NFS_V3_ACL +@@ -194,7 +195,6 @@ config NFS_USE_KERNEL_DNS + config NFS_DEBUG + bool + depends on NFS_FS && SUNRPC_DEBUG +- select CRC32 + default y + + config NFS_DISABLE_UDP_SUPPORT +diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h +index d511d66bd8a3a..ece517ebcca0b 100644 +--- a/fs/nfs/internal.h ++++ b/fs/nfs/internal.h +@@ -826,18 +826,11 @@ u64 nfs_timespec_to_change_attr(const struct timespec64 *ts) + return ((u64)ts->tv_sec << 30) + ts->tv_nsec; + } + +-#ifdef CONFIG_CRC32 + static inline u32 nfs_stateid_hash(const nfs4_stateid *stateid) + { + return ~crc32_le(0xFFFFFFFF, &stateid->other[0], + NFS4_STATEID_OTHER_SIZE); + } +-#else +-static inline u32 nfs_stateid_hash(nfs4_stateid *stateid) +-{ +- return 0; +-} +-#endif + + static inline bool nfs_error_is_fatal(int err) + { +diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h +index 351616c61df54..f9c291e2165cd 100644 +--- a/fs/nfs/nfs4session.h ++++ b/fs/nfs/nfs4session.h +@@ -148,16 +148,12 @@ static inline void nfs4_copy_sessionid(struct nfs4_sessionid *dst, + memcpy(dst->data, src->data, NFS4_MAX_SESSIONID_LEN); + } + +-#ifdef CONFIG_CRC32 + /* + * nfs_session_id_hash - calculate the crc32 hash for the session id + * @session - pointer to session + */ + #define nfs_session_id_hash(sess_id) \ + (~crc32_le(0xFFFFFFFF, &(sess_id)->data[0], sizeof((sess_id)->data))) +-#else +-#define nfs_session_id_hash(session) (0) +-#endif + #else /* defined(CONFIG_NFS_V4_1) */ + + static inline int nfs4_init_session(struct nfs_client *clp) +diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig +index 7c441f2bd4440..4f704f868d9c9 100644 +--- a/fs/nfsd/Kconfig ++++ b/fs/nfsd/Kconfig +@@ -4,6 +4,7 @@ config NFSD + depends on INET + depends on FILE_LOCKING + depends on FSNOTIFY ++ select CRC32 + select LOCKD + select SUNRPC + select EXPORTFS +diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h +index 513e028b0bbee..40aee06ebd952 100644 +--- a/fs/nfsd/nfsfh.h ++++ b/fs/nfsd/nfsfh.h +@@ -263,7 +263,6 @@ static inline bool fh_fsid_match(const struct knfsd_fh *fh1, + return true; + } + +-#ifdef CONFIG_CRC32 + /** + * knfsd_fh_hash - calculate the crc32 hash for the filehandle + * @fh - pointer to filehandle +@@ -275,12 +274,6 @@ static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh) + { + return ~crc32_le(0xFFFFFFFF, fh->fh_raw, fh->fh_size); + } +-#else +-static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh) +-{ +- return 0; +-} +-#endif + + /** + * fh_clear_pre_post_attrs - Reset pre/post attributes +diff --git a/include/linux/nfs.h b/include/linux/nfs.h +index ceb70a926b95e..095a95c1fae82 100644 +--- a/include/linux/nfs.h ++++ b/include/linux/nfs.h +@@ -46,7 +46,6 @@ enum nfs3_stable_how { + NFS_INVALID_STABLE_HOW = -1 + }; + +-#ifdef CONFIG_CRC32 + /** + * nfs_fhandle_hash - calculate the crc32 hash for the filehandle + * @fh - pointer to filehandle +@@ -58,10 +57,4 @@ static inline u32 nfs_fhandle_hash(const struct nfs_fh *fh) + { + return ~crc32_le(0xFFFFFFFF, &fh->data[0], fh->size); + } +-#else /* CONFIG_CRC32 */ +-static inline u32 nfs_fhandle_hash(const struct nfs_fh *fh) +-{ +- return 0; +-} +-#endif /* CONFIG_CRC32 */ + #endif /* _LINUX_NFS_H */ +-- +2.39.5 + diff --git a/queue-6.1/nfs-move-nfs_fhandle_hash-to-common-include-file.patch b/queue-6.1/nfs-move-nfs_fhandle_hash-to-common-include-file.patch new file mode 100644 index 0000000000..03bfb2320d --- /dev/null +++ b/queue-6.1/nfs-move-nfs_fhandle_hash-to-common-include-file.patch @@ -0,0 +1,92 @@ +From 46181bd821cc20fac9d83d95e2f706893557e896 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Mar 2023 07:16:02 -0500 +Subject: nfs: move nfs_fhandle_hash to common include file + +From: Jeff Layton + +[ Upstream commit e59fb6749ed833deee5b3cfd7e89925296d41f49 ] + +lockd needs to be able to hash filehandles for tracepoints. Move the +nfs_fhandle_hash() helper to a common nfs include file. + +Signed-off-by: Jeff Layton +Signed-off-by: Chuck Lever +Stable-dep-of: cd35b6cb4664 ("nfs: add missing selections of CONFIG_CRC32") +Signed-off-by: Sasha Levin +--- + fs/nfs/internal.h | 15 --------------- + include/linux/nfs.h | 20 ++++++++++++++++++++ + 2 files changed, 20 insertions(+), 15 deletions(-) + +diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h +index 7fa23a6368e0b..d511d66bd8a3a 100644 +--- a/fs/nfs/internal.h ++++ b/fs/nfs/internal.h +@@ -827,27 +827,12 @@ u64 nfs_timespec_to_change_attr(const struct timespec64 *ts) + } + + #ifdef CONFIG_CRC32 +-/** +- * nfs_fhandle_hash - calculate the crc32 hash for the filehandle +- * @fh - pointer to filehandle +- * +- * returns a crc32 hash for the filehandle that is compatible with +- * the one displayed by "wireshark". +- */ +-static inline u32 nfs_fhandle_hash(const struct nfs_fh *fh) +-{ +- return ~crc32_le(0xFFFFFFFF, &fh->data[0], fh->size); +-} + static inline u32 nfs_stateid_hash(const nfs4_stateid *stateid) + { + return ~crc32_le(0xFFFFFFFF, &stateid->other[0], + NFS4_STATEID_OTHER_SIZE); + } + #else +-static inline u32 nfs_fhandle_hash(const struct nfs_fh *fh) +-{ +- return 0; +-} + static inline u32 nfs_stateid_hash(nfs4_stateid *stateid) + { + return 0; +diff --git a/include/linux/nfs.h b/include/linux/nfs.h +index b06375e88e589..ceb70a926b95e 100644 +--- a/include/linux/nfs.h ++++ b/include/linux/nfs.h +@@ -10,6 +10,7 @@ + + #include + #include ++#include + #include + + /* +@@ -44,4 +45,23 @@ enum nfs3_stable_how { + /* used by direct.c to mark verf as invalid */ + NFS_INVALID_STABLE_HOW = -1 + }; ++ ++#ifdef CONFIG_CRC32 ++/** ++ * nfs_fhandle_hash - calculate the crc32 hash for the filehandle ++ * @fh - pointer to filehandle ++ * ++ * returns a crc32 hash for the filehandle that is compatible with ++ * the one displayed by "wireshark". ++ */ ++static inline u32 nfs_fhandle_hash(const struct nfs_fh *fh) ++{ ++ return ~crc32_le(0xFFFFFFFF, &fh->data[0], fh->size); ++} ++#else /* CONFIG_CRC32 */ ++static inline u32 nfs_fhandle_hash(const struct nfs_fh *fh) ++{ ++ return 0; ++} ++#endif /* CONFIG_CRC32 */ + #endif /* _LINUX_NFS_H */ +-- +2.39.5 + diff --git a/queue-6.1/nfsd-decrease-sc_count-directly-if-fail-to-queue-dl_.patch b/queue-6.1/nfsd-decrease-sc_count-directly-if-fail-to-queue-dl_.patch new file mode 100644 index 0000000000..040c0d7116 --- /dev/null +++ b/queue-6.1/nfsd-decrease-sc_count-directly-if-fail-to-queue-dl_.patch @@ -0,0 +1,75 @@ +From 13baebc23a89b7ef227b4d8f6a1a5ee36e390342 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Apr 2025 09:57:08 +0800 +Subject: nfsd: decrease sc_count directly if fail to queue dl_recall + +From: Li Lingfeng + +[ Upstream commit a1d14d931bf700c1025db8c46d6731aa5cf440f9 ] + +A deadlock warning occurred when invoking nfs4_put_stid following a failed +dl_recall queue operation: + T1 T2 + nfs4_laundromat + nfs4_get_client_reaplist + nfs4_anylock_blockers +__break_lease + spin_lock // ctx->flc_lock + spin_lock // clp->cl_lock + nfs4_lockowner_has_blockers + locks_owner_has_blockers + spin_lock // flctx->flc_lock + nfsd_break_deleg_cb + nfsd_break_one_deleg + nfs4_put_stid + refcount_dec_and_lock + spin_lock // clp->cl_lock + +When a file is opened, an nfs4_delegation is allocated with sc_count +initialized to 1, and the file_lease holds a reference to the delegation. +The file_lease is then associated with the file through kernel_setlease. + +The disassociation is performed in nfsd4_delegreturn via the following +call chain: +nfsd4_delegreturn --> destroy_delegation --> destroy_unhashed_deleg --> +nfs4_unlock_deleg_lease --> kernel_setlease --> generic_delete_lease +The corresponding sc_count reference will be released after this +disassociation. + +Since nfsd_break_one_deleg executes while holding the flc_lock, the +disassociation process becomes blocked when attempting to acquire flc_lock +in generic_delete_lease. This means: +1) sc_count in nfsd_break_one_deleg will not be decremented to 0; +2) The nfs4_put_stid called by nfsd_break_one_deleg will not attempt to +acquire cl_lock; +3) Consequently, no deadlock condition is created. + +Given that sc_count in nfsd_break_one_deleg remains non-zero, we can +safely perform refcount_dec on sc_count directly. This approach +effectively avoids triggering deadlock warnings. + +Fixes: 230ca758453c ("nfsd: put dl_stid if fail to queue dl_recall") +Signed-off-by: Li Lingfeng +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4state.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index 628d20574a919..bdee95d714d0e 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -4941,7 +4941,7 @@ static void nfsd_break_one_deleg(struct nfs4_delegation *dp) + queued = nfsd4_run_cb(&dp->dl_recall); + WARN_ON_ONCE(!queued); + if (!queued) +- nfs4_put_stid(&dp->dl_stid); ++ refcount_dec(&dp->dl_stid.sc_count); + } + + /* Called from break_lease() with flc_lock held. */ +-- +2.39.5 + diff --git a/queue-6.1/series b/queue-6.1/series index f43bede492..f325997268 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -197,3 +197,6 @@ riscv-properly-export-reserved-regions-in-proc-iomem.patch riscv-kgdb-do-not-inline-arch_kgdb_breakpoint.patch riscv-kgdb-remove-.option-norvc-.option-rvc-for-kgdb.patch cpufreq-sched-fix-the-usage-of-cpufreq_need_update_l.patch +nfs-move-nfs_fhandle_hash-to-common-include-file.patch +nfs-add-missing-selections-of-config_crc32.patch +nfsd-decrease-sc_count-directly-if-fail-to-queue-dl_.patch -- 2.47.3