sched,psi: Handle potential task count underflow bugs more gracefully
authorCharan Teja Reddy <charante@codeaurora.org>
Fri, 16 Apr 2021 15:02:16 +0000 (20:32 +0530)
committerPeter Zijlstra <peterz@infradead.org>
Wed, 21 Apr 2021 11:55:41 +0000 (13:55 +0200)
psi_group_cpu->tasks, represented by the unsigned int, stores the
number of tasks that could be stalled on a psi resource(io/mem/cpu).
Decrementing these counters at zero leads to wrapping which further
leads to the psi_group_cpu->state_mask is being set with the
respective pressure state. This could result into the unnecessary time
sampling for the pressure state thus cause the spurious psi events.
This can further lead to wrong actions being taken at the user land
based on these psi events.

Though psi_bug is set under these conditions but that just for debug
purpose. Fix it by decrementing the ->tasks count only when it is
non-zero.

Signed-off-by: Charan Teja Reddy <charante@codeaurora.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Link: https://lkml.kernel.org/r/1618585336-37219-1-git-send-email-charante@codeaurora.org
kernel/sched/psi.c

index d1212f17a8982975d0ec8d151ab16f033c22b60a..db27b69fa92a0756a0fe06d9b98f1f09573f66f7 100644 (file)
@@ -699,14 +699,15 @@ static void psi_group_change(struct psi_group *group, int cpu,
        for (t = 0, m = clear; m; m &= ~(1 << t), t++) {
                if (!(m & (1 << t)))
                        continue;
-               if (groupc->tasks[t] == 0 && !psi_bug) {
+               if (groupc->tasks[t]) {
+                       groupc->tasks[t]--;
+               } else if (!psi_bug) {
                        printk_deferred(KERN_ERR "psi: task underflow! cpu=%d t=%d tasks=[%u %u %u %u] clear=%x set=%x\n",
                                        cpu, t, groupc->tasks[0],
                                        groupc->tasks[1], groupc->tasks[2],
                                        groupc->tasks[3], clear, set);
                        psi_bug = 1;
                }
-               groupc->tasks[t]--;
        }
 
        for (t = 0; set; set &= ~(1 << t), t++)