From: Trond Myklebust Date: Tue, 14 Mar 2006 05:20:48 +0000 (-0800) Subject: [PATCH] SUNRPC: Fix potential deadlock in RPC code X-Git-Tag: v2.6.16~39 X-Git-Url: http://www.pilppa.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=e6d83d55698b73b4d5d55d3d7715a4c26030d577;p=linux-2.6-omap-h63xx.git [PATCH] SUNRPC: Fix potential deadlock in RPC code 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 Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 802d4fe0f55..e838d042f7f 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -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); }