| From: Fan Yu <fan.yu9@zte.com.cn> |
| Subject: tools/getdelays: add backward compatibility for taskstats version |
| Date: Thu, 31 Jul 2025 22:53:26 +0800 (CST) |
| |
| Add version checks to print_delayacct() to handle differences in struct |
| taskstats across kernel versions. Field availability depends on taskstats |
| version (t->version), corresponding to TASKSTATS_VERSION in kernel headers |
| (see include/uapi/linux/taskstats.h). |
| |
| Version feature mapping: |
| - version >= 11 - supports COMPACT statistics |
| - version >= 13 - supports WPCOPY statistics |
| - version >= 14 - supports IRQ statistics |
| - version >= 16 - supports *_max and *_min delay statistics |
| |
| This ensures the tool works correctly with both older and newer kernel |
| versions by conditionally printing fields based on the reported version. |
| |
| eg.1 |
| bash# grep -r "#define TASKSTATS_VERSION" /usr/include/linux/taskstats.h |
| "#define TASKSTATS_VERSION 10" |
| bash# ./getdelays -d -p 1 |
| CPU count real total virtual total delay total delay average |
| 7481 3786181709 3807098291 36393725 0.005ms |
| IO count delay total delay average |
| 369 1116046035 3.025ms |
| SWAP count delay total delay average |
| 0 0 0.000ms |
| RECLAIM count delay total delay average |
| 0 0 0.000ms |
| THRASHING count delay total delay average |
| 0 0 0.000ms |
| |
| eg.2 |
| bash# grep -r "#define TASKSTATS_VERSION" /usr/include/linux/taskstats.h |
| "#define TASKSTATS_VERSION 14" |
| bash# ./getdelays -d -p 1 |
| CPU count real total virtual total delay total delay average |
| 68862 163474790046 174584722267 19962496806 0.290ms |
| IO count delay total delay average |
| 0 0 0.000ms |
| SWAP count delay total delay average |
| 0 0 0.000ms |
| RECLAIM count delay total delay average |
| 0 0 0.000ms |
| THRASHING count delay total delay average |
| 0 0 0.000ms |
| COMPACT count delay total delay average |
| 0 0 0.000ms |
| WPCOPY count delay total delay average |
| 0 0 0.000ms |
| IRQ count delay total delay average |
| 0 0 0.000ms |
| |
| Link: https://lkml.kernel.org/r/20250731225326549CttJ7g9NfjTlaqBwl015T@zte.com.cn |
| Signed-off-by: Fan Yu <fan.yu9@zte.com.cn> |
| Cc: Fan Yu <fan.yu9@zte.com.cn> |
| Cc: Jonathan Corbet <corbet@lwn.net> |
| Cc: Wang Yaxin <wang.yaxin@zte.com.cn> |
| Cc: xu xin <xu.xin16@zte.com.cn> |
| Cc: Yang Yang <yang.yang29@zte.com.cn> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| tools/accounting/getdelays.c | 167 +++++++++++++++++++-------------- |
| 1 file changed, 100 insertions(+), 67 deletions(-) |
| |
| --- a/tools/accounting/getdelays.c~tools-getdelays-add-backward-compatibility-for-taskstats-version |
| +++ a/tools/accounting/getdelays.c |
| @@ -194,75 +194,108 @@ static int get_family_id(int sd) |
| #define average_ms(t, c) (t / 1000000ULL / (c ? c : 1)) |
| #define delay_ms(t) (t / 1000000ULL) |
| |
| +/* |
| + * Version compatibility note: |
| + * Field availability depends on taskstats version (t->version), |
| + * corresponding to TASKSTATS_VERSION in kernel headers |
| + * see include/uapi/linux/taskstats.h |
| + * |
| + * Version feature mapping: |
| + * version >= 11 - supports COMPACT statistics |
| + * version >= 13 - supports WPCOPY statistics |
| + * version >= 14 - supports IRQ statistics |
| + * version >= 16 - supports *_max and *_min delay statistics |
| + * |
| + * Always verify version before accessing version-dependent fields |
| + * to maintain backward compatibility. |
| + */ |
| +#define PRINT_CPU_DELAY(version, t) \ |
| + do { \ |
| + if (version >= 16) { \ |
| + printf("%-10s%15s%15s%15s%15s%15s%15s%15s\n", \ |
| + "CPU", "count", "real total", "virtual total", \ |
| + "delay total", "delay average", "delay max", "delay min"); \ |
| + printf(" %15llu%15llu%15llu%15llu%15.3fms%13.6fms%13.6fms\n", \ |
| + (unsigned long long)(t)->cpu_count, \ |
| + (unsigned long long)(t)->cpu_run_real_total, \ |
| + (unsigned long long)(t)->cpu_run_virtual_total, \ |
| + (unsigned long long)(t)->cpu_delay_total, \ |
| + average_ms((double)(t)->cpu_delay_total, (t)->cpu_count), \ |
| + delay_ms((double)(t)->cpu_delay_max), \ |
| + delay_ms((double)(t)->cpu_delay_min)); \ |
| + } else { \ |
| + printf("%-10s%15s%15s%15s%15s%15s\n", \ |
| + "CPU", "count", "real total", "virtual total", \ |
| + "delay total", "delay average"); \ |
| + printf(" %15llu%15llu%15llu%15llu%15.3fms\n", \ |
| + (unsigned long long)(t)->cpu_count, \ |
| + (unsigned long long)(t)->cpu_run_real_total, \ |
| + (unsigned long long)(t)->cpu_run_virtual_total, \ |
| + (unsigned long long)(t)->cpu_delay_total, \ |
| + average_ms((double)(t)->cpu_delay_total, (t)->cpu_count)); \ |
| + } \ |
| + } while (0) |
| +#define PRINT_FILED_DELAY(name, version, t, count, total, max, min) \ |
| + do { \ |
| + if (version >= 16) { \ |
| + printf("%-10s%15s%15s%15s%15s%15s\n", \ |
| + name, "count", "delay total", "delay average", \ |
| + "delay max", "delay min"); \ |
| + printf(" %15llu%15llu%15.3fms%13.6fms%13.6fms\n", \ |
| + (unsigned long long)(t)->count, \ |
| + (unsigned long long)(t)->total, \ |
| + average_ms((double)(t)->total, (t)->count), \ |
| + delay_ms((double)(t)->max), \ |
| + delay_ms((double)(t)->min)); \ |
| + } else { \ |
| + printf("%-10s%15s%15s%15s\n", \ |
| + name, "count", "delay total", "delay average"); \ |
| + printf(" %15llu%15llu%15.3fms\n", \ |
| + (unsigned long long)(t)->count, \ |
| + (unsigned long long)(t)->total, \ |
| + average_ms((double)(t)->total, (t)->count)); \ |
| + } \ |
| + } while (0) |
| + |
| static void print_delayacct(struct taskstats *t) |
| { |
| - printf("\n\nCPU %15s%15s%15s%15s%15s%15s%15s\n" |
| - " %15llu%15llu%15llu%15llu%15.3fms%13.6fms%13.6fms\n" |
| - "IO %15s%15s%15s%15s%15s\n" |
| - " %15llu%15llu%15.3fms%13.6fms%13.6fms\n" |
| - "SWAP %15s%15s%15s%15s%15s\n" |
| - " %15llu%15llu%15.3fms%13.6fms%13.6fms\n" |
| - "RECLAIM %12s%15s%15s%15s%15s\n" |
| - " %15llu%15llu%15.3fms%13.6fms%13.6fms\n" |
| - "THRASHING%12s%15s%15s%15s%15s\n" |
| - " %15llu%15llu%15.3fms%13.6fms%13.6fms\n" |
| - "COMPACT %12s%15s%15s%15s%15s\n" |
| - " %15llu%15llu%15.3fms%13.6fms%13.6fms\n" |
| - "WPCOPY %12s%15s%15s%15s%15s\n" |
| - " %15llu%15llu%15.3fms%13.6fms%13.6fms\n" |
| - "IRQ %15s%15s%15s%15s%15s\n" |
| - " %15llu%15llu%15.3fms%13.6fms%13.6fms\n", |
| - "count", "real total", "virtual total", |
| - "delay total", "delay average", "delay max", "delay min", |
| - (unsigned long long)t->cpu_count, |
| - (unsigned long long)t->cpu_run_real_total, |
| - (unsigned long long)t->cpu_run_virtual_total, |
| - (unsigned long long)t->cpu_delay_total, |
| - average_ms((double)t->cpu_delay_total, t->cpu_count), |
| - delay_ms((double)t->cpu_delay_max), |
| - delay_ms((double)t->cpu_delay_min), |
| - "count", "delay total", "delay average", "delay max", "delay min", |
| - (unsigned long long)t->blkio_count, |
| - (unsigned long long)t->blkio_delay_total, |
| - average_ms((double)t->blkio_delay_total, t->blkio_count), |
| - delay_ms((double)t->blkio_delay_max), |
| - delay_ms((double)t->blkio_delay_min), |
| - "count", "delay total", "delay average", "delay max", "delay min", |
| - (unsigned long long)t->swapin_count, |
| - (unsigned long long)t->swapin_delay_total, |
| - average_ms((double)t->swapin_delay_total, t->swapin_count), |
| - delay_ms((double)t->swapin_delay_max), |
| - delay_ms((double)t->swapin_delay_min), |
| - "count", "delay total", "delay average", "delay max", "delay min", |
| - (unsigned long long)t->freepages_count, |
| - (unsigned long long)t->freepages_delay_total, |
| - average_ms((double)t->freepages_delay_total, t->freepages_count), |
| - delay_ms((double)t->freepages_delay_max), |
| - delay_ms((double)t->freepages_delay_min), |
| - "count", "delay total", "delay average", "delay max", "delay min", |
| - (unsigned long long)t->thrashing_count, |
| - (unsigned long long)t->thrashing_delay_total, |
| - average_ms((double)t->thrashing_delay_total, t->thrashing_count), |
| - delay_ms((double)t->thrashing_delay_max), |
| - delay_ms((double)t->thrashing_delay_min), |
| - "count", "delay total", "delay average", "delay max", "delay min", |
| - (unsigned long long)t->compact_count, |
| - (unsigned long long)t->compact_delay_total, |
| - average_ms((double)t->compact_delay_total, t->compact_count), |
| - delay_ms((double)t->compact_delay_max), |
| - delay_ms((double)t->compact_delay_min), |
| - "count", "delay total", "delay average", "delay max", "delay min", |
| - (unsigned long long)t->wpcopy_count, |
| - (unsigned long long)t->wpcopy_delay_total, |
| - average_ms((double)t->wpcopy_delay_total, t->wpcopy_count), |
| - delay_ms((double)t->wpcopy_delay_max), |
| - delay_ms((double)t->wpcopy_delay_min), |
| - "count", "delay total", "delay average", "delay max", "delay min", |
| - (unsigned long long)t->irq_count, |
| - (unsigned long long)t->irq_delay_total, |
| - average_ms((double)t->irq_delay_total, t->irq_count), |
| - delay_ms((double)t->irq_delay_max), |
| - delay_ms((double)t->irq_delay_min)); |
| + printf("\n\n"); |
| + |
| + PRINT_CPU_DELAY(t->version, t); |
| + |
| + PRINT_FILED_DELAY("IO", t->version, t, |
| + blkio_count, blkio_delay_total, |
| + blkio_delay_max, blkio_delay_min); |
| + |
| + PRINT_FILED_DELAY("SWAP", t->version, t, |
| + swapin_count, swapin_delay_total, |
| + swapin_delay_max, swapin_delay_min); |
| + |
| + PRINT_FILED_DELAY("RECLAIM", t->version, t, |
| + freepages_count, freepages_delay_total, |
| + freepages_delay_max, freepages_delay_min); |
| + |
| + PRINT_FILED_DELAY("THRASHING", t->version, t, |
| + thrashing_count, thrashing_delay_total, |
| + thrashing_delay_max, thrashing_delay_min); |
| + |
| + if (t->version >= 11) { |
| + PRINT_FILED_DELAY("COMPACT", t->version, t, |
| + compact_count, compact_delay_total, |
| + compact_delay_max, compact_delay_min); |
| + } |
| + |
| + if (t->version >= 13) { |
| + PRINT_FILED_DELAY("WPCOPY", t->version, t, |
| + wpcopy_count, wpcopy_delay_total, |
| + wpcopy_delay_max, wpcopy_delay_min); |
| + } |
| + |
| + if (t->version >= 14) { |
| + PRINT_FILED_DELAY("IRQ", t->version, t, |
| + irq_count, irq_delay_total, |
| + irq_delay_max, irq_delay_min); |
| + } |
| } |
| |
| static void task_context_switch_counts(struct taskstats *t) |
| _ |