Skip to content

Commit 0c10f9c

Browse files
Fan Yuakpm00
authored andcommitted
tools/delaytop: improve error handling for missing PSI support
Enhanced display logic to conditionally show PSI information only when successfully read, with helpful guidance for users to enable PSI support (psi=1 cmdline parameter). Link: https://lkml.kernel.org/r/20250907001417537vSx6nUsb3ILqI0iQ-WnGp@zte.com.cn Signed-off-by: Fan Yu <fan.yu9@zte.com.cn> Reviewed-by: xu xin <xu.xin16@zte.com.cn> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 5e57515 commit 0c10f9c

1 file changed

Lines changed: 116 additions & 66 deletions

File tree

tools/accounting/delaytop.c

Lines changed: 116 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,11 @@
4444
#include <linux/cgroupstats.h>
4545
#include <stddef.h>
4646

47-
#define PSI_CPU_SOME "/proc/pressure/cpu"
48-
#define PSI_CPU_FULL "/proc/pressure/cpu"
49-
#define PSI_MEMORY_SOME "/proc/pressure/memory"
50-
#define PSI_MEMORY_FULL "/proc/pressure/memory"
51-
#define PSI_IO_SOME "/proc/pressure/io"
52-
#define PSI_IO_FULL "/proc/pressure/io"
53-
#define PSI_IRQ_FULL "/proc/pressure/irq"
47+
#define PSI_PATH "/proc/pressure"
48+
#define PSI_CPU_PATH "/proc/pressure/cpu"
49+
#define PSI_MEMORY_PATH "/proc/pressure/memory"
50+
#define PSI_IO_PATH "/proc/pressure/io"
51+
#define PSI_IRQ_PATH "/proc/pressure/irq"
5452

5553
#define NLA_NEXT(na) ((struct nlattr *)((char *)(na) + NLA_ALIGN((na)->nla_len)))
5654
#define NLA_DATA(na) ((void *)((char *)(na) + NLA_HDRLEN))
@@ -499,87 +497,134 @@ static int get_family_id(int sd)
499497
return id;
500498
}
501499

502-
static void read_psi_stats(void)
500+
static int read_psi_stats(void)
503501
{
504502
FILE *fp;
505503
char line[256];
506504
int ret = 0;
505+
int error_count = 0;
506+
507+
/* Check if PSI path exists */
508+
if (access(PSI_PATH, F_OK) != 0) {
509+
fprintf(stderr, "Error: PSI interface not found at %s\n", PSI_PATH);
510+
fprintf(stderr, "Please ensure your kernel supports PSI (Pressure Stall Information)\n");
511+
return -1;
512+
}
513+
507514
/* Zero all fields */
508515
memset(&psi, 0, sizeof(psi));
516+
509517
/* CPU pressure */
510-
fp = fopen(PSI_CPU_SOME, "r");
518+
fp = fopen(PSI_CPU_PATH, "r");
511519
if (fp) {
512520
while (fgets(line, sizeof(line), fp)) {
513521
if (strncmp(line, "some", 4) == 0) {
514522
ret = sscanf(line, "some avg10=%lf avg60=%lf avg300=%lf total=%llu",
515523
&psi.cpu_some_avg10, &psi.cpu_some_avg60,
516524
&psi.cpu_some_avg300, &psi.cpu_some_total);
517-
if (ret != 4)
525+
if (ret != 4) {
518526
fprintf(stderr, "Failed to parse CPU some PSI data\n");
527+
error_count++;
528+
}
519529
} else if (strncmp(line, "full", 4) == 0) {
520530
ret = sscanf(line, "full avg10=%lf avg60=%lf avg300=%lf total=%llu",
521531
&psi.cpu_full_avg10, &psi.cpu_full_avg60,
522532
&psi.cpu_full_avg300, &psi.cpu_full_total);
523-
if (ret != 4)
533+
if (ret != 4) {
524534
fprintf(stderr, "Failed to parse CPU full PSI data\n");
535+
error_count++;
536+
}
525537
}
526538
}
527539
fclose(fp);
540+
} else {
541+
fprintf(stderr, "Warning: Failed to open %s\n", PSI_CPU_PATH);
542+
error_count++;
528543
}
544+
529545
/* Memory pressure */
530-
fp = fopen(PSI_MEMORY_SOME, "r");
546+
fp = fopen(PSI_MEMORY_PATH, "r");
531547
if (fp) {
532548
while (fgets(line, sizeof(line), fp)) {
533549
if (strncmp(line, "some", 4) == 0) {
534550
ret = sscanf(line, "some avg10=%lf avg60=%lf avg300=%lf total=%llu",
535551
&psi.memory_some_avg10, &psi.memory_some_avg60,
536552
&psi.memory_some_avg300, &psi.memory_some_total);
537-
if (ret != 4)
553+
if (ret != 4) {
538554
fprintf(stderr, "Failed to parse Memory some PSI data\n");
555+
error_count++;
556+
}
539557
} else if (strncmp(line, "full", 4) == 0) {
540558
ret = sscanf(line, "full avg10=%lf avg60=%lf avg300=%lf total=%llu",
541559
&psi.memory_full_avg10, &psi.memory_full_avg60,
542560
&psi.memory_full_avg300, &psi.memory_full_total);
543-
}
544-
if (ret != 4)
561+
if (ret != 4) {
545562
fprintf(stderr, "Failed to parse Memory full PSI data\n");
563+
error_count++;
564+
}
565+
}
546566
}
547567
fclose(fp);
568+
} else {
569+
fprintf(stderr, "Warning: Failed to open %s\n", PSI_MEMORY_PATH);
570+
error_count++;
548571
}
572+
549573
/* IO pressure */
550-
fp = fopen(PSI_IO_SOME, "r");
574+
fp = fopen(PSI_IO_PATH, "r");
551575
if (fp) {
552576
while (fgets(line, sizeof(line), fp)) {
553577
if (strncmp(line, "some", 4) == 0) {
554578
ret = sscanf(line, "some avg10=%lf avg60=%lf avg300=%lf total=%llu",
555579
&psi.io_some_avg10, &psi.io_some_avg60,
556580
&psi.io_some_avg300, &psi.io_some_total);
557-
if (ret != 4)
581+
if (ret != 4) {
558582
fprintf(stderr, "Failed to parse IO some PSI data\n");
583+
error_count++;
584+
}
559585
} else if (strncmp(line, "full", 4) == 0) {
560586
ret = sscanf(line, "full avg10=%lf avg60=%lf avg300=%lf total=%llu",
561587
&psi.io_full_avg10, &psi.io_full_avg60,
562588
&psi.io_full_avg300, &psi.io_full_total);
563-
if (ret != 4)
589+
if (ret != 4) {
564590
fprintf(stderr, "Failed to parse IO full PSI data\n");
591+
error_count++;
592+
}
565593
}
566594
}
567595
fclose(fp);
596+
} else {
597+
fprintf(stderr, "Warning: Failed to open %s\n", PSI_IO_PATH);
598+
error_count++;
568599
}
600+
569601
/* IRQ pressure (only full) */
570-
fp = fopen(PSI_IRQ_FULL, "r");
602+
fp = fopen(PSI_IRQ_PATH, "r");
571603
if (fp) {
572604
while (fgets(line, sizeof(line), fp)) {
573605
if (strncmp(line, "full", 4) == 0) {
574606
ret = sscanf(line, "full avg10=%lf avg60=%lf avg300=%lf total=%llu",
575607
&psi.irq_full_avg10, &psi.irq_full_avg60,
576608
&psi.irq_full_avg300, &psi.irq_full_total);
577-
if (ret != 4)
609+
if (ret != 4) {
578610
fprintf(stderr, "Failed to parse IRQ full PSI data\n");
611+
error_count++;
612+
}
579613
}
580614
}
581615
fclose(fp);
616+
} else {
617+
fprintf(stderr, "Warning: Failed to open %s\n", PSI_IRQ_PATH);
618+
error_count++;
582619
}
620+
621+
/* Return error count: 0 means success, >0 means warnings, -1 means fatal error */
622+
if (error_count > 0) {
623+
fprintf(stderr, "PSI stats reading completed with %d warnings\n", error_count);
624+
return error_count;
625+
}
626+
627+
return 0;
583628
}
584629

585630
static int read_comm(int pid, char *comm_buf, size_t buf_size)
@@ -820,7 +865,7 @@ static void get_container_stats(void)
820865
}
821866

822867
/* Display results to stdout or log file */
823-
static void display_results(void)
868+
static void display_results(int psi_ret)
824869
{
825870
time_t now = time(NULL);
826871
struct tm *tm_now = localtime(&now);
@@ -833,49 +878,53 @@ static void display_results(void)
833878
suc &= BOOL_FPRINT(out, "\033[H\033[J");
834879

835880
/* PSI output (one-line, no cat style) */
836-
suc &= BOOL_FPRINT(out, "System Pressure Information: (avg10/avg60/avg300/total)\n");
837-
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
838-
"CPU some:",
839-
psi.cpu_some_avg10,
840-
psi.cpu_some_avg60,
841-
psi.cpu_some_avg300,
842-
psi.cpu_some_total / 1000);
843-
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
844-
"CPU full:",
845-
psi.cpu_full_avg10,
846-
psi.cpu_full_avg60,
847-
psi.cpu_full_avg300,
848-
psi.cpu_full_total / 1000);
849-
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
850-
"Memory full:",
851-
psi.memory_full_avg10,
852-
psi.memory_full_avg60,
853-
psi.memory_full_avg300,
854-
psi.memory_full_total / 1000);
855-
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
856-
"Memory some:",
857-
psi.memory_some_avg10,
858-
psi.memory_some_avg60,
859-
psi.memory_some_avg300,
860-
psi.memory_some_total / 1000);
861-
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
862-
"IO full:",
863-
psi.io_full_avg10,
864-
psi.io_full_avg60,
865-
psi.io_full_avg300,
866-
psi.io_full_total / 1000);
867-
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
868-
"IO some:",
869-
psi.io_some_avg10,
870-
psi.io_some_avg60,
871-
psi.io_some_avg300,
872-
psi.io_some_total / 1000);
873-
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
874-
"IRQ full:",
875-
psi.irq_full_avg10,
876-
psi.irq_full_avg60,
877-
psi.irq_full_avg300,
878-
psi.irq_full_total / 1000);
881+
suc &= BOOL_FPRINT(out, "System Pressure Information: (avg10/avg60vg300/total)\n");
882+
if (psi_ret) {
883+
suc &= BOOL_FPRINT(out, " PSI not found: check if psi=1 enabled in cmdline\n");
884+
} else {
885+
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
886+
"CPU some:",
887+
psi.cpu_some_avg10,
888+
psi.cpu_some_avg60,
889+
psi.cpu_some_avg300,
890+
psi.cpu_some_total / 1000);
891+
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
892+
"CPU full:",
893+
psi.cpu_full_avg10,
894+
psi.cpu_full_avg60,
895+
psi.cpu_full_avg300,
896+
psi.cpu_full_total / 1000);
897+
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
898+
"Memory full:",
899+
psi.memory_full_avg10,
900+
psi.memory_full_avg60,
901+
psi.memory_full_avg300,
902+
psi.memory_full_total / 1000);
903+
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
904+
"Memory some:",
905+
psi.memory_some_avg10,
906+
psi.memory_some_avg60,
907+
psi.memory_some_avg300,
908+
psi.memory_some_total / 1000);
909+
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
910+
"IO full:",
911+
psi.io_full_avg10,
912+
psi.io_full_avg60,
913+
psi.io_full_avg300,
914+
psi.io_full_total / 1000);
915+
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
916+
"IO some:",
917+
psi.io_some_avg10,
918+
psi.io_some_avg60,
919+
psi.io_some_avg300,
920+
psi.io_some_total / 1000);
921+
suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT,
922+
"IRQ full:",
923+
psi.irq_full_avg10,
924+
psi.irq_full_avg60,
925+
psi.irq_full_avg300,
926+
psi.irq_full_total / 1000);
927+
}
879928

880929
if (cfg.container_path) {
881930
suc &= BOOL_FPRINT(out, "Container Information (%s):\n", cfg.container_path);
@@ -1017,6 +1066,7 @@ int main(int argc, char **argv)
10171066
{
10181067
const struct field_desc *field;
10191068
int iterations = 0;
1069+
int psi_ret = 0;
10201070
char keypress;
10211071

10221072
/* Parse command line arguments */
@@ -1054,7 +1104,7 @@ int main(int argc, char **argv)
10541104
}
10551105

10561106
/* Read PSI statistics */
1057-
read_psi_stats();
1107+
psi_ret = read_psi_stats();
10581108

10591109
/* Get container stats if container path provided */
10601110
if (cfg.container_path)
@@ -1067,7 +1117,7 @@ int main(int argc, char **argv)
10671117
sort_tasks();
10681118

10691119
/* Display results to stdout or log file */
1070-
display_results();
1120+
display_results(psi_ret);
10711121

10721122
/* Check for iterations */
10731123
if (cfg.iterations > 0 && ++iterations >= cfg.iterations)

0 commit comments

Comments
 (0)