History

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 c05eecf636101dd4347b2d8fa457626bf0088e0a (SUNRPC: Don't allow low priority tasks to pre-empt higher priority ones).

Trond Myklebust committed 13 years ago

Commit edd2e361 parent ab225411 file · +17 −1Browse files

Unified · Split

net/sunrpc/sched.c+17−1
@@ -98,9 +98,25 @@ __rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task) · 97 unmodified lines
9898 list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list);
9999 }
100100
101+static void rpc_rotate_queue_owner(struct rpc_wait_queue *queue)
102+{
103+ struct list_head *q = &queue->tasks[queue->priority];
104+ struct rpc_task *task;
105+
106+ if (!list_empty(q)) {
107+ task = list_first_entry(q, struct rpc_task, u.tk_wait.list);
108+ if (task->tk_owner == queue->owner)
109+ list_move_tail(&task->u.tk_wait.list, q);
110+ }
111+}
112+
101113 static void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority)
102114 {
103− queue->priority = priority;
115+ if (queue->priority != priority) {
116+ /* Fairness: rotate the list when changing priority */
117+ rpc_rotate_queue_owner(queue);
118+ queue->priority = priority;
119+ }
104120 }
105121
106122 static void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid)