aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4callback.c71
1 files changed, 34 insertions, 37 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 31d6633c7fe4..c17a5202ee3f 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -39,6 +39,7 @@
39#include <linux/errno.h> 39#include <linux/errno.h>
40#include <linux/delay.h> 40#include <linux/delay.h>
41#include <linux/sched.h> 41#include <linux/sched.h>
42#include <linux/kthread.h>
42#include <linux/sunrpc/xdr.h> 43#include <linux/sunrpc/xdr.h>
43#include <linux/sunrpc/svc.h> 44#include <linux/sunrpc/svc.h>
44#include <linux/sunrpc/clnt.h> 45#include <linux/sunrpc/clnt.h>
@@ -365,6 +366,35 @@ nfsd4_lookupcred(struct nfs4_client *clp, int taskflags)
365 return ret; 366 return ret;
366} 367}
367 368
369/* Reference counting, callback cleanup, etc., all look racy as heck.
370 * And why is cb_set an atomic? */
371
372static int do_probe_callback(void *data)
373{
374 struct nfs4_client *clp = data;
375 struct nfs4_callback *cb = &clp->cl_callback;
376 struct rpc_message msg = {
377 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
378 .rpc_argp = clp,
379 };
380 int status;
381
382 msg.rpc_cred = nfsd4_lookupcred(clp, 0);
383 if (IS_ERR(msg.rpc_cred))
384 goto out;
385 status = rpc_call_sync(cb->cb_client, &msg, RPC_TASK_SOFT);
386 put_rpccred(msg.rpc_cred);
387
388 if (status) {
389 rpc_shutdown_client(cb->cb_client);
390 cb->cb_client = NULL;
391 } else
392 atomic_set(&cb->cb_set, 1);
393out:
394 put_nfs4_client(clp);
395 return 0;
396}
397
368/* 398/*
369 * Set up the callback client and put a NFSPROC4_CB_NULL on the wire... 399 * Set up the callback client and put a NFSPROC4_CB_NULL on the wire...
370 */ 400 */
@@ -390,11 +420,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
390 .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ 420 .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
391 .flags = (RPC_CLNT_CREATE_NOPING), 421 .flags = (RPC_CLNT_CREATE_NOPING),
392 }; 422 };
393 struct rpc_message msg = { 423 struct task_struct *t;
394 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
395 .rpc_argp = clp,
396 };
397 int status;
398 424
399 if (atomic_read(&cb->cb_set)) 425 if (atomic_read(&cb->cb_set))
400 return; 426 return;
@@ -426,16 +452,11 @@ nfsd4_probe_callback(struct nfs4_client *clp)
426 /* the task holds a reference to the nfs4_client struct */ 452 /* the task holds a reference to the nfs4_client struct */
427 atomic_inc(&clp->cl_count); 453 atomic_inc(&clp->cl_count);
428 454
429 msg.rpc_cred = nfsd4_lookupcred(clp,0); 455 t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe");
430 if (IS_ERR(msg.rpc_cred))
431 goto out_release_clp;
432 status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL);
433 put_rpccred(msg.rpc_cred);
434 456
435 if (status != 0) { 457 if (IS_ERR(t))
436 dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n");
437 goto out_release_clp; 458 goto out_release_clp;
438 } 459
439 return; 460 return;
440 461
441out_release_clp: 462out_release_clp:
@@ -447,30 +468,6 @@ out_err:
447 (int)clp->cl_name.len, clp->cl_name.data); 468 (int)clp->cl_name.len, clp->cl_name.data);
448} 469}
449 470
450static void
451nfs4_cb_null(struct rpc_task *task, void *dummy)
452{
453 struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp;
454 struct nfs4_callback *cb = &clp->cl_callback;
455 __be32 addr = htonl(cb->cb_addr);
456
457 dprintk("NFSD: nfs4_cb_null task->tk_status %d\n", task->tk_status);
458
459 if (task->tk_status < 0) {
460 dprintk("NFSD: callback establishment to client %.*s failed\n",
461 (int)clp->cl_name.len, clp->cl_name.data);
462 goto out;
463 }
464 atomic_set(&cb->cb_set, 1);
465 dprintk("NFSD: callback set to client %u.%u.%u.%u\n", NIPQUAD(addr));
466out:
467 put_nfs4_client(clp);
468}
469
470static const struct rpc_call_ops nfs4_cb_null_ops = {
471 .rpc_call_done = nfs4_cb_null,
472};
473
474/* 471/*
475 * called with dp->dl_count inc'ed. 472 * called with dp->dl_count inc'ed.
476 * nfs4_lock_state() may or may not have been called. 473 * nfs4_lock_state() may or may not have been called.