Pull release into acpica branch
[powerpc.git] / fs / nfs / nfs4state.c
index 2d5a6a2..5ef4c57 100644 (file)
@@ -69,10 +69,8 @@ init_nfsv4_state(struct nfs_server *server)
 void
 destroy_nfsv4_state(struct nfs_server *server)
 {
-       if (server->mnt_path) {
-               kfree(server->mnt_path);
-               server->mnt_path = NULL;
-       }
+       kfree(server->mnt_path);
+       server->mnt_path = NULL;
        if (server->nfs4_state) {
                nfs4_put_client(server->nfs4_state);
                server->nfs4_state = NULL;
@@ -311,8 +309,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
                new = NULL;
        }
        spin_unlock(&clp->cl_lock);
-       if (new)
-               kfree(new);
+       kfree(new);
        if (sp != NULL)
                return sp;
        put_rpccred(cred);
@@ -366,30 +363,21 @@ nfs4_alloc_open_state(void)
        return state;
 }
 
-static struct nfs4_state *
-__nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode)
+void
+nfs4_state_set_mode_locked(struct nfs4_state *state, mode_t mode)
 {
-       struct nfs_inode *nfsi = NFS_I(inode);
-       struct nfs4_state *state;
-
-       mode &= (FMODE_READ|FMODE_WRITE);
-       list_for_each_entry(state, &nfsi->open_states, inode_states) {
-               if (state->owner->so_cred != cred)
-                       continue;
-               if ((mode & FMODE_READ) != 0 && state->nreaders == 0)
-                       continue;
-               if ((mode & FMODE_WRITE) != 0 && state->nwriters == 0)
-                       continue;
-               if ((state->state & mode) != mode)
-                       continue;
-               atomic_inc(&state->count);
-               if (mode & FMODE_READ)
-                       state->nreaders++;
+       if (state->state == mode)
+               return;
+       /* NB! List reordering - see the reclaim code for why.  */
+       if ((mode & FMODE_WRITE) != (state->state & FMODE_WRITE)) {
                if (mode & FMODE_WRITE)
-                       state->nwriters++;
-               return state;
+                       list_move(&state->open_states, &state->owner->so_states);
+               else
+                       list_move_tail(&state->open_states, &state->owner->so_states);
        }
-       return NULL;
+       if (mode == 0)
+               list_del_init(&state->inode_states);
+       state->state = mode;
 }
 
 static struct nfs4_state *
@@ -400,7 +388,7 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
 
        list_for_each_entry(state, &nfsi->open_states, inode_states) {
                /* Is this in the process of being freed? */
-               if (state->nreaders == 0 && state->nwriters == 0)
+               if (state->state == 0)
                        continue;
                if (state->owner == owner) {
                        atomic_inc(&state->count);
@@ -410,17 +398,6 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
        return NULL;
 }
 
-struct nfs4_state *
-nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode)
-{
-       struct nfs4_state *state;
-
-       spin_lock(&inode->i_lock);
-       state = __nfs4_find_state(inode, cred, mode);
-       spin_unlock(&inode->i_lock);
-       return state;
-}
-
 static void
 nfs4_free_open_state(struct nfs4_state *state)
 {
@@ -481,7 +458,6 @@ void nfs4_put_open_state(struct nfs4_state *state)
        spin_unlock(&inode->i_lock);
        spin_unlock(&owner->so_lock);
        iput(inode);
-       BUG_ON (state->state != 0);
        nfs4_free_open_state(state);
        nfs4_put_state_owner(owner);
 }
@@ -493,7 +469,7 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
 {
        struct inode *inode = state->inode;
        struct nfs4_state_owner *owner = state->owner;
-       int newstate;
+       int oldstate, newstate = 0;
 
        atomic_inc(&owner->so_count);
        /* Protect against nfs4_find_state() */
@@ -503,30 +479,20 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
                state->nreaders--;
        if (mode & FMODE_WRITE)
                state->nwriters--;
-       if (state->nwriters == 0) {
-               if (state->nreaders == 0)
-                       list_del_init(&state->inode_states);
-               /* See reclaim code */
-               list_move_tail(&state->open_states, &owner->so_states);
+       oldstate = newstate = state->state;
+       if (state->nreaders == 0)
+               newstate &= ~FMODE_READ;
+       if (state->nwriters == 0)
+               newstate &= ~FMODE_WRITE;
+       if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
+               nfs4_state_set_mode_locked(state, newstate);
+               oldstate = newstate;
        }
        spin_unlock(&inode->i_lock);
        spin_unlock(&owner->so_lock);
-       newstate = 0;
-       if (state->state != 0) {
-               if (state->nreaders)
-                       newstate |= FMODE_READ;
-               if (state->nwriters)
-                       newstate |= FMODE_WRITE;
-               if (state->state == newstate)
-                       goto out;
-               if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
-                       state->state = newstate;
-                       goto out;
-               }
-               if (nfs4_do_close(inode, state, newstate) == 0)
-                       return;
-       }
-out:
+
+       if (oldstate != newstate && nfs4_do_close(inode, state) == 0)
+               return;
        nfs4_put_open_state(state);
        nfs4_put_state_owner(owner);
 }
@@ -678,12 +644,15 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f
 
 struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
 {
+       struct rpc_sequence *sequence = counter->sequence;
        struct nfs_seqid *new;
 
        new = kmalloc(sizeof(*new), GFP_KERNEL);
        if (new != NULL) {
                new->sequence = counter;
-               INIT_LIST_HEAD(&new->list);
+               spin_lock(&sequence->lock);
+               list_add_tail(&new->list, &sequence->list);
+               spin_unlock(&sequence->lock);
        }
        return new;
 }
@@ -692,12 +661,10 @@ void nfs_free_seqid(struct nfs_seqid *seqid)
 {
        struct rpc_sequence *sequence = seqid->sequence->sequence;
 
-       if (!list_empty(&seqid->list)) {
-               spin_lock(&sequence->lock);
-               list_del(&seqid->list);
-               spin_unlock(&sequence->lock);
-       }
-       rpc_wake_up_next(&sequence->wait);
+       spin_lock(&sequence->lock);
+       list_del(&seqid->list);
+       spin_unlock(&sequence->lock);
+       rpc_wake_up(&sequence->wait);
        kfree(seqid);
 }
 
@@ -756,11 +723,10 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
        if (sequence->list.next == &seqid->list)
                goto out;
        spin_lock(&sequence->lock);
-       if (!list_empty(&sequence->list)) {
+       if (sequence->list.next != &seqid->list) {
                rpc_sleep_on(&sequence->wait, task, NULL, NULL);
                status = -EAGAIN;
-       } else
-               list_add(&seqid->list, &sequence->list);
+       }
        spin_unlock(&sequence->lock);
 out:
        return status;
@@ -815,7 +781,7 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s
        int status = 0;
 
        for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) {
-               if (!(fl->fl_flags & FL_POSIX))
+               if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
                        continue;
                if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state)
                        continue;
@@ -830,7 +796,7 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s
                        case -NFS4ERR_NO_GRACE:
                        case -NFS4ERR_RECLAIM_BAD:
                        case -NFS4ERR_RECLAIM_CONFLICT:
-                               /* kill_proc(fl->fl_owner, SIGLOST, 1); */
+                               /* kill_proc(fl->fl_pid, SIGLOST, 1); */
                                break;
                        case -NFS4ERR_STALE_CLIENTID:
                                goto out_err;