credit2: make sure we pick a runnable unit from the runq if there is one

A !runnable unit (temporarily) present in the runq may cause us to
stop scanning the runq itself too early. Of course, we don't run any
non-runnable vCPUs, but we end the scan and we fallback to picking
the idle unit. In other word, this prevent us to find there and pick
the actual unit that we're meant to start running (which might be
further ahead in the runq).

Depending on the vCPU pinning configuration, this may lead to such
unit to be stuck in the runq for long time, causing malfunctioning
inside the guest.

Fix this by checking runnable/non-runnable status up-front, in the runq
scanning function.

Reported-by: Michał Leszczyński <michal.leszczynski@cert.pl>
Reported-by: Dion Kant <g.w.kant@hunenet.nl>
Signed-off-by: Dario Faggioli <dfaggioli@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
This commit is contained in:
Dario Faggioli authored and George Dunlap committed 2021-06-07 13:16:36 +01:00
1 parent 75f13e9b22
commit 07b0eb5d0e
1 file changed
+5 -2
+5 -2
View File
@@ -3463,6 +3463,10 @@ runq_candidate(struct csched2_runqueue_data *rqd,
(unsigned char *)&d);
}
/* Skip non runnable units that we (temporarily) have in the runq */
if ( unlikely(!unit_runnable_state(svc->unit)) )
continue;
/* Only consider vcpus that are allowed to run on this processor. */
if ( !cpumask_test_cpu(cpu, svc->unit->cpu_hard_affinity) )
continue;
@@ -3496,8 +3500,7 @@ runq_candidate(struct csched2_runqueue_data *rqd,
* some budget, then choose it.
*/
if ( (yield || svc->credit > snext->credit) &&
(!has_cap(svc) || unit_grab_budget(svc)) &&
unit_runnable_state(svc->unit) )
(!has_cap(svc) || unit_grab_budget(svc)) )
snext = svc;
/* In any case, if we got this far, break. */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.