VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   33 Branches   55 Tags
author: yanghui <yanghui.def@bytedance.com> 2021-09-08 18:10:20 -0700 committer: Linus Torvalds <torvalds@linux-foundation.org> 2021-09-08 18:45:53 -0700 commit: 276aeee1c5fc00df700f0782060beae126600472 parent: 79d3705040c3b41075f894fdeeebdcbb46550c63
Commit Summary:
mm/mempolicy: fix a race between offset_il_node and mpol_rebind_task
Diffstat:
1 file changed, 13 insertions, 4 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 5e90b3fb7794..b44f54768766 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1979,17 +1979,26 @@ unsigned int mempolicy_slab_node(void)
  */
 static unsigned offset_il_node(struct mempolicy *pol, unsigned long n)
 {
-	unsigned nnodes = nodes_weight(pol->nodes);
-	unsigned target;
+	nodemask_t nodemask = pol->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->nodes);
+	nid = first_node(nodemask);
 	for (i = 0; i < target; i++)
-		nid = next_node(nid, pol->nodes);
+		nid = next_node(nid, nodemask);
 	return nid;
 }