Re: [PATCH] SUNRPC: We must not use list_for_each_entry_safe() in rpc_wake_up()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Andy Adamson<andros@xxxxxxxxxx>

-->Andy

On Mar 19, 2012, at 2:16 PM, Trond Myklebust wrote:

> The problem is that for the case of priority queues, we
> have to assume that __rpc_remove_wait_queue_priority will move new
> elements from the tk_wait.links lists into the queue->tasks[] list.
> We therefore cannot use list_for_each_entry_safe() on queue->tasks[],
> since that will skip these new tasks that __rpc_remove_wait_queue_priority
> is adding.
> 
> Without this fix, rpc_wake_up and rpc_wake_up_status will both fail
> to wake up all functions on priority wait queues, which can result
> in some nasty hangs.
> 
> Reported-by: Andy Adamson <andros@xxxxxxxxxx>
> Signed-off-by: Trond Myklebust <Trond.Myklebust@xxxxxxxxxx>
> Cc: stable@xxxxxxxxxxxxxxx
> ---
> net/sunrpc/sched.c |   15 +++++++++++----
> 1 files changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
> index 1c570a8..994cfea 100644
> --- a/net/sunrpc/sched.c

> +++ b/net/sunrpc/sched.c
> @@ -534,14 +534,18 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_next);
>  */
> void rpc_wake_up(struct rpc_wait_queue *queue)
> {
> -	struct rpc_task *task, *next;
> 	struct list_head *head;
> 
> 	spin_lock_bh(&queue->lock);
> 	head = &queue->tasks[queue->maxpriority];
> 	for (;;) {
> -		list_for_each_entry_safe(task, next, head, u.tk_wait.list)
> +		while (!list_empty(head)) {
> +			struct rpc_task *task;
> +			task = list_first_entry(head,
> +					struct rpc_task,
> +					u.tk_wait.list);
> 			rpc_wake_up_task_queue_locked(queue, task);
> +		}
> 		if (head == &queue->tasks[0])
> 			break;
> 		head--;
> @@ -559,13 +563,16 @@ EXPORT_SYMBOL_GPL(rpc_wake_up);
>  */
> void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
> {
> -	struct rpc_task *task, *next;
> 	struct list_head *head;
> 
> 	spin_lock_bh(&queue->lock);
> 	head = &queue->tasks[queue->maxpriority];
> 	for (;;) {
> -		list_for_each_entry_safe(task, next, head, u.tk_wait.list) {
> +		while (!list_empty(head)) {
> +			struct rpc_task *task;
> +			task = list_first_entry(head,
> +					struct rpc_task,
> +					u.tk_wait.list);
> 			task->tk_status = status;
> 			rpc_wake_up_task_queue_locked(queue, task);
> 		}
> -- 
> 1.7.7.6
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux