diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 746383b54605cddc85e5bcade698b66e4a9a99fa..5ce39dbc84e1c7c4c6cf0c9b4298c3cf4101009a 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2014,17 +2014,26 @@ unsigned int mempolicy_slab_node(void) */ static unsigned offset_il_node(struct mempolicy *pol, unsigned long n) { - unsigned nnodes = nodes_weight(pol->v.nodes); - unsigned target; + nodemask_t nodemask = pol->v.nodes; + unsigned int target, nnodes; int i; int nid; + /* + * The barrier will stabilize the nodemask in a register or on + * the stack so that it will stop changing under the code. + * + * Between first_node() and next_node(), pol->nodes could be changed + * by other threads. So we put pol->nodes in a local stack. + */ + barrier(); + nnodes = nodes_weight(nodemask); if (!nnodes) return numa_node_id(); target = (unsigned int)n % nnodes; - nid = first_node(pol->v.nodes); + nid = first_node(nodemask); for (i = 0; i < target; i++) - nid = next_node(nid, pol->v.nodes); + nid = next_node(nid, nodemask); return nid; }