]> git.neil.brown.name Git - history.git/commitdiff
NFSv4: Fix a list corruption in the NFSv4 state engine.
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Sat, 13 Mar 2004 17:01:26 +0000 (12:01 -0500)
committerTrond Myklebust <trond.myklebust@fys.uio.no>
Sat, 13 Mar 2004 17:01:26 +0000 (12:01 -0500)
fs/nfs/inode.c
fs/nfs/nfs4state.c

index 88c409df4e0e113dd2a9518afd7348eab085aabc..8f18c62476f90e4ef7b65a35d524a96140367c84 100644 (file)
@@ -1407,8 +1407,8 @@ static void nfs4_clear_inode(struct inode *inode)
                                inode->i_sb->s_id,
                                (long long)NFS_FILEID(inode),
                                state);
-               list_del(&state->inode_states);
-               nfs4_put_open_state(state);
+               BUG_ON(atomic_read(&state->count) != 1);
+               nfs4_close_state(state, state->state);
        }
        /* Now call standard NFS clear_inode() code */
        nfs_clear_inode(inode);
index 2be56d994d50a9c853aa02897d130f31377fa239..7d19679f6952af601cf504fe2ecd63f62f1b3608 100644 (file)
@@ -411,18 +411,20 @@ out:
        return state;
 }
 
-void
-nfs4_put_open_state(struct nfs4_state *state)
+static void
+__nfs4_put_open_state(struct nfs4_state *state)
 {
        struct inode *inode = state->inode;
        struct nfs4_state_owner *owner = state->owner;
        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;
-       list_del(&state->inode_states);
+       }
+       if (!list_empty(&state->inode_states))
+               list_del(&state->inode_states);
        spin_unlock(&inode->i_lock);
-       down(&owner->so_sema);
        list_del(&state->open_states);
        if (state->state != 0) {
                do {
@@ -439,6 +441,13 @@ nfs4_put_open_state(struct nfs4_state *state)
        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
 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);
                down(&owner->so_sema);
        } while (!status);
-       up(&owner->so_sema);
-       nfs4_put_open_state(state);
+       __nfs4_put_open_state(state);
 }
 
 /*