aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c111
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);
320out: 329out:
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
348static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid) 357static 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);
400out: 411out:
@@ -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 }
492out_nodeleg: 507out_nodeleg:
508 nfs_free_seqid(o_arg.seqid);
493 clear_bit(NFS_DELEGATED_STATE, &state->flags); 509 clear_bit(NFS_DELEGATED_STATE, &state->flags);
494out: 510out:
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);
2741out: 2771out:
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