aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-19 02:19:39 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-19 02:19:39 -0400
commit7f709a48fa798cfa0f2f777c8752e12995054f78 (patch)
treefde5f4b4918205ba4c547ecaac95acbc8a37caa0
parentcb1f7be73b6f708d4f4ce225a3bbc02908b729e4 (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>
-rw-r--r--fs/nfs/nfs4_fs.h1
-rw-r--r--fs/nfs/nfs4state.c9
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 {
112struct nfs_seqid { 112struct 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
118static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status) 117static 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)
687void nfs_free_seqid(struct nfs_seqid *seqid) 686void 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 }