diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-10-19 02:19:39 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-10-19 02:19:39 -0400 |
commit | 7f709a48fa798cfa0f2f777c8752e12995054f78 (patch) | |
tree | fde5f4b4918205ba4c547ecaac95acbc8a37caa0 /fs/nfs/nfs4state.c | |
parent | cb1f7be73b6f708d4f4ce225a3bbc02908b729e4 (diff) |
NFSv4: Fix an oopsable condition in nfs_free_seqid
Storing a pointer to the struct rpc_task in the nfs_seqid is broken
since the nfs_seqid may be freed well after the task has been destroyed.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 9 |
1 files changed, 1 insertions, 8 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 23834c8fb740..da0861db57fb 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -676,7 +676,6 @@ struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) | |||
676 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 676 | new = kmalloc(sizeof(*new), GFP_KERNEL); |
677 | if (new != NULL) { | 677 | if (new != NULL) { |
678 | new->sequence = counter; | 678 | new->sequence = counter; |
679 | new->task = NULL; | ||
680 | spin_lock(&sequence->lock); | 679 | spin_lock(&sequence->lock); |
681 | list_add_tail(&new->list, &sequence->list); | 680 | list_add_tail(&new->list, &sequence->list); |
682 | spin_unlock(&sequence->lock); | 681 | spin_unlock(&sequence->lock); |
@@ -687,15 +686,10 @@ struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) | |||
687 | void nfs_free_seqid(struct nfs_seqid *seqid) | 686 | void nfs_free_seqid(struct nfs_seqid *seqid) |
688 | { | 687 | { |
689 | struct rpc_sequence *sequence = seqid->sequence->sequence; | 688 | struct rpc_sequence *sequence = seqid->sequence->sequence; |
690 | struct rpc_task *next = NULL; | ||
691 | 689 | ||
692 | spin_lock(&sequence->lock); | 690 | spin_lock(&sequence->lock); |
693 | list_del(&seqid->list); | 691 | list_del(&seqid->list); |
694 | if (!list_empty(&sequence->list)) { | 692 | rpc_wake_up(&sequence->wait); |
695 | next = list_entry(sequence->list.next, struct nfs_seqid, list)->task; | ||
696 | if (next) | ||
697 | rpc_wake_up_task(next); | ||
698 | } | ||
699 | spin_unlock(&sequence->lock); | 693 | spin_unlock(&sequence->lock); |
700 | kfree(seqid); | 694 | kfree(seqid); |
701 | } | 695 | } |
@@ -754,7 +748,6 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task) | |||
754 | 748 | ||
755 | spin_lock(&sequence->lock); | 749 | spin_lock(&sequence->lock); |
756 | if (sequence->list.next != &seqid->list) { | 750 | if (sequence->list.next != &seqid->list) { |
757 | seqid->task = task; | ||
758 | rpc_sleep_on(&sequence->wait, task, NULL, NULL); | 751 | rpc_sleep_on(&sequence->wait, task, NULL, NULL); |
759 | status = -EAGAIN; | 752 | status = -EAGAIN; |
760 | } | 753 | } |