diff options
-rw-r--r-- | fs/nfs/nfs4_fs.h | 42 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 111 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 145 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 43 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 15 |
5 files changed, 273 insertions, 83 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index ec1a22d7b876..6ac6708484f5 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -93,6 +93,35 @@ struct nfs4_client { | |||
93 | }; | 93 | }; |
94 | 94 | ||
95 | /* | 95 | /* |
96 | * struct rpc_sequence ensures that RPC calls are sent in the exact | ||
97 | * order that they appear on the list. | ||
98 | */ | ||
99 | struct rpc_sequence { | ||
100 | struct rpc_wait_queue wait; /* RPC call delay queue */ | ||
101 | spinlock_t lock; /* Protects the list */ | ||
102 | struct list_head list; /* Defines sequence of RPC calls */ | ||
103 | }; | ||
104 | |||
105 | #define NFS_SEQID_CONFIRMED 1 | ||
106 | struct nfs_seqid_counter { | ||
107 | struct rpc_sequence *sequence; | ||
108 | int flags; | ||
109 | u32 counter; | ||
110 | }; | ||
111 | |||
112 | struct nfs_seqid { | ||
113 | struct list_head list; | ||
114 | struct nfs_seqid_counter *sequence; | ||
115 | struct rpc_task *task; | ||
116 | }; | ||
117 | |||
118 | static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status) | ||
119 | { | ||
120 | if (seqid_mutating_err(-status)) | ||
121 | seqid->flags |= NFS_SEQID_CONFIRMED; | ||
122 | } | ||
123 | |||
124 | /* | ||
96 | * NFS4 state_owners and lock_owners are simply labels for ordered | 125 | * NFS4 state_owners and lock_owners are simply labels for ordered |
97 | * sequences of RPC calls. Their sole purpose is to provide once-only | 126 | * sequences of RPC calls. Their sole purpose is to provide once-only |
98 | * semantics by allowing the server to identify replayed requests. | 127 | * semantics by allowing the server to identify replayed requests. |
@@ -106,12 +135,13 @@ struct nfs4_state_owner { | |||
106 | struct nfs4_client *so_client; | 135 | struct nfs4_client *so_client; |
107 | u32 so_id; /* 32-bit identifier, unique */ | 136 | u32 so_id; /* 32-bit identifier, unique */ |
108 | struct semaphore so_sema; | 137 | struct semaphore so_sema; |
109 | u32 so_seqid; /* protected by so_sema */ | ||
110 | atomic_t so_count; | 138 | atomic_t so_count; |
111 | 139 | ||
112 | struct rpc_cred *so_cred; /* Associated cred */ | 140 | struct rpc_cred *so_cred; /* Associated cred */ |
113 | struct list_head so_states; | 141 | struct list_head so_states; |
114 | struct list_head so_delegations; | 142 | struct list_head so_delegations; |
143 | struct nfs_seqid_counter so_seqid; | ||
144 | struct rpc_sequence so_sequence; | ||
115 | }; | 145 | }; |
116 | 146 | ||
117 | /* | 147 | /* |
@@ -132,7 +162,7 @@ struct nfs4_lock_state { | |||
132 | fl_owner_t ls_owner; /* POSIX lock owner */ | 162 | fl_owner_t ls_owner; /* POSIX lock owner */ |
133 | #define NFS_LOCK_INITIALIZED 1 | 163 | #define NFS_LOCK_INITIALIZED 1 |
134 | int ls_flags; | 164 | int ls_flags; |
135 | u32 ls_seqid; | 165 | struct nfs_seqid_counter ls_seqid; |
136 | u32 ls_id; | 166 | u32 ls_id; |
137 | nfs4_stateid ls_stateid; | 167 | nfs4_stateid ls_stateid; |
138 | atomic_t ls_count; | 168 | atomic_t ls_count; |
@@ -224,12 +254,16 @@ extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state | |||
224 | extern void nfs4_put_open_state(struct nfs4_state *); | 254 | extern void nfs4_put_open_state(struct nfs4_state *); |
225 | extern void nfs4_close_state(struct nfs4_state *, mode_t); | 255 | extern void nfs4_close_state(struct nfs4_state *, mode_t); |
226 | extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode); | 256 | extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode); |
227 | extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp); | ||
228 | extern void nfs4_schedule_state_recovery(struct nfs4_client *); | 257 | extern void nfs4_schedule_state_recovery(struct nfs4_client *); |
229 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); | 258 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); |
230 | extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls); | ||
231 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); | 259 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); |
232 | 260 | ||
261 | extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter); | ||
262 | extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task); | ||
263 | extern void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid); | ||
264 | extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid); | ||
265 | extern void nfs_free_seqid(struct nfs_seqid *seqid); | ||
266 | |||
233 | extern const nfs4_stateid zero_stateid; | 267 | extern const nfs4_stateid zero_stateid; |
234 | 268 | ||
235 | /* nfs4xdr.c */ | 269 | /* nfs4xdr.c */ |
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 | ||
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index afe587d82f1e..f535c219cf3a 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -264,13 +264,16 @@ nfs4_alloc_state_owner(void) | |||
264 | { | 264 | { |
265 | struct nfs4_state_owner *sp; | 265 | struct nfs4_state_owner *sp; |
266 | 266 | ||
267 | sp = kmalloc(sizeof(*sp),GFP_KERNEL); | 267 | sp = kzalloc(sizeof(*sp),GFP_KERNEL); |
268 | if (!sp) | 268 | if (!sp) |
269 | return NULL; | 269 | return NULL; |
270 | init_MUTEX(&sp->so_sema); | 270 | init_MUTEX(&sp->so_sema); |
271 | sp->so_seqid = 0; /* arbitrary */ | ||
272 | INIT_LIST_HEAD(&sp->so_states); | 271 | INIT_LIST_HEAD(&sp->so_states); |
273 | INIT_LIST_HEAD(&sp->so_delegations); | 272 | INIT_LIST_HEAD(&sp->so_delegations); |
273 | rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue"); | ||
274 | sp->so_seqid.sequence = &sp->so_sequence; | ||
275 | spin_lock_init(&sp->so_sequence.lock); | ||
276 | INIT_LIST_HEAD(&sp->so_sequence.list); | ||
274 | atomic_set(&sp->so_count, 1); | 277 | atomic_set(&sp->so_count, 1); |
275 | return sp; | 278 | return sp; |
276 | } | 279 | } |
@@ -553,12 +556,10 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f | |||
553 | struct nfs4_lock_state *lsp; | 556 | struct nfs4_lock_state *lsp; |
554 | struct nfs4_client *clp = state->owner->so_client; | 557 | struct nfs4_client *clp = state->owner->so_client; |
555 | 558 | ||
556 | lsp = kmalloc(sizeof(*lsp), GFP_KERNEL); | 559 | lsp = kzalloc(sizeof(*lsp), GFP_KERNEL); |
557 | if (lsp == NULL) | 560 | if (lsp == NULL) |
558 | return NULL; | 561 | return NULL; |
559 | lsp->ls_flags = 0; | 562 | lsp->ls_seqid.sequence = &state->owner->so_sequence; |
560 | lsp->ls_seqid = 0; /* arbitrary */ | ||
561 | memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data)); | ||
562 | atomic_set(&lsp->ls_count, 1); | 563 | atomic_set(&lsp->ls_count, 1); |
563 | lsp->ls_owner = fl_owner; | 564 | lsp->ls_owner = fl_owner; |
564 | spin_lock(&clp->cl_lock); | 565 | spin_lock(&clp->cl_lock); |
@@ -673,29 +674,102 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f | |||
673 | nfs4_put_lock_state(lsp); | 674 | nfs4_put_lock_state(lsp); |
674 | } | 675 | } |
675 | 676 | ||
676 | /* | 677 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) |
677 | * Called with state->lock_sema and clp->cl_sem held. | 678 | { |
678 | */ | 679 | struct rpc_sequence *sequence = counter->sequence; |
679 | void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp) | 680 | struct nfs_seqid *new; |
681 | |||
682 | new = kmalloc(sizeof(*new), GFP_KERNEL); | ||
683 | if (new != NULL) { | ||
684 | new->sequence = counter; | ||
685 | new->task = NULL; | ||
686 | spin_lock(&sequence->lock); | ||
687 | list_add_tail(&new->list, &sequence->list); | ||
688 | spin_unlock(&sequence->lock); | ||
689 | } | ||
690 | return new; | ||
691 | } | ||
692 | |||
693 | void nfs_free_seqid(struct nfs_seqid *seqid) | ||
680 | { | 694 | { |
681 | if (status == NFS_OK || seqid_mutating_err(-status)) | 695 | struct rpc_sequence *sequence = seqid->sequence->sequence; |
682 | lsp->ls_seqid++; | 696 | struct rpc_task *next = NULL; |
697 | |||
698 | spin_lock(&sequence->lock); | ||
699 | list_del(&seqid->list); | ||
700 | if (!list_empty(&sequence->list)) { | ||
701 | next = list_entry(sequence->list.next, struct nfs_seqid, list)->task; | ||
702 | if (next) | ||
703 | rpc_wake_up_task(next); | ||
704 | } | ||
705 | spin_unlock(&sequence->lock); | ||
706 | kfree(seqid); | ||
683 | } | 707 | } |
684 | 708 | ||
685 | /* | 709 | /* |
686 | * Called with sp->so_sema and clp->cl_sem held. | 710 | * Called with sp->so_sema and clp->cl_sem held. |
687 | * | 711 | * |
688 | * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or | 712 | * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or |
689 | * failed with a seqid incrementing error - | 713 | * failed with a seqid incrementing error - |
690 | * see comments nfs_fs.h:seqid_mutating_error() | 714 | * see comments nfs_fs.h:seqid_mutating_error() |
691 | */ | 715 | */ |
692 | void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp) | 716 | static inline void nfs_increment_seqid(int status, struct nfs_seqid *seqid) |
693 | { | 717 | { |
694 | if (status == NFS_OK || seqid_mutating_err(-status)) | 718 | switch (status) { |
695 | sp->so_seqid++; | 719 | case 0: |
696 | /* If the server returns BAD_SEQID, unhash state_owner here */ | 720 | break; |
697 | if (status == -NFS4ERR_BAD_SEQID) | 721 | case -NFS4ERR_BAD_SEQID: |
722 | case -NFS4ERR_STALE_CLIENTID: | ||
723 | case -NFS4ERR_STALE_STATEID: | ||
724 | case -NFS4ERR_BAD_STATEID: | ||
725 | case -NFS4ERR_BADXDR: | ||
726 | case -NFS4ERR_RESOURCE: | ||
727 | case -NFS4ERR_NOFILEHANDLE: | ||
728 | /* Non-seqid mutating errors */ | ||
729 | return; | ||
730 | }; | ||
731 | /* | ||
732 | * Note: no locking needed as we are guaranteed to be first | ||
733 | * on the sequence list | ||
734 | */ | ||
735 | seqid->sequence->counter++; | ||
736 | } | ||
737 | |||
738 | void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid) | ||
739 | { | ||
740 | if (status == -NFS4ERR_BAD_SEQID) { | ||
741 | struct nfs4_state_owner *sp = container_of(seqid->sequence, | ||
742 | struct nfs4_state_owner, so_seqid); | ||
698 | nfs4_drop_state_owner(sp); | 743 | nfs4_drop_state_owner(sp); |
744 | } | ||
745 | return nfs_increment_seqid(status, seqid); | ||
746 | } | ||
747 | |||
748 | /* | ||
749 | * Called with ls->lock_sema and clp->cl_sem held. | ||
750 | * | ||
751 | * Increment the seqid if the LOCK/LOCKU succeeded, or | ||
752 | * failed with a seqid incrementing error - | ||
753 | * see comments nfs_fs.h:seqid_mutating_error() | ||
754 | */ | ||
755 | void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid) | ||
756 | { | ||
757 | return nfs_increment_seqid(status, seqid); | ||
758 | } | ||
759 | |||
760 | int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task) | ||
761 | { | ||
762 | struct rpc_sequence *sequence = seqid->sequence->sequence; | ||
763 | int status = 0; | ||
764 | |||
765 | spin_lock(&sequence->lock); | ||
766 | if (sequence->list.next != &seqid->list) { | ||
767 | seqid->task = task; | ||
768 | rpc_sleep_on(&sequence->wait, task, NULL, NULL); | ||
769 | status = -EAGAIN; | ||
770 | } | ||
771 | spin_unlock(&sequence->lock); | ||
772 | return status; | ||
699 | } | 773 | } |
700 | 774 | ||
701 | static int reclaimer(void *); | 775 | static int reclaimer(void *); |
@@ -791,8 +865,6 @@ static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct n | |||
791 | if (state->state == 0) | 865 | if (state->state == 0) |
792 | continue; | 866 | continue; |
793 | status = ops->recover_open(sp, state); | 867 | status = ops->recover_open(sp, state); |
794 | list_for_each_entry(lock, &state->lock_states, ls_locks) | ||
795 | lock->ls_flags &= ~NFS_LOCK_INITIALIZED; | ||
796 | if (status >= 0) { | 868 | if (status >= 0) { |
797 | status = nfs4_reclaim_locks(ops, state); | 869 | status = nfs4_reclaim_locks(ops, state); |
798 | if (status < 0) | 870 | if (status < 0) |
@@ -831,6 +903,26 @@ out_err: | |||
831 | return status; | 903 | return status; |
832 | } | 904 | } |
833 | 905 | ||
906 | static void nfs4_state_mark_reclaim(struct nfs4_client *clp) | ||
907 | { | ||
908 | struct nfs4_state_owner *sp; | ||
909 | struct nfs4_state *state; | ||
910 | struct nfs4_lock_state *lock; | ||
911 | |||
912 | /* Reset all sequence ids to zero */ | ||
913 | list_for_each_entry(sp, &clp->cl_state_owners, so_list) { | ||
914 | sp->so_seqid.counter = 0; | ||
915 | sp->so_seqid.flags = 0; | ||
916 | list_for_each_entry(state, &sp->so_states, open_states) { | ||
917 | list_for_each_entry(lock, &state->lock_states, ls_locks) { | ||
918 | lock->ls_seqid.counter = 0; | ||
919 | lock->ls_seqid.flags = 0; | ||
920 | lock->ls_flags &= ~NFS_LOCK_INITIALIZED; | ||
921 | } | ||
922 | } | ||
923 | } | ||
924 | } | ||
925 | |||
834 | static int reclaimer(void *ptr) | 926 | static int reclaimer(void *ptr) |
835 | { | 927 | { |
836 | struct reclaimer_args *args = (struct reclaimer_args *)ptr; | 928 | struct reclaimer_args *args = (struct reclaimer_args *)ptr; |
@@ -864,6 +956,7 @@ restart_loop: | |||
864 | default: | 956 | default: |
865 | ops = &nfs4_network_partition_recovery_ops; | 957 | ops = &nfs4_network_partition_recovery_ops; |
866 | }; | 958 | }; |
959 | nfs4_state_mark_reclaim(clp); | ||
867 | status = __nfs4_init_client(clp); | 960 | status = __nfs4_init_client(clp); |
868 | if (status) | 961 | if (status) |
869 | goto out_error; | 962 | goto out_error; |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 6c564ef9489e..fcd28a29a2f8 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -604,7 +604,7 @@ static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg) | |||
604 | 604 | ||
605 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); | 605 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); |
606 | WRITE32(OP_CLOSE); | 606 | WRITE32(OP_CLOSE); |
607 | WRITE32(arg->seqid); | 607 | WRITE32(arg->seqid->sequence->counter); |
608 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); | 608 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); |
609 | 609 | ||
610 | return 0; | 610 | return 0; |
@@ -732,9 +732,9 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lockargs *arg) | |||
732 | struct nfs_open_to_lock *ol = opargs->u.open_lock; | 732 | struct nfs_open_to_lock *ol = opargs->u.open_lock; |
733 | 733 | ||
734 | RESERVE_SPACE(40); | 734 | RESERVE_SPACE(40); |
735 | WRITE32(ol->open_seqid); | 735 | WRITE32(ol->open_seqid->sequence->counter); |
736 | WRITEMEM(&ol->open_stateid, sizeof(ol->open_stateid)); | 736 | WRITEMEM(&ol->open_stateid, sizeof(ol->open_stateid)); |
737 | WRITE32(ol->lock_seqid); | 737 | WRITE32(ol->lock_seqid->sequence->counter); |
738 | WRITE64(ol->lock_owner.clientid); | 738 | WRITE64(ol->lock_owner.clientid); |
739 | WRITE32(4); | 739 | WRITE32(4); |
740 | WRITE32(ol->lock_owner.id); | 740 | WRITE32(ol->lock_owner.id); |
@@ -744,7 +744,7 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lockargs *arg) | |||
744 | 744 | ||
745 | RESERVE_SPACE(20); | 745 | RESERVE_SPACE(20); |
746 | WRITEMEM(&el->stateid, sizeof(el->stateid)); | 746 | WRITEMEM(&el->stateid, sizeof(el->stateid)); |
747 | WRITE32(el->seqid); | 747 | WRITE32(el->seqid->sequence->counter); |
748 | } | 748 | } |
749 | 749 | ||
750 | return 0; | 750 | return 0; |
@@ -775,7 +775,7 @@ static int encode_locku(struct xdr_stream *xdr, const struct nfs_lockargs *arg) | |||
775 | RESERVE_SPACE(44); | 775 | RESERVE_SPACE(44); |
776 | WRITE32(OP_LOCKU); | 776 | WRITE32(OP_LOCKU); |
777 | WRITE32(arg->type); | 777 | WRITE32(arg->type); |
778 | WRITE32(opargs->seqid); | 778 | WRITE32(opargs->seqid->sequence->counter); |
779 | WRITEMEM(&opargs->stateid, sizeof(opargs->stateid)); | 779 | WRITEMEM(&opargs->stateid, sizeof(opargs->stateid)); |
780 | WRITE64(arg->offset); | 780 | WRITE64(arg->offset); |
781 | WRITE64(arg->length); | 781 | WRITE64(arg->length); |
@@ -826,7 +826,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena | |||
826 | */ | 826 | */ |
827 | RESERVE_SPACE(8); | 827 | RESERVE_SPACE(8); |
828 | WRITE32(OP_OPEN); | 828 | WRITE32(OP_OPEN); |
829 | WRITE32(arg->seqid); | 829 | WRITE32(arg->seqid->sequence->counter); |
830 | encode_share_access(xdr, arg->open_flags); | 830 | encode_share_access(xdr, arg->open_flags); |
831 | RESERVE_SPACE(16); | 831 | RESERVE_SPACE(16); |
832 | WRITE64(arg->clientid); | 832 | WRITE64(arg->clientid); |
@@ -941,7 +941,7 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_con | |||
941 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); | 941 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); |
942 | WRITE32(OP_OPEN_CONFIRM); | 942 | WRITE32(OP_OPEN_CONFIRM); |
943 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); | 943 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); |
944 | WRITE32(arg->seqid); | 944 | WRITE32(arg->seqid->sequence->counter); |
945 | 945 | ||
946 | return 0; | 946 | return 0; |
947 | } | 947 | } |
@@ -953,7 +953,7 @@ static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closea | |||
953 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); | 953 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); |
954 | WRITE32(OP_OPEN_DOWNGRADE); | 954 | WRITE32(OP_OPEN_DOWNGRADE); |
955 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); | 955 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); |
956 | WRITE32(arg->seqid); | 956 | WRITE32(arg->seqid->sequence->counter); |
957 | encode_share_access(xdr, arg->open_flags); | 957 | encode_share_access(xdr, arg->open_flags); |
958 | return 0; | 958 | return 0; |
959 | } | 959 | } |
@@ -1416,6 +1416,9 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_clos | |||
1416 | }; | 1416 | }; |
1417 | int status; | 1417 | int status; |
1418 | 1418 | ||
1419 | status = nfs_wait_on_sequence(args->seqid, req->rq_task); | ||
1420 | if (status != 0) | ||
1421 | goto out; | ||
1419 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1422 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
1420 | encode_compound_hdr(&xdr, &hdr); | 1423 | encode_compound_hdr(&xdr, &hdr); |
1421 | status = encode_putfh(&xdr, args->fh); | 1424 | status = encode_putfh(&xdr, args->fh); |
@@ -1437,6 +1440,9 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena | |||
1437 | }; | 1440 | }; |
1438 | int status; | 1441 | int status; |
1439 | 1442 | ||
1443 | status = nfs_wait_on_sequence(args->seqid, req->rq_task); | ||
1444 | if (status != 0) | ||
1445 | goto out; | ||
1440 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1446 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
1441 | encode_compound_hdr(&xdr, &hdr); | 1447 | encode_compound_hdr(&xdr, &hdr); |
1442 | status = encode_putfh(&xdr, args->fh); | 1448 | status = encode_putfh(&xdr, args->fh); |
@@ -1464,6 +1470,9 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct n | |||
1464 | }; | 1470 | }; |
1465 | int status; | 1471 | int status; |
1466 | 1472 | ||
1473 | status = nfs_wait_on_sequence(args->seqid, req->rq_task); | ||
1474 | if (status != 0) | ||
1475 | goto out; | ||
1467 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1476 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
1468 | encode_compound_hdr(&xdr, &hdr); | 1477 | encode_compound_hdr(&xdr, &hdr); |
1469 | status = encode_putfh(&xdr, args->fh); | 1478 | status = encode_putfh(&xdr, args->fh); |
@@ -1485,6 +1494,9 @@ static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, uint32_t *p, struct nf | |||
1485 | }; | 1494 | }; |
1486 | int status; | 1495 | int status; |
1487 | 1496 | ||
1497 | status = nfs_wait_on_sequence(args->seqid, req->rq_task); | ||
1498 | if (status != 0) | ||
1499 | goto out; | ||
1488 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1500 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
1489 | encode_compound_hdr(&xdr, &hdr); | 1501 | encode_compound_hdr(&xdr, &hdr); |
1490 | status = encode_putfh(&xdr, args->fh); | 1502 | status = encode_putfh(&xdr, args->fh); |
@@ -1506,6 +1518,9 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct | |||
1506 | }; | 1518 | }; |
1507 | int status; | 1519 | int status; |
1508 | 1520 | ||
1521 | status = nfs_wait_on_sequence(args->seqid, req->rq_task); | ||
1522 | if (status != 0) | ||
1523 | goto out; | ||
1509 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1524 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
1510 | encode_compound_hdr(&xdr, &hdr); | 1525 | encode_compound_hdr(&xdr, &hdr); |
1511 | status = encode_putfh(&xdr, args->fh); | 1526 | status = encode_putfh(&xdr, args->fh); |
@@ -1525,8 +1540,17 @@ static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_locka | |||
1525 | struct compound_hdr hdr = { | 1540 | struct compound_hdr hdr = { |
1526 | .nops = 2, | 1541 | .nops = 2, |
1527 | }; | 1542 | }; |
1543 | struct nfs_lock_opargs *opargs = args->u.lock; | ||
1544 | struct nfs_seqid *seqid; | ||
1528 | int status; | 1545 | int status; |
1529 | 1546 | ||
1547 | if (opargs->new_lock_owner) | ||
1548 | seqid = opargs->u.open_lock->lock_seqid; | ||
1549 | else | ||
1550 | seqid = opargs->u.exist_lock->seqid; | ||
1551 | status = nfs_wait_on_sequence(seqid, req->rq_task); | ||
1552 | if (status != 0) | ||
1553 | goto out; | ||
1530 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1554 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
1531 | encode_compound_hdr(&xdr, &hdr); | 1555 | encode_compound_hdr(&xdr, &hdr); |
1532 | status = encode_putfh(&xdr, args->fh); | 1556 | status = encode_putfh(&xdr, args->fh); |
@@ -1569,6 +1593,9 @@ static int nfs4_xdr_enc_locku(struct rpc_rqst *req, uint32_t *p, struct nfs_lock | |||
1569 | }; | 1593 | }; |
1570 | int status; | 1594 | int status; |
1571 | 1595 | ||
1596 | status = nfs_wait_on_sequence(args->u.locku->seqid, req->rq_task); | ||
1597 | if (status != 0) | ||
1598 | goto out; | ||
1572 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1599 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
1573 | encode_compound_hdr(&xdr, &hdr); | 1600 | encode_compound_hdr(&xdr, &hdr); |
1574 | status = encode_putfh(&xdr, args->fh); | 1601 | status = encode_putfh(&xdr, args->fh); |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index a2bf6914ff1b..d578912bf9a9 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -96,12 +96,13 @@ struct nfs4_change_info { | |||
96 | u64 after; | 96 | u64 after; |
97 | }; | 97 | }; |
98 | 98 | ||
99 | struct nfs_seqid; | ||
99 | /* | 100 | /* |
100 | * Arguments to the open call. | 101 | * Arguments to the open call. |
101 | */ | 102 | */ |
102 | struct nfs_openargs { | 103 | struct nfs_openargs { |
103 | const struct nfs_fh * fh; | 104 | const struct nfs_fh * fh; |
104 | __u32 seqid; | 105 | struct nfs_seqid * seqid; |
105 | int open_flags; | 106 | int open_flags; |
106 | __u64 clientid; | 107 | __u64 clientid; |
107 | __u32 id; | 108 | __u32 id; |
@@ -136,7 +137,7 @@ struct nfs_openres { | |||
136 | struct nfs_open_confirmargs { | 137 | struct nfs_open_confirmargs { |
137 | const struct nfs_fh * fh; | 138 | const struct nfs_fh * fh; |
138 | nfs4_stateid stateid; | 139 | nfs4_stateid stateid; |
139 | __u32 seqid; | 140 | struct nfs_seqid * seqid; |
140 | }; | 141 | }; |
141 | 142 | ||
142 | struct nfs_open_confirmres { | 143 | struct nfs_open_confirmres { |
@@ -149,7 +150,7 @@ struct nfs_open_confirmres { | |||
149 | struct nfs_closeargs { | 150 | struct nfs_closeargs { |
150 | struct nfs_fh * fh; | 151 | struct nfs_fh * fh; |
151 | nfs4_stateid stateid; | 152 | nfs4_stateid stateid; |
152 | __u32 seqid; | 153 | struct nfs_seqid * seqid; |
153 | int open_flags; | 154 | int open_flags; |
154 | }; | 155 | }; |
155 | 156 | ||
@@ -165,15 +166,15 @@ struct nfs_lowner { | |||
165 | }; | 166 | }; |
166 | 167 | ||
167 | struct nfs_open_to_lock { | 168 | struct nfs_open_to_lock { |
168 | __u32 open_seqid; | 169 | struct nfs_seqid * open_seqid; |
169 | nfs4_stateid open_stateid; | 170 | nfs4_stateid open_stateid; |
170 | __u32 lock_seqid; | 171 | struct nfs_seqid * lock_seqid; |
171 | struct nfs_lowner lock_owner; | 172 | struct nfs_lowner lock_owner; |
172 | }; | 173 | }; |
173 | 174 | ||
174 | struct nfs_exist_lock { | 175 | struct nfs_exist_lock { |
175 | nfs4_stateid stateid; | 176 | nfs4_stateid stateid; |
176 | __u32 seqid; | 177 | struct nfs_seqid * seqid; |
177 | }; | 178 | }; |
178 | 179 | ||
179 | struct nfs_lock_opargs { | 180 | struct nfs_lock_opargs { |
@@ -186,7 +187,7 @@ struct nfs_lock_opargs { | |||
186 | }; | 187 | }; |
187 | 188 | ||
188 | struct nfs_locku_opargs { | 189 | struct nfs_locku_opargs { |
189 | __u32 seqid; | 190 | struct nfs_seqid * seqid; |
190 | nfs4_stateid stateid; | 191 | nfs4_stateid stateid; |
191 | }; | 192 | }; |
192 | 193 | ||