Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Fan Yu and committed by
Andrew Morton
0c10f9cd 5e57515d

+116 -66
+116 -66
tools/accounting/delaytop.c
··· 44 44 #include <linux/cgroupstats.h> 45 45 #include <stddef.h> 46 46 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" 54 52 55 53 #define NLA_NEXT(na) ((struct nlattr *)((char *)(na) + NLA_ALIGN((na)->nla_len))) 56 54 #define NLA_DATA(na) ((void *)((char *)(na) + NLA_HDRLEN)) ··· 497 499 return id; 498 500 } 499 501 500 - static void read_psi_stats(void) 502 + static int read_psi_stats(void) 501 503 { 502 504 FILE *fp; 503 505 char line[256]; 504 506 int ret = 0; 507 + int error_count = 0; 508 + 509 + /* Check if PSI path exists */ 510 + if (access(PSI_PATH, F_OK) != 0) { 511 + fprintf(stderr, "Error: PSI interface not found at %s\n", PSI_PATH); 512 + fprintf(stderr, "Please ensure your kernel supports PSI (Pressure Stall Information)\n"); 513 + return -1; 514 + } 515 + 505 516 /* Zero all fields */ 506 517 memset(&psi, 0, sizeof(psi)); 518 + 507 519 /* CPU pressure */ 508 - fp = fopen(PSI_CPU_SOME, "r"); 520 + fp = fopen(PSI_CPU_PATH, "r"); 509 521 if (fp) { 510 522 while (fgets(line, sizeof(line), fp)) { 511 523 if (strncmp(line, "some", 4) == 0) { 512 524 ret = sscanf(line, "some avg10=%lf avg60=%lf avg300=%lf total=%llu", 513 525 &psi.cpu_some_avg10, &psi.cpu_some_avg60, 514 526 &psi.cpu_some_avg300, &psi.cpu_some_total); 515 - if (ret != 4) 527 + if (ret != 4) { 516 528 fprintf(stderr, "Failed to parse CPU some PSI data\n"); 529 + error_count++; 530 + } 517 531 } else if (strncmp(line, "full", 4) == 0) { 518 532 ret = sscanf(line, "full avg10=%lf avg60=%lf avg300=%lf total=%llu", 519 533 &psi.cpu_full_avg10, &psi.cpu_full_avg60, 520 534 &psi.cpu_full_avg300, &psi.cpu_full_total); 521 - if (ret != 4) 535 + if (ret != 4) { 522 536 fprintf(stderr, "Failed to parse CPU full PSI data\n"); 537 + error_count++; 538 + } 523 539 } 524 540 } 525 541 fclose(fp); 542 + } else { 543 + fprintf(stderr, "Warning: Failed to open %s\n", PSI_CPU_PATH); 544 + error_count++; 526 545 } 546 + 527 547 /* Memory pressure */ 528 - fp = fopen(PSI_MEMORY_SOME, "r"); 548 + fp = fopen(PSI_MEMORY_PATH, "r"); 529 549 if (fp) { 530 550 while (fgets(line, sizeof(line), fp)) { 531 551 if (strncmp(line, "some", 4) == 0) { 532 552 ret = sscanf(line, "some avg10=%lf avg60=%lf avg300=%lf total=%llu", 533 553 &psi.memory_some_avg10, &psi.memory_some_avg60, 534 554 &psi.memory_some_avg300, &psi.memory_some_total); 535 - if (ret != 4) 555 + if (ret != 4) { 536 556 fprintf(stderr, "Failed to parse Memory some PSI data\n"); 557 + error_count++; 558 + } 537 559 } else if (strncmp(line, "full", 4) == 0) { 538 560 ret = sscanf(line, "full avg10=%lf avg60=%lf avg300=%lf total=%llu", 539 561 &psi.memory_full_avg10, &psi.memory_full_avg60, 540 562 &psi.memory_full_avg300, &psi.memory_full_total); 541 - } 542 - if (ret != 4) 563 + if (ret != 4) { 543 564 fprintf(stderr, "Failed to parse Memory full PSI data\n"); 565 + error_count++; 566 + } 567 + } 544 568 } 545 569 fclose(fp); 570 + } else { 571 + fprintf(stderr, "Warning: Failed to open %s\n", PSI_MEMORY_PATH); 572 + error_count++; 546 573 } 574 + 547 575 /* IO pressure */ 548 - fp = fopen(PSI_IO_SOME, "r"); 576 + fp = fopen(PSI_IO_PATH, "r"); 549 577 if (fp) { 550 578 while (fgets(line, sizeof(line), fp)) { 551 579 if (strncmp(line, "some", 4) == 0) { 552 580 ret = sscanf(line, "some avg10=%lf avg60=%lf avg300=%lf total=%llu", 553 581 &psi.io_some_avg10, &psi.io_some_avg60, 554 582 &psi.io_some_avg300, &psi.io_some_total); 555 - if (ret != 4) 583 + if (ret != 4) { 556 584 fprintf(stderr, "Failed to parse IO some PSI data\n"); 585 + error_count++; 586 + } 557 587 } else if (strncmp(line, "full", 4) == 0) { 558 588 ret = sscanf(line, "full avg10=%lf avg60=%lf avg300=%lf total=%llu", 559 589 &psi.io_full_avg10, &psi.io_full_avg60, 560 590 &psi.io_full_avg300, &psi.io_full_total); 561 - if (ret != 4) 591 + if (ret != 4) { 562 592 fprintf(stderr, "Failed to parse IO full PSI data\n"); 593 + error_count++; 594 + } 563 595 } 564 596 } 565 597 fclose(fp); 598 + } else { 599 + fprintf(stderr, "Warning: Failed to open %s\n", PSI_IO_PATH); 600 + error_count++; 566 601 } 602 + 567 603 /* IRQ pressure (only full) */ 568 - fp = fopen(PSI_IRQ_FULL, "r"); 604 + fp = fopen(PSI_IRQ_PATH, "r"); 569 605 if (fp) { 570 606 while (fgets(line, sizeof(line), fp)) { 571 607 if (strncmp(line, "full", 4) == 0) { 572 608 ret = sscanf(line, "full avg10=%lf avg60=%lf avg300=%lf total=%llu", 573 609 &psi.irq_full_avg10, &psi.irq_full_avg60, 574 610 &psi.irq_full_avg300, &psi.irq_full_total); 575 - if (ret != 4) 611 + if (ret != 4) { 576 612 fprintf(stderr, "Failed to parse IRQ full PSI data\n"); 613 + error_count++; 614 + } 577 615 } 578 616 } 579 617 fclose(fp); 618 + } else { 619 + fprintf(stderr, "Warning: Failed to open %s\n", PSI_IRQ_PATH); 620 + error_count++; 580 621 } 622 + 623 + /* Return error count: 0 means success, >0 means warnings, -1 means fatal error */ 624 + if (error_count > 0) { 625 + fprintf(stderr, "PSI stats reading completed with %d warnings\n", error_count); 626 + return error_count; 627 + } 628 + 629 + return 0; 581 630 } 582 631 583 632 static int read_comm(int pid, char *comm_buf, size_t buf_size) ··· 865 820 } 866 821 867 822 /* Display results to stdout or log file */ 868 - static void display_results(void) 823 + static void display_results(int psi_ret) 869 824 { 870 825 time_t now = time(NULL); 871 826 struct tm *tm_now = localtime(&now); ··· 878 833 suc &= BOOL_FPRINT(out, "\033[H\033[J"); 879 834 880 835 /* PSI output (one-line, no cat style) */ 881 - suc &= BOOL_FPRINT(out, "System Pressure Information: (avg10/avg60/avg300/total)\n"); 882 - suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 883 - "CPU some:", 884 - psi.cpu_some_avg10, 885 - psi.cpu_some_avg60, 886 - psi.cpu_some_avg300, 887 - psi.cpu_some_total / 1000); 888 - suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 889 - "CPU full:", 890 - psi.cpu_full_avg10, 891 - psi.cpu_full_avg60, 892 - psi.cpu_full_avg300, 893 - psi.cpu_full_total / 1000); 894 - suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 895 - "Memory full:", 896 - psi.memory_full_avg10, 897 - psi.memory_full_avg60, 898 - psi.memory_full_avg300, 899 - psi.memory_full_total / 1000); 900 - suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 901 - "Memory some:", 902 - psi.memory_some_avg10, 903 - psi.memory_some_avg60, 904 - psi.memory_some_avg300, 905 - psi.memory_some_total / 1000); 906 - suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 907 - "IO full:", 908 - psi.io_full_avg10, 909 - psi.io_full_avg60, 910 - psi.io_full_avg300, 911 - psi.io_full_total / 1000); 912 - suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 913 - "IO some:", 914 - psi.io_some_avg10, 915 - psi.io_some_avg60, 916 - psi.io_some_avg300, 917 - psi.io_some_total / 1000); 918 - suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 919 - "IRQ full:", 920 - psi.irq_full_avg10, 921 - psi.irq_full_avg60, 922 - psi.irq_full_avg300, 923 - psi.irq_full_total / 1000); 836 + suc &= BOOL_FPRINT(out, "System Pressure Information: (avg10/avg60vg300/total)\n"); 837 + if (psi_ret) { 838 + suc &= BOOL_FPRINT(out, " PSI not found: check if psi=1 enabled in cmdline\n"); 839 + } else { 840 + suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 841 + "CPU some:", 842 + psi.cpu_some_avg10, 843 + psi.cpu_some_avg60, 844 + psi.cpu_some_avg300, 845 + psi.cpu_some_total / 1000); 846 + suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 847 + "CPU full:", 848 + psi.cpu_full_avg10, 849 + psi.cpu_full_avg60, 850 + psi.cpu_full_avg300, 851 + psi.cpu_full_total / 1000); 852 + suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 853 + "Memory full:", 854 + psi.memory_full_avg10, 855 + psi.memory_full_avg60, 856 + psi.memory_full_avg300, 857 + psi.memory_full_total / 1000); 858 + suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 859 + "Memory some:", 860 + psi.memory_some_avg10, 861 + psi.memory_some_avg60, 862 + psi.memory_some_avg300, 863 + psi.memory_some_total / 1000); 864 + suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 865 + "IO full:", 866 + psi.io_full_avg10, 867 + psi.io_full_avg60, 868 + psi.io_full_avg300, 869 + psi.io_full_total / 1000); 870 + suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 871 + "IO some:", 872 + psi.io_some_avg10, 873 + psi.io_some_avg60, 874 + psi.io_some_avg300, 875 + psi.io_some_total / 1000); 876 + suc &= BOOL_FPRINT(out, PSI_LINE_FORMAT, 877 + "IRQ full:", 878 + psi.irq_full_avg10, 879 + psi.irq_full_avg60, 880 + psi.irq_full_avg300, 881 + psi.irq_full_total / 1000); 882 + } 924 883 925 884 if (cfg.container_path) { 926 885 suc &= BOOL_FPRINT(out, "Container Information (%s):\n", cfg.container_path); ··· 1066 1017 { 1067 1018 const struct field_desc *field; 1068 1019 int iterations = 0; 1020 + int psi_ret = 0; 1069 1021 char keypress; 1070 1022 1071 1023 /* Parse command line arguments */ ··· 1104 1054 } 1105 1055 1106 1056 /* Read PSI statistics */ 1107 - read_psi_stats(); 1057 + psi_ret = read_psi_stats(); 1108 1058 1109 1059 /* Get container stats if container path provided */ 1110 1060 if (cfg.container_path) ··· 1117 1067 sort_tasks(); 1118 1068 1119 1069 /* Display results to stdout or log file */ 1120 - display_results(); 1070 + display_results(psi_ret); 1121 1071 1122 1072 /* Check for iterations */ 1123 1073 if (cfg.iterations > 0 && ++iterations >= cfg.iterations)