aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-18 17:20:12 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-18 17:20:12 -0400
commitcee54fc944422c44e476736c045a9e8053cb0644 (patch)
tree95f4728b3ffa8a2456727b10cd3a68f2a3065415 /fs/nfs
parent5e5ce5be6f0161d2a069a4f8a1154fe639c5c02f (diff)
NFSv4: Add functions to order RPC calls
NFSv4 file state-changing functions such as OPEN, CLOSE, LOCK,... are all labelled with "sequence identifiers" in order to prevent the server from reordering RPC requests, as this could cause its file state to become out of sync with the client. Currently the NFS client code enforces this ordering locally using semaphores to restrict access to structures until the RPC call is done. This, of course, only works with synchronous RPC calls, since the user process must first grab the semaphore. By dropping semaphores, and instead teaching the RPC engine to hold the RPC calls until they are ready to be sent, we can extend this process to work nicely with asynchronous RPC calls too. This patch adds a new list called "rpc_sequence" that defines the order of the RPC calls to be sent. We add one such list for each state_owner. When an RPC call is ready to be sent, it checks if it is top of the rpc_sequence list. If so, it proceeds. If not, it goes back to sleep, and loops until it hits top of the list. Once the RPC call has completed, it can then bump the sequence id counter, and remove itself from the rpc_sequence list, and then wake up the next sleeper. Note that the state_owner sequence ids and lock_owner sequence ids are all indexed to the same rpc_sequence list, so OPEN, LOCK,... requests are all ordered w.r.t. each other. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4_fs.h42
-rw-r--r--fs/nfs/nfs4proc.c111
-rw-r--r--fs/nfs/nfs4state.c145
-rw-r--r--fs/nfs/nfs4xdr.c43
4 files changed, 265 insertions, 76 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 */
99struct 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
106struct nfs_seqid_counter {
107 struct rpc_sequence *sequence;
108 int flags;
109 u32 counter;
110};
111
112struct nfs_seqid {
113 struct list_head list;
114 struct nfs_seqid_counter *sequence;
115 struct rpc_task *task;
116};
117
118static 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
224extern void nfs4_put_open_state(struct nfs4_state *); 254extern void nfs4_put_open_state(struct nfs4_state *);
225extern void nfs4_close_state(struct nfs4_state *, mode_t); 255extern void nfs4_close_state(struct nfs4_state *, mode_t);
226extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode); 256extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode);
227extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp);
228extern void nfs4_schedule_state_recovery(struct nfs4_client *); 257extern void nfs4_schedule_state_recovery(struct nfs4_client *);
229extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); 258extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
230extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls);
231extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); 259extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
232 260
261extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter);
262extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task);
263extern void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid);
264extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid);
265extern void nfs_free_seqid(struct nfs_seqid *seqid);
266
233extern const nfs4_stateid zero_stateid; 267extern 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);
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 = &el; 2850 largs.u.exist_lock = &el;
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/* 677struct 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;
679void 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
693void 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 */
692void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp) 716static 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
738void 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 */
755void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid)
756{
757 return nfs_increment_seqid(status, seqid);
758}
759
760int 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
701static int reclaimer(void *); 775static 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
906static 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
834static int reclaimer(void *ptr) 926static 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);