Commit 0cfcd405 authored by Dai Ngo's avatar Dai Ngo Committed by J. Bruce Fields

NFSv4.2: Fix NFS4ERR_STALE error when doing inter server copy

NFS_FS=y as dependency of CONFIG_NFSD_V4_2_INTER_SSC still have
build errors and some configs with NFSD=m to get NFS4ERR_STALE
error when doing inter server copy.

Added ops table in nfs_common for knfsd to access NFS client modules.

Fixes: 3ac3711a ("NFSD: Fix NFS server build errors")
Signed-off-by: default avatarDai Ngo <dai.ngo@oracle.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent d48c8124
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/falloc.h> #include <linux/falloc.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/nfs_fs.h> #include <linux/nfs_fs.h>
#include <linux/nfs_ssc.h>
#include "delegation.h" #include "delegation.h"
#include "internal.h" #include "internal.h"
#include "iostat.h" #include "iostat.h"
...@@ -314,9 +315,8 @@ static loff_t nfs42_remap_file_range(struct file *src_file, loff_t src_off, ...@@ -314,9 +315,8 @@ static loff_t nfs42_remap_file_range(struct file *src_file, loff_t src_off,
static int read_name_gen = 1; static int read_name_gen = 1;
#define SSC_READ_NAME_BODY "ssc_read_%d" #define SSC_READ_NAME_BODY "ssc_read_%d"
struct file * static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt,
nfs42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh, struct nfs_fh *src_fh, nfs4_stateid *stateid)
nfs4_stateid *stateid)
{ {
struct nfs_fattr fattr; struct nfs_fattr fattr;
struct file *filep, *res; struct file *filep, *res;
...@@ -398,14 +398,40 @@ nfs42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh, ...@@ -398,14 +398,40 @@ nfs42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh,
fput(filep); fput(filep);
goto out_free_name; goto out_free_name;
} }
EXPORT_SYMBOL_GPL(nfs42_ssc_open);
void nfs42_ssc_close(struct file *filep) static void __nfs42_ssc_close(struct file *filep)
{ {
struct nfs_open_context *ctx = nfs_file_open_context(filep); struct nfs_open_context *ctx = nfs_file_open_context(filep);
ctx->state->flags = 0; ctx->state->flags = 0;
} }
EXPORT_SYMBOL_GPL(nfs42_ssc_close);
static const struct nfs4_ssc_client_ops nfs4_ssc_clnt_ops_tbl = {
.sco_open = __nfs42_ssc_open,
.sco_close = __nfs42_ssc_close,
};
/**
* nfs42_ssc_register_ops - Wrapper to register NFS_V4 ops in nfs_common
*
* Return values:
* None
*/
void nfs42_ssc_register_ops(void)
{
nfs42_ssc_register(&nfs4_ssc_clnt_ops_tbl);
}
/**
* nfs42_ssc_unregister_ops - wrapper to un-register NFS_V4 ops in nfs_common
*
* Return values:
* None.
*/
void nfs42_ssc_unregister_ops(void)
{
nfs42_ssc_unregister(&nfs4_ssc_clnt_ops_tbl);
}
#endif /* CONFIG_NFS_V4_2 */ #endif /* CONFIG_NFS_V4_2 */
const struct file_operations nfs4_file_operations = { const struct file_operations nfs4_file_operations = {
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/nfs4_mount.h> #include <linux/nfs4_mount.h>
#include <linux/nfs_fs.h> #include <linux/nfs_fs.h>
#include <linux/nfs_ssc.h>
#include "delegation.h" #include "delegation.h"
#include "internal.h" #include "internal.h"
#include "nfs4_fs.h" #include "nfs4_fs.h"
...@@ -279,6 +280,9 @@ static int __init init_nfs_v4(void) ...@@ -279,6 +280,9 @@ static int __init init_nfs_v4(void)
if (err) if (err)
goto out2; goto out2;
#ifdef CONFIG_NFS_V4_2
nfs42_ssc_register_ops();
#endif
register_nfs_version(&nfs_v4); register_nfs_version(&nfs_v4);
return 0; return 0;
out2: out2:
...@@ -297,6 +301,7 @@ static void __exit exit_nfs_v4(void) ...@@ -297,6 +301,7 @@ static void __exit exit_nfs_v4(void)
unregister_nfs_version(&nfs_v4); unregister_nfs_version(&nfs_v4);
#ifdef CONFIG_NFS_V4_2 #ifdef CONFIG_NFS_V4_2
nfs4_xattr_cache_exit(); nfs4_xattr_cache_exit();
nfs42_ssc_unregister_ops();
#endif #endif
nfs4_unregister_sysctl(); nfs4_unregister_sysctl();
nfs_idmap_quit(); nfs_idmap_quit();
......
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/nfs_ssc.h>
#include "nfs4_fs.h" #include "nfs4_fs.h"
#include "callback.h" #include "callback.h"
...@@ -85,6 +86,10 @@ const struct super_operations nfs_sops = { ...@@ -85,6 +86,10 @@ const struct super_operations nfs_sops = {
}; };
EXPORT_SYMBOL_GPL(nfs_sops); EXPORT_SYMBOL_GPL(nfs_sops);
static const struct nfs_ssc_client_ops nfs_ssc_clnt_ops_tbl = {
.sco_sb_deactive = nfs_sb_deactive,
};
#if IS_ENABLED(CONFIG_NFS_V4) #if IS_ENABLED(CONFIG_NFS_V4)
static int __init register_nfs4_fs(void) static int __init register_nfs4_fs(void)
{ {
...@@ -106,6 +111,16 @@ static void unregister_nfs4_fs(void) ...@@ -106,6 +111,16 @@ static void unregister_nfs4_fs(void)
} }
#endif #endif
static void nfs_ssc_register_ops(void)
{
nfs_ssc_register(&nfs_ssc_clnt_ops_tbl);
}
static void nfs_ssc_unregister_ops(void)
{
nfs_ssc_unregister(&nfs_ssc_clnt_ops_tbl);
}
static struct shrinker acl_shrinker = { static struct shrinker acl_shrinker = {
.count_objects = nfs_access_cache_count, .count_objects = nfs_access_cache_count,
.scan_objects = nfs_access_cache_scan, .scan_objects = nfs_access_cache_scan,
...@@ -133,6 +148,7 @@ int __init register_nfs_fs(void) ...@@ -133,6 +148,7 @@ int __init register_nfs_fs(void)
ret = register_shrinker(&acl_shrinker); ret = register_shrinker(&acl_shrinker);
if (ret < 0) if (ret < 0)
goto error_3; goto error_3;
nfs_ssc_register_ops();
return 0; return 0;
error_3: error_3:
nfs_unregister_sysctl(); nfs_unregister_sysctl();
...@@ -152,6 +168,7 @@ void __exit unregister_nfs_fs(void) ...@@ -152,6 +168,7 @@ void __exit unregister_nfs_fs(void)
unregister_shrinker(&acl_shrinker); unregister_shrinker(&acl_shrinker);
nfs_unregister_sysctl(); nfs_unregister_sysctl();
unregister_nfs4_fs(); unregister_nfs4_fs();
nfs_ssc_unregister_ops();
unregister_filesystem(&nfs_fs_type); unregister_filesystem(&nfs_fs_type);
} }
......
...@@ -7,3 +7,4 @@ obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o ...@@ -7,3 +7,4 @@ obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o
nfs_acl-objs := nfsacl.o nfs_acl-objs := nfsacl.o
obj-$(CONFIG_GRACE_PERIOD) += grace.o obj-$(CONFIG_GRACE_PERIOD) += grace.o
obj-$(CONFIG_GRACE_PERIOD) += nfs_ssc.o
// SPDX-License-Identifier: GPL-2.0-only
/*
* fs/nfs_common/nfs_ssc_comm.c
*
* Helper for knfsd's SSC to access ops in NFS client modules
*
* Author: Dai Ngo <dai.ngo@oracle.com>
*
* Copyright (c) 2020, Oracle and/or its affiliates.
*/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/nfs_ssc.h>
#include "../nfs/nfs4_fs.h"
MODULE_LICENSE("GPL");
struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl;
EXPORT_SYMBOL_GPL(nfs_ssc_client_tbl);
#ifdef CONFIG_NFS_V4_2
/**
* nfs42_ssc_register - install the NFS_V4 client ops in the nfs_ssc_client_tbl
* @ops: NFS_V4 ops to be installed
*
* Return values:
* None
*/
void nfs42_ssc_register(const struct nfs4_ssc_client_ops *ops)
{
nfs_ssc_client_tbl.ssc_nfs4_ops = ops;
}
EXPORT_SYMBOL_GPL(nfs42_ssc_register);
/**
* nfs42_ssc_unregister - uninstall the NFS_V4 client ops from
* the nfs_ssc_client_tbl
* @ops: ops to be uninstalled
*
* Return values:
* None
*/
void nfs42_ssc_unregister(const struct nfs4_ssc_client_ops *ops)
{
if (nfs_ssc_client_tbl.ssc_nfs4_ops != ops)
return;
nfs_ssc_client_tbl.ssc_nfs4_ops = NULL;
}
EXPORT_SYMBOL_GPL(nfs42_ssc_unregister);
#endif /* CONFIG_NFS_V4_2 */
#ifdef CONFIG_NFS_V4_2
/**
* nfs_ssc_register - install the NFS_FS client ops in the nfs_ssc_client_tbl
* @ops: NFS_FS ops to be installed
*
* Return values:
* None
*/
void nfs_ssc_register(const struct nfs_ssc_client_ops *ops)
{
nfs_ssc_client_tbl.ssc_nfs_ops = ops;
}
EXPORT_SYMBOL_GPL(nfs_ssc_register);
/**
* nfs_ssc_unregister - uninstall the NFS_FS client ops from
* the nfs_ssc_client_tbl
* @ops: ops to be uninstalled
*
* Return values:
* None
*/
void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops)
{
if (nfs_ssc_client_tbl.ssc_nfs_ops != ops)
return;
nfs_ssc_client_tbl.ssc_nfs_ops = NULL;
}
EXPORT_SYMBOL_GPL(nfs_ssc_unregister);
#else
void nfs_ssc_register(const struct nfs_ssc_client_ops *ops)
{
}
EXPORT_SYMBOL_GPL(nfs_ssc_register);
void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops)
{
}
EXPORT_SYMBOL_GPL(nfs_ssc_unregister);
#endif /* CONFIG_NFS_V4_2 */
...@@ -136,7 +136,7 @@ config NFSD_FLEXFILELAYOUT ...@@ -136,7 +136,7 @@ config NFSD_FLEXFILELAYOUT
config NFSD_V4_2_INTER_SSC config NFSD_V4_2_INTER_SSC
bool "NFSv4.2 inter server to server COPY" bool "NFSv4.2 inter server to server COPY"
depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2 && NFS_FS=y depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2
help help
This option enables support for NFSv4.2 inter server to This option enables support for NFSv4.2 inter server to
server copy where the destination server calls the NFSv4.2 server copy where the destination server calls the NFSv4.2
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/sunrpc/addr.h> #include <linux/sunrpc/addr.h>
#include <linux/nfs_ssc.h>
#include "idmap.h" #include "idmap.h"
#include "cache.h" #include "cache.h"
...@@ -1247,7 +1248,7 @@ nfsd4_interssc_connect(struct nl4_server *nss, struct svc_rqst *rqstp, ...@@ -1247,7 +1248,7 @@ nfsd4_interssc_connect(struct nl4_server *nss, struct svc_rqst *rqstp,
static void static void
nfsd4_interssc_disconnect(struct vfsmount *ss_mnt) nfsd4_interssc_disconnect(struct vfsmount *ss_mnt)
{ {
nfs_sb_deactive(ss_mnt->mnt_sb); nfs_do_sb_deactive(ss_mnt->mnt_sb);
mntput(ss_mnt); mntput(ss_mnt);
} }
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* include/linux/nfs_ssc.h
*
* Author: Dai Ngo <dai.ngo@oracle.com>
*
* Copyright (c) 2020, Oracle and/or its affiliates.
*/
#include <linux/nfs_fs.h>
extern struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl;
/*
* NFS_V4
*/
struct nfs4_ssc_client_ops {
struct file *(*sco_open)(struct vfsmount *ss_mnt,
struct nfs_fh *src_fh, nfs4_stateid *stateid);
void (*sco_close)(struct file *filep);
};
/*
* NFS_FS
*/
struct nfs_ssc_client_ops {
void (*sco_sb_deactive)(struct super_block *sb);
};
struct nfs_ssc_client_ops_tbl {
const struct nfs4_ssc_client_ops *ssc_nfs4_ops;
const struct nfs_ssc_client_ops *ssc_nfs_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 (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)
{
if (nfs_ssc_client_tbl.ssc_nfs4_ops)
(*nfs_ssc_client_tbl.ssc_nfs4_ops->sco_close)(filep);
}
#endif
/*
* NFS_FS
*/
extern void nfs_ssc_register(const struct nfs_ssc_client_ops *ops);
extern void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops);
static inline void nfs_do_sb_deactive(struct super_block *sb)
{
if (nfs_ssc_client_tbl.ssc_nfs_ops)
(*nfs_ssc_client_tbl.ssc_nfs_ops->sco_sb_deactive)(sb);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment