[pnfs] [PATCH 03/19] nfs41: Refactor NFSv4 callback service
Benny Halevy
bhalevy at panasas.com
Wed Jul 16 05:29:37 EDT 2008
Prepare the NFSv4 callback service mechanism to understand v4.0 and v4.1
callbacks. Create a new function nfs4_callback_up() that contains the
minor version 0 specific logic. It is invoked by nfs_callback_up().
Augment the list of arguments passed to nfs_callback_up() since it will need
to deal with minor version 1 as well. Move the creation of the backchannel
after the rpc_client has been initialized since the rpc_xprt structure will be
needed to crated the NFSv4.1 callback.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga at netapp.com>
Signed-off-by: Benny Halevy <bhalevy at panasas.com>
nfs41: set error ret in nfs_callback_up only on error path
Signed-off-by: Benny Halevy <bhalevy at panasas.com>
nfs41: callback_svc needs to be set for v4 and v4.1 mounts
callback_svc needs not be defined as static in nfs_callback_up since
it needs to be adjusted to point to either nfs4_callback_svc or
nfs41_callback_svc depending on the minorversion passed in. Its
current static definition causes NFSv4 mounts to panic the system
if they were preceded by an NFSv4.1 mount.
This happens because the NFSv4.1 mount left the value pointing to
nfs41_callback_svc which is not reset back to nfs4_callback_svc
when the NFSv4 callback is created.
This patch should be squashed with commit:
5a53e9776d4a0030d698667edf66aa535d60a37a "nfs41: Refactor NFSv4 callback service"
Signed-off-by: Ricardo Labiaga <ricardo.labiaga at netapp.com>
Signed-off-by: Benny Halevy <bhalevy at panasas.com>
---
fs/nfs/callback.c | 53 ++++++++++++++++++++++++++++++++++++++---------------
fs/nfs/callback.h | 2 +-
fs/nfs/client.c | 23 ++++++++++++-----------
3 files changed, 51 insertions(+), 27 deletions(-)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index c1e7c83..02b67db 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -57,7 +57,7 @@ module_param_call(callback_tcpport, param_set_port, param_get_int,
* This is the callback kernel thread.
*/
static int
-nfs_callback_svc(void *vrqstp)
+nfs4_callback_svc(void *vrqstp)
{
int err, preverr = 0;
struct svc_rqst *rqstp = vrqstp;
@@ -96,13 +96,36 @@ nfs_callback_svc(void *vrqstp)
return 0;
}
+
+/*
+ * Prepare to bring up the NFSv4 callback service
+ */
+struct svc_rqst *
+nfs4_callback_up(struct svc_serv *serv)
+{
+ int ret;
+
+ ret = svc_create_xprt(serv, "tcp", nfs_callback_set_tcpport,
+ SVC_SOCK_ANONYMOUS);
+ if (unlikely(ret <= 0)) {
+ if (ret == 0)
+ ret = -EIO;
+ return ERR_PTR(ret);
+ }
+ nfs_callback_tcpport = ret;
+ dprintk("Callback port = 0x%x\n", nfs_callback_tcpport);
+ return svc_prepare_thread(serv, &serv->sv_pools[0]);
+}
+
/*
* Bring up the server process if it is not already up.
*/
-int nfs_callback_up(void)
+int nfs_callback_up(u32 minorversion, void *args)
{
struct svc_serv *serv = NULL;
struct svc_rqst *rqstp;
+ int (* callback_svc)(void *vrqstp);
+ char svc_name[12];
int ret = 0;
lock_kernel();
@@ -110,18 +133,19 @@ int nfs_callback_up(void)
if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
goto out;
serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
- ret = -ENOMEM;
- if (!serv)
- goto out_err;
-
- ret = svc_create_xprt(serv, "tcp", nfs_callback_set_tcpport,
- SVC_SOCK_ANONYMOUS);
- if (ret <= 0)
+ if (!serv) {
+ ret = -ENOMEM;
goto out_err;
- nfs_callback_tcpport = ret;
- dprintk("Callback port = 0x%x\n", nfs_callback_tcpport);
+ }
- rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
+ switch (minorversion) {
+ case 0:
+ rqstp = nfs4_callback_up(serv);
+ callback_svc = nfs4_callback_svc;
+ break;
+ default:
+ BUG();
+ }
if (IS_ERR(rqstp)) {
ret = PTR_ERR(rqstp);
goto out_err;
@@ -129,9 +153,8 @@ int nfs_callback_up(void)
svc_sock_update_bufs(serv);
nfs_callback_info.serv = serv;
-
- nfs_callback_info.task = kthread_run(nfs_callback_svc, rqstp,
- "nfsv4-svc");
+ sprintf(svc_name, "nfsv4.%u-svc", minorversion);
+ nfs_callback_info.task = kthread_run(callback_svc, rqstp, svc_name);
if (IS_ERR(nfs_callback_info.task)) {
ret = PTR_ERR(nfs_callback_info.task);
nfs_callback_info.serv = NULL;
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index bb25d21..a2b3ce4 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -63,7 +63,7 @@ extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getat
extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
#ifdef CONFIG_NFS_V4
-extern int nfs_callback_up(void);
+extern int nfs_callback_up(u32 minorversion, void *args);
extern void nfs_callback_down(void);
#else
#define nfs_callback_up() (0)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 5c530f1..5d8e93b 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -129,12 +129,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
clp->rpc_ops = cl_init->rpc_ops;
- if (cl_init->rpc_ops->version == 4) {
- if (nfs_callback_up() < 0)
- goto error_2;
- __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
- }
-
atomic_set(&clp->cl_count, 1);
clp->cl_cons_state = NFS_CS_INITING;
@@ -144,7 +138,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
if (cl_init->hostname) {
clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL);
if (!clp->cl_hostname)
- goto error_3;
+ goto error_cleanup;
}
INIT_LIST_HEAD(&clp->cl_superblocks);
@@ -167,10 +161,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
return clp;
-error_3:
- if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
- nfs_callback_down();
-error_2:
+error_cleanup:
kfree(clp);
error_0:
return NULL;
@@ -1012,6 +1003,16 @@ static int nfs4_init_client(struct nfs_client *clp,
goto error;
memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
+ /* Start the callback server */
+ error = nfs_callback_up(clp->cl_minorversion,
+ clp->cl_rpcclient->cl_xprt);
+ if (error < 0) {
+ dprintk("%s: failed to start callback. Error = %d\n",
+ __func__, error);
+ goto error;
+ }
+ __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
+
error = nfs_idmap_new(clp);
if (error < 0) {
dprintk("%s: failed to create idmapper. Error = %d\n",
--
1.5.6.3
More information about the pNFS
mailing list