Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package powerpc-utils for openSUSE:Factory 
checked in at 2026-05-24 19:34:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/powerpc-utils (Old)
 and      /work/SRC/openSUSE:Factory/.powerpc-utils.new.2084 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "powerpc-utils"

Sun May 24 19:34:44 2026 rev:158 rq:1354721 version:1.3.14

Changes:
--------
--- /work/SRC/openSUSE:Factory/powerpc-utils/powerpc-utils.changes      
2026-04-28 14:30:46.511465913 +0200
+++ /work/SRC/openSUSE:Factory/.powerpc-utils.new.2084/powerpc-utils.changes    
2026-05-24 19:35:10.050083583 +0200
@@ -1,0 +2,16 @@
+Thu May 21 08:17:04 UTC 2026 - Michal Suchanek <[email protected]>
+
+- NUMA aware CPU hotplug (bsc#1263891 ltc#213837)
+  * 0001-drmgr-Update-cpuless_lmb_count-NUMA-counter-during-L.patch
+  * 0002-drmgr-Remove-only-available-LMBs-from-CPU-less-NUMA-.patch
+  * 0003-drmgr-Move-numa_topology-code-to-common_numa.c.patch
+  * 0004-drmgr-Move-read-lmb-size-property-code-to-common_ofd.patch
+  * 0005-drmgr-Add-get_next_cpu-to-identify-the-removable-CPU.patch
+  * 0006-drmgr-Allocate-CPU-bitmap-for-each-NUMA-node.patch
+  * 0007-drmgr-Add-NUMA-configuration-update-for-CPU-remove.patch
+  * 0008-drmgr-Add-NUMA-based-CPU-removal.patch
+  * 0009-drmgr-Allow-signals-mentioned-in-new-sigset_t.patch
+  * 0010-drmgr-Add-timeout-signal-handling-for-NUMA-memory-RE.patch 
(bsc#1265903 ltc#216658)
+  * 0011-drmgr-Do-not-remove-LMBs-when-the-timer-expires.patch
+
+-------------------------------------------------------------------

New:
----
  0001-drmgr-Update-cpuless_lmb_count-NUMA-counter-during-L.patch
  0002-drmgr-Remove-only-available-LMBs-from-CPU-less-NUMA-.patch
  0003-drmgr-Move-numa_topology-code-to-common_numa.c.patch
  0004-drmgr-Move-read-lmb-size-property-code-to-common_ofd.patch
  0005-drmgr-Add-get_next_cpu-to-identify-the-removable-CPU.patch
  0006-drmgr-Allocate-CPU-bitmap-for-each-NUMA-node.patch
  0007-drmgr-Add-NUMA-configuration-update-for-CPU-remove.patch
  0008-drmgr-Add-NUMA-based-CPU-removal.patch
  0009-drmgr-Allow-signals-mentioned-in-new-sigset_t.patch
  0010-drmgr-Add-timeout-signal-handling-for-NUMA-memory-RE.patch
  0011-drmgr-Do-not-remove-LMBs-when-the-timer-expires.patch

----------(New B)----------
  New:- NUMA aware CPU hotplug (bsc#1263891 ltc#213837)
  * 0001-drmgr-Update-cpuless_lmb_count-NUMA-counter-during-L.patch
  * 0002-drmgr-Remove-only-available-LMBs-from-CPU-less-NUMA-.patch
  New:  * 0001-drmgr-Update-cpuless_lmb_count-NUMA-counter-during-L.patch
  * 0002-drmgr-Remove-only-available-LMBs-from-CPU-less-NUMA-.patch
  * 0003-drmgr-Move-numa_topology-code-to-common_numa.c.patch
  New:  * 0002-drmgr-Remove-only-available-LMBs-from-CPU-less-NUMA-.patch
  * 0003-drmgr-Move-numa_topology-code-to-common_numa.c.patch
  * 0004-drmgr-Move-read-lmb-size-property-code-to-common_ofd.patch
  New:  * 0003-drmgr-Move-numa_topology-code-to-common_numa.c.patch
  * 0004-drmgr-Move-read-lmb-size-property-code-to-common_ofd.patch
  * 0005-drmgr-Add-get_next_cpu-to-identify-the-removable-CPU.patch
  New:  * 0004-drmgr-Move-read-lmb-size-property-code-to-common_ofd.patch
  * 0005-drmgr-Add-get_next_cpu-to-identify-the-removable-CPU.patch
  * 0006-drmgr-Allocate-CPU-bitmap-for-each-NUMA-node.patch
  New:  * 0005-drmgr-Add-get_next_cpu-to-identify-the-removable-CPU.patch
  * 0006-drmgr-Allocate-CPU-bitmap-for-each-NUMA-node.patch
  * 0007-drmgr-Add-NUMA-configuration-update-for-CPU-remove.patch
  New:  * 0006-drmgr-Allocate-CPU-bitmap-for-each-NUMA-node.patch
  * 0007-drmgr-Add-NUMA-configuration-update-for-CPU-remove.patch
  * 0008-drmgr-Add-NUMA-based-CPU-removal.patch
  New:  * 0007-drmgr-Add-NUMA-configuration-update-for-CPU-remove.patch
  * 0008-drmgr-Add-NUMA-based-CPU-removal.patch
  * 0009-drmgr-Allow-signals-mentioned-in-new-sigset_t.patch
  New:  * 0008-drmgr-Add-NUMA-based-CPU-removal.patch
  * 0009-drmgr-Allow-signals-mentioned-in-new-sigset_t.patch
  * 0010-drmgr-Add-timeout-signal-handling-for-NUMA-memory-RE.patch 
(bsc#1265903 ltc#216658)
  New:  * 0009-drmgr-Allow-signals-mentioned-in-new-sigset_t.patch
  * 0010-drmgr-Add-timeout-signal-handling-for-NUMA-memory-RE.patch 
(bsc#1265903 ltc#216658)
  * 0011-drmgr-Do-not-remove-LMBs-when-the-timer-expires.patch
  New:  * 0010-drmgr-Add-timeout-signal-handling-for-NUMA-memory-RE.patch 
(bsc#1265903 ltc#216658)
  * 0011-drmgr-Do-not-remove-LMBs-when-the-timer-expires.patch
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ powerpc-utils.spec ++++++
--- /var/tmp/diff_new_pack.7QWcyJ/_old  2026-05-24 19:35:13.026205354 +0200
+++ /var/tmp/diff_new_pack.7QWcyJ/_new  2026-05-24 19:35:13.050206336 +0200
@@ -25,6 +25,17 @@
 URL:            https://github.com/ibm-power-utilities/powerpc-utils
 Source0:        
https://github.com/ibm-power-utilities/powerpc-utils/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
 Source1:        nvsetenv
+Patch1:         0001-drmgr-Update-cpuless_lmb_count-NUMA-counter-during-L.patch
+Patch2:         0002-drmgr-Remove-only-available-LMBs-from-CPU-less-NUMA-.patch
+Patch3:         0003-drmgr-Move-numa_topology-code-to-common_numa.c.patch
+Patch4:         0004-drmgr-Move-read-lmb-size-property-code-to-common_ofd.patch
+Patch5:         0005-drmgr-Add-get_next_cpu-to-identify-the-removable-CPU.patch
+Patch6:         0006-drmgr-Allocate-CPU-bitmap-for-each-NUMA-node.patch
+Patch7:         0007-drmgr-Add-NUMA-configuration-update-for-CPU-remove.patch
+Patch8:         0008-drmgr-Add-NUMA-based-CPU-removal.patch
+Patch9:         0009-drmgr-Allow-signals-mentioned-in-new-sigset_t.patch
+Patch10:        0010-drmgr-Add-timeout-signal-handling-for-NUMA-memory-RE.patch
+Patch11:        0011-drmgr-Do-not-remove-LMBs-when-the-timer-expires.patch
 Patch41:        powerpc-utils-lsprop.patch
 Patch42:        ofpathname_powernv.patch
 Patch43:        fix_kexec_service_name_for_suse.patch

++++++ 0001-drmgr-Update-cpuless_lmb_count-NUMA-counter-during-L.patch ++++++
>From f74288cf94d73f58a338fc58d8e2907673bb36e5 Mon Sep 17 00:00:00 2001
From: Haren Myneni <[email protected]>
Date: Mon, 9 Feb 2026 22:18:58 -0800
Subject: [PATCH 01/11] drmgr: Update cpuless_lmb_count NUMA counter during LMB
 removal

Upstream: merged, expected in v1.3.15
Git-commit: f74288cf94d73f58a338fc58d8e2907673bb36e5

After removing LMBs from a NUMA node, LMB counters should be
decremented. In the case of CPU less node, cpuless_lmb_count
should be decremented. But the current code reduces
cpuless_node_count instead of cpuless_lmb_count. This patch
reduces cpuless_lmb_count NUMA counter based on number of LMBs
selected from that specific CPU less NUMA node.

Signed-off-by: Ryan Whittaker <[email protected]>
Reviewed-by: Mingming Cao <[email protected]>
Signed-off-by: Haren Myneni <[email protected]>
Signed-off-by: Tyrel Datwyler <[email protected]>
---
 src/drmgr/drslot_chrp_mem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/drmgr/drslot_chrp_mem.c b/src/drmgr/drslot_chrp_mem.c
index d37ee80..179fb17 100644
--- a/src/drmgr/drslot_chrp_mem.c
+++ b/src/drmgr/drslot_chrp_mem.c
@@ -1502,7 +1502,7 @@ static int remove_lmb_from_node(struct ppcnuma_node 
*node, uint32_t count)
        if (node->n_cpus)
                numa.lmb_count -= unlinked;
        else
-               numa.cpuless_node_count -= unlinked;
+               numa.cpuless_lmb_count -= unlinked;
 
        if (!node->n_lmbs) {
                node->ratio = 0; /* for sanity only */
-- 
2.51.0


++++++ 0002-drmgr-Remove-only-available-LMBs-from-CPU-less-NUMA-.patch ++++++
>From 8e0a9410baba62f16e9b9ac1a7096dc6c704ffa1 Mon Sep 17 00:00:00 2001
From: Haren Myneni <[email protected]>
Date: Mon, 9 Feb 2026 22:18:59 -0800
Subject: [PATCH 02/11] drmgr: Remove only available LMBs from CPU less NUMA
 node

Upstream: merged, expected in v1.3.15
Git-commit: 8e0a9410baba62f16e9b9ac1a7096dc6c704ffa1

The current logic in remove_cpuless_lmbs() may remove more LMB
than requested.

todo = (count * node->ratio) / 100;  --> can be 0
todo = min(todo, node->n_lmbs);
if (!todo && node->n_lmbs)
        todo = (count - this_loop); -> todo may be > node->n_lmbs

Removing more lmbs than requested caused a decrement of count
(unsigned int) integer overflow, eventually leading to the drmgr
removing all available memory in the system. Existing testing
exposed the out of memory issue triggered by this counter
overflow.

This patch fixed this logic by adjusting todo per node dynamically
based on the count value and then determine todo value based on
number of available LMBs in the node.

Signed-off-by: Ryan Whittaker <[email protected]>
Reviewed-by: Mingming Cao <[email protected]>
Signed-off-by: Haren Myneni <[email protected]>
Signed-off-by: Tyrel Datwyler <[email protected]>
---
 src/drmgr/drslot_chrp_mem.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/src/drmgr/drslot_chrp_mem.c b/src/drmgr/drslot_chrp_mem.c
index 179fb17..4a36c73 100644
--- a/src/drmgr/drslot_chrp_mem.c
+++ b/src/drmgr/drslot_chrp_mem.c
@@ -1565,11 +1565,16 @@ static int remove_cpuless_lmbs(uint32_t count)
                                continue;
 
                        todo = (count * node->ratio) / 100;
-                       todo = min(todo, node->n_lmbs);
-                       /* Fix rounded value to 0 */
-                       if (!todo && node->n_lmbs)
+                        /*
+                         * Fix rounded value to 0 and fix if a 0 ratio has
+                         * been processed
+                         */
+                       if ((!todo && node->n_lmbs) || (count - this_loop < 
todo))
                                todo = (count - this_loop);
 
+                       /* Donot request more than available */
+                       todo = min(todo, node->n_lmbs);
+
                        if (todo)
                                todo = remove_lmb_from_node(node, todo);
 
@@ -1583,7 +1588,13 @@ static int remove_cpuless_lmbs(uint32_t count)
                if (!this_loop)
                        break;
 
-               count -= this_loop;
+               /*
+                * Should not happen, but in case prevent integer overflow
+                */
+               if (this_loop < count)
+                       count -= this_loop;
+               else
+                       count = 0;
        }
 
        say(DEBUG, "%d / %d LMBs removed from the CPU less nodes\n",
-- 
2.51.0


++++++ 0003-drmgr-Move-numa_topology-code-to-common_numa.c.patch ++++++
>From 27dd4cce01450d94ab58fa2e632eac34307a4a82 Mon Sep 17 00:00:00 2001
From: Haren Myneni <[email protected]>
Date: Sat, 16 May 2026 11:34:17 -0700
Subject: [PATCH 03/11] drmgr: Move numa_topology code to common_numa.c

Upstream: merged, expected in v1.3.15
Git-commit: 27dd4cce01450d94ab58fa2e632eac34307a4a82

Move build_numa_topology and sort NUMA node ratio list code to
common_numa.c. These functions will also be used for NUMA aware
CPU removal in later patch.

Signed-off-by: Haren Myneni <[email protected]>
Signed-off-by: Tyrel Datwyler <[email protected]>
---
 src/drmgr/common_numa.c     | 37 ++++++++++++++++++++++++++++++++++++-
 src/drmgr/common_numa.h     |  6 +++++-
 src/drmgr/drslot_chrp_mem.c | 29 ++---------------------------
 3 files changed, 43 insertions(+), 29 deletions(-)

diff --git a/src/drmgr/common_numa.c b/src/drmgr/common_numa.c
index 898aab6..6bc2ea8 100644
--- a/src/drmgr/common_numa.c
+++ b/src/drmgr/common_numa.c
@@ -27,6 +27,9 @@
 #include "drmem.h"             /* for DYNAMIC_RECONFIG_MEM */
 #include "common_numa.h"
 
+int numa_enabled = 0;
+struct ppcnuma_topology numa;
+
 struct ppcnuma_node *ppcnuma_fetch_node(struct ppcnuma_topology *numa, int nid)
 {
        struct ppcnuma_node *node;
@@ -118,7 +121,7 @@ static int read_numa_topology(struct ppcnuma_topology *numa)
        return rc;
 }
 
-int ppcnuma_get_topology(struct ppcnuma_topology *numa)
+static int ppcnuma_get_topology(struct ppcnuma_topology *numa)
 {
        int rc;
 
@@ -145,3 +148,35 @@ int ppcnuma_get_topology(struct ppcnuma_topology *numa)
 
        return 0;
 }
+
+void build_numa_topology(void)
+{
+       int rc;
+
+       rc = ppcnuma_get_topology(&numa);
+       if (rc)
+               return;
+
+       numa_enabled = 1;
+}
+
+void order_numa_node_ratio_list(void)
+{
+       int nid;
+       struct ppcnuma_node *node, *n, **p;
+
+       numa.ratio = NULL;
+
+       /* Create an ordered link of the nodes */
+       ppcnuma_foreach_node(&numa, nid, node) {
+               if (!node->n_lmbs || !node->n_cpus)
+                       continue;
+
+               p = &numa.ratio;
+               for (n = numa.ratio;
+                       n && n->ratio < node->ratio; n = n->ratio_next)
+                       p = &n->ratio_next;
+               *p = node;
+               node->ratio_next = n;
+       }
+}
diff --git a/src/drmgr/common_numa.h b/src/drmgr/common_numa.h
index c209a3e..2b0901e 100644
--- a/src/drmgr/common_numa.h
+++ b/src/drmgr/common_numa.h
@@ -44,7 +44,11 @@ struct ppcnuma_topology {
        struct assoc_arrays     aa;
 };
 
-int ppcnuma_get_topology(struct ppcnuma_topology *numa);
+extern int numa_enabled;
+extern struct ppcnuma_topology numa;
+void build_numa_topology(void);
+void order_numa_node_ratio_list(void);
+
 struct ppcnuma_node *ppcnuma_fetch_node(struct ppcnuma_topology *numa,
                                        int node_id);
 
diff --git a/src/drmgr/drslot_chrp_mem.c b/src/drmgr/drslot_chrp_mem.c
index 4a36c73..eb75ccf 100644
--- a/src/drmgr/drslot_chrp_mem.c
+++ b/src/drmgr/drslot_chrp_mem.c
@@ -38,9 +38,6 @@ static char *state_strs[] = {"offline", "online"};
 
 static char *usagestr = "-c mem {-a | -r} {-q <quantity> -p {variable_weight | 
ent_capacity} | {-q <quantity> | -s [<drc_name> | <drc_index>]}}";
 
-static struct ppcnuma_topology numa;
-static int numa_enabled = 0;
-
 /**
  * mem_usage
  * @brief return usage string
@@ -1605,7 +1602,7 @@ static int remove_cpuless_lmbs(uint32_t count)
 static void update_node_ratio(void)
 {
        int nid;
-       struct ppcnuma_node *node, *n, **p;
+       struct ppcnuma_node *node;
        uint32_t cpu_ratio, mem_ratio;
 
        /*
@@ -1626,18 +1623,7 @@ static void update_node_ratio(void)
                node->ratio = (cpu_ratio * 9 + mem_ratio) / 10;
        }
 
-       /* Create an ordered link of the nodes */
-       ppcnuma_foreach_node(&numa, nid, node) {
-               if (!node->n_lmbs || !node->n_cpus)
-                       continue;
-
-               p = &numa.ratio;
-               for (n = numa.ratio;
-                    n && n->ratio < node->ratio; n = n->ratio_next)
-                       p = &n->ratio_next;
-               *p = node;
-               node->ratio_next = n;
-       }
+       order_numa_node_ratio_list();
 }
 
 /*
@@ -1693,17 +1679,6 @@ static int remove_cpu_lmbs(uint32_t count)
        return done;
 }
 
-static void build_numa_topology(void)
-{
-       int rc;
-
-       rc = ppcnuma_get_topology(&numa);
-       if (rc)
-               return;
-
-       numa_enabled = 1;
-}
-
 static void clear_numa_lmb_links(void)
 {
        int nid;
-- 
2.51.0


++++++ 0004-drmgr-Move-read-lmb-size-property-code-to-common_ofd.patch ++++++
>From cbdbefdb8c82acae997cf1a30816e69b323f9979 Mon Sep 17 00:00:00 2001
From: Haren Myneni <[email protected]>
Date: Sat, 16 May 2026 11:34:18 -0700
Subject: [PATCH 04/11] drmgr: Move read lmb-size property code to
 common_ofdt.c

Upstream: merged, expected in v1.3.15
Git-commit: cbdbefdb8c82acae997cf1a30816e69b323f9979

get_dynamic_lmb_size() is used to get lmb size from "ibm,lmb-size"
property. This lmb size is needed to determine the number of LMBs
and used to find NUMA node ratio for NUMA aware memory and CPU
removal code. So move this function to common_ofdt.c

Signed-off-by: Haren Myneni <[email protected]>
Signed-off-by: Tyrel Datwyler <[email protected]>
---
 src/drmgr/common_ofdt.c     | 17 +++++++++++++++++
 src/drmgr/drslot_chrp_mem.c | 11 ++---------
 src/drmgr/ofdt.h            |  1 +
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/src/drmgr/common_ofdt.c b/src/drmgr/common_ofdt.c
index 1e5fe53..0655559 100644
--- a/src/drmgr/common_ofdt.c
+++ b/src/drmgr/common_ofdt.c
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include "dr.h"
 #include "ofdt.h"
+#include "drmem.h"
 
 #define RTAS_DIRECTORY         "/proc/device-tree/rtas"
 #define CHOSEN_DIRECTORY       "/proc/device-tree/chosen"
@@ -932,3 +933,19 @@ int of_associativity_to_node(const char *dir, int 
min_common_depth)
        return be32toh(prop[min_common_depth]);
 }
 
+int get_dynamic_lmb_size(uint64_t *lmb_sz)
+{
+       int rc = 0;
+       uint64_t sz;
+
+       rc = get_property(DYNAMIC_RECONFIG_MEM, "ibm,lmb-size",
+                               &sz, sizeof(sz));
+       if (rc) {
+               say(DEBUG, "Could not retrieve drconf LMB size\n");
+               return rc;
+       }
+
+       /* convert for LE systems */
+       *lmb_sz = be64toh(sz);
+       return 0;
+}
diff --git a/src/drmgr/drslot_chrp_mem.c b/src/drmgr/drslot_chrp_mem.c
index eb75ccf..2d22bff 100644
--- a/src/drmgr/drslot_chrp_mem.c
+++ b/src/drmgr/drslot_chrp_mem.c
@@ -506,16 +506,9 @@ get_dynamic_reconfig_lmbs(struct lmb_list_head *lmb_list)
        uint64_t lmb_sz;
        int rc = 0;
 
-       rc = get_property(DYNAMIC_RECONFIG_MEM, "ibm,lmb-size",
-                         &lmb_sz, sizeof(lmb_sz));
-
-       /* convert for LE systems */
-       lmb_sz = be64toh(lmb_sz);
-
-       if (rc) {
-               say(DEBUG, "Could not retrieve drconf LMB size\n");
+       rc = get_dynamic_lmb_size(&lmb_sz);
+       if (rc)
                return rc;
-       }
 
        if (stat(DYNAMIC_RECONFIG_MEM_V1, &sbuf) == 0) {
                rc = get_dynamic_reconfig_lmbs_v1(lmb_sz, lmb_list);
diff --git a/src/drmgr/ofdt.h b/src/drmgr/ofdt.h
index e9ebd03..c79ed65 100644
--- a/src/drmgr/ofdt.h
+++ b/src/drmgr/ofdt.h
@@ -185,6 +185,7 @@ int get_assoc_arrays(const char *dir, struct assoc_arrays 
*aa,
                     int min_common_depth);
 int of_associativity_to_node(const char *dir, int min_common_depth);
 int init_node(struct dr_node *);
+int get_dynamic_lmb_size(uint64_t *lmb_sz);
 
 static inline int aa_index_to_node(struct assoc_arrays *aa, uint32_t aa_index)
 {
-- 
2.51.0


++++++ 0005-drmgr-Add-get_next_cpu-to-identify-the-removable-CPU.patch ++++++
>From fc252eaf3f1e2b6dcf2a646459ac7399db0ab18d Mon Sep 17 00:00:00 2001
From: Haren Myneni <[email protected]>
Date: Sat, 16 May 2026 11:34:19 -0700
Subject: [PATCH 05/11] drmgr: Add get_next_cpu() to identify the removable CPU

Upstream: merged, expected in v1.3.15
Git-commit: fc252eaf3f1e2b6dcf2a646459ac7399db0ab18d

Move code which identifies the removable CPU to get_next_cpu().
This function is used only for the current non-numa based CPU
removal but helps to add for NUMA based CPU removal code in later
patch.

Signed-off-by: Haren Myneni <[email protected]>
Signed-off-by: Tyrel Datwyler <[email protected]>
---
 src/drmgr/drslot_chrp_cpu.c | 34 ++++++++++++++++++++++++----------
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/src/drmgr/drslot_chrp_cpu.c b/src/drmgr/drslot_chrp_cpu.c
index 3ef24f4..6a21663 100644
--- a/src/drmgr/drslot_chrp_cpu.c
+++ b/src/drmgr/drslot_chrp_cpu.c
@@ -160,11 +160,33 @@ static struct dr_node *get_available_cpu_by_index(struct 
dr_info *dr_info)
        return cpu;
 }
 
+/*
+ * Scan all CPUs from the last one for the next available CPU.
+ * Used only for non-NUMA based CPU removal.
+ */
+static struct dr_node *get_next_cpu(struct dr_info *dr_info)
+{
+       struct dr_node *cpu = NULL;
+       struct thread *t;
+
+       /* Find the first cpu with an online thread */
+       for (cpu = dr_info->all_cpus; cpu; cpu = cpu->next) {
+               if (cpu->unusable)
+                       continue;
+
+               for (t = cpu->cpu_threads; t; t = t->next) {
+                       if (get_thread_state(t) == ONLINE)
+                               return cpu;
+               }
+       }
+
+       return NULL;
+}
+
 static struct dr_node *get_next_available_cpu(struct dr_info *dr_info)
 {
        struct dr_node *cpu = NULL;
        struct dr_node *survivor = NULL;
-       struct thread *t;
        
        if (usr_action == ADD) {
                for (cpu = dr_info->all_cpus; cpu; cpu = cpu->next) {
@@ -177,15 +199,7 @@ static struct dr_node *get_next_available_cpu(struct 
dr_info *dr_info)
                cpu = survivor;
        } else if (usr_action == REMOVE) {
                /* Find the first cpu with an online thread */
-               for (cpu = dr_info->all_cpus; cpu; cpu = cpu->next) {
-                       if (cpu->unusable)
-                               continue;
-
-                       for (t = cpu->cpu_threads; t; t = t->next) {
-                               if (get_thread_state(t) == ONLINE)
-                                       return cpu;
-                       }
-               }
+               cpu = get_next_cpu(dr_info);
        }
 
        if (!cpu)
-- 
2.51.0


++++++ 0006-drmgr-Allocate-CPU-bitmap-for-each-NUMA-node.patch ++++++
>From 1c4812fb35510c7e02ff27fc39badbe5eef24611 Mon Sep 17 00:00:00 2001
From: Haren Myneni <[email protected]>
Date: Sat, 16 May 2026 11:34:20 -0700
Subject: [PATCH 06/11] drmgr: Allocate CPU bitmap for each NUMA node

Upstream: merged, expected in v1.3.15
Git-commit: 1c4812fb35510c7e02ff27fc39badbe5eef24611

The current code allocates one bitmap and uses it to determine
number of valid CPUs for each NUMA node and then frees the bitmap.
The NUMA based CPU removal needs this bitmap per node to determine
the valid CPU in that node. So this patch retains bitmap per node
and frees it after DLPAR memory / CPU removal.

Signed-off-by: Haren Myneni <[email protected]>
Reviewed-by: Dave Marquardt <[email protected]>
Signed-off-by: Tyrel Datwyler <[email protected]>
---
 src/drmgr/common_numa.c     | 27 +++++++++++++++++++++------
 src/drmgr/common_numa.h     |  2 ++
 src/drmgr/drslot_chrp_mem.c |  5 +++--
 3 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/src/drmgr/common_numa.c b/src/drmgr/common_numa.c
index 6bc2ea8..eba6c3d 100644
--- a/src/drmgr/common_numa.c
+++ b/src/drmgr/common_numa.c
@@ -84,9 +84,6 @@ static int read_numa_topology(struct ppcnuma_topology *numa)
 
        rc = 0;
 
-       /* In case of allocation error, the libnuma is calling exit() */
-       cpus = numa_allocate_cpumask();
-
        for (nid = 0; nid <= max_node; nid++) {
 
                if (!numa_bitmask_isbitset(numa_nodes_ptr, nid))
@@ -98,20 +95,24 @@ static int read_numa_topology(struct ppcnuma_topology *numa)
                        break;
                }
 
+               /* In case of allocation error, the libnuma is calling exit() */
+               cpus = numa_allocate_cpumask();
+
                rc = numa_node_to_cpus(nid, cpus);
-               if (rc < 0)
+               if (rc < 0) {
+                       numa_bitmask_free(cpus);
                        break;
+               }
 
                /* Count the CPUs in that node */
                for (i = 0; i < cpus->size; i++)
                        if (numa_bitmask_isbitset(cpus, i))
                                node->n_cpus++;
 
+               node->cpus = cpus;
                numa->cpu_count += node->n_cpus;
        }
 
-       numa_bitmask_free(cpus);
-
        if (rc) {
                ppcnuma_foreach_node(numa, nid, node)
                        node->n_cpus = 0;
@@ -160,6 +161,20 @@ void build_numa_topology(void)
        numa_enabled = 1;
 }
 
+void free_numa_topology(void)
+{
+       struct ppcnuma_node *node;
+       int nid;
+
+       ppcnuma_foreach_node(&numa, nid, node) {
+               if (node) {
+                       if (node->cpus)
+                               numa_bitmask_free(node->cpus);
+                       free(node);
+               }
+       }
+}
+
 void order_numa_node_ratio_list(void)
 {
        int nid;
diff --git a/src/drmgr/common_numa.h b/src/drmgr/common_numa.h
index 2b0901e..7aea026 100644
--- a/src/drmgr/common_numa.h
+++ b/src/drmgr/common_numa.h
@@ -30,6 +30,7 @@ struct ppcnuma_node {
        unsigned int    ratio;
        struct dr_node  *lmbs;                  /* linked by lmb_numa_next */
        struct ppcnuma_node *ratio_next;
+       struct bitmask *cpus;
 };
 
 struct ppcnuma_topology {
@@ -48,6 +49,7 @@ extern int numa_enabled;
 extern struct ppcnuma_topology numa;
 void build_numa_topology(void);
 void order_numa_node_ratio_list(void);
+void free_numa_topology(void);
 
 struct ppcnuma_node *ppcnuma_fetch_node(struct ppcnuma_topology *numa,
                                        int node_id);
diff --git a/src/drmgr/drslot_chrp_mem.c b/src/drmgr/drslot_chrp_mem.c
index 2d22bff..fe04ad1 100644
--- a/src/drmgr/drslot_chrp_mem.c
+++ b/src/drmgr/drslot_chrp_mem.c
@@ -1731,9 +1731,10 @@ int do_mem_kernel_dlpar(void)
        if (usr_action == REMOVE && usr_drc_count && !usr_drc_index) {
                build_numa_topology();
                if (numa_enabled) {
-                       if (!numa_based_remove(usr_drc_count))
+                       rc = numa_based_remove(usr_drc_count);
+                       free_numa_topology();
+                       if (!rc)
                                return 0;
-
                        /*
                         * If the NUMA based removal failed, lets try the legacy
                         * way.
-- 
2.51.0


++++++ 0007-drmgr-Add-NUMA-configuration-update-for-CPU-remove.patch ++++++
>From 4cf04b9e75db0da2c199fa12003433b3d0427fd0 Mon Sep 17 00:00:00 2001
From: Haren Myneni <[email protected]>
Date: Sat, 16 May 2026 11:34:21 -0700
Subject: [PATCH 07/11] drmgr: Add NUMA configuration update for CPU remove

Upstream: merged, expected in v1.3.15
Git-commit: 4cf04b9e75db0da2c199fa12003433b3d0427fd0

This patch adds NUMA node config update for CPU removal. Updates
number of LMBs and CPUs for each node and also calculates total
number of CPUs from memory less nodes. This node configuration is
used to identify the node based on the node ratio from which the
CPU is selected to remove

Signed-off-by: Haren Myneni <[email protected]>
Reviewed-by: Dave Marquardt <[email protected]>
Signed-off-by: Tyrel Datwyler <[email protected]>
---
 src/drmgr/common_numa.h     |  1 +
 src/drmgr/drslot_chrp_cpu.c | 53 +++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/src/drmgr/common_numa.h b/src/drmgr/common_numa.h
index 7aea026..edf4349 100644
--- a/src/drmgr/common_numa.h
+++ b/src/drmgr/common_numa.h
@@ -38,6 +38,7 @@ struct ppcnuma_topology {
        unsigned int            lmb_count;
        unsigned int            cpuless_node_count;
        unsigned int            cpuless_lmb_count;
+       unsigned int            memless_cpu_count;
        unsigned int            node_count, node_min, node_max;
        struct ppcnuma_node     *nodes[MAX_NUMNODES];
        struct ppcnuma_node     *ratio;
diff --git a/src/drmgr/drslot_chrp_cpu.c b/src/drmgr/drslot_chrp_cpu.c
index 6a21663..e367634 100644
--- a/src/drmgr/drslot_chrp_cpu.c
+++ b/src/drmgr/drslot_chrp_cpu.c
@@ -26,10 +26,14 @@
 #include <sys/types.h>
 #include <dirent.h>
 #include <librtas.h>
+#include <numa.h>
 #include "dr.h"
 #include "drcpu.h"
 #include "drpci.h"
 #include "ofdt.h"
+#include "common_numa.h"
+
+#define        DEFAULT_LMB_SIZE        0x10000000      /* 256MB */
 
 struct cpu_operation;
 typedef int (cpu_op_func_t) (void);
@@ -395,6 +399,43 @@ static int smt_threads_func(struct dr_info *dr_info)
        return rc;
 }
 
+/*
+ * Per node CPUs are defined as part of build_numa_topology().
+ * This function calculates number of LMBs per node based on
+ * node mememory / lmb-size.
+ * n_cpus and n_lmbs are used to determine node ratio.
+ */
+static int cpu_update_numa_config(void)
+{
+       struct ppcnuma_node *node;
+       unsigned long long node_size;
+       int rc, nid;
+       uint64_t lmb_sz;
+
+       rc = get_dynamic_lmb_size(&lmb_sz);
+       /*
+        * Use the default value if lmb-size property is not available.
+        * For CPU removal, node ratio will be calculated based on
+        * total n_lmbs per CPU.
+        */
+       if (rc)
+               lmb_sz = DEFAULT_LMB_SIZE;
+
+       ppcnuma_foreach_node(&numa, nid, node) {
+               node_size = numa_node_size(nid, 0);
+               /*
+                * Node has memory
+                * n_lmbs = Total memory / lmb-size
+                */
+               if (node_size) {
+                       node->n_lmbs = node_size / lmb_sz;
+               } else
+                       numa.memless_cpu_count += node->n_cpus;
+       }
+
+       return 0;
+}
+
 int valid_cpu_options(void)
 {
        /* default to a quantity of 1 */
@@ -442,6 +483,15 @@ int drslot_chrp_cpu(void)
                return -1;
        }
 
+       /*
+        * Maintain NUMA aware hotplug only for remove and with count request.
+        */
+       if (usr_drc_count && (usr_action == REMOVE)) {
+               build_numa_topology();
+               if (numa_enabled)
+                       cpu_update_numa_config();
+       }
+
        /* If a user specifies a drc name, the quantity to add/remove is
         * one. Enforce that here so the loops in add/remove code behave
         * accordingly.
@@ -473,6 +523,9 @@ int drslot_chrp_cpu(void)
        if (usr_action == ADD || usr_action == REMOVE)
                run_hooks(DRC_TYPE_CPU, usr_action, HOOK_POST, count);
 
+       if ((usr_action == REMOVE) && numa_enabled)
+               free_numa_topology();
+
        free_cpu_drc_info(&dr_info);
        return rc;
 }
-- 
2.51.0


++++++ 0008-drmgr-Add-NUMA-based-CPU-removal.patch ++++++
>From 908986e43b6c67288aa084fe13155964caa807a8 Mon Sep 17 00:00:00 2001
From: Haren Myneni <[email protected]>
Date: Sat, 16 May 2026 11:34:22 -0700
Subject: [PATCH 08/11] drmgr: Add NUMA based CPU removal

Upstream: merged, expected in v1.3.15
Git-commit: 908986e43b6c67288aa084fe13155964caa807a8

The current CPU removal process reads CPU list from last CPU and
remove CPUs based on the userspace request. This process can
result in CPU less NUMA nodes even though these nodes have more
memory which can affect on the system performance.

This patch adds NUMA aware CPU removal process to remove CPUs from
specific NUMA nodes and maintains NUMA balance. The selection of
node from which the CPU to be removed is based on the available
memory per CPU in that node called node ratio. So CPU is selected
from the node which has lower ratio.

If the NUMA topology can't be read, fallback using the current
process.

The node selection process is as follows:
- For each CPU removal request, update node ratios and sort the list.
- Select the next removable CPU from the dr_info CPU list and it
  should belong to the first node.
- CPU associated to memory less nodes is considered first and then
  the first node that has memory in the list.
- Repeat all CPUs in dr_info list until the next removable CPU is
  matched with node CPU bitmap.
- The total number of CPU threads in the selected node is
  decremented and cleared in the node CPU bitmap.

Signed-off-by: Haren Myneni <[email protected]>
Signed-off-by: Tyrel Datwyler <[email protected]>
---
 src/drmgr/drslot_chrp_cpu.c | 143 +++++++++++++++++++++++++++++++++++-
 1 file changed, 141 insertions(+), 2 deletions(-)

diff --git a/src/drmgr/drslot_chrp_cpu.c b/src/drmgr/drslot_chrp_cpu.c
index e367634..60956a0 100644
--- a/src/drmgr/drslot_chrp_cpu.c
+++ b/src/drmgr/drslot_chrp_cpu.c
@@ -164,6 +164,141 @@ static struct dr_node *get_available_cpu_by_index(struct 
dr_info *dr_info)
        return cpu;
 }
 
+/*
+ * Return node if CPU ID matches in node CPU bitmap.
+ */
+static struct ppcnuma_node *match_cpu_node(struct ppcnuma_node *node,
+                                       struct dr_node *cpu)
+{
+       int nid;
+
+       if (cpu->cpu_threads) {
+               nid = numa_node_of_cpu(cpu->cpu_threads->id);
+               if (nid == node->node_id) {
+                       if (numa_bitmask_isbitset(node->cpus,
+                                               cpu->cpu_threads->id))
+                               return node;
+               }
+       }
+
+       return NULL;
+}
+
+/*
+ * Return node if CPU belongs to any memoryless NUMA node.
+ */
+static struct ppcnuma_node *find_cpu_memless_node(struct dr_node *cpu)
+{
+       struct ppcnuma_node *node = NULL;
+       int nid;
+
+       ppcnuma_foreach_node(&numa, nid, node) {
+               if (node->n_lmbs)
+                       continue;
+
+               if (match_cpu_node(node, cpu))
+                       return node;
+       }
+
+       return NULL;
+}
+
+/*
+ * The node list is sorted by node ratio (less memory per CPU).
+ * So consider the first node
+ * Return node if CPU belongs to the first NUMA node which
+ * has memory.
+ */
+static struct ppcnuma_node *find_cpu_numa_node(struct dr_node *cpu)
+{
+       struct ppcnuma_node *node = NULL;
+       int found = 0;
+
+       ppcnuma_foreach_node_by_ratio(&numa, node) {
+               if (node->n_cpus && node->n_lmbs) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (found && match_cpu_node(node, cpu))
+               return node;
+
+       return NULL;
+}
+
+/*
+ * Calculate node ratio based on amount of memory per CPU and sort
+ * the node ratio list.
+ */
+static void cpu_update_node_ratio(void)
+{
+       struct ppcnuma_node *node;
+       int nid;
+
+       ppcnuma_foreach_node(&numa, nid, node) {
+               if (!node->n_lmbs || !node->n_cpus)
+                       continue;
+
+               /*
+                * Node ratio = n_lmbs per CPU
+                */
+               node->ratio = (node->n_lmbs * 100) / node->n_cpus;
+       }
+
+       order_numa_node_ratio_list();
+}
+
+/*
+ * Scan CPUs from the last one in the list and select the first CPU
+ * based on:
+ * - CPU from memory less node
+ * - If no CPUs are available in memory less nodes, CPU belongs to
+ *   the first node from node ratio list.
+ */
+static struct dr_node *numa_get_next_cpu(struct dr_info *dr_info)
+{
+       struct ppcnuma_node *node;
+       struct dr_node *cpu = NULL;
+       struct thread *t;
+       int i, found = 0;
+
+       /*
+        * Update node ratio for each CPU removal request
+        */
+       cpu_update_node_ratio();
+
+       /* Find the first cpu with an online thread */
+       for (cpu = dr_info->all_cpus; cpu; cpu = cpu->next) {
+               if (cpu->unusable)
+                       continue;
+
+               if (numa.memless_cpu_count)
+                       node = find_cpu_memless_node(cpu);
+               else
+                       node = find_cpu_numa_node(cpu);
+
+               if (!node)
+                       continue;
+
+               t = cpu->cpu_threads;
+               for (i = 0; i < cpu->cpu_nthreads && t; i++, t = t->next) {
+                       if (get_thread_state(t) == ONLINE)
+                               found = 1;
+                       numa_bitmask_clearbit(node->cpus, t->id);
+               }
+               if (found) {
+                       node->n_cpus -= cpu->cpu_nthreads;
+                       numa.cpu_count -= cpu->cpu_nthreads;
+                       if (!node->n_lmbs)
+                               numa.memless_cpu_count -= cpu->cpu_nthreads;
+                       return cpu;
+               }
+       }
+
+       return NULL;
+}
+
 /*
  * Scan all CPUs from the last one for the next available CPU.
  * Used only for non-NUMA based CPU removal.
@@ -202,8 +337,12 @@ static struct dr_node *get_next_available_cpu(struct 
dr_info *dr_info)
 
                cpu = survivor;
        } else if (usr_action == REMOVE) {
-               /* Find the first cpu with an online thread */
-               cpu = get_next_cpu(dr_info);
+               if (numa_enabled)
+                       /* Find the first CPU from NUMA nodes */
+                       cpu = numa_get_next_cpu(dr_info);
+               else
+                       /* Find the first cpu with an online thread */
+                       cpu = get_next_cpu(dr_info);
        }
 
        if (!cpu)
-- 
2.51.0


++++++ 0009-drmgr-Allow-signals-mentioned-in-new-sigset_t.patch ++++++
>From 3a7d0b61e7a5f364660007a45cc9dcf1c3cb5ab4 Mon Sep 17 00:00:00 2001
From: Haren Myneni <[email protected]>
Date: Mon, 18 May 2026 22:37:52 -0700
Subject: [PATCH 09/11] drmgr: Allow signals mentioned in new sigset_t

Upstream: merged, expected in v1.3.15
Git-commit: 3a7d0b61e7a5f364660007a45cc9dcf1c3cb5ab4

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 <[email protected]>
Signed-off-by: Tyrel Datwyler <[email protected]>
---
 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.51.0


++++++ 0010-drmgr-Add-timeout-signal-handling-for-NUMA-memory-RE.patch ++++++
>From 1dee26c2a60dd9a5264331cc20143a5590289187 Mon Sep 17 00:00:00 2001
From: Haren Myneni <[email protected]>
Date: Mon, 18 May 2026 22:37:53 -0700
Subject: [PATCH 10/11] drmgr: Add timeout signal handling for NUMA memory
 REMOVE

Upstream: merged, expected in v1.3.15
Git-commit: 1dee26c2a60dd9a5264331cc20143a5590289187

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 <[email protected]>
Signed-off-by: Tyrel Datwyler <[email protected]>
---
 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.51.0


++++++ 0011-drmgr-Do-not-remove-LMBs-when-the-timer-expires.patch ++++++
>From 7926241f576de24df8b342858f5278911e035658 Mon Sep 17 00:00:00 2001
From: Haren Myneni <[email protected]>
Date: Mon, 18 May 2026 22:37:54 -0700
Subject: [PATCH 11/11] drmgr: Do not remove LMBs when the timer expires

Upstream: merged, expected in v1.3.15
Git-commit: 7926241f576de24df8b342858f5278911e035658

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 <[email protected]>
Signed-off-by: Tyrel Datwyler <[email protected]>
---
 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.51.0

Reply via email to