SUNRPC: When changing the queue priority, ensure that we change the owner
This fixes a livelock in the xprt->sending queue where we end up never
making progress on lower priority tasks because sleep_on_priority()
keeps adding new tasks with the same owner to the head of the queue,
and priority bumps mean that we keep resetting the queue->owner to
whatever task is at the head of the queue.
Regression introduced by commit c05eecf636
(SUNRPC: Don't allow low priority tasks to pre-empt higher priority ones).
Reported-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
ab22541782
commit
edd2e36fe8
|
@ -98,9 +98,25 @@ __rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
|
|||
list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list);
|
||||
}
|
||||
|
||||
static void rpc_rotate_queue_owner(struct rpc_wait_queue *queue)
|
||||
{
|
||||
struct list_head *q = &queue->tasks[queue->priority];
|
||||
struct rpc_task *task;
|
||||
|
||||
if (!list_empty(q)) {
|
||||
task = list_first_entry(q, struct rpc_task, u.tk_wait.list);
|
||||
if (task->tk_owner == queue->owner)
|
||||
list_move_tail(&task->u.tk_wait.list, q);
|
||||
}
|
||||
}
|
||||
|
||||
static void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority)
|
||||
{
|
||||
queue->priority = priority;
|
||||
if (queue->priority != priority) {
|
||||
/* Fairness: rotate the list when changing priority */
|
||||
rpc_rotate_queue_owner(queue);
|
||||
queue->priority = priority;
|
||||
}
|
||||
}
|
||||
|
||||
static void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid)
|
||||
|
|
Loading…
Reference in New Issue
Block a user