Re: OOM behavior in constrained memory situations

From: Christoph Lameter
Date: Tue Feb 07 2006 - 13:59:07 EST


On Tue, 7 Feb 2006, Andi Kleen wrote:

> On Tuesday 07 February 2006 19:19, Christoph Lameter wrote:
>
> > @@ -1261,7 +1261,7 @@ struct page *alloc_pages_current(gfp_t g
> > cpuset_update_task_memory_state();
> > if (!pol || in_interrupt())
> > pol = &default_policy;
> > - gfp |= pol->gfp_flags;
> > + gfp |= (pol->gfp_flags_high << 16);
>
> Why don't you put it into zonelist_policy and pass a pointer to gfp
> and then only do it for MPOL_BIND? The code should be similar because
> it should be inline anyways (perhaps add a force_inline to be sure)

Like this?

Index: linux-2.6.16-rc2/mm/mempolicy.c
===================================================================
--- linux-2.6.16-rc2.orig/mm/mempolicy.c 2006-02-07 10:14:43.000000000 -0800
+++ linux-2.6.16-rc2/mm/mempolicy.c 2006-02-07 10:58:55.000000000 -0800
@@ -162,9 +162,9 @@ static struct mempolicy *mpol_new(int mo
return ERR_PTR(-ENOMEM);
atomic_set(&policy->refcnt, 1);

- policy->gfp_flags = 0;
+ policy->flags = 0;
if (!nodes_equal(*nodes, node_online_map))
- policy->gfp_flags |= __GFP_NO_OOM_KILLER;
+ policy->flags = 1;

switch (mode) {
case MPOL_INTERLEAVE:
@@ -1064,7 +1064,7 @@ static struct mempolicy * get_vma_policy
}

/* Return a zonelist representing a mempolicy */
-static struct zonelist *zonelist_policy(gfp_t gfp, struct mempolicy *policy)
+static struct zonelist *zonelist_policy(gfp_t *gfp, struct mempolicy *policy)
{
int nd;

@@ -1077,9 +1077,12 @@ static struct zonelist *zonelist_policy(
case MPOL_BIND:
/* Lower zones don't get a policy applied */
/* Careful: current->mems_allowed might have moved */
- if (gfp_zone(gfp) >= policy_zone)
- if (cpuset_zonelist_valid_mems_allowed(policy->v.zonelist))
+ if (gfp_zone(*gfp) >= policy_zone)
+ if (cpuset_zonelist_valid_mems_allowed(policy->v.zonelist)) {
+ if (policy->flags)
+ *gfp |= __GFP_NO_OOM_KILLER;
return policy->v.zonelist;
+ }
/*FALL THROUGH*/
case MPOL_INTERLEAVE: /* should not happen */
case MPOL_DEFAULT:
@@ -1089,7 +1092,7 @@ static struct zonelist *zonelist_policy(
nd = 0;
BUG();
}
- return NODE_DATA(nd)->node_zonelists + gfp_zone(gfp);
+ return NODE_DATA(nd)->node_zonelists + gfp_zone(*gfp);
}

/* Do dynamic interleaving for a process */
@@ -1168,14 +1171,15 @@ static inline unsigned interleave_nid(st
struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr)
{
struct mempolicy *pol = get_vma_policy(current, vma, addr);
-
+ gfp_t gfp = GFP_HIGHUSER;
+
if (pol->policy == MPOL_INTERLEAVE) {
unsigned nid;

nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT);
- return NODE_DATA(nid)->node_zonelists + gfp_zone(GFP_HIGHUSER);
+ return NODE_DATA(nid)->node_zonelists + gfp_zone(gfp);
}
- return zonelist_policy(GFP_HIGHUSER, pol);
+ return zonelist_policy(&gfp, pol);
}

/* Allocate a page in interleaved policy.
@@ -1224,14 +1228,13 @@ alloc_page_vma(gfp_t gfp, struct vm_area

cpuset_update_task_memory_state();

- gfp |= pol->gfp_flags;
if (unlikely(pol->policy == MPOL_INTERLEAVE)) {
unsigned nid;

nid = interleave_nid(pol, vma, addr, PAGE_SHIFT);
return alloc_page_interleave(gfp, 0, nid);
}
- return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol));
+ return __alloc_pages(gfp, 0, zonelist_policy(&gfp, pol));
}

/**
@@ -1261,10 +1264,9 @@ struct page *alloc_pages_current(gfp_t g
cpuset_update_task_memory_state();
if (!pol || in_interrupt())
pol = &default_policy;
- gfp |= pol->gfp_flags;
if (pol->policy == MPOL_INTERLEAVE)
return alloc_page_interleave(gfp, order, interleave_nodes(pol));
- return __alloc_pages(gfp, order, zonelist_policy(gfp, pol));
+ return __alloc_pages(gfp, order, zonelist_policy(&gfp, pol));
}
EXPORT_SYMBOL(alloc_pages_current);

@@ -1598,7 +1600,7 @@ void mpol_rebind_policy(struct mempolicy
return;

if (!nodes_equal(*newmask, node_online_map))
- pol->gfp_flags |= __GFP_NO_OOM_KILLER;
+ pol->flags = 1;

switch (pol->policy) {
case MPOL_DEFAULT:
Index: linux-2.6.16-rc2/include/linux/mempolicy.h
===================================================================
--- linux-2.6.16-rc2.orig/include/linux/mempolicy.h 2006-02-07 10:14:43.000000000 -0800
+++ linux-2.6.16-rc2/include/linux/mempolicy.h 2006-02-07 10:57:30.000000000 -0800
@@ -62,7 +62,7 @@ struct vm_area_struct;
struct mempolicy {
atomic_t refcnt;
short policy; /* See MPOL_* above */
- gfp_t gfp_flags; /* flags ORed into gfp_flags for each allocation */
+ short flags; /* 1 = Set __GFP_NO_OOM_KILLER on allocation for BIND */
union {
struct zonelist *zonelist; /* bind */
short preferred_node; /* preferred */

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/