From b666915bc41d8b5720911d8d61eadd5c91aef4bf Mon Sep 17 00:00:00 2001 From: Than Ngo Date: Thu, 6 Aug 2026 12:14:45 +0200 Subject: [PATCH] Resolves: RHEL-223933, Use 30 secs timeout for each LMB removal kernel interface --- ...or-each-LMB-removal-kernel-interface.patch | 117 ++++++++++++------ powerpc-utils.spec | 5 +- 2 files changed, 85 insertions(+), 37 deletions(-) diff --git a/powerpc-utils-1.3.13-use-30-secs-timeout-for-each-LMB-removal-kernel-interface.patch b/powerpc-utils-1.3.13-use-30-secs-timeout-for-each-LMB-removal-kernel-interface.patch index b19336f..8345861 100644 --- a/powerpc-utils-1.3.13-use-30-secs-timeout-for-each-LMB-removal-kernel-interface.patch +++ b/powerpc-utils-1.3.13-use-30-secs-timeout-for-each-LMB-removal-kernel-interface.patch @@ -1,19 +1,23 @@ -The drmgr selects the removal LMB based on NUMA node ratio and -calls the kernel interface to remove the each selected LMB. Then -the kernel interface removes the LMB only after all pages are -isolated. But this page isolation can take longer which may affect -the memory removal process. The kernel interface returns to the -user space if sny signals are pending. +commit 4e9a9d74cbf7728e59858dccabc17e8cd24ff778 +Author: Haren Myneni +Date: Mon Aug 3 14:23:55 2026 -0700 -So do not allow the kernel interface execute more then 30 secs for -each LMB removal. Setup 30 secs timer and generate SIGUSR1 signal -for each kernel interface. - -Signed-off-by: Haren Myneni ---- - src/drmgr/common.c | 1 + - src/drmgr/drslot_chrp_mem.c | 68 +++++++++++++++++++++++++++++++++---- - 2 files changed, 63 insertions(+), 6 deletions(-) + drmgr: Use 30 secs timeout for each LMB removal kernel interface + + The drmgr selects the removal LMB based on NUMA node ratio and + calls the kernel interface for each selected LMB. Then the + kernel interface removes the LMB only after all pages are isolated. + But this page isolation can take longer which may affect the + memory removal process. The kernel interface returns to the user + space if any signals are pending. + + So do not allow the kernel interface to execute more than 30 secs + for each LMB removal. Setup 30 secs timer to generate SIGUSR1 + signal for each kernel interface call. + + Signed-off-by: Haren Myneni + [tyreld: zero .tv_nsec as well at disarm] + Signed-off-by: Tyrel Datwyler diff --git a/src/drmgr/common.c b/src/drmgr/common.c index 68041a9..70f5d3b 100644 @@ -28,10 +32,10 @@ index 68041a9..70f5d3b 100644 /* Now block all remaining signals */ rc = sigprocmask(SIG_SETMASK, &sigset, NULL); diff --git a/src/drmgr/drslot_chrp_mem.c b/src/drmgr/drslot_chrp_mem.c -index 4a3fe3a..ea8e8ce 100644 +index 4a3fe3a..c37c2dc 100644 --- a/src/drmgr/drslot_chrp_mem.c +++ b/src/drmgr/drslot_chrp_mem.c -@@ -39,6 +39,10 @@ +@@ -39,6 +39,16 @@ uint64_t block_sz_bytes = 0; static char *state_strs[] = {"offline", "online"}; sig_atomic_t numa_mem_timeout = 0; @@ -39,10 +43,16 @@ index 4a3fe3a..ea8e8ce 100644 +struct itimerspec lmb_tval; +struct sigevent lmb_sevent; +timer_t lmb_timer; ++ ++/* ++ * Timer to generate SIGUSR1 signal for each LMB removal ++ * kernel request ++ */ ++#define LMB_REMOVAL_TIMER_SECS 30 static char *usagestr = "-c mem {-a | -r} {-q -p {variable_weight | ent_capacity} | {-q | -s [ | ]}}"; -@@ -62,6 +66,15 @@ void mem_timeout_handler(int sig) +@@ -62,6 +72,16 @@ void mem_timeout_handler(int sig) numa_mem_timeout = 1; } @@ -52,13 +62,14 @@ index 4a3fe3a..ea8e8ce 100644 + */ +void lmb_rm_timeout_handler(int sig) +{ -+ if (sig == SIGUSR1) lmb_rm_timeout = 1; ++ if (sig == SIGUSR1) ++ lmb_rm_timeout = 1; +} + /** * report_resource_count * @brief Report the number of LMBs that were added or removed. -@@ -1461,12 +1474,36 @@ int valid_mem_options(void) +@@ -1461,12 +1481,46 @@ int valid_mem_options(void) static int remove_lmb_by_index(uint32_t drc_index) { char cmdbuf[128]; @@ -79,26 +90,57 @@ index 4a3fe3a..ea8e8ce 100644 + * the kernel request takes longer than 30 secs. + */ + lmb_rm_timeout = 0; -+ lmb_tval.it_value.tv_sec = 30; -+ timer_settime(lmb_timer, 0, &lmb_tval, NULL); ++ lmb_tval.it_value.tv_sec = LMB_REMOVAL_TIMER_SECS; ++ if (timer_settime(lmb_timer, 0, &lmb_tval, NULL)) { ++ say(ERROR, "Set LMB removal timer failed %s\n", ++ strerror(errno)); ++ return -errno; ++ } + + rc = do_kernel_dlpar_common(cmdbuf, offset, + 1 /* Don't report error */); + -+ if (!lmb_rm_timeout) { -+ /* -+ * Disable the timer if the kernel request returned before -+ * 30 secs interval. -+ */ -+ lmb_tval.it_value.tv_sec = 0; -+ timer_settime(lmb_timer, 0, &lmb_tval, NULL); -+ } ++ /* ++ * Disable the timer in case if the kernel request returned ++ * before 30 secs interval. ++ */ ++ lmb_tval.it_value.tv_sec = 0; ++ lmb_tval.it_value.tv_nsec = 0; ++ /* ++ * The caller of this function expects the return value 0 for ++ * LMB remove success and failure for other values. The success ++ * return is considered to increment the number of LMBs removed ++ * which is used to report the total removed LMBs to HMC. ++ * So do not consider the failure of disable timer. ++ */ ++ timer_settime(lmb_timer, 0, &lmb_tval, NULL); + + return rc; } static int remove_lmb_from_node(struct ppcnuma_node *node, uint32_t count) -@@ -1707,12 +1744,30 @@ static void clear_numa_lmb_links(void) +@@ -1483,10 +1537,16 @@ static int remove_lmb_from_node(struct ppcnuma_node *node, uint32_t count) + + unlinked++; + err = remove_lmb_by_index(lmb->drc_index); +- if (err) +- say(WARN, "Can't remove LMB node:%d index:0x%x: %s\n", +- node->node_id, lmb->drc_index, strerror(-err)); +- else ++ if (err) { ++ if (lmb_rm_timeout) ++ say(WARN, "LMB remove timeout. node:%d index:0x%x: %s\n", ++ node->node_id, lmb->drc_index, ++ strerror(-err)); ++ else ++ say(WARN, "Can't remove LMB node:%d index:0x%x: %s\n", ++ node->node_id, lmb->drc_index, ++ strerror(-err)); ++ } else + done++; + } + +@@ -1707,12 +1767,33 @@ static void clear_numa_lmb_links(void) * (with -w option). In the case of LMB removal, the kernel * interface can run longer until all pages in LMB are isolated * and can return to the user space if any pending signals. @@ -108,7 +150,7 @@ index 4a3fe3a..ea8e8ce 100644 + * make progress further. So setup SIGUSR1 30 secs timer for each + * LMB kernel removal request. + * -+ * This SIGALRM signal is used to exit drmgr in case if the complete ++ * This SIGUSR1 signal is used to exit drmgr in case if the complete + * memory removal process takes longer than the timeout value. */ static int drmem_timer_setup(void) @@ -119,20 +161,23 @@ index 4a3fe3a..ea8e8ce 100644 + lmb_sigact.sa_handler = lmb_rm_timeout_handler; + sigemptyset(&lmb_sigact.sa_mask); + lmb_sigact.sa_flags = 0; -+ sigaction(SIGUSR1, &lmb_sigact, NULL); ++ if (sigaction(SIGUSR1, &lmb_sigact, NULL)) ++ return -1; + + lmb_sevent.sigev_notify = SIGEV_SIGNAL; + lmb_sevent.sigev_signo = SIGUSR1; + lmb_sevent.sigev_value.sival_ptr = &lmb_timer; -+ timer_create(CLOCK_MONOTONIC, &lmb_sevent, &lmb_timer); -+ lmb_tval.it_value.tv_sec = 30; ++ if (timer_create(CLOCK_MONOTONIC, &lmb_sevent, &lmb_timer)) ++ return -1; ++ ++ lmb_tval.it_value.tv_sec = LMB_REMOVAL_TIMER_SECS; + lmb_tval.it_value.tv_nsec = 0; + lmb_tval.it_interval.tv_sec = 0; + lmb_tval.it_interval.tv_nsec = 0; if (!usr_timeout) return 0; -@@ -1770,6 +1825,7 @@ static int numa_based_remove(uint32_t count) +@@ -1770,6 +1851,7 @@ static int numa_based_remove(uint32_t count) out_free: free_lmbs(lmb_list); out_clear: diff --git a/powerpc-utils.spec b/powerpc-utils.spec index d2e24b7..f727943 100644 --- a/powerpc-utils.spec +++ b/powerpc-utils.spec @@ -1,6 +1,6 @@ Name: powerpc-utils Version: 1.3.13 -Release: 5%{?dist} +Release: 6%{?dist} Summary: PERL-based scripts for maintaining and servicing PowerPC systems License: GPL-2.0-only @@ -233,6 +233,9 @@ systemctl enable hcn-init.service >/dev/null 2>&1 || : %changelog +* Thu Aug 06 2026 Than Ngo - 1.3.13-6 +- Resolves: RHEL-223933, Use 30 secs timeout for each LMB removal kernel interface + * Thu Jul 16 2026 Than Ngo - 1.3.13-5 - Resolves: RHEL-138523, Add ability to display Resource group - Resolves: RHEL-184808, Dynamically removing cores from an LPAR is not taking care of NUMA topology