summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChuck Lever <cel@kernel.org>2026-07-21 12:23:04 -0400
committerChuck Lever <cel@kernel.org>2026-08-26 16:41:09 -0400
commit6d9145cb88fb11943eb53a598564796e43f832ba (patch)
tree27ba9ea32f94bffed1d66cdf5ce6abcb6fb19588
parent9471bbfeea239f0dbf641c5f1b185aa72d3db32f (diff)
downloadlinux-next-6d9145cb88fb11943eb53a598564796e43f832ba.tar.gz
linux-next-6d9145cb88fb11943eb53a598564796e43f832ba.zip
NFSD: Hoist nfs42_ssc_open() into fs/nfs_common/nfs_ssc.c
Refactor: The infrastructure and details for calling the client's ssc_open method can be hidden in nfs_ssc.c. This reduces the SSC footprint in fs/nfsd/nfs4proc.c, a step toward removing that file's dependency on <linux/nfs_fs.h>, which indirectly includes <uapi/linux/nfs.h>. The open and close functions are named "nfsd42_" since they are meant to be invoked only by NFSD. Cc: Olga Kornievskaia <okorniev@redhat.com> Cc: Dai Ngo <dai.ngo@oracle.com> Link: https://patch.msgid.link/20260721162306.894558-3-cel@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
-rw-r--r--fs/nfs_common/nfs_ssc.c56
-rw-r--r--fs/nfsd/nfs4proc.c17
-rw-r--r--include/linux/nfs_ssc.h23
3 files changed, 66 insertions, 30 deletions
diff --git a/fs/nfs_common/nfs_ssc.c b/fs/nfs_common/nfs_ssc.c
index 8d8b7344ab4f..a8e79ec68701 100644
--- a/fs/nfs_common/nfs_ssc.c
+++ b/fs/nfs_common/nfs_ssc.c
@@ -12,9 +12,61 @@
#include <linux/nfs_ssc.h>
#include "../nfs/nfs4_fs.h"
+struct nfs_ssc_client_ops_tbl {
+ const struct nfs4_ssc_client_ops *ssc_nfs4_ops;
+};
-struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl;
-EXPORT_SYMBOL_GPL(nfs_ssc_client_tbl);
+static struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl __read_mostly;
+
+/**
+ * nfsd42_ssc_open - Open a file to be used for server-to-server copy
+ * @ss_mnt: active mount point on which the source file resides
+ * @src_fh: file handle of the source file to be copied
+ * @stateid: stateid to use for COPY operation
+ *
+ * Caller must close the returned file using nfsd42_ssc_close().
+ *
+ * Return: an open file, or an ERR_PTR on error
+ */
+struct file *nfsd42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh,
+ nfs4_stateid *stateid)
+{
+ /*
+ * Built under CONFIG_NFS_V4_2_SSC_HELPER, which the NFS client
+ * enables on its own. The dispatch below is live only when the
+ * server also sets CONFIG_NFSD_V4_2_INTER_SSC; without it the
+ * source file cannot be opened, so callers get -EIO.
+ */
+#if IS_ENABLED(CONFIG_NFSD_V4_2_INTER_SSC)
+ const struct nfs4_ssc_client_ops *ops = nfs_ssc_client_tbl.ssc_nfs4_ops;
+
+ if (ops)
+ return ops->sco_open(ss_mnt, src_fh, stateid);
+#endif
+
+ return ERR_PTR(-EIO);
+}
+EXPORT_SYMBOL_GPL(nfsd42_ssc_open);
+
+/**
+ * nfsd42_ssc_close - Close a file opened with nfsd42_ssc_open()
+ * @filp: struct file to be closed
+ *
+ * The real cleanup happens unconditionally in nfsd4_cleanup_inter_ssc().
+ * The vfsmount is pinned until this function is called, preventing
+ * the client from unregistering its SSC ops.
+ */
+void nfsd42_ssc_close(struct file *filp)
+{
+ /* Live only under CONFIG_NFSD_V4_2_INTER_SSC; see nfsd42_ssc_open(). */
+#if IS_ENABLED(CONFIG_NFSD_V4_2_INTER_SSC)
+ const struct nfs4_ssc_client_ops *ops = nfs_ssc_client_tbl.ssc_nfs4_ops;
+
+ if (ops)
+ ops->sco_close(filp);
+#endif
+}
+EXPORT_SYMBOL_GPL(nfsd42_ssc_close);
#ifdef CONFIG_NFS_V4_2
/**
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 8a2742d248c0..aacfa80bddd8 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1693,11 +1693,6 @@ void nfsd4_cancel_copy_by_sb(struct net *net, struct super_block *sb)
#ifdef CONFIG_NFSD_V4_2_INTER_SSC
-extern struct file *nfs42_ssc_open(struct vfsmount *ss_mnt,
- struct nfs_fh *src_fh,
- nfs4_stateid *stateid);
-extern void nfs42_ssc_close(struct file *filep);
-
#define NFSD42_INTERSSC_MOUNTOPS "vers=4.2,addr=%s,sec=sys"
/*
@@ -1920,7 +1915,7 @@ nfsd4_cleanup_inter_ssc(struct nfsd4_ssc_umount_item *nsui, struct file *filp,
struct nfsd_net *nn = net_generic(dst->nf_net, nfsd_net_id);
long timeout = msecs_to_jiffies(nfsd4_ssc_umount_timeout);
- nfs42_ssc_close(filp);
+ nfsd42_ssc_close(filp);
fput(filp);
spin_lock(&nn->nfsd_ssc_lock);
@@ -1952,12 +1947,6 @@ nfsd4_cleanup_inter_ssc(struct nfsd4_ssc_umount_item *nsui, struct file *filp,
{
}
-static struct file *nfs42_ssc_open(struct vfsmount *ss_mnt,
- struct nfs_fh *src_fh,
- nfs4_stateid *stateid)
-{
- return NULL;
-}
#endif /* CONFIG_NFSD_V4_2_INTER_SSC */
static __be32
@@ -2180,8 +2169,8 @@ static int nfsd4_do_async_copy(void *data)
if (nfsd4_ssc_is_inter(copy)) {
struct file *filp;
- filp = nfs42_ssc_open(copy->ss_nsui->nsui_vfsmount,
- &copy->c_fh, &copy->stateid);
+ filp = nfsd42_ssc_open(copy->ss_nsui->nsui_vfsmount,
+ &copy->c_fh, &copy->stateid);
if (IS_ERR(filp)) {
switch (PTR_ERR(filp)) {
case -EBADF:
diff --git a/include/linux/nfs_ssc.h b/include/linux/nfs_ssc.h
index ba236dba8975..fc0d5d48dec2 100644
--- a/include/linux/nfs_ssc.h
+++ b/include/linux/nfs_ssc.h
@@ -10,8 +10,6 @@
#include <linux/nfs_fs.h>
#include <linux/sunrpc/svc.h>
-extern struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl;
-
/*
* NFS_V4
*/
@@ -21,29 +19,26 @@ struct nfs4_ssc_client_ops {
void (*sco_close)(struct file *filep);
};
-struct nfs_ssc_client_ops_tbl {
- const struct nfs4_ssc_client_ops *ssc_nfs4_ops;
-};
-
extern void nfs42_ssc_register_ops(void);
extern void nfs42_ssc_unregister_ops(void);
extern void nfs42_ssc_register(const struct nfs4_ssc_client_ops *ops);
extern void nfs42_ssc_unregister(const struct nfs4_ssc_client_ops *ops);
-#ifdef CONFIG_NFSD_V4_2_INTER_SSC
-static inline struct file *nfs42_ssc_open(struct vfsmount *ss_mnt,
- struct nfs_fh *src_fh, nfs4_stateid *stateid)
+#if IS_ENABLED(CONFIG_NFS_V4_2_SSC_HELPER)
+struct file *nfsd42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh,
+ nfs4_stateid *stateid);
+void nfsd42_ssc_close(struct file *filp);
+#else
+static inline struct file *nfsd42_ssc_open(struct vfsmount *ss_mnt,
+ struct nfs_fh *src_fh,
+ nfs4_stateid *stateid)
{
- if (nfs_ssc_client_tbl.ssc_nfs4_ops)
- return (*nfs_ssc_client_tbl.ssc_nfs4_ops->sco_open)(ss_mnt, src_fh, stateid);
return ERR_PTR(-EIO);
}
-static inline void nfs42_ssc_close(struct file *filep)
+static inline void nfsd42_ssc_close(struct file *filp)
{
- if (nfs_ssc_client_tbl.ssc_nfs4_ops)
- (*nfs_ssc_client_tbl.ssc_nfs4_ops->sco_close)(filep);
}
#endif