summaryrefslogtreecommitdiff
path: root/fs/nfs/localio.c
diff options
context:
space:
mode:
authorNeilBrown <neil@brown.name>2025-05-09 10:46:43 +1000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-06-19 15:40:25 +0200
commit3f28e08941e340ecdea818323777a909c40f824c (patch)
treed14858d2d0c7b74056e0355deeaa9b9ebdf939f3 /fs/nfs/localio.c
parent0965a7f65808c2b940e53d5559e14476464554e3 (diff)
nfs_localio: change nfsd_file_put_local() to take a pointer to __rcu pointer
[ Upstream commit c25a89770d1f216dcedfc2d25d56b604f62ce0bd ] Instead of calling xchg() and unrcu_pointer() before nfsd_file_put_local(), we now pass pointer to the __rcu pointer and call xchg() and unrcu_pointer() inside that function. Where unrcu_pointer() is currently called the internals of "struct nfsd_file" are not known and that causes older compilers such as gcc-8 to complain. In some cases we have a __kernel (aka normal) pointer not an __rcu pointer so we need to cast it to __rcu first. This is strictly a weakening so no information is lost. Somewhat surprisingly, this cast is accepted by gcc-8. This has the pleasing result that the cmpxchg() which sets ro_file and rw_file, and also the xchg() which clears them, are both now in the nfsd code. Reported-by: Pali Rohár <pali@kernel.org> Reported-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr> Fixes: 86e00412254a ("nfs: cache all open LOCALIO nfsd_file(s) in client") Signed-off-by: NeilBrown <neil@brown.name> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'fs/nfs/localio.c')
-rw-r--r--fs/nfs/localio.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c
index 030a54c8c9d8b..e6d36b3d3fc05 100644
--- a/fs/nfs/localio.c
+++ b/fs/nfs/localio.c
@@ -207,9 +207,16 @@ void nfs_local_probe_async(struct nfs_client *clp)
}
EXPORT_SYMBOL_GPL(nfs_local_probe_async);
-static inline void nfs_local_file_put(struct nfsd_file *nf)
+static inline void nfs_local_file_put(struct nfsd_file *localio)
{
- nfs_to_nfsd_file_put_local(nf);
+ /* nfs_to_nfsd_file_put_local() expects an __rcu pointer
+ * but we have a __kernel pointer. It is always safe
+ * to cast a __kernel pointer to an __rcu pointer
+ * because the cast only weakens what is known about the pointer.
+ */
+ struct nfsd_file __rcu *nf = (struct nfsd_file __rcu*) localio;
+
+ nfs_to_nfsd_file_put_local(&nf);
}
/*