diff options
Diffstat (limited to 'fs/nfsd/nfs4callback.c')
-rw-r--r-- | fs/nfsd/nfs4callback.c | 92 |
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[] = { | |||
350 | static int do_probe_callback(void *data) | 350 | static 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 | */ | ||
374 | void | ||
375 | nfsd4_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; | ||
413 | out_release_client: | ||
414 | rpc_shutdown_client(client); | ||
415 | out_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 | */ | ||
425 | void | ||
426 | nfsd4_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 | |||
435 | out_release_clp: | ||
436 | atomic_dec(&clp->cl_count); | ||
437 | rpc_shutdown_client(cb->cb_client); | ||
438 | out_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 | } |
483 | out_put_cred: | 480 | out_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; |