@@ -2776,6 +2776,103 @@ util_unmap_all_hdrs(struct pool_set *set)
27762776 }
27772777}
27782778
2779+ /*
2780+ * util_ipmctl_log_dimm_shutdown_status -- query ipmctl for every DIMM's last
2781+ * shutdown time and shutdown status (both latched and unlatched) and report
2782+ * the output of each command via CORE_LOG_ERROR.
2783+ *
2784+ * Steps:
2785+ * 1. Run "ipmctl show -display DimmID -dimm" and collect all DimmID values
2786+ * from lines of the form ---DimmID=0x0001---.
2787+ * 2. For every discovered DimmID run three ipmctl queries and emit one
2788+ * CORE_LOG_ERROR entry per query containing the raw command output.
2789+ */
2790+ static void
2791+ util_ipmctl_log_dimm_shutdown_status (void )
2792+ {
2793+ /*
2794+ * Collect DimmID strings from "ipmctl show -display DimmID -dimm".
2795+ * A DimmID is always 6 characters (e.g. 0x0001) + NUL = 7 bytes.
2796+ */
2797+ #define IPMCTL_MAX_DIMMS 64
2798+ #define IPMCTL_DIMMID_LEN 7 /* "0x0001" + NUL */
2799+ #define IPMCTL_CMD_LEN 128
2800+ #define IPMCTL_OUTPUT_LEN 1024
2801+
2802+ char dimm_ids [IPMCTL_MAX_DIMMS ][IPMCTL_DIMMID_LEN ];
2803+ int ndimms = 0 ;
2804+
2805+ FILE * fp = popen ("ipmctl show -display DimmID -dimm" , "r" );
2806+ if (fp == NULL ) {
2807+ CORE_LOG_ERROR_W_ERRNO (
2808+ "popen failed: ipmctl show -display DimmID -dimm" );
2809+ return ;
2810+ }
2811+
2812+ char line [256 ];
2813+ while (fgets (line , sizeof (line ), fp ) != NULL ) {
2814+ char id [IPMCTL_DIMMID_LEN ];
2815+ /* match lines of the form ---DimmID=0x0001--- */
2816+ if (sscanf (line , "---DimmID=%6[^-]---" , id ) == 1 ) {
2817+ if (ndimms < IPMCTL_MAX_DIMMS ) {
2818+ memcpy (dimm_ids [ndimms ], id , IPMCTL_DIMMID_LEN );
2819+ ndimms ++ ;
2820+ } else {
2821+ CORE_LOG_ERROR (
2822+ "ipmctl DIMM count exceeds limit (%d); "
2823+ "remaining DIMMs skipped" ,
2824+ IPMCTL_MAX_DIMMS );
2825+ break ;
2826+ }
2827+ }
2828+ }
2829+ pclose (fp );
2830+
2831+ /* Three queries to run per DIMM, in order */
2832+ static const char * const queries [] = {
2833+ "LastShutdownTime" ,
2834+ "UnlatchedLastShutdownStatus" ,
2835+ "LatchedLastShutdownStatus" ,
2836+ };
2837+
2838+ for (int i = 0 ; i < ndimms ; i ++ ) {
2839+ for (size_t q = 0 ; q < ARRAY_SIZE (queries ); q ++ ) {
2840+ char cmd [IPMCTL_CMD_LEN ];
2841+ snprintf (cmd , sizeof (cmd ),
2842+ "ipmctl show -display %s -dimm %s" ,
2843+ queries [q ], dimm_ids [i ]);
2844+
2845+ FILE * qfp = popen (cmd , "r" );
2846+ if (qfp == NULL ) {
2847+ CORE_LOG_ERROR_W_ERRNO (
2848+ "popen failed: %s" , cmd );
2849+ continue ;
2850+ }
2851+
2852+ char output [IPMCTL_OUTPUT_LEN ];
2853+ if (fgets (output , sizeof (output ), qfp ) == NULL )
2854+ output [0 ] = '\0' ;
2855+
2856+ /* strip trailing newline */
2857+ size_t off = strlen (output );
2858+ while (off > 0 &&
2859+ (output [off - 1 ] == '\n' ||
2860+ output [off - 1 ] == '\r' )) {
2861+ output [-- off ] = '\0' ;
2862+ }
2863+
2864+ pclose (qfp );
2865+
2866+ CORE_LOG_ERROR ("DimmID=%s: %s" , dimm_ids [i ], output );
2867+ }
2868+ }
2869+
2870+ #undef IPMCTL_MAX_DIMMS
2871+ #undef IPMCTL_DIMMID_LEN
2872+ #undef IPMCTL_CMD_LEN
2873+ #undef IPMCTL_OUTPUT_LEN
2874+ }
2875+
27792876/*
27802877 * util_replica_check -- check headers, check UUID's, check replicas linkage
27812878 */
@@ -2833,6 +2930,7 @@ util_replica_check(struct pool_set *set, const struct pool_attr *attr)
28332930 if (shutdown_state_check (& sds , & HDR (rep , 0 )-> sds ,
28342931 rep )) {
28352932 CORE_LOG_ERROR ("ADR failure detected" );
2933+ util_ipmctl_log_dimm_shutdown_status ();
28362934 errno = EINVAL ;
28372935 return -1 ;
28382936 }
0 commit comments