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>
This commit is contained in:
Chuck Lever 2026-07-21 12:23:04 -04:00
parent 53f0adfd76
commit 8ee28f0992
3 changed files with 66 additions and 30 deletions

View File

@ -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
/**

View File

@ -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:

View File

@ -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