[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-ti33x-psp-3.2 / 3.2.14 / 0093-SUNRPC-We-must-not-use-list_for_each_entry_safe-in-r.patch
1 From cdc2a3f4e2494e413531264d3949ce6801123ad9 Mon Sep 17 00:00:00 2001
2 From: Trond Myklebust <Trond.Myklebust@netapp.com>
3 Date: Mon, 19 Mar 2012 13:39:35 -0400
4 Subject: [PATCH 093/147] SUNRPC: We must not use list_for_each_entry_safe()
5 in rpc_wake_up()
7 commit 540a0f7584169651f485e8ab67461fcb06934e38 upstream.
9 The problem is that for the case of priority queues, we
10 have to assume that __rpc_remove_wait_queue_priority will move new
11 elements from the tk_wait.links lists into the queue->tasks[] list.
12 We therefore cannot use list_for_each_entry_safe() on queue->tasks[],
13 since that will skip these new tasks that __rpc_remove_wait_queue_priority
14 is adding.
16 Without this fix, rpc_wake_up and rpc_wake_up_status will both fail
17 to wake up all functions on priority wait queues, which can result
18 in some nasty hangs.
20 Reported-by: Andy Adamson <andros@netapp.com>
21 Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
22 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
23 ---
24 net/sunrpc/sched.c | 15 +++++++++++----
25 1 file changed, 11 insertions(+), 4 deletions(-)
27 diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
28 index 00a1a2a..4e2b3b4 100644
29 --- a/net/sunrpc/sched.c
30 +++ b/net/sunrpc/sched.c
31 @@ -500,14 +500,18 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_next);
32 */
33 void rpc_wake_up(struct rpc_wait_queue *queue)
34 {
35 - struct rpc_task *task, *next;
36 struct list_head *head;
38 spin_lock_bh(&queue->lock);
39 head = &queue->tasks[queue->maxpriority];
40 for (;;) {
41 - list_for_each_entry_safe(task, next, head, u.tk_wait.list)
42 + while (!list_empty(head)) {
43 + struct rpc_task *task;
44 + task = list_first_entry(head,
45 + struct rpc_task,
46 + u.tk_wait.list);
47 rpc_wake_up_task_queue_locked(queue, task);
48 + }
49 if (head == &queue->tasks[0])
50 break;
51 head--;
52 @@ -525,13 +529,16 @@ EXPORT_SYMBOL_GPL(rpc_wake_up);
53 */
54 void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
55 {
56 - struct rpc_task *task, *next;
57 struct list_head *head;
59 spin_lock_bh(&queue->lock);
60 head = &queue->tasks[queue->maxpriority];
61 for (;;) {
62 - list_for_each_entry_safe(task, next, head, u.tk_wait.list) {
63 + while (!list_empty(head)) {
64 + struct rpc_task *task;
65 + task = list_first_entry(head,
66 + struct rpc_task,
67 + u.tk_wait.list);
68 task->tk_status = status;
69 rpc_wake_up_task_queue_locked(queue, task);
70 }
71 --
72 1.7.9.4