Re: [PATCH v5 29/36] mm: add NODE_PRIVATE_CAP_DEMOTION for private-node tiering demotion
[email protected] Tue, 21 Jul 2026 20:28:53 +0000
| Newsgroups | dev.linux.lists.nvdimm,dev.linux.lists.damon,org.kernel.vger.kvm,org.kernel.vger.linux-cxl |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] Concurrent, unprotected access to the global `tierable_nodes` nodemask can result in a torn read. -- --- Patch [29]: [PATCH v5 29/36] mm: add NODE_PRIVATE_CAP_DEMOTION for private-node tiering demotion --- commit e4de60011eb318a533982e5d4b896e77cc0ad141 Author: Gregory Price <[email protected]> mm: add NODE_PRIVATE_CAP_DEMOTION for private-node tiering demotion This commit introduces NODE_PRIVATE_CAP_DEMOTION, allowing private memory nodes to be included in the tiering and demotion hierarchy. By opting into this capability, memory-tiers will include the private node in demotion paths, allowing page reclaim to target it. > diff --git a/mm/memory-tiers.c b/mm/memory-tiers.c > index 25e121851b586..c673080d153e4 100644 > --- a/mm/memory-tiers.c > +++ b/mm/memory-tiers.c > @@ -317,6 +318,21 @@ void node_get_allowed_targets(pg_data_t *pgdat, nodemask_t *targets) > rcu_read_unlock(); > } > > +/* Tiering set: N_MEMORY | (N_MEMORY_PRIVATE w/ CAP_DEMOTION) */ > +static nodemask_t tierable_nodes; > + > +static void update_tierable_nodes(void) > +{ > + int node; > + > + lockdep_assert_held_once(&memory_tier_lock); > + > + tierable_nodes = node_states[N_MEMORY]; > + for_each_node_state(node, N_MEMORY_PRIVATE) > + if (node_allows_demotion(node)) > + node_set(node, tierable_nodes); > +} > + [ ... ] > @@ -330,7 +346,7 @@ void node_get_allowed_targets(pg_data_t *pgdat, nodemask_t *targets) > int next_demotion_node(int node, const nodemask_t *allowed_mask) > { > struct demotion_nodes *nd; > - nodemask_t mask; > + nodemask_t mask, tierable; > > if (!node_demotion) > return NUMA_NO_NODE; [ ... ] > @@ -370,7 +386,8 @@ int next_demotion_node(int node, const nodemask_t *allowed_mask) > * closest demotion target. > */ > nodes_complement(mask, *allowed_mask); > - return find_next_best_node_in(node, &mask, &node_states[N_MEMORY]); > + tierable = tierable_nodes; [Severity: Medium] Could this lockless copy result in a torn read of the tierable_nodes nodemask? In update_tierable_nodes(), the global tierable_nodes mask is updated via a non-atomic struct assignment and iterative node_set() modifications. Here in next_demotion_node(), the mask is copied locklessly to the stack during the reclaim hotpath. Since nodemask_t can be up to 128 bytes depending on MAX_NUMNODES, concurrent updates from memory hotplug could cause next_demotion_node() to see a partially updated mask. This could cause page reclaim to transiently skip valid private nodes or behave suboptimally during demotion. > + return find_next_best_node_in(node, &mask, &tierable); > } > > static void disable_all_demotion_targets(void) -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=29