diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index a0ead0c57268..551f32d7f5c7 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -96,6 +96,8 @@ static struct kmem_cache *deleg_slab; | |||
96 | 96 | ||
97 | static void free_session(struct nfsd4_session *); | 97 | static void free_session(struct nfsd4_session *); |
98 | 98 | ||
99 | static struct nfsd4_callback_ops nfsd4_cb_recall_ops; | ||
100 | |||
99 | static bool is_session_dead(struct nfsd4_session *ses) | 101 | static bool is_session_dead(struct nfsd4_session *ses) |
100 | { | 102 | { |
101 | return ses->se_flags & NFS4_SESSION_DEAD; | 103 | return ses->se_flags & NFS4_SESSION_DEAD; |
@@ -647,8 +649,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct svc_fh *current_fh) | |||
647 | dp->dl_type = NFS4_OPEN_DELEGATE_READ; | 649 | dp->dl_type = NFS4_OPEN_DELEGATE_READ; |
648 | dp->dl_retries = 1; | 650 | dp->dl_retries = 1; |
649 | nfsd4_init_cb(&dp->dl_recall, dp->dl_stid.sc_client, | 651 | nfsd4_init_cb(&dp->dl_recall, dp->dl_stid.sc_client, |
650 | NFSPROC4_CLNT_CB_RECALL); | 652 | &nfsd4_cb_recall_ops, NFSPROC4_CLNT_CB_RECALL); |
651 | INIT_WORK(&dp->dl_recall.cb_work, nfsd4_run_cb_recall); | ||
652 | return dp; | 653 | return dp; |
653 | out_dec: | 654 | out_dec: |
654 | atomic_long_dec(&num_delegations); | 655 | atomic_long_dec(&num_delegations); |
@@ -1872,8 +1873,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, | |||
1872 | free_client(clp); | 1873 | free_client(clp); |
1873 | return NULL; | 1874 | return NULL; |
1874 | } | 1875 | } |
1875 | nfsd4_init_cb(&clp->cl_cb_null, clp, NFSPROC4_CLNT_CB_NULL); | 1876 | nfsd4_init_cb(&clp->cl_cb_null, clp, NULL, NFSPROC4_CLNT_CB_NULL); |
1876 | INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_run_cb_null); | ||
1877 | clp->cl_time = get_seconds(); | 1877 | clp->cl_time = get_seconds(); |
1878 | clear_bit(0, &clp->cl_cb_slot_busy); | 1878 | clear_bit(0, &clp->cl_cb_slot_busy); |
1879 | copy_verf(clp, verf); | 1879 | copy_verf(clp, verf); |
@@ -3360,8 +3360,12 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type) | |||
3360 | return ret; | 3360 | return ret; |
3361 | } | 3361 | } |
3362 | 3362 | ||
3363 | void nfsd4_prepare_cb_recall(struct nfs4_delegation *dp) | 3363 | #define cb_to_delegation(cb) \ |
3364 | container_of(cb, struct nfs4_delegation, dl_recall) | ||
3365 | |||
3366 | static void nfsd4_cb_recall_prepare(struct nfsd4_callback *cb) | ||
3364 | { | 3367 | { |
3368 | struct nfs4_delegation *dp = cb_to_delegation(cb); | ||
3365 | struct nfsd_net *nn = net_generic(dp->dl_stid.sc_client->net, | 3369 | struct nfsd_net *nn = net_generic(dp->dl_stid.sc_client->net, |
3366 | nfsd_net_id); | 3370 | nfsd_net_id); |
3367 | 3371 | ||
@@ -3382,6 +3386,43 @@ void nfsd4_prepare_cb_recall(struct nfs4_delegation *dp) | |||
3382 | spin_unlock(&state_lock); | 3386 | spin_unlock(&state_lock); |
3383 | } | 3387 | } |
3384 | 3388 | ||
3389 | static int nfsd4_cb_recall_done(struct nfsd4_callback *cb, | ||
3390 | struct rpc_task *task) | ||
3391 | { | ||
3392 | struct nfs4_delegation *dp = cb_to_delegation(cb); | ||
3393 | |||
3394 | switch (task->tk_status) { | ||
3395 | case 0: | ||
3396 | return 1; | ||
3397 | case -EBADHANDLE: | ||
3398 | case -NFS4ERR_BAD_STATEID: | ||
3399 | /* | ||
3400 | * Race: client probably got cb_recall before open reply | ||
3401 | * granting delegation. | ||
3402 | */ | ||
3403 | if (dp->dl_retries--) { | ||
3404 | rpc_delay(task, 2 * HZ); | ||
3405 | return 0; | ||
3406 | } | ||
3407 | /*FALLTHRU*/ | ||
3408 | default: | ||
3409 | return -1; | ||
3410 | } | ||
3411 | } | ||
3412 | |||
3413 | static void nfsd4_cb_recall_release(struct nfsd4_callback *cb) | ||
3414 | { | ||
3415 | struct nfs4_delegation *dp = cb_to_delegation(cb); | ||
3416 | |||
3417 | nfs4_put_stid(&dp->dl_stid); | ||
3418 | } | ||
3419 | |||
3420 | static struct nfsd4_callback_ops nfsd4_cb_recall_ops = { | ||
3421 | .prepare = nfsd4_cb_recall_prepare, | ||
3422 | .done = nfsd4_cb_recall_done, | ||
3423 | .release = nfsd4_cb_recall_release, | ||
3424 | }; | ||
3425 | |||
3385 | static void nfsd_break_one_deleg(struct nfs4_delegation *dp) | 3426 | static void nfsd_break_one_deleg(struct nfs4_delegation *dp) |
3386 | { | 3427 | { |
3387 | /* | 3428 | /* |