Skip to contentSkip to conversation

Use MPOL_PREFERRED for system default policy

PATCH In review Lee Schermerhorn 2 participants 11 messages Aug 14, 2007 – Aug 21, 2007

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Use MPOL_PREFERRED for system default policy

Christoph, Andi:

What do you think of this? OK to merge?

Also, Michael Kerrisk has been pinging you about the man page updates I posted. If we can get those in, I'll post additional updates for any cleanups like this. I can send you patches/formatted copies of the updated man pages, if you like.

Lee

------------------
PATCH/RFC Use MPOL_PREFERRED for system-wide default policy

Against: 2.6.23-rc2-mm2

Currently, when one specifies MPOL_DEFAULT via a NUMA memory policy API [set_mempolicy(), mbind() and internal versions], the kernel simply installs a NULL struct mempolicy pointer in the appropriate context: task policy, vma policy, or shared policy. This causes any use of that policy to "fall back" to the next most specific policy scope. The only use of MPOL_DEFAULT to mean "local allocation" is in the system default policy.

There is another, "preferred" way to specify local allocation via the APIs. That is using the MPOL_PREFERRED policy mode with an empty nodemask. Internally, the empty nodemask gets converted to a preferred_node id of '-1'. All internal usage of MPOL_PREFERRED will convert the '-1' to the local node id.

Now, system default policy, except during boot, is "local allocation". By using the MPOL_PREFERRED mode with a negative value of preferred node for system default policy, MPOL_DEFAULT will never occur in the 'policy' member of a struct mempolicy. Thus, we can remove all checks for MPOL_DEFAULT when converting policy to a node id/zonelist in the allocation paths.

Note: in slab_node() I kept the use of MPOL_DEFAULT when the policy pointer is NULL to force the switch to take the default:
case. This seemed more efficient than pointing policy at the system default, and having to deref that. Any value not covered by one of the existing case's would have served, but MPOL_DEFAULT is guaranteed to be a different value from any of the other MPOL_* handled explicitly by the switch.

With this patch MPOL_DEFAULT is just used in the APIs, including internal calls to do_set_mempolicy() and in the display of policy in /proc/<pid>/numa_maps. It always means "fall back" to the the next most specific policy scope. This simplifies the description of memory policies quite a bit, with no visible change in behavior.

Change the "BUG()s" in default switch(policy) cases [unexpected policy] to WARN_ON_ONCE(1), and try to do "something reasonable". It doesn't seem worth bugging out, possibly leaving locks held, for this condition.

Tested with set_mempolicy() using numactl with memtoy, and tested mbind() with memtoy. All seems to work "as expected".

 Documentation/vm/numa_memory_policy.txt |   70 ++++++++++++--------------------
 mm/mempolicy.c                          |   37 ++++++++--------
 2 files changed, 46 insertions(+), 61 deletions(-)
mm/mempolicy.c +19 -18
Index: Linux/mm/mempolicy.c
===================================================================
@@ -104,9 +104,13 @@ static struct kmem_cache *sn_cache;
    policied. */
 enum zone_type policy_zone = 0;
 
+/*
+ * run-time system-wide default policy => local allocation
+ */
 struct mempolicy default_policy = {
 	.refcnt = ATOMIC_INIT(1), /* never free it */
-	.policy = MPOL_DEFAULT,
+	.policy = MPOL_PREFERRED,
+	.v =  { .preferred_node =  -1 },
 };
 
 static void mpol_rebind_policy(struct mempolicy *pol,
@@ -492,8 +496,6 @@ static void get_zonemask(struct mempolic
 			node_set(zone_to_nid(p->v.zonelist->zones[i]),
 				*nodes);
 		break;
-	case MPOL_DEFAULT:
-		break;
 	case MPOL_INTERLEAVE:
 		*nodes = p->v.nodes;
 		break;
@@ -505,7 +507,11 @@ static void get_zonemask(struct mempolic
 			node_set(p->v.preferred_node, *nodes);
 		break;
 	default:
-		BUG();
+		/*
+		 * shouldn't happen
+		 */
+		WARN_ON_ONCE(1);
+		node_set(numa_node_id(), *nodes);
 	}
 }
 
@@ -1087,8 +1093,7 @@ static struct mempolicy * get_vma_policy
 	if (vma) {
 		if (vma->vm_ops && vma->vm_ops->get_policy)
 			pol = vma->vm_ops->get_policy(vma, addr);
-		else if (vma->vm_policy &&
-				vma->vm_policy->policy != MPOL_DEFAULT)
+		else if (vma->vm_policy)
 			pol = vma->vm_policy;
 	}
 	if (!pol)
@@ -1115,12 +1120,11 @@ static struct zonelist *zonelist_policy(
 				return policy->v.zonelist;
 		/*FALL THROUGH*/
 	case MPOL_INTERLEAVE: /* should not happen */
-	case MPOL_DEFAULT:
 		nd = numa_node_id();
 		break;
 	default:
-		nd = 0;
-		BUG();
+		WARN_ON_ONCE(1);
+		nd = numa_node_id();
 	}
 	return NODE_DATA(nd)->node_zonelists + gfp_zone(gfp);
 }
@@ -1350,8 +1354,6 @@ int __mpol_equal(struct mempolicy *a, st
 	if (a->policy != b->policy)
 		return 0;
 	switch (a->policy) {
-	case MPOL_DEFAULT:
-		return 1;
 	case MPOL_INTERLEAVE:
 		return nodes_equal(a->v.nodes, b->v.nodes);
 	case MPOL_PREFERRED:
@@ -1364,7 +1366,7 @@ int __mpol_equal(struct mempolicy *a, st
 		return b->v.zonelist->zones[i] == NULL;
 	}
 	default:
-		BUG();
+		WARN_ON_ONCE(1);
 		return 0;
 	}
 }
@@ -1376,7 +1378,8 @@ void __mpol_free(struct mempolicy *p)
 		return;
 	if (p->policy == MPOL_BIND)
 		kfree(p->v.zonelist);
-	p->policy = MPOL_DEFAULT;
+	p->policy = MPOL_PREFERRED;
+	p->v.preferred_node = -1;
 	kmem_cache_free(policy_cache, p);
 }
 
@@ -1543,7 +1546,7 @@ void mpol_shared_policy_init(struct shar
 	if (policy != MPOL_DEFAULT) {
 		struct mempolicy *newpol;
 
-		/* Falls back to MPOL_DEFAULT on any error */
+		/* Falls back to NULL policy [MPOL_DEFAULT] on any error */
 		newpol = mpol_new(policy, policy_nodes);
 		if (!IS_ERR(newpol)) {
 			/* Create pseudo-vma that contains just the policy */
@@ -1664,8 +1667,6 @@ static void mpol_rebind_policy(struct me
 		return;
 
 	switch (pol->policy) {
-	case MPOL_DEFAULT:
-		break;
 	case MPOL_INTERLEAVE:
 		nodes_remap(tmp, pol->v.nodes, *mpolmask, *newmask);
 		pol->v.nodes = tmp;
@@ -1705,7 +1706,7 @@ static void mpol_rebind_policy(struct me
 		break;
 	}
 	default:
-		BUG();
+		WARN_ON_ONCE(1);
 		break;
 	}
 }
@@ -1774,7 +1775,7 @@ static inline int mpol_to_str(char *buff
 		break;
 
 	default:
-		BUG();
+		WARN_ON_ONCE(1);
 		return -EFAULT;
 	}
 
Documentation/vm/numa_memory_policy.txt +27 -43

90 lines not on this page · raw message

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#1 lore raw
Quoted 6 lines · Lee Schermerhorn

Now, system default policy, except during boot, is "local allocation". By using the MPOL_PREFERRED mode with a negative value of preferred node for system default policy, MPOL_DEFAULT will never occur in the 'policy' member of a struct mempolicy. Thus, we can remove all checks for MPOL_DEFAULT when converting policy to a node id/zonelist in the allocation paths.

Isnt it possible to set a task policy or VMA policy to MPOL_DEFAULT through the API? For the VMA policy this would mean fall back to task policy. Is that still possible?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#2 lore raw
Quoted 9 lines · Christoph Lameter
Quoted 6 lines · Lee Schermerhorn

Now, system default policy, except during boot, is "local allocation". By using the MPOL_PREFERRED mode with a negative value of preferred node for system default policy, MPOL_DEFAULT will never occur in the 'policy' member of a struct mempolicy. Thus, we can remove all checks for MPOL_DEFAULT when converting policy to a node id/zonelist in the allocation paths.

Quoted 3 lines

Isnt it possible to set a task policy or VMA policy to MPOL_DEFAULT through the API? For the VMA policy this would mean fall back to task policy. Is that still possible?

No. mpol_new() returns NULL if policy==MPOL_DEFAULT, so you end up just deleting any existing task policy and replacing it with a NULL pointer. This is pretty cool, I think. I have checked back, but Andi may have done this from day 1.

Lee

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#3 lore raw
Quoted 10 lines · Lee Schermerhorn
Quoted 9 lines · Christoph Lameter
Quoted 6 lines · Lee Schermerhorn

Now, system default policy, except during boot, is "local allocation". By using the MPOL_PREFERRED mode with a negative value of preferred node for system default policy, MPOL_DEFAULT will never occur in the 'policy' member of a struct mempolicy. Thus, we can remove all checks for MPOL_DEFAULT when converting policy to a node id/zonelist in the allocation paths.

Quoted 7 lines
Quoted 3 lines

Isnt it possible to set a task policy or VMA policy to MPOL_DEFAULT through the API? For the VMA policy this would mean fall back to task policy. Is that still possible?

No. mpol_new() returns NULL if policy==MPOL_DEFAULT, so you end up just deleting any existing task policy and replacing it with a NULL pointer. This is pretty cool, I think. I have checked back, but Andi may have

                                   ^^^^ haven't!
Quoted 9 lines

done this from day 1.

Lee

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#4 lore raw
Quoted 11 lines · Lee Schermerhorn
Quoted 10 lines · Lee Schermerhorn
Quoted 9 lines · Christoph Lameter
Quoted 6 lines · Lee Schermerhorn

Now, system default policy, except during boot, is "local allocation". By using the MPOL_PREFERRED mode with a negative value of preferred node for system default policy, MPOL_DEFAULT will never occur in the 'policy' member of a struct mempolicy. Thus, we can remove all checks for MPOL_DEFAULT when converting policy to a node id/zonelist in the allocation paths.

Quoted 10 lines
Quoted 7 lines
Quoted 3 lines

Isnt it possible to set a task policy or VMA policy to MPOL_DEFAULT through the API? For the VMA policy this would mean fall back to task policy. Is that still possible?

No. mpol_new() returns NULL if policy==MPOL_DEFAULT, so you end up just deleting any existing task policy and replacing it with a NULL pointer. This is pretty cool, I think. I have checked back, but Andi may have

                                   ^^^^ haven't!
Quoted 2 lines

done this from day 1.

Christoph, Andi:

Given that the mem policy does the right thing with this patch, can we merge it? I think it cleans up the mem policy concepts to have MPOL_DEFAULT mean "use default policy for this context/scope" rather than have an additional allocation behavior of its own.

I'll update the man pages as well, once you've had a chance to review the current patches that Michael is holding.

Lee

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#5 lore raw
Quoted 4 lines · Lee Schermerhorn

Given that the mem policy does the right thing with this patch, can we merge it? I think it cleans up the mem policy concepts to have MPOL_DEFAULT mean "use default policy for this context/scope" rather than have an additional allocation behavior of its own.

I still have not gotten my head around this one. Lets wait awhile.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#6 lore raw
Quoted 8 lines · Christoph Lameter
Quoted 4 lines · Lee Schermerhorn

Given that the mem policy does the right thing with this patch, can we merge it? I think it cleans up the mem policy concepts to have MPOL_DEFAULT mean "use default policy for this context/scope" rather than have an additional allocation behavior of its own.

I still have not gotten my head around this one. Lets wait awhile.

Well, it doesn't get much additional testing just sitting in my tree.

I have placed WARN_ON_ONCE() and a fall back to local in the 'default:' switch cases where I've removed the MPOL_DEFAULT cases. So, it'll still have the same behavior while warning us that an MPOL_DEFAULT has snuck into a struct mempolicy. There shouldn't be any occurrences of this in the kernel, once system default policy is changed to MPOL_PREFERRED w/ preferred_node == -1. I'd sure like to have more testing exposure, tho'.

Still, if you need more time, please do look at what mpol_new() returns for MPOL_DEFAULT and how that result gets used. From my investigations, system default policy is the only place where MPOL_DEFAULT occurs in a struct mempolicy. Well, that and when we return a mempolicy to the kmem cache--we null out the policy member with MPOL_DEFAULT. I've "fixed" that, too.

Later,
Lee

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#7 lore raw
In reply to Lee Schermerhorn
Quoted 5 lines · Lee Schermerhorn

There is another, "preferred" way to specify local allocation via the APIs. That is using the MPOL_PREFERRED policy mode with an empty nodemask. Internally, the empty nodemask gets converted to a preferred_node id of '-1'. All internal usage of MPOL_PREFERRED will convert the '-1' to the local node id.

But the comparison with an MPOL_PREFERRED policy is different from comparing with a MPOL_DEFAULT policy. MPOL_DEFAULT matches any other policy. MPOL_PREFERRED only matches other MPOL_DEFERRED policies.

Quoted 6 lines

Now, system default policy, except during boot, is "local allocation". By using the MPOL_PREFERRED mode with a negative value of preferred node for system default policy, MPOL_DEFAULT will never occur in the 'policy' member of a struct mempolicy. Thus, we can remove all checks for MPOL_DEFAULT when converting policy to a node id/zonelist in the allocation paths.

So we can also avoid having to check for NULL pointers?

Quoted 19 lines

Note: in slab_node() I kept the use of MPOL_DEFAULT when the policy pointer is NULL to force the switch to take the default:
case. This seemed more efficient than pointing policy at the system default, and having to deref that. Any value not covered by one of the existing case's would have served, but MPOL_DEFAULT is guaranteed to be a different value from any of the other MPOL_* handled explicitly by the switch.

static void mpol_rebind_policy(struct mempolicy *pol,

mm/mempolicy.c +0 -2
@@ -492,8 +496,6 @@ static void get_zonemask(struct mempolic
 			node_set(zone_to_nid(p->v.zonelist->zones[i]),
 				*nodes);
 		break;
-	case MPOL_DEFAULT:
-		break;
 	case MPOL_INTERLEAVE:
 		*nodes = p->v.nodes;
 		break;

mm/mempolicy.c static void get_zonemask(struct mempolic · line 514

Quoted 9 lines
mm/mempolicy.c +5 -1
@@ -505,7 +507,11 @@ static void get_zonemask(struct mempolic
 			node_set(p->v.preferred_node, *nodes);
 		break;
 	default:
-		BUG();
+		/*
+		 * shouldn't happen
+		 */
+		WARN_ON_ONCE(1);
+		node_set(numa_node_id(), *nodes);

Safety features? Are these triggered? Could we leave the BUG() in?

mm/mempolicy.c static struct mempolicy * get_vma_policy · line 1099

Quoted 10 lines
mm/mempolicy.c +1 -2
@@ -1087,8 +1093,7 @@ static struct mempolicy * get_vma_policy
 	if (vma) {
 		if (vma->vm_ops && vma->vm_ops->get_policy)
 			pol = vma->vm_ops->get_policy(vma, addr);
-		else if (vma->vm_policy &&
-				vma->vm_policy->policy != MPOL_DEFAULT)
+		else if (vma->vm_policy)
 			pol = vma->vm_policy;
 	}
 	if (!pol)

Good.

mm/mempolicy.c static struct zonelist *zonelist_policy( · line 1122

Quoted 4 lines
mm/mempolicy.c +0 -0
@@ -1115,12 +1120,11 @@ static struct zonelist *zonelist_policy(
 				return policy->v.zonelist;
 		/*FALL THROUGH*/
 	case MPOL_INTERLEAVE: /* should not happen */

Hmmmm does the MPOL_INTERLEAVE happen at all? Does it also need a WARN_ON?

mm/mempolicy.c void __mpol_free(struct mempolicy *p) · line 1382

Quoted 7 lines
mm/mempolicy.c +2 -1
@@ -1376,7 +1378,8 @@ void __mpol_free(struct mempolicy *p)
 		return;
 	if (p->policy == MPOL_BIND)
 		kfree(p->v.zonelist);
-	p->policy = MPOL_DEFAULT;
+	p->policy = MPOL_PREFERRED;
+	p->v.preferred_node = -1;

Why are we initializing values here in an object that is then freed?

Otherwise looks okay.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#8 lore raw
Quoted 11 lines · Christoph Lameter
Quoted 5 lines · Lee Schermerhorn

There is another, "preferred" way to specify local allocation via the APIs. That is using the MPOL_PREFERRED policy mode with an empty nodemask. Internally, the empty nodemask gets converted to a preferred_node id of '-1'. All internal usage of MPOL_PREFERRED will convert the '-1' to the local node id.

But the comparison with an MPOL_PREFERRED policy is different from comparing with a MPOL_DEFAULT policy. MPOL_DEFAULT matches any other policy. MPOL_PREFERRED only matches other MPOL_DEFERRED policies.

MPOL_DEFAULT doesn't match anything but itself. Everywhere but in the system default policy, specifying MPOL_DEFAULT means "delete the current policy [task or vma] and replace it with a null pointer. Again, the only place that MPOL_DEFAULT actually occurs in a struct mempolicy is in the system default policy. By changing that, I can eliminate the MPOL_DEFAULT checks in the run time [allocation path] use of mempolicy.

Quoted 9 lines
Quoted 7 lines

Now, system default policy, except during boot, is "local allocation". By using the MPOL_PREFERRED mode with a negative value of preferred node for system default policy, MPOL_DEFAULT will never occur in the 'policy' member of a struct mempolicy. Thus, we can remove all checks for MPOL_DEFAULT when converting policy to a node id/zonelist in the allocation paths.

So we can also avoid having to check for NULL pointers?

No, we still check for them, just as we always have been. Look at get_vma_policy(). I removed the check for MPOL_DEFAULT because it never occured in vma policies. But, NULL vma policy means fall back to task policy. NULL task policy means fall back to system default. Just as it always has

Quoted 23 lines
Quoted 23 lines

Note: in slab_node() I kept the use of MPOL_DEFAULT when the policy pointer is NULL to force the switch to take the default:
case. This seemed more efficient than pointing policy at the system default, and having to deref that. Any value not covered by one of the existing case's would have served, but MPOL_DEFAULT is guaranteed to be a different value from any of the other MPOL_* handled explicitly by the switch.

static void mpol_rebind_policy(struct mempolicy *pol,

mm/mempolicy.c +0 -2
@@ -492,8 +496,6 @@ static void get_zonemask(struct mempolic
 			node_set(zone_to_nid(p->v.zonelist->zones[i]),
 				*nodes);
 		break;
-	case MPOL_DEFAULT:
-		break;
 	case MPOL_INTERLEAVE:
 		*nodes = p->v.nodes;
 		break;
@@ -505,7 +507,11 @@ static void get_zonemask(struct mempolic
 			node_set(p->v.preferred_node, *nodes);
 		break;
 	default:
Quoted 8 lines

mm/mempolicy.c static void get_zonemask(struct mempolic · line 514

Quoted 6 lines
mm/mempolicy.c +5 -1
-		BUG();
+		/*
+		 * shouldn't happen
+		 */
+		WARN_ON_ONCE(1);
+		node_set(numa_node_id(), *nodes);

Safety features? Are these triggered? Could we leave the BUG() in?

I haven't seen them triggered. I'm hoping that testing in -mm will not hit them either. I suppose we could leave the BUG. Seems a bit drastic for this case, where we have a reasonable fallback. But, the BUG will more likely get someone's attention, I suppose :-).

Quoted 13 lines

mm/mempolicy.c static struct mempolicy * get_vma_policy · line 1099

Quoted 11 lines
mm/mempolicy.c +1 -2
@@ -1087,8 +1093,7 @@ static struct mempolicy * get_vma_policy
 	if (vma) {
 		if (vma->vm_ops && vma->vm_ops->get_policy)
 			pol = vma->vm_ops->get_policy(vma, addr);
-		else if (vma->vm_policy &&
-				vma->vm_policy->policy != MPOL_DEFAULT)
+		else if (vma->vm_policy)
 			pol = vma->vm_policy;
 	}
 	if (!pol)

Good

Yeah. Eliminates the extra check in the case of a non-NULL vma policy. I'm convinced that check was never true.

Quoted 8 lines

mm/mempolicy.c static struct zonelist *zonelist_policy( · line 1122

Quoted 5 lines
mm/mempolicy.c +0 -0
@@ -1115,12 +1120,11 @@ static struct zonelist *zonelist_policy(
 				return policy->v.zonelist;
 		/*FALL THROUGH*/
 	case MPOL_INTERLEAVE: /* should not happen */

Hmmmm does the MPOL_INTERLEAVE happen at all? Does it also need a WARN_ON?

Quoted 9 lines

mm/mempolicy.c void __mpol_free(struct mempolicy *p) · line 1382

Quoted 7 lines
mm/mempolicy.c +2 -1
@@ -1376,7 +1378,8 @@ void __mpol_free(struct mempolicy *p)
 		return;
 	if (p->policy == MPOL_BIND)
 		kfree(p->v.zonelist);
-	p->policy = MPOL_DEFAULT;
+	p->policy = MPOL_PREFERRED;
+	p->v.preferred_node = -1;

Why are we initializing values here in an object that is then freed?

I wondered that myself. I think Andi was stuffing MPOL_DEFAULT "just in case" or to NULL out the policy member. I just replaced it so that I was sure that MPOL_DEFAULT never occurs in a struct mempolicy. We always initialize the policy member when we alloc one, so I guess we can drop the reinit here.

Quoted 2 lines

Otherwise looks okay.

Thanks. I'll clean it up. Next week. Won't be on-line for a few days.

Later,
Lee

Quoted 1 line

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#9 lore raw
Quoted 10 lines · Lee Schermerhorn
Quoted 3 lines

But the comparison with an MPOL_PREFERRED policy is different from comparing with a MPOL_DEFAULT policy. MPOL_DEFAULT matches any other policy. MPOL_PREFERRED only matches other MPOL_DEFERRED policies.

MPOL_DEFAULT doesn't match anything but itself. Everywhere but in the system default policy, specifying MPOL_DEFAULT means "delete the current policy [task or vma] and replace it with a null pointer. Again, the only place that MPOL_DEFAULT actually occurs in a struct mempolicy is in the system default policy. By changing that, I can eliminate the MPOL_DEFAULT checks in the run time [allocation path] use of mempolicy.

Look at mpol_equal(). If the policy to compare it MPOL_DEFAULT then it returns true. If its MPOL_PREFERRED then it requires a matching on the node. Wont your change break this?

Quoted 6 lines
Quoted 1 line

Safety features? Are these triggered? Could we leave the BUG() in?

I haven't seen them triggered. I'm hoping that testing in -mm will not hit them either. I suppose we could leave the BUG. Seems a bit drastic for this case, where we have a reasonable fallback. But, the BUG will more likely get someone's attention, I suppose :-).

So you have never seen warnings in testing and there should not be any? Then leave the BUG() in. WARN is useful if there is something that another developer could fix.

Quoted 10 lines
Quoted 9 lines

mm/mempolicy.c void __mpol_free(struct mempolicy *p) · line 1382

Quoted 7 lines
mm/mempolicy.c +2 -1
@@ -1376,7 +1378,8 @@ void __mpol_free(struct mempolicy *p)
 		return;
 	if (p->policy == MPOL_BIND)
 		kfree(p->v.zonelist);
-	p->policy = MPOL_DEFAULT;
+	p->policy = MPOL_PREFERRED;
+	p->v.preferred_node = -1;

Why are we initializing values here in an object that is then freed?

Quoted 5 lines

I wondered that myself. I think Andi was stuffing MPOL_DEFAULT "just in case" or to NULL out the policy member. I just replaced it so that I was sure that MPOL_DEFAULT never occurs in a struct mempolicy. We always initialize the policy member when we alloc one, so I guess we can drop the reinit here.

I'd say remove the useless assignements. They are confusing.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#10 lore raw
Quoted 13 lines · Christoph Lameter
Quoted 10 lines · Lee Schermerhorn
Quoted 3 lines

But the comparison with an MPOL_PREFERRED policy is different from comparing with a MPOL_DEFAULT policy. MPOL_DEFAULT matches any other policy. MPOL_PREFERRED only matches other MPOL_DEFERRED policies.

MPOL_DEFAULT doesn't match anything but itself. Everywhere but in the system default policy, specifying MPOL_DEFAULT means "delete the current policy [task or vma] and replace it with a null pointer. Again, the only place that MPOL_DEFAULT actually occurs in a struct mempolicy is in the system default policy. By changing that, I can eliminate the MPOL_DEFAULT checks in the run time [allocation path] use of mempolicy.

Quoted 3 lines

Look at mpol_equal(). If the policy to compare it MPOL_DEFAULT then it returns true. If its MPOL_PREFERRED then it requires a matching on the node. Wont your change break this?

Shouldn't. I removed that check [from __mpol_equal()]. But, that should be OK, because in the mpol_equal() static inline wrapper, we return true of the policy pointers are equal--includes both being NULL. Again, we'll never see MPOL_DEFAULT in a mempolicy structure's policy member, if this change goes in. All attempts to set a default policy will install a NULL struct mempolicy pointer.

Quoted 11 lines
Quoted 7 lines
Quoted 2 lines

Safety features? Are these triggered? Could we leave the BUG() in?

I haven't seen them triggered. I'm hoping that testing in -mm will not hit them either. I suppose we could leave the BUG. Seems a bit drastic for this case, where we have a reasonable fallback. But, the BUG will more likely get someone's attention, I suppose :-).

So you have never seen warnings in testing and there should not be any? Then leave the BUG() in. WARN is useful if there is something that another developer could fix.

OK, I reverted all of those changes.

Quoted 11 lines
Quoted 11 lines
Quoted 10 lines

mm/mempolicy.c void __mpol_free(struct mempolicy *p) · line 1382

Quoted 8 lines
mm/mempolicy.c +2 -1
@@ -1376,7 +1378,8 @@ void __mpol_free(struct mempolicy *p)
 		return;
 	if (p->policy == MPOL_BIND)
 		kfree(p->v.zonelist);
-	p->policy = MPOL_DEFAULT;
+	p->policy = MPOL_PREFERRED;
+	p->v.preferred_node = -1;

Why are we initializing values here in an object that is then freed?

Quoted 7 lines
Quoted 5 lines

I wondered that myself. I think Andi was stuffing MPOL_DEFAULT "just in case" or to NULL out the policy member. I just replaced it so that I was sure that MPOL_DEFAULT never occurs in a struct mempolicy. We always initialize the policy member when we alloc one, so I guess we can drop the reinit here.

I'd say remove the useless assignements. They are confusing.

OK. Looks like mpol_new() and __mpol_copy()--the two places where we allocate from the 'policy_cache'--will correctly initialize the policy member of the allocated mempolicy. So, no worries re: stale policy member.

I'll repost the cleaned up patch later this week.

Lee

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>