diff options
author | Andy Adamson <andros@netapp.com> | 2011-01-05 21:04:32 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-01-06 14:46:24 -0500 |
commit | c36fca52f5e4594ffd0ff175b328966b0d393184 (patch) | |
tree | 6d771744cc49f0edc0d2b6b2f9fe919163002346 /fs/nfs/callback.c | |
parent | 2c2618c6f29c41a0a966f14f05c8bf45fcabb750 (diff) |
NFS refactor nfs_find_client and reference client across callback processing
Fixes a bug where the nfs_client could be freed during callback processing.
Refactor nfs_find_client to use minorversion specific means to locate the
correct nfs_client structure.
In the NFS layer, V4.0 clients are found using the callback_ident field in the
CB_COMPOUND header. V4.1 clients are found using the sessionID in the
CB_SEQUENCE operation which is also compared against the sessionID associated
with the back channel thread after a successful CREATE_SESSION.
Each of these methods finds the one an only nfs_client associated
with the incoming callback request - so nfs_find_client_next is not needed.
In the RPC layer, the pg_authenticate call needs to find the nfs_client. For
the v4.0 callback service, the callback identifier has not been decoded so a
search by address, version, and minorversion is used. The sessionid for the
sessions based callback service has (usually) not been set for the
pg_authenticate on a CB_NULL call which can be sent prior to the return
of a CREATE_SESSION call, so the sessionid associated with the back channel
thread is not used to find the client in pg_authenticate for CB_NULL calls.
Pass the referenced nfs_client to each CB_COMPOUND operation being proceesed
via the new cb_process_state structure. The reference is held across
cb_compound processing.
Use the new cb_process_state struct to move the NFS4ERR_RETRY_UNCACHED_REP
processing from process_op into nfs4_callback_sequence where it belongs.
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/callback.c')
-rw-r--r-- | fs/nfs/callback.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index c0b05497972b..15677e7bede5 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -16,9 +16,7 @@ | |||
16 | #include <linux/freezer.h> | 16 | #include <linux/freezer.h> |
17 | #include <linux/kthread.h> | 17 | #include <linux/kthread.h> |
18 | #include <linux/sunrpc/svcauth_gss.h> | 18 | #include <linux/sunrpc/svcauth_gss.h> |
19 | #if defined(CONFIG_NFS_V4_1) | ||
20 | #include <linux/sunrpc/bc_xprt.h> | 19 | #include <linux/sunrpc/bc_xprt.h> |
21 | #endif | ||
22 | 20 | ||
23 | #include <net/inet_sock.h> | 21 | #include <net/inet_sock.h> |
24 | 22 | ||
@@ -384,6 +382,23 @@ static int check_gss_callback_principal(struct nfs_client *clp, | |||
384 | return SVC_OK; | 382 | return SVC_OK; |
385 | } | 383 | } |
386 | 384 | ||
385 | /* pg_authenticate method helper */ | ||
386 | static struct nfs_client *nfs_cb_find_client(struct svc_rqst *rqstp) | ||
387 | { | ||
388 | struct nfs4_sessionid *sessionid = bc_xprt_sid(rqstp); | ||
389 | int is_cb_compound = rqstp->rq_proc == CB_COMPOUND ? 1 : 0; | ||
390 | |||
391 | dprintk("--> %s rq_proc %d\n", __func__, rqstp->rq_proc); | ||
392 | if (svc_is_backchannel(rqstp)) | ||
393 | /* Sessionid (usually) set after CB_NULL ping */ | ||
394 | return nfs4_find_client_sessionid(svc_addr(rqstp), sessionid, | ||
395 | is_cb_compound); | ||
396 | else | ||
397 | /* No callback identifier in pg_authenticate */ | ||
398 | return nfs4_find_client_no_ident(svc_addr(rqstp)); | ||
399 | } | ||
400 | |||
401 | /* pg_authenticate method for nfsv4 callback threads. */ | ||
387 | static int nfs_callback_authenticate(struct svc_rqst *rqstp) | 402 | static int nfs_callback_authenticate(struct svc_rqst *rqstp) |
388 | { | 403 | { |
389 | struct nfs_client *clp; | 404 | struct nfs_client *clp; |
@@ -391,7 +406,7 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp) | |||
391 | int ret = SVC_OK; | 406 | int ret = SVC_OK; |
392 | 407 | ||
393 | /* Don't talk to strangers */ | 408 | /* Don't talk to strangers */ |
394 | clp = nfs_find_client(svc_addr(rqstp), 4); | 409 | clp = nfs_cb_find_client(rqstp); |
395 | if (clp == NULL) | 410 | if (clp == NULL) |
396 | return SVC_DROP; | 411 | return SVC_DROP; |
397 | 412 | ||