[PATCH v2 2/3] drmgr: Add timeout signal handling for NUMA memory REMOVE

19 views
Skip to first unread message

Haren Myneni

<haren@linux.ibm.com>
unread,
May 19, 2026, 1:38:12 AM (7 days ago) May 19
to powerpc-utils-devel@googlegroups.com, tyreld@linux.ibm.com, mmc@linux.ibm.com, davemarq@linux.ibm.com, hbabu@us.ibm.com, haren@linux.ibm.com
RMC expects drmgr timeout based on value passed with -w option and
drmgr can check fequently for each LMB removal request and exits
once reached the timeout value. But this check happens only in the
user space and does not consider when executes in the kernel to
remove memory. In the case of LMB removal, the kernel expects to
run longer until all pages in LMB are isolated and can return to
the user space for any pending signals.

This patch enables SIGALRM signal based on the user defined
value which generates signal when the timer expires. It allows
the kernel interface returns in case [age isolation is taking
longer and drmgr timeout.

Signed-off-by: Haren Myneni <ha...@linux.ibm.com>
---
src/drmgr/drslot_chrp_mem.c | 46 ++++++++++++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/src/drmgr/drslot_chrp_mem.c b/src/drmgr/drslot_chrp_mem.c
index fe04ad1..5a08839 100644
--- a/src/drmgr/drslot_chrp_mem.c
+++ b/src/drmgr/drslot_chrp_mem.c
@@ -26,6 +26,9 @@
#include <dirent.h>
#include <inttypes.h>
#include <time.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdbool.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include "dr.h"
@@ -35,6 +38,7 @@

uint64_t block_sz_bytes = 0;
static char *state_strs[] = {"offline", "online"};
+sig_atomic_t numa_mem_timeout = 0;

static char *usagestr = "-c mem {-a | -r} {-q <quantity> -p {variable_weight | ent_capacity} | {-q <quantity> | -s [<drc_name> | <drc_index>]}}";

@@ -50,6 +54,14 @@ mem_usage(char **pusage)
*pusage = usagestr;
}

+/*
+ * SIGALRM handler for drmgr timeout
+ */
+void mem_timeout_handler(int sig)
+{
+ numa_mem_timeout = 1;
+}
+
/**
* report_resource_count
* @brief Report the number of LMBs that were added or removed.
@@ -1681,13 +1693,45 @@ static void clear_numa_lmb_links(void)
node->lmbs = NULL;
}

+/*
+ * Setup SIGALRM signal based on timeout value passed by the user
+ * (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.
+ * This SIGALRM signal can exit the kernel in case LMB removal
+ * is taking longer than timeout.
+ */
+static int drmem_timer_setup(void)
+{
+ struct sigaction sigact;
+
+ if (!usr_timeout)
+ return 0;
+
+ sigact.sa_handler = mem_timeout_handler;
+ sigemptyset(&sigact.sa_mask);
+ sigact.sa_flags = 0;
+ if (sigaction(SIGALRM, &sigact, NULL))
+ return -1;
+
+ alarm(usr_timeout);
+ return 0;
+}
+
static int numa_based_remove(uint32_t count)
{
struct lmb_list_head *lmb_list;
struct ppcnuma_node *node;
- int nid;
+ int nid, rc = 0;
uint32_t done = 0;

+ /*
+ * Enable alarm signal handler for usr_timeout
+ */
+ rc = drmem_timer_setup();
+ if (rc)
+ return rc;
+
/*
* Read the LMBs
* Link the LMBs to their node
--
2.53.0

Haren Myneni

<haren@linux.ibm.com>
unread,
May 19, 2026, 1:38:13 AM (7 days ago) May 19
to powerpc-utils-devel@googlegroups.com, tyreld@linux.ibm.com, mmc@linux.ibm.com, davemarq@linux.ibm.com, hbabu@us.ibm.com, haren@linux.ibm.com
The current code uses sigdelset() to unblock some signals such as
SIGBUS, SIGALRM, and etc. But sigprocmask() with SIG_BLOCK sets
the union of this new set and the current sigset which ends up
blocking some of them (Ex: SIGALRM). Insted of using SIG_BLOCK,
SIG_SETMASK allows to use the complete new sigset_t.

Signed-off-by: Haren Myneni <ha...@linux.ibm.com>
---
src/drmgr/common.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/drmgr/common.c b/src/drmgr/common.c
index 70f4dfd..68041a9 100644
--- a/src/drmgr/common.c
+++ b/src/drmgr/common.c
@@ -939,7 +939,7 @@ sig_setup(void)
sigdelset(&sigset, SIGABRT);

/* Now block all remaining signals */
- rc = sigprocmask(SIG_BLOCK, &sigset, NULL);
+ rc = sigprocmask(SIG_SETMASK, &sigset, NULL);
if (rc)
return -1;

--
2.53.0

Haren Myneni

<haren@linux.ibm.com>
unread,
May 19, 2026, 1:38:15 AM (7 days ago) May 19
to powerpc-utils-devel@googlegroups.com, tyreld@linux.ibm.com, mmc@linux.ibm.com, davemarq@linux.ibm.com, hbabu@us.ibm.com, haren@linux.ibm.com
The current code selects LMBs from all NUMA node based on node
ratio and removes them until reaches the the requested limit. This
patch stops removing LMBs when receives SIGALRM signal based on
the user defined timeout.

Also reports total numaber of LMBs removed with DR_TOTAL_RESOURCES
to RMC even for partial memory removal or with an error.

Signed-off-by: Haren Myneni <ha...@linux.ibm.com>
---
src/drmgr/drslot_chrp_mem.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/src/drmgr/drslot_chrp_mem.c b/src/drmgr/drslot_chrp_mem.c
index 5a08839..4a3fe3a 100644
--- a/src/drmgr/drslot_chrp_mem.c
+++ b/src/drmgr/drslot_chrp_mem.c
@@ -1478,6 +1478,9 @@ static int remove_lmb_from_node(struct ppcnuma_node *node, uint32_t count)
count, node->n_lmbs, node->node_id);

for (lmb = node->lmbs; lmb && done < count; lmb = lmb->lmb_numa_next) {
+ if (numa_mem_timeout)
+ break;
+
unlinked++;
err = remove_lmb_by_index(lmb->drc_index);
if (err)
@@ -1563,6 +1566,9 @@ static int remove_cpuless_lmbs(uint32_t count)

this_loop = 0;
ppcnuma_foreach_node(&numa, nid, node) {
+ if (numa_mem_timeout)
+ break;
+
if (!node->n_lmbs || node->n_cpus)
continue;

@@ -1656,6 +1662,9 @@ static int remove_cpu_lmbs(uint32_t count)

this_loop = 0;
ppcnuma_foreach_node_by_ratio(&numa, node) {
+ if (numa_mem_timeout)
+ break;
+
if (!node->n_lmbs || !node->n_cpus)
continue;

@@ -1739,14 +1748,13 @@ static int numa_based_remove(uint32_t count)
*/
lmb_list = get_lmbs(LMB_NORMAL_SORT);
if (lmb_list == NULL) {
- clear_numa_lmb_links();
- return -1;
+ rc = -1;
+ goto out_clear;
}

if (!numa.node_count) {
- clear_numa_lmb_links();
- free_lmbs(lmb_list);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out_free;
}

ppcnuma_foreach_node(&numa, nid, node) {
@@ -1759,11 +1767,12 @@ static int numa_based_remove(uint32_t count)

done += remove_cpu_lmbs(count);

- report_resource_count(done);
-
- clear_numa_lmb_links();
+out_free:
free_lmbs(lmb_list);
- return 0;
+out_clear:
+ clear_numa_lmb_links();
+ report_resource_count(done);
+ return rc;
}

int do_mem_kernel_dlpar(void)
--
2.53.0

Tyrel Datwyler

<tyreld@linux.ibm.com>
unread,
May 20, 2026, 6:12:58 PM (5 days ago) May 20
to Haren Myneni, powerpc-utils-devel@googlegroups.com, mmc@linux.ibm.com, davemarq@linux.ibm.com, hbabu@us.ibm.com
On 5/18/26 10:37 PM, Haren Myneni wrote:
> The current code uses sigdelset() to unblock some signals such as
> SIGBUS, SIGALRM, and etc. But sigprocmask() with SIG_BLOCK sets
> the union of this new set and the current sigset which ends up
> blocking some of them (Ex: SIGALRM). Insted of using SIG_BLOCK,
> SIG_SETMASK allows to use the complete new sigset_t.
>
> Signed-off-by: Haren Myneni <ha...@linux.ibm.com>
> ---

Patches applied to powerpc-utils/next branch.

[1/3]
https://github.com/ibm-power-utilities/powerpc-utils/commit/3a7d0b61e7a5f364660007a45cc9dcf1c3cb5ab4

[2/3]
https://github.com/ibm-power-utilities/powerpc-utils/commit/1dee26c2a60dd9a5264331cc20143a5590289187

[3/3]
https://github.com/ibm-power-utilities/powerpc-utils/commit/7926241f576de24df8b342858f5278911e035658

Thanks,
-Tyrel
Reply all
Reply to author
Forward
0 new messages