NFSv4: Fix an oopsable condition in nfs_free_seqid
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 19 Oct 2005 06:19:39 +0000 (23:19 -0700)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 19 Oct 2005 06:19:39 +0000 (23:19 -0700)
 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>
fs/nfs/nfs4_fs.h
fs/nfs/nfs4state.c

index 8a37881..45bff1d 100644 (file)
@@ -112,7 +112,6 @@ struct nfs_seqid_counter {
 struct nfs_seqid {
        struct list_head list;
        struct nfs_seqid_counter *sequence;
-       struct rpc_task *task;
 };
 
 static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status)
index 23834c8..da0861d 100644 (file)
@@ -676,7 +676,6 @@ struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
        new = kmalloc(sizeof(*new), GFP_KERNEL);
        if (new != NULL) {
                new->sequence = counter;
-               new->task = NULL;
                spin_lock(&sequence->lock);
                list_add_tail(&new->list, &sequence->list);
                spin_unlock(&sequence->lock);
@@ -687,15 +686,10 @@ struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
 void nfs_free_seqid(struct nfs_seqid *seqid)
 {
        struct rpc_sequence *sequence = seqid->sequence->sequence;
-       struct rpc_task *next = NULL;
 
        spin_lock(&sequence->lock);
        list_del(&seqid->list);
-       if (!list_empty(&sequence->list)) {
-               next = list_entry(sequence->list.next, struct nfs_seqid, list)->task;
-               if (next)
-                       rpc_wake_up_task(next);
-       }
+       rpc_wake_up(&sequence->wait);
        spin_unlock(&sequence->lock);
        kfree(seqid);
 }
@@ -754,7 +748,6 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
 
        spin_lock(&sequence->lock);
        if (sequence->list.next != &seqid->list) {
-               seqid->task = task;
                rpc_sleep_on(&sequence->wait, task, NULL, NULL);
                status = -EAGAIN;
        }