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 | |
| 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')
| -rw-r--r-- | fs/nfs/nfs4_fs.h | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 9 |
2 files changed, 1 insertions, 9 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 8a3788199052..45bff1d1a513 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
| @@ -112,7 +112,6 @@ struct nfs_seqid_counter { | |||
| 112 | struct nfs_seqid { | 112 | struct nfs_seqid { |
| 113 | struct list_head list; | 113 | struct list_head list; |
| 114 | struct nfs_seqid_counter *sequence; | 114 | struct nfs_seqid_counter *sequence; |
| 115 | struct rpc_task *task; | ||
| 116 | }; | 115 | }; |
| 117 | 116 | ||
| 118 | static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status) | 117 | static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status) |
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 | } |
