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
585630static 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