diff options
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 28 |
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; |