diff options
Diffstat (limited to 'fs/nfsd/nfs4callback.c')
-rw-r--r-- | fs/nfsd/nfs4callback.c | 57 |
1 files changed, 32 insertions, 25 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index eb78e7e22077..988cbb3a19b6 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -143,8 +143,6 @@ struct nfs4_cb_compound_hdr { | |||
143 | u32 minorversion; | 143 | u32 minorversion; |
144 | /* res */ | 144 | /* res */ |
145 | int status; | 145 | int status; |
146 | u32 taglen; | ||
147 | char *tag; | ||
148 | }; | 146 | }; |
149 | 147 | ||
150 | static struct { | 148 | static struct { |
@@ -205,6 +203,16 @@ nfs_cb_stat_to_errno(int stat) | |||
205 | */ | 203 | */ |
206 | 204 | ||
207 | static void | 205 | static void |
206 | encode_stateid(struct xdr_stream *xdr, stateid_t *sid) | ||
207 | { | ||
208 | __be32 *p; | ||
209 | |||
210 | RESERVE_SPACE(sizeof(stateid_t)); | ||
211 | WRITE32(sid->si_generation); | ||
212 | WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t)); | ||
213 | } | ||
214 | |||
215 | static void | ||
208 | encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr) | 216 | encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr) |
209 | { | 217 | { |
210 | __be32 * p; | 218 | __be32 * p; |
@@ -229,10 +237,10 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp, | |||
229 | __be32 *p; | 237 | __be32 *p; |
230 | int len = dp->dl_fh.fh_size; | 238 | int len = dp->dl_fh.fh_size; |
231 | 239 | ||
232 | RESERVE_SPACE(12+sizeof(dp->dl_stateid) + len); | 240 | RESERVE_SPACE(4); |
233 | WRITE32(OP_CB_RECALL); | 241 | WRITE32(OP_CB_RECALL); |
234 | WRITE32(dp->dl_stateid.si_generation); | 242 | encode_stateid(xdr, &dp->dl_stateid); |
235 | WRITEMEM(&dp->dl_stateid.si_opaque, sizeof(stateid_opaque_t)); | 243 | RESERVE_SPACE(8 + (XDR_QUADLEN(len) << 2)); |
236 | WRITE32(0); /* truncate optimization not implemented */ | 244 | WRITE32(0); /* truncate optimization not implemented */ |
237 | WRITE32(len); | 245 | WRITE32(len); |
238 | WRITEMEM(&dp->dl_fh.fh_base, len); | 246 | WRITEMEM(&dp->dl_fh.fh_base, len); |
@@ -293,13 +301,14 @@ nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, | |||
293 | static int | 301 | static int |
294 | decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){ | 302 | decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){ |
295 | __be32 *p; | 303 | __be32 *p; |
304 | u32 taglen; | ||
296 | 305 | ||
297 | READ_BUF(8); | 306 | READ_BUF(8); |
298 | READ32(hdr->status); | 307 | READ32(hdr->status); |
299 | READ32(hdr->taglen); | 308 | /* We've got no use for the tag; ignore it: */ |
300 | READ_BUF(hdr->taglen + 4); | 309 | READ32(taglen); |
301 | hdr->tag = (char *)p; | 310 | READ_BUF(taglen + 4); |
302 | p += XDR_QUADLEN(hdr->taglen); | 311 | p += XDR_QUADLEN(taglen); |
303 | READ32(hdr->nops); | 312 | READ32(hdr->nops); |
304 | return 0; | 313 | return 0; |
305 | } | 314 | } |
@@ -667,28 +676,28 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) | |||
667 | } | 676 | } |
668 | 677 | ||
669 | switch (task->tk_status) { | 678 | switch (task->tk_status) { |
670 | case -EIO: | 679 | case 0: |
680 | return; | ||
681 | case -EBADHANDLE: | ||
682 | case -NFS4ERR_BAD_STATEID: | ||
683 | /* Race: client probably got cb_recall | ||
684 | * before open reply granting delegation */ | ||
685 | break; | ||
686 | default: | ||
671 | /* Network partition? */ | 687 | /* Network partition? */ |
672 | atomic_set(&clp->cl_cb_set, 0); | 688 | atomic_set(&clp->cl_cb_set, 0); |
673 | warn_no_callback_path(clp, task->tk_status); | 689 | warn_no_callback_path(clp, task->tk_status); |
674 | if (current_rpc_client != task->tk_client) { | 690 | if (current_rpc_client != task->tk_client) { |
675 | /* queue a callback on the new connection: */ | 691 | /* queue a callback on the new connection: */ |
692 | atomic_inc(&dp->dl_count); | ||
676 | nfsd4_cb_recall(dp); | 693 | nfsd4_cb_recall(dp); |
677 | return; | 694 | return; |
678 | } | 695 | } |
679 | case -EBADHANDLE: | ||
680 | case -NFS4ERR_BAD_STATEID: | ||
681 | /* Race: client probably got cb_recall | ||
682 | * before open reply granting delegation */ | ||
683 | break; | ||
684 | default: | ||
685 | /* success, or error we can't handle */ | ||
686 | return; | ||
687 | } | 696 | } |
688 | if (dp->dl_retries--) { | 697 | if (dp->dl_retries--) { |
689 | rpc_delay(task, 2*HZ); | 698 | rpc_delay(task, 2*HZ); |
690 | task->tk_status = 0; | 699 | task->tk_status = 0; |
691 | rpc_restart_call(task); | 700 | rpc_restart_call_prepare(task); |
692 | return; | 701 | return; |
693 | } else { | 702 | } else { |
694 | atomic_set(&clp->cl_cb_set, 0); | 703 | atomic_set(&clp->cl_cb_set, 0); |
@@ -752,18 +761,16 @@ static void _nfsd4_cb_recall(struct nfs4_delegation *dp) | |||
752 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL], | 761 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL], |
753 | .rpc_cred = callback_cred | 762 | .rpc_cred = callback_cred |
754 | }; | 763 | }; |
755 | int status; | ||
756 | 764 | ||
757 | if (clnt == NULL) | 765 | if (clnt == NULL) { |
766 | nfs4_put_delegation(dp); | ||
758 | return; /* Client is shutting down; give up. */ | 767 | return; /* Client is shutting down; give up. */ |
768 | } | ||
759 | 769 | ||
760 | args->args_op = dp; | 770 | args->args_op = dp; |
761 | msg.rpc_argp = args; | 771 | msg.rpc_argp = args; |
762 | dp->dl_retries = 1; | 772 | dp->dl_retries = 1; |
763 | status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT, | 773 | rpc_call_async(clnt, &msg, RPC_TASK_SOFT, &nfsd4_cb_recall_ops, dp); |
764 | &nfsd4_cb_recall_ops, dp); | ||
765 | if (status) | ||
766 | nfs4_put_delegation(dp); | ||
767 | } | 774 | } |
768 | 775 | ||
769 | void nfsd4_do_callback_rpc(struct work_struct *w) | 776 | void nfsd4_do_callback_rpc(struct work_struct *w) |