Commit a5210eec authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: Fix a list corruption in the NFSv4 state engine.

parent 8d2a4538
...@@ -1407,8 +1407,8 @@ static void nfs4_clear_inode(struct inode *inode) ...@@ -1407,8 +1407,8 @@ static void nfs4_clear_inode(struct inode *inode)
inode->i_sb->s_id, inode->i_sb->s_id,
(long long)NFS_FILEID(inode), (long long)NFS_FILEID(inode),
state); state);
list_del(&state->inode_states); BUG_ON(atomic_read(&state->count) != 1);
nfs4_put_open_state(state); nfs4_close_state(state, state->state);
} }
/* Now call standard NFS clear_inode() code */ /* Now call standard NFS clear_inode() code */
nfs_clear_inode(inode); nfs_clear_inode(inode);
......
...@@ -411,18 +411,20 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner) ...@@ -411,18 +411,20 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
return state; return state;
} }
void static void
nfs4_put_open_state(struct nfs4_state *state) __nfs4_put_open_state(struct nfs4_state *state)
{ {
struct inode *inode = state->inode; struct inode *inode = state->inode;
struct nfs4_state_owner *owner = state->owner; struct nfs4_state_owner *owner = state->owner;
int status = 0; int status = 0;
if (!atomic_dec_and_lock(&state->count, &inode->i_lock)) if (!atomic_dec_and_lock(&state->count, &inode->i_lock)) {
up(&owner->so_sema);
return; return;
}
if (!list_empty(&state->inode_states))
list_del(&state->inode_states); list_del(&state->inode_states);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
down(&owner->so_sema);
list_del(&state->open_states); list_del(&state->open_states);
if (state->state != 0) { if (state->state != 0) {
do { do {
...@@ -439,6 +441,13 @@ nfs4_put_open_state(struct nfs4_state *state) ...@@ -439,6 +441,13 @@ nfs4_put_open_state(struct nfs4_state *state)
nfs4_put_state_owner(owner); nfs4_put_state_owner(owner);
} }
void
nfs4_put_open_state(struct nfs4_state *state)
{
down(&state->owner->so_sema);
__nfs4_put_open_state(state);
}
void void
nfs4_close_state(struct nfs4_state *state, mode_t mode) nfs4_close_state(struct nfs4_state *state, mode_t mode)
{ {
...@@ -479,8 +488,7 @@ nfs4_close_state(struct nfs4_state *state, mode_t mode) ...@@ -479,8 +488,7 @@ nfs4_close_state(struct nfs4_state *state, mode_t mode)
status = nfs4_handle_error(NFS_SERVER(inode), status); status = nfs4_handle_error(NFS_SERVER(inode), status);
down(&owner->so_sema); down(&owner->so_sema);
} while (!status); } while (!status);
up(&owner->so_sema); __nfs4_put_open_state(state);
nfs4_put_open_state(state);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment