aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4callback.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4callback.c')
-rw-r--r--fs/nfsd/nfs4callback.c92
1 files changed, 44 insertions, 48 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 9d536a8cb379..aae2b29ae2c9 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -350,30 +350,6 @@ static struct rpc_version * nfs_cb_version[] = {
350static int do_probe_callback(void *data) 350static int do_probe_callback(void *data)
351{ 351{
352 struct nfs4_client *clp = data; 352 struct nfs4_client *clp = data;
353 struct nfs4_callback *cb = &clp->cl_callback;
354 struct rpc_message msg = {
355 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
356 .rpc_argp = clp,
357 };
358 int status;
359
360 status = rpc_call_sync(cb->cb_client, &msg, RPC_TASK_SOFT);
361
362 if (status) {
363 rpc_shutdown_client(cb->cb_client);
364 cb->cb_client = NULL;
365 } else
366 atomic_set(&cb->cb_set, 1);
367 put_nfs4_client(clp);
368 return 0;
369}
370
371/*
372 * Set up the callback client and put a NFSPROC4_CB_NULL on the wire...
373 */
374void
375nfsd4_probe_callback(struct nfs4_client *clp)
376{
377 struct sockaddr_in addr; 353 struct sockaddr_in addr;
378 struct nfs4_callback *cb = &clp->cl_callback; 354 struct nfs4_callback *cb = &clp->cl_callback;
379 struct rpc_timeout timeparms = { 355 struct rpc_timeout timeparms = {
@@ -390,13 +366,15 @@ nfsd4_probe_callback(struct nfs4_client *clp)
390 .timeout = &timeparms, 366 .timeout = &timeparms,
391 .program = program, 367 .program = program,
392 .version = nfs_cb_version[1]->number, 368 .version = nfs_cb_version[1]->number,
393 .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ 369 .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
394 .flags = (RPC_CLNT_CREATE_NOPING), 370 .flags = (RPC_CLNT_CREATE_NOPING),
395 }; 371 };
396 struct task_struct *t; 372 struct rpc_message msg = {
397 373 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
398 if (atomic_read(&cb->cb_set)) 374 .rpc_argp = clp,
399 return; 375 };
376 struct rpc_clnt *client;
377 int status;
400 378
401 /* Initialize address */ 379 /* Initialize address */
402 memset(&addr, 0, sizeof(addr)); 380 memset(&addr, 0, sizeof(addr));
@@ -416,29 +394,50 @@ nfsd4_probe_callback(struct nfs4_client *clp)
416 program->stats->program = program; 394 program->stats->program = program;
417 395
418 /* Create RPC client */ 396 /* Create RPC client */
419 cb->cb_client = rpc_create(&args); 397 client = rpc_create(&args);
420 if (IS_ERR(cb->cb_client)) { 398 if (IS_ERR(client)) {
421 dprintk("NFSD: couldn't create callback client\n"); 399 dprintk("NFSD: couldn't create callback client\n");
400 status = PTR_ERR(client);
422 goto out_err; 401 goto out_err;
423 } 402 }
424 403
404 status = rpc_call_sync(client, &msg, RPC_TASK_SOFT);
405
406 if (status)
407 goto out_release_client;
408
409 cb->cb_client = client;
410 atomic_set(&cb->cb_set, 1);
411 put_nfs4_client(clp);
412 return 0;
413out_release_client:
414 rpc_shutdown_client(client);
415out_err:
416 put_nfs4_client(clp);
417 dprintk("NFSD: warning: no callback path to client %.*s\n",
418 (int)clp->cl_name.len, clp->cl_name.data);
419 return status;
420}
421
422/*
423 * Set up the callback client and put a NFSPROC4_CB_NULL on the wire...
424 */
425void
426nfsd4_probe_callback(struct nfs4_client *clp)
427{
428 struct task_struct *t;
429
430 BUG_ON(atomic_read(&clp->cl_callback.cb_set));
431
425 /* the task holds a reference to the nfs4_client struct */ 432 /* the task holds a reference to the nfs4_client struct */
426 atomic_inc(&clp->cl_count); 433 atomic_inc(&clp->cl_count);
427 434
428 t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe"); 435 t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe");
429 436
430 if (IS_ERR(t)) 437 if (IS_ERR(t))
431 goto out_release_clp; 438 atomic_dec(&clp->cl_count);
432 439
433 return; 440 return;
434
435out_release_clp:
436 atomic_dec(&clp->cl_count);
437 rpc_shutdown_client(cb->cb_client);
438out_err:
439 cb->cb_client = NULL;
440 dprintk("NFSD: warning: no callback path to client %.*s\n",
441 (int)clp->cl_name.len, clp->cl_name.data);
442} 441}
443 442
444/* 443/*
@@ -458,9 +457,6 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
458 int retries = 1; 457 int retries = 1;
459 int status = 0; 458 int status = 0;
460 459
461 if ((!atomic_read(&clp->cl_callback.cb_set)) || !clnt)
462 return;
463
464 cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */ 460 cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */
465 cbr->cbr_dp = dp; 461 cbr->cbr_dp = dp;
466 462
@@ -469,6 +465,7 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
469 switch (status) { 465 switch (status) {
470 case -EIO: 466 case -EIO:
471 /* Network partition? */ 467 /* Network partition? */
468 atomic_set(&clp->cl_callback.cb_set, 0);
472 case -EBADHANDLE: 469 case -EBADHANDLE:
473 case -NFS4ERR_BAD_STATEID: 470 case -NFS4ERR_BAD_STATEID:
474 /* Race: client probably got cb_recall 471 /* Race: client probably got cb_recall
@@ -481,11 +478,10 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
481 status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT); 478 status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
482 } 479 }
483out_put_cred: 480out_put_cred:
484 if (status == -EIO) 481 /*
485 atomic_set(&clp->cl_callback.cb_set, 0); 482 * Success or failure, now we're either waiting for lease expiration
486 /* Success or failure, now we're either waiting for lease expiration 483 * or deleg_return.
487 * or deleg_return. */ 484 */
488 dprintk("NFSD: nfs4_cb_recall: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count));
489 put_nfs4_client(clp); 485 put_nfs4_client(clp);
490 nfs4_put_delegation(dp); 486 nfs4_put_delegation(dp);
491 return; 487 return;