Skip to content

Commit 5b9f8ff

Browse files
Valentin SchneiderIngo Molnar
authored andcommitted
sched/debug: Output SD flag names rather than their values
Decoding the output of /proc/sys/kernel/sched_domain/cpu*/domain*/flags has always been somewhat annoying, as one needs to go fetch the bit -> name mapping from the source code itself. This encoding can be saved in a script somewhere, but that isn't safe from flags being added, removed or even shuffled around. What matters for debugging purposes is to get *which* flags are set in a given domain, their associated value is pretty much meaningless. Make the sd flags debug file output flag names. Signed-off-by: Valentin Schneider <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Acked-by: Peter Zijlstra <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 65c5e25 commit 5b9f8ff

File tree

1 file changed

+55
-1
lines changed

1 file changed

+55
-1
lines changed

kernel/sched/debug.c

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,60 @@ set_table_entry(struct ctl_table *entry,
245245
entry->proc_handler = proc_handler;
246246
}
247247

248+
static int sd_ctl_doflags(struct ctl_table *table, int write,
249+
void *buffer, size_t *lenp, loff_t *ppos)
250+
{
251+
unsigned long flags = *(unsigned long *)table->data;
252+
size_t data_size = 0;
253+
size_t len = 0;
254+
char *tmp;
255+
int idx;
256+
257+
if (write)
258+
return 0;
259+
260+
for_each_set_bit(idx, &flags, __SD_FLAG_CNT) {
261+
char *name = sd_flag_debug[idx].name;
262+
263+
/* Name plus whitespace */
264+
data_size += strlen(name) + 1;
265+
}
266+
267+
if (*ppos > data_size) {
268+
*lenp = 0;
269+
return 0;
270+
}
271+
272+
tmp = kcalloc(data_size + 1, sizeof(*tmp), GFP_KERNEL);
273+
if (!tmp)
274+
return -ENOMEM;
275+
276+
for_each_set_bit(idx, &flags, __SD_FLAG_CNT) {
277+
char *name = sd_flag_debug[idx].name;
278+
279+
len += snprintf(tmp + len, strlen(name) + 2, "%s ", name);
280+
}
281+
282+
tmp += *ppos;
283+
len -= *ppos;
284+
285+
if (len > *lenp)
286+
len = *lenp;
287+
if (len)
288+
memcpy(buffer, tmp, len);
289+
if (len < *lenp) {
290+
((char *)buffer)[len] = '\n';
291+
len++;
292+
}
293+
294+
*lenp = len;
295+
*ppos += len;
296+
297+
kfree(tmp);
298+
299+
return 0;
300+
}
301+
248302
static struct ctl_table *
249303
sd_alloc_ctl_domain_table(struct sched_domain *sd)
250304
{
@@ -258,7 +312,7 @@ sd_alloc_ctl_domain_table(struct sched_domain *sd)
258312
set_table_entry(&table[2], "busy_factor", &sd->busy_factor, sizeof(int), 0644, proc_dointvec_minmax);
259313
set_table_entry(&table[3], "imbalance_pct", &sd->imbalance_pct, sizeof(int), 0644, proc_dointvec_minmax);
260314
set_table_entry(&table[4], "cache_nice_tries", &sd->cache_nice_tries, sizeof(int), 0644, proc_dointvec_minmax);
261-
set_table_entry(&table[5], "flags", &sd->flags, sizeof(int), 0444, proc_dointvec_minmax);
315+
set_table_entry(&table[5], "flags", &sd->flags, sizeof(int), 0444, sd_ctl_doflags);
262316
set_table_entry(&table[6], "max_newidle_lb_cost", &sd->max_newidle_lb_cost, sizeof(long), 0644, proc_doulongvec_minmax);
263317
set_table_entry(&table[7], "name", sd->name, CORENAME_MAX_SIZE, 0444, proc_dostring);
264318
/* &table[8] is terminator */

0 commit comments

Comments
 (0)