aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4_fs.h1
-rw-r--r--fs/nfs/nfs4proc.c2
-rw-r--r--fs/nfs/nfs4state.c20
3 files changed, 18 insertions, 5 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 5c0dd26d0985..78a53f5a9f18 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -126,6 +126,7 @@ static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status
126 * semantics by allowing the server to identify replayed requests. 126 * semantics by allowing the server to identify replayed requests.
127 */ 127 */
128struct nfs4_state_owner { 128struct nfs4_state_owner {
129 spinlock_t so_lock;
129 struct list_head so_list; /* per-clientid list of state_owners */ 130 struct list_head so_list; /* per-clientid list of state_owners */
130 struct nfs4_client *so_client; 131 struct nfs4_client *so_client;
131 u32 so_id; /* 32-bit identifier, unique */ 132 u32 so_id; /* 32-bit identifier, unique */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 2d9357cf3fc5..9c1da34036aa 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -212,6 +212,7 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid,
212 212
213 open_flags &= (FMODE_READ|FMODE_WRITE); 213 open_flags &= (FMODE_READ|FMODE_WRITE);
214 /* Protect against nfs4_find_state() */ 214 /* Protect against nfs4_find_state() */
215 spin_lock(&state->owner->so_lock);
215 spin_lock(&inode->i_lock); 216 spin_lock(&inode->i_lock);
216 state->state |= open_flags; 217 state->state |= open_flags;
217 /* NB! List reordering - see the reclaim code for why. */ 218 /* NB! List reordering - see the reclaim code for why. */
@@ -221,6 +222,7 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid,
221 state->nreaders++; 222 state->nreaders++;
222 memcpy(&state->stateid, stateid, sizeof(state->stateid)); 223 memcpy(&state->stateid, stateid, sizeof(state->stateid));
223 spin_unlock(&inode->i_lock); 224 spin_unlock(&inode->i_lock);
225 spin_unlock(&state->owner->so_lock);
224} 226}
225 227
226/* 228/*
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index c59ef90e956b..2d5a6a2b9dec 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -267,6 +267,7 @@ nfs4_alloc_state_owner(void)
267 sp = kzalloc(sizeof(*sp),GFP_KERNEL); 267 sp = kzalloc(sizeof(*sp),GFP_KERNEL);
268 if (!sp) 268 if (!sp)
269 return NULL; 269 return NULL;
270 spin_lock_init(&sp->so_lock);
270 INIT_LIST_HEAD(&sp->so_states); 271 INIT_LIST_HEAD(&sp->so_states);
271 INIT_LIST_HEAD(&sp->so_delegations); 272 INIT_LIST_HEAD(&sp->so_delegations);
272 rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue"); 273 rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue");
@@ -438,20 +439,23 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
438 if (state) 439 if (state)
439 goto out; 440 goto out;
440 new = nfs4_alloc_open_state(); 441 new = nfs4_alloc_open_state();
442 spin_lock(&owner->so_lock);
441 spin_lock(&inode->i_lock); 443 spin_lock(&inode->i_lock);
442 state = __nfs4_find_state_byowner(inode, owner); 444 state = __nfs4_find_state_byowner(inode, owner);
443 if (state == NULL && new != NULL) { 445 if (state == NULL && new != NULL) {
444 state = new; 446 state = new;
445 /* Note: The reclaim code dictates that we add stateless
446 * and read-only stateids to the end of the list */
447 list_add_tail(&state->open_states, &owner->so_states);
448 state->owner = owner; 447 state->owner = owner;
449 atomic_inc(&owner->so_count); 448 atomic_inc(&owner->so_count);
450 list_add(&state->inode_states, &nfsi->open_states); 449 list_add(&state->inode_states, &nfsi->open_states);
451 state->inode = igrab(inode); 450 state->inode = igrab(inode);
452 spin_unlock(&inode->i_lock); 451 spin_unlock(&inode->i_lock);
452 /* Note: The reclaim code dictates that we add stateless
453 * and read-only stateids to the end of the list */
454 list_add_tail(&state->open_states, &owner->so_states);
455 spin_unlock(&owner->so_lock);
453 } else { 456 } else {
454 spin_unlock(&inode->i_lock); 457 spin_unlock(&inode->i_lock);
458 spin_unlock(&owner->so_lock);
455 if (new) 459 if (new)
456 nfs4_free_open_state(new); 460 nfs4_free_open_state(new);
457 } 461 }
@@ -468,12 +472,14 @@ void nfs4_put_open_state(struct nfs4_state *state)
468 struct inode *inode = state->inode; 472 struct inode *inode = state->inode;
469 struct nfs4_state_owner *owner = state->owner; 473 struct nfs4_state_owner *owner = state->owner;
470 474
471 if (!atomic_dec_and_lock(&state->count, &inode->i_lock)) 475 if (!atomic_dec_and_lock(&state->count, &owner->so_lock))
472 return; 476 return;
477 spin_lock(&inode->i_lock);
473 if (!list_empty(&state->inode_states)) 478 if (!list_empty(&state->inode_states))
474 list_del(&state->inode_states); 479 list_del(&state->inode_states);
475 spin_unlock(&inode->i_lock);
476 list_del(&state->open_states); 480 list_del(&state->open_states);
481 spin_unlock(&inode->i_lock);
482 spin_unlock(&owner->so_lock);
477 iput(inode); 483 iput(inode);
478 BUG_ON (state->state != 0); 484 BUG_ON (state->state != 0);
479 nfs4_free_open_state(state); 485 nfs4_free_open_state(state);
@@ -491,6 +497,7 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
491 497
492 atomic_inc(&owner->so_count); 498 atomic_inc(&owner->so_count);
493 /* Protect against nfs4_find_state() */ 499 /* Protect against nfs4_find_state() */
500 spin_lock(&owner->so_lock);
494 spin_lock(&inode->i_lock); 501 spin_lock(&inode->i_lock);
495 if (mode & FMODE_READ) 502 if (mode & FMODE_READ)
496 state->nreaders--; 503 state->nreaders--;
@@ -503,6 +510,7 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
503 list_move_tail(&state->open_states, &owner->so_states); 510 list_move_tail(&state->open_states, &owner->so_states);
504 } 511 }
505 spin_unlock(&inode->i_lock); 512 spin_unlock(&inode->i_lock);
513 spin_unlock(&owner->so_lock);
506 newstate = 0; 514 newstate = 0;
507 if (state->state != 0) { 515 if (state->state != 0) {
508 if (state->nreaders) 516 if (state->nreaders)
@@ -899,6 +907,7 @@ static void nfs4_state_mark_reclaim(struct nfs4_client *clp)
899 list_for_each_entry(sp, &clp->cl_state_owners, so_list) { 907 list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
900 sp->so_seqid.counter = 0; 908 sp->so_seqid.counter = 0;
901 sp->so_seqid.flags = 0; 909 sp->so_seqid.flags = 0;
910 spin_lock(&sp->so_lock);
902 list_for_each_entry(state, &sp->so_states, open_states) { 911 list_for_each_entry(state, &sp->so_states, open_states) {
903 list_for_each_entry(lock, &state->lock_states, ls_locks) { 912 list_for_each_entry(lock, &state->lock_states, ls_locks) {
904 lock->ls_seqid.counter = 0; 913 lock->ls_seqid.counter = 0;
@@ -906,6 +915,7 @@ static void nfs4_state_mark_reclaim(struct nfs4_client *clp)
906 lock->ls_flags &= ~NFS_LOCK_INITIALIZED; 915 lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
907 } 916 }
908 } 917 }
918 spin_unlock(&sp->so_lock);
909 } 919 }
910} 920}
911 921