diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-11-25 17:09:57 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-11-25 17:11:28 -0500 |
commit | 36f20c6df75d599393d79c7feb6283b20913e3d5 (patch) | |
tree | 89b95044fe7342fd585f8ebfb62d816d46dc7f1d /fs/nfs/nfs4state.c | |
parent | af95598744a83506063b411d81c4f819bf774f62 (diff) |
NFSv4: Fix buggy nfs_wait_on_sequence()
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 0675f3215e0a..5ef4c57618fe 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -644,12 +644,15 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f | |||
644 | 644 | ||
645 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) | 645 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) |
646 | { | 646 | { |
647 | struct rpc_sequence *sequence = counter->sequence; | ||
647 | struct nfs_seqid *new; | 648 | struct nfs_seqid *new; |
648 | 649 | ||
649 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 650 | new = kmalloc(sizeof(*new), GFP_KERNEL); |
650 | if (new != NULL) { | 651 | if (new != NULL) { |
651 | new->sequence = counter; | 652 | new->sequence = counter; |
652 | INIT_LIST_HEAD(&new->list); | 653 | spin_lock(&sequence->lock); |
654 | list_add_tail(&new->list, &sequence->list); | ||
655 | spin_unlock(&sequence->lock); | ||
653 | } | 656 | } |
654 | return new; | 657 | return new; |
655 | } | 658 | } |
@@ -658,12 +661,10 @@ void nfs_free_seqid(struct nfs_seqid *seqid) | |||
658 | { | 661 | { |
659 | struct rpc_sequence *sequence = seqid->sequence->sequence; | 662 | struct rpc_sequence *sequence = seqid->sequence->sequence; |
660 | 663 | ||
661 | if (!list_empty(&seqid->list)) { | 664 | spin_lock(&sequence->lock); |
662 | spin_lock(&sequence->lock); | 665 | list_del(&seqid->list); |
663 | list_del(&seqid->list); | 666 | spin_unlock(&sequence->lock); |
664 | spin_unlock(&sequence->lock); | 667 | rpc_wake_up(&sequence->wait); |
665 | } | ||
666 | rpc_wake_up_next(&sequence->wait); | ||
667 | kfree(seqid); | 668 | kfree(seqid); |
668 | } | 669 | } |
669 | 670 | ||
@@ -722,11 +723,10 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task) | |||
722 | if (sequence->list.next == &seqid->list) | 723 | if (sequence->list.next == &seqid->list) |
723 | goto out; | 724 | goto out; |
724 | spin_lock(&sequence->lock); | 725 | spin_lock(&sequence->lock); |
725 | if (!list_empty(&sequence->list)) { | 726 | if (sequence->list.next != &seqid->list) { |
726 | rpc_sleep_on(&sequence->wait, task, NULL, NULL); | 727 | rpc_sleep_on(&sequence->wait, task, NULL, NULL); |
727 | status = -EAGAIN; | 728 | status = -EAGAIN; |
728 | } else | 729 | } |
729 | list_add(&seqid->list, &sequence->list); | ||
730 | spin_unlock(&sequence->lock); | 730 | spin_unlock(&sequence->lock); |
731 | out: | 731 | out: |
732 | return status; | 732 | return status; |