Re: [PATCH 2/2] mm/mempolicy: stop copying the nodemask in the interleave paths
From: Gregory Price
Date: Fri Sep 04 2026 - 13:16:22 EST
On Fri, Sep 04, 2026 at 05:01:37PM +0900, Rakie Kim wrote:
>
> What I had in mind is the gap between the two reads. Say the policy
> starts with two nodes, every weight is 10, and 100 pages are
> requested:
>
> /* the mask is {0,1} here */
> do {
> cpuset_mems_cookie = read_mems_allowed_begin();
> nnodes = nodes_weight(pol->nodes); /* nnodes = 2 */
> } while (read_mems_allowed_retry(cpuset_mems_cookie));
>
> /* a rebind grows the mask to {0,1,2,3} at this point */
>
> /* calculate total, detect system default usage */
> for_each_node_mask(node, pol->nodes)
> weight_total += ...; /* 10 * 4 = 40 */
>
> rounds = rem_pages / weight_total; /* 100 / 40 = 2 */
>
> for (i = 0; i < nnodes; i++) /* bounded by 2 */
> ...
>
Consider:
/* nodemask: {0,1} */
for_each_node_mask(node, pol->nodes) {
weight_total += ...;
nnodes++;
}
/* a rebind grows the mask to {2,3,4,5} */
rounds = rem_pages / weight_total; /* 100 / 10 = 10 */
for (i = 0; i < nnodes; i++) /* bounded by 2 */
...
in this scenario every value is wrong. The weight total was calculated
based on {0,1} and the loop will use {2,3} weights and ignore {4,5}
entirely.
It's the nature of the mechanism and race - best we can do is ensure
safety. Ensuring correct distributions would likely require locks or
reworking the entire weight mechanism.
I'd rather keep the change simple (cookie the value that can cause a
div/0) and leave the math alone.
~Gregory