aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r--fs/nfs/nfs4state.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index ac816b303f3a..4f78c0d1eab5 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -412,7 +412,8 @@ void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
412{ 412{
413 struct inode *inode = state->inode; 413 struct inode *inode = state->inode;
414 struct nfs4_state_owner *owner = state->owner; 414 struct nfs4_state_owner *owner = state->owner;
415 int oldstate, newstate = 0; 415 int call_close = 0;
416 int newstate;
416 417
417 atomic_inc(&owner->so_count); 418 atomic_inc(&owner->so_count);
418 /* Protect against nfs4_find_state() */ 419 /* Protect against nfs4_find_state() */
@@ -428,21 +429,26 @@ void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
428 case FMODE_READ|FMODE_WRITE: 429 case FMODE_READ|FMODE_WRITE:
429 state->n_rdwr--; 430 state->n_rdwr--;
430 } 431 }
431 oldstate = newstate = state->state; 432 newstate = FMODE_READ|FMODE_WRITE;
432 if (state->n_rdwr == 0) { 433 if (state->n_rdwr == 0) {
433 if (state->n_rdonly == 0) 434 if (state->n_rdonly == 0) {
434 newstate &= ~FMODE_READ; 435 newstate &= ~FMODE_READ;
435 if (state->n_wronly == 0) 436 call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags);
437 call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
438 }
439 if (state->n_wronly == 0) {
436 newstate &= ~FMODE_WRITE; 440 newstate &= ~FMODE_WRITE;
441 call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags);
442 call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
443 }
444 if (newstate == 0)
445 clear_bit(NFS_DELEGATED_STATE, &state->flags);
437 } 446 }
438 if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { 447 nfs4_state_set_mode_locked(state, newstate);
439 nfs4_state_set_mode_locked(state, newstate);
440 oldstate = newstate;
441 }
442 spin_unlock(&inode->i_lock); 448 spin_unlock(&inode->i_lock);
443 spin_unlock(&owner->so_lock); 449 spin_unlock(&owner->so_lock);
444 450
445 if (oldstate == newstate) { 451 if (!call_close) {
446 nfs4_put_open_state(state); 452 nfs4_put_open_state(state);
447 nfs4_put_state_owner(owner); 453 nfs4_put_state_owner(owner);
448 } else 454 } else
@@ -838,6 +844,10 @@ static void nfs4_state_mark_reclaim(struct nfs_client *clp)
838 sp->so_seqid.flags = 0; 844 sp->so_seqid.flags = 0;
839 spin_lock(&sp->so_lock); 845 spin_lock(&sp->so_lock);
840 list_for_each_entry(state, &sp->so_states, open_states) { 846 list_for_each_entry(state, &sp->so_states, open_states) {
847 clear_bit(NFS_DELEGATED_STATE, &state->flags);
848 clear_bit(NFS_O_RDONLY_STATE, &state->flags);
849 clear_bit(NFS_O_WRONLY_STATE, &state->flags);
850 clear_bit(NFS_O_RDWR_STATE, &state->flags);
841 list_for_each_entry(lock, &state->lock_states, ls_locks) { 851 list_for_each_entry(lock, &state->lock_states, ls_locks) {
842 lock->ls_seqid.counter = 0; 852 lock->ls_seqid.counter = 0;
843 lock->ls_seqid.flags = 0; 853 lock->ls_seqid.flags = 0;