diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 111 |
1 files changed, 73 insertions, 38 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9701ca8c9428..9ba89e7cdd28 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -218,7 +218,6 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
218 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; | 218 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; |
219 | struct nfs_openargs o_arg = { | 219 | struct nfs_openargs o_arg = { |
220 | .fh = NFS_FH(inode), | 220 | .fh = NFS_FH(inode), |
221 | .seqid = sp->so_seqid, | ||
222 | .id = sp->so_id, | 221 | .id = sp->so_id, |
223 | .open_flags = state->state, | 222 | .open_flags = state->state, |
224 | .clientid = server->nfs4_state->cl_clientid, | 223 | .clientid = server->nfs4_state->cl_clientid, |
@@ -245,8 +244,13 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
245 | } | 244 | } |
246 | o_arg.u.delegation_type = delegation->type; | 245 | o_arg.u.delegation_type = delegation->type; |
247 | } | 246 | } |
247 | o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); | ||
248 | if (o_arg.seqid == NULL) | ||
249 | return -ENOMEM; | ||
248 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 250 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
249 | nfs4_increment_seqid(status, sp); | 251 | /* Confirm the sequence as being established */ |
252 | nfs_confirm_seqid(&sp->so_seqid, status); | ||
253 | nfs_increment_open_seqid(status, o_arg.seqid); | ||
250 | if (status == 0) { | 254 | if (status == 0) { |
251 | memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid)); | 255 | memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid)); |
252 | if (o_res.delegation_type != 0) { | 256 | if (o_res.delegation_type != 0) { |
@@ -256,6 +260,7 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
256 | nfs_async_inode_return_delegation(inode, &o_res.stateid); | 260 | nfs_async_inode_return_delegation(inode, &o_res.stateid); |
257 | } | 261 | } |
258 | } | 262 | } |
263 | nfs_free_seqid(o_arg.seqid); | ||
259 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 264 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
260 | /* Ensure we update the inode attributes */ | 265 | /* Ensure we update the inode attributes */ |
261 | NFS_CACHEINV(inode); | 266 | NFS_CACHEINV(inode); |
@@ -307,16 +312,20 @@ static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state | |||
307 | goto out; | 312 | goto out; |
308 | if (state->state == 0) | 313 | if (state->state == 0) |
309 | goto out; | 314 | goto out; |
310 | arg.seqid = sp->so_seqid; | 315 | arg.seqid = nfs_alloc_seqid(&sp->so_seqid); |
316 | status = -ENOMEM; | ||
317 | if (arg.seqid == NULL) | ||
318 | goto out; | ||
311 | arg.open_flags = state->state; | 319 | arg.open_flags = state->state; |
312 | memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data)); | 320 | memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data)); |
313 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 321 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
314 | nfs4_increment_seqid(status, sp); | 322 | nfs_increment_open_seqid(status, arg.seqid); |
315 | if (status >= 0) { | 323 | if (status >= 0) { |
316 | memcpy(state->stateid.data, res.stateid.data, | 324 | memcpy(state->stateid.data, res.stateid.data, |
317 | sizeof(state->stateid.data)); | 325 | sizeof(state->stateid.data)); |
318 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 326 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
319 | } | 327 | } |
328 | nfs_free_seqid(arg.seqid); | ||
320 | out: | 329 | out: |
321 | up(&sp->so_sema); | 330 | up(&sp->so_sema); |
322 | dput(parent); | 331 | dput(parent); |
@@ -345,11 +354,11 @@ int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state) | |||
345 | return err; | 354 | return err; |
346 | } | 355 | } |
347 | 356 | ||
348 | static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid) | 357 | static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid) |
349 | { | 358 | { |
350 | struct nfs_open_confirmargs arg = { | 359 | struct nfs_open_confirmargs arg = { |
351 | .fh = fh, | 360 | .fh = fh, |
352 | .seqid = sp->so_seqid, | 361 | .seqid = seqid, |
353 | .stateid = *stateid, | 362 | .stateid = *stateid, |
354 | }; | 363 | }; |
355 | struct nfs_open_confirmres res; | 364 | struct nfs_open_confirmres res; |
@@ -362,7 +371,9 @@ static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nf | |||
362 | int status; | 371 | int status; |
363 | 372 | ||
364 | status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR); | 373 | status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR); |
365 | nfs4_increment_seqid(status, sp); | 374 | /* Confirm the sequence as being established */ |
375 | nfs_confirm_seqid(&sp->so_seqid, status); | ||
376 | nfs_increment_open_seqid(status, seqid); | ||
366 | if (status >= 0) | 377 | if (status >= 0) |
367 | memcpy(stateid, &res.stateid, sizeof(*stateid)); | 378 | memcpy(stateid, &res.stateid, sizeof(*stateid)); |
368 | return status; | 379 | return status; |
@@ -380,21 +391,21 @@ static int _nfs4_proc_open(struct inode *dir, struct nfs4_state_owner *sp, stru | |||
380 | int status; | 391 | int status; |
381 | 392 | ||
382 | /* Update sequence id. The caller must serialize! */ | 393 | /* Update sequence id. The caller must serialize! */ |
383 | o_arg->seqid = sp->so_seqid; | ||
384 | o_arg->id = sp->so_id; | 394 | o_arg->id = sp->so_id; |
385 | o_arg->clientid = sp->so_client->cl_clientid; | 395 | o_arg->clientid = sp->so_client->cl_clientid; |
386 | 396 | ||
387 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 397 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
388 | nfs4_increment_seqid(status, sp); | 398 | nfs_increment_open_seqid(status, o_arg->seqid); |
389 | if (status != 0) | 399 | if (status != 0) |
390 | goto out; | 400 | goto out; |
391 | update_changeattr(dir, &o_res->cinfo); | 401 | update_changeattr(dir, &o_res->cinfo); |
392 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { | 402 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { |
393 | status = _nfs4_proc_open_confirm(server->client, &o_res->fh, | 403 | status = _nfs4_proc_open_confirm(server->client, &o_res->fh, |
394 | sp, &o_res->stateid); | 404 | sp, &o_res->stateid, o_arg->seqid); |
395 | if (status != 0) | 405 | if (status != 0) |
396 | goto out; | 406 | goto out; |
397 | } | 407 | } |
408 | nfs_confirm_seqid(&sp->so_seqid, 0); | ||
398 | if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) | 409 | if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) |
399 | status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); | 410 | status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); |
400 | out: | 411 | out: |
@@ -465,6 +476,10 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
465 | set_bit(NFS_DELEGATED_STATE, &state->flags); | 476 | set_bit(NFS_DELEGATED_STATE, &state->flags); |
466 | goto out; | 477 | goto out; |
467 | } | 478 | } |
479 | o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); | ||
480 | status = -ENOMEM; | ||
481 | if (o_arg.seqid == NULL) | ||
482 | goto out; | ||
468 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); | 483 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); |
469 | if (status != 0) | 484 | if (status != 0) |
470 | goto out_nodeleg; | 485 | goto out_nodeleg; |
@@ -490,6 +505,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
490 | nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res); | 505 | nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res); |
491 | } | 506 | } |
492 | out_nodeleg: | 507 | out_nodeleg: |
508 | nfs_free_seqid(o_arg.seqid); | ||
493 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 509 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
494 | out: | 510 | out: |
495 | dput(parent); | 511 | dput(parent); |
@@ -667,6 +683,9 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
667 | /* Serialization for the sequence id */ | 683 | /* Serialization for the sequence id */ |
668 | down(&sp->so_sema); | 684 | down(&sp->so_sema); |
669 | 685 | ||
686 | o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); | ||
687 | if (o_arg.seqid == NULL) | ||
688 | return -ENOMEM; | ||
670 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); | 689 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); |
671 | if (status != 0) | 690 | if (status != 0) |
672 | goto out_err; | 691 | goto out_err; |
@@ -681,6 +700,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
681 | update_open_stateid(state, &o_res.stateid, flags); | 700 | update_open_stateid(state, &o_res.stateid, flags); |
682 | if (o_res.delegation_type != 0) | 701 | if (o_res.delegation_type != 0) |
683 | nfs_inode_set_delegation(inode, cred, &o_res); | 702 | nfs_inode_set_delegation(inode, cred, &o_res); |
703 | nfs_free_seqid(o_arg.seqid); | ||
684 | up(&sp->so_sema); | 704 | up(&sp->so_sema); |
685 | nfs4_put_state_owner(sp); | 705 | nfs4_put_state_owner(sp); |
686 | up_read(&clp->cl_sem); | 706 | up_read(&clp->cl_sem); |
@@ -690,6 +710,7 @@ out_err: | |||
690 | if (sp != NULL) { | 710 | if (sp != NULL) { |
691 | if (state != NULL) | 711 | if (state != NULL) |
692 | nfs4_put_open_state(state); | 712 | nfs4_put_open_state(state); |
713 | nfs_free_seqid(o_arg.seqid); | ||
693 | up(&sp->so_sema); | 714 | up(&sp->so_sema); |
694 | nfs4_put_state_owner(sp); | 715 | nfs4_put_state_owner(sp); |
695 | } | 716 | } |
@@ -718,7 +739,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, | |||
718 | * It is actually a sign of a bug on the client or on the server. | 739 | * It is actually a sign of a bug on the client or on the server. |
719 | * | 740 | * |
720 | * If we receive a BAD_SEQID error in the particular case of | 741 | * If we receive a BAD_SEQID error in the particular case of |
721 | * doing an OPEN, we assume that nfs4_increment_seqid() will | 742 | * doing an OPEN, we assume that nfs_increment_open_seqid() will |
722 | * have unhashed the old state_owner for us, and that we can | 743 | * have unhashed the old state_owner for us, and that we can |
723 | * therefore safely retry using a new one. We should still warn | 744 | * therefore safely retry using a new one. We should still warn |
724 | * the user though... | 745 | * the user though... |
@@ -799,7 +820,7 @@ static void nfs4_close_done(struct rpc_task *task) | |||
799 | /* hmm. we are done with the inode, and in the process of freeing | 820 | /* hmm. we are done with the inode, and in the process of freeing |
800 | * the state_owner. we keep this around to process errors | 821 | * the state_owner. we keep this around to process errors |
801 | */ | 822 | */ |
802 | nfs4_increment_seqid(task->tk_status, sp); | 823 | nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid); |
803 | switch (task->tk_status) { | 824 | switch (task->tk_status) { |
804 | case 0: | 825 | case 0: |
805 | memcpy(&state->stateid, &calldata->res.stateid, | 826 | memcpy(&state->stateid, &calldata->res.stateid, |
@@ -818,6 +839,7 @@ static void nfs4_close_done(struct rpc_task *task) | |||
818 | } | 839 | } |
819 | state->state = calldata->arg.open_flags; | 840 | state->state = calldata->arg.open_flags; |
820 | nfs4_put_open_state(state); | 841 | nfs4_put_open_state(state); |
842 | nfs_free_seqid(calldata->arg.seqid); | ||
821 | up(&sp->so_sema); | 843 | up(&sp->so_sema); |
822 | nfs4_put_state_owner(sp); | 844 | nfs4_put_state_owner(sp); |
823 | up_read(&server->nfs4_state->cl_sem); | 845 | up_read(&server->nfs4_state->cl_sem); |
@@ -865,7 +887,11 @@ int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode) | |||
865 | calldata->state = state; | 887 | calldata->state = state; |
866 | calldata->arg.fh = NFS_FH(inode); | 888 | calldata->arg.fh = NFS_FH(inode); |
867 | /* Serialization for the sequence id */ | 889 | /* Serialization for the sequence id */ |
868 | calldata->arg.seqid = state->owner->so_seqid; | 890 | calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid); |
891 | if (calldata->arg.seqid == NULL) { | ||
892 | kfree(calldata); | ||
893 | return -ENOMEM; | ||
894 | } | ||
869 | calldata->arg.open_flags = mode; | 895 | calldata->arg.open_flags = mode; |
870 | memcpy(&calldata->arg.stateid, &state->stateid, | 896 | memcpy(&calldata->arg.stateid, &state->stateid, |
871 | sizeof(calldata->arg.stateid)); | 897 | sizeof(calldata->arg.stateid)); |
@@ -2729,15 +2755,19 @@ static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock | |||
2729 | /* We might have lost the locks! */ | 2755 | /* We might have lost the locks! */ |
2730 | if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) | 2756 | if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) |
2731 | goto out; | 2757 | goto out; |
2732 | luargs.seqid = lsp->ls_seqid; | 2758 | luargs.seqid = nfs_alloc_seqid(&lsp->ls_seqid); |
2733 | memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid)); | 2759 | status = -ENOMEM; |
2760 | if (luargs.seqid == NULL) | ||
2761 | goto out; | ||
2762 | memcpy(luargs.stateid.data, lsp->ls_stateid.data, sizeof(luargs.stateid.data)); | ||
2734 | arg.u.locku = &luargs; | 2763 | arg.u.locku = &luargs; |
2735 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 2764 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
2736 | nfs4_increment_lock_seqid(status, lsp); | 2765 | nfs_increment_lock_seqid(status, luargs.seqid); |
2737 | 2766 | ||
2738 | if (status == 0) | 2767 | if (status == 0) |
2739 | memcpy(&lsp->ls_stateid, &res.u.stateid, | 2768 | memcpy(lsp->ls_stateid.data, res.u.stateid.data, |
2740 | sizeof(lsp->ls_stateid)); | 2769 | sizeof(lsp->ls_stateid.data)); |
2770 | nfs_free_seqid(luargs.seqid); | ||
2741 | out: | 2771 | out: |
2742 | up(&state->lock_sema); | 2772 | up(&state->lock_sema); |
2743 | if (status == 0) | 2773 | if (status == 0) |
@@ -2783,9 +2813,13 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r | |||
2783 | .reclaim = reclaim, | 2813 | .reclaim = reclaim, |
2784 | .new_lock_owner = 0, | 2814 | .new_lock_owner = 0, |
2785 | }; | 2815 | }; |
2786 | int status; | 2816 | struct nfs_seqid *lock_seqid; |
2817 | int status = -ENOMEM; | ||
2787 | 2818 | ||
2788 | if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) { | 2819 | lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); |
2820 | if (lock_seqid == NULL) | ||
2821 | return -ENOMEM; | ||
2822 | if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) { | ||
2789 | struct nfs4_state_owner *owner = state->owner; | 2823 | struct nfs4_state_owner *owner = state->owner; |
2790 | struct nfs_open_to_lock otl = { | 2824 | struct nfs_open_to_lock otl = { |
2791 | .lock_owner = { | 2825 | .lock_owner = { |
@@ -2793,39 +2827,40 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r | |||
2793 | }, | 2827 | }, |
2794 | }; | 2828 | }; |
2795 | 2829 | ||
2796 | otl.lock_seqid = lsp->ls_seqid; | 2830 | otl.lock_seqid = lock_seqid; |
2797 | otl.lock_owner.id = lsp->ls_id; | 2831 | otl.lock_owner.id = lsp->ls_id; |
2798 | memcpy(&otl.open_stateid, &state->stateid, sizeof(otl.open_stateid)); | 2832 | memcpy(&otl.open_stateid, &state->stateid, sizeof(otl.open_stateid)); |
2799 | largs.u.open_lock = &otl; | 2833 | largs.u.open_lock = &otl; |
2800 | largs.new_lock_owner = 1; | 2834 | largs.new_lock_owner = 1; |
2801 | arg.u.lock = &largs; | 2835 | arg.u.lock = &largs; |
2802 | down(&owner->so_sema); | 2836 | down(&owner->so_sema); |
2803 | otl.open_seqid = owner->so_seqid; | 2837 | otl.open_seqid = nfs_alloc_seqid(&owner->so_seqid); |
2804 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 2838 | if (otl.open_seqid != NULL) { |
2805 | /* increment open_owner seqid on success, and | 2839 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
2806 | * seqid mutating errors */ | 2840 | /* increment seqid on success, and seqid mutating errors */ |
2807 | nfs4_increment_seqid(status, owner); | 2841 | nfs_increment_open_seqid(status, otl.open_seqid); |
2808 | up(&owner->so_sema); | 2842 | nfs_free_seqid(otl.open_seqid); |
2809 | if (status == 0) { | ||
2810 | lsp->ls_flags |= NFS_LOCK_INITIALIZED; | ||
2811 | lsp->ls_seqid++; | ||
2812 | } | 2843 | } |
2844 | up(&owner->so_sema); | ||
2845 | if (status == 0) | ||
2846 | nfs_confirm_seqid(&lsp->ls_seqid, 0); | ||
2813 | } else { | 2847 | } else { |
2814 | struct nfs_exist_lock el = { | 2848 | struct nfs_exist_lock el; |
2815 | .seqid = lsp->ls_seqid, | ||
2816 | }; | ||
2817 | memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid)); | 2849 | memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid)); |
2818 | largs.u.exist_lock = ⪙ | 2850 | largs.u.exist_lock = ⪙ |
2819 | arg.u.lock = &largs; | 2851 | arg.u.lock = &largs; |
2852 | el.seqid = lock_seqid; | ||
2820 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 2853 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
2821 | /* increment seqid on success, and * seqid mutating errors*/ | ||
2822 | nfs4_increment_lock_seqid(status, lsp); | ||
2823 | } | 2854 | } |
2855 | /* increment seqid on success, and seqid mutating errors*/ | ||
2856 | nfs_increment_lock_seqid(status, lock_seqid); | ||
2824 | /* save the returned stateid. */ | 2857 | /* save the returned stateid. */ |
2825 | if (status == 0) | 2858 | if (status == 0) { |
2826 | memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid)); | 2859 | memcpy(lsp->ls_stateid.data, res.u.stateid.data, sizeof(lsp->ls_stateid.data)); |
2827 | else if (status == -NFS4ERR_DENIED) | 2860 | lsp->ls_flags |= NFS_LOCK_INITIALIZED; |
2861 | } else if (status == -NFS4ERR_DENIED) | ||
2828 | status = -EAGAIN; | 2862 | status = -EAGAIN; |
2863 | nfs_free_seqid(lock_seqid); | ||
2829 | return status; | 2864 | return status; |
2830 | } | 2865 | } |
2831 | 2866 | ||