[PATCH] SUNRPC: Fix potential deadlock in RPC code
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 14 Mar 2006 05:20:48 +0000 (21:20 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Tue, 14 Mar 2006 15:57:18 +0000 (07:57 -0800)
In rpc_wake_up() and rpc_wake_up_status(), it is possible for the call to
__rpc_wake_up_task() to fail if another thread happens to be calling
rpc_wake_up_task() on the same rpc_task.

Problem noticed by Bruno Faccini.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
net/sunrpc/sched.c

index 802d4fe0f55cb5fc37b358b360a7bffb5ee3bbb5..e838d042f7f51e2f0ded4852ddc08441ba8ff687 100644 (file)
@@ -515,16 +515,14 @@ struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue)
  */
 void rpc_wake_up(struct rpc_wait_queue *queue)
 {
-       struct rpc_task *task;
-
+       struct rpc_task *task, *next;
        struct list_head *head;
+
        spin_lock_bh(&queue->lock);
        head = &queue->tasks[queue->maxpriority];
        for (;;) {
-               while (!list_empty(head)) {
-                       task = list_entry(head->next, struct rpc_task, u.tk_wait.list);
+               list_for_each_entry_safe(task, next, head, u.tk_wait.list)
                        __rpc_wake_up_task(task);
-               }
                if (head == &queue->tasks[0])
                        break;
                head--;
@@ -541,14 +539,13 @@ void rpc_wake_up(struct rpc_wait_queue *queue)
  */
 void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
 {
+       struct rpc_task *task, *next;
        struct list_head *head;
-       struct rpc_task *task;
 
        spin_lock_bh(&queue->lock);
        head = &queue->tasks[queue->maxpriority];
        for (;;) {
-               while (!list_empty(head)) {
-                       task = list_entry(head->next, struct rpc_task, u.tk_wait.list);
+               list_for_each_entry_safe(task, next, head, u.tk_wait.list) {
                        task->tk_status = status;
                        __rpc_wake_up_task(task);
                }