|
@@ -196,27 +196,46 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
|
|
/*
|
|
/*
|
|
* Determine the type of allocation constraint.
|
|
* Determine the type of allocation constraint.
|
|
*/
|
|
*/
|
|
-static inline enum oom_constraint constrained_alloc(struct zonelist *zonelist,
|
|
|
|
- gfp_t gfp_mask)
|
|
|
|
-{
|
|
|
|
#ifdef CONFIG_NUMA
|
|
#ifdef CONFIG_NUMA
|
|
|
|
+static enum oom_constraint constrained_alloc(struct zonelist *zonelist,
|
|
|
|
+ gfp_t gfp_mask, nodemask_t *nodemask)
|
|
|
|
+{
|
|
struct zone *zone;
|
|
struct zone *zone;
|
|
struct zoneref *z;
|
|
struct zoneref *z;
|
|
enum zone_type high_zoneidx = gfp_zone(gfp_mask);
|
|
enum zone_type high_zoneidx = gfp_zone(gfp_mask);
|
|
- nodemask_t nodes = node_states[N_HIGH_MEMORY];
|
|
|
|
|
|
|
|
- for_each_zone_zonelist(zone, z, zonelist, high_zoneidx)
|
|
|
|
- if (cpuset_zone_allowed_softwall(zone, gfp_mask))
|
|
|
|
- node_clear(zone_to_nid(zone), nodes);
|
|
|
|
- else
|
|
|
|
- return CONSTRAINT_CPUSET;
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Reach here only when __GFP_NOFAIL is used. So, we should avoid
|
|
|
|
+ * to kill current.We have to random task kill in this case.
|
|
|
|
+ * Hopefully, CONSTRAINT_THISNODE...but no way to handle it, now.
|
|
|
|
+ */
|
|
|
|
+ if (gfp_mask & __GFP_THISNODE)
|
|
|
|
+ return CONSTRAINT_NONE;
|
|
|
|
|
|
- if (!nodes_empty(nodes))
|
|
|
|
|
|
+ /*
|
|
|
|
+ * The nodemask here is a nodemask passed to alloc_pages(). Now,
|
|
|
|
+ * cpuset doesn't use this nodemask for its hardwall/softwall/hierarchy
|
|
|
|
+ * feature. mempolicy is an only user of nodemask here.
|
|
|
|
+ * check mempolicy's nodemask contains all N_HIGH_MEMORY
|
|
|
|
+ */
|
|
|
|
+ if (nodemask && !nodes_subset(node_states[N_HIGH_MEMORY], *nodemask))
|
|
return CONSTRAINT_MEMORY_POLICY;
|
|
return CONSTRAINT_MEMORY_POLICY;
|
|
-#endif
|
|
|
|
|
|
+
|
|
|
|
+ /* Check this allocation failure is caused by cpuset's wall function */
|
|
|
|
+ for_each_zone_zonelist_nodemask(zone, z, zonelist,
|
|
|
|
+ high_zoneidx, nodemask)
|
|
|
|
+ if (!cpuset_zone_allowed_softwall(zone, gfp_mask))
|
|
|
|
+ return CONSTRAINT_CPUSET;
|
|
|
|
|
|
return CONSTRAINT_NONE;
|
|
return CONSTRAINT_NONE;
|
|
}
|
|
}
|
|
|
|
+#else
|
|
|
|
+static enum oom_constraint constrained_alloc(struct zonelist *zonelist,
|
|
|
|
+ gfp_t gfp_mask, nodemask_t *nodemask)
|
|
|
|
+{
|
|
|
|
+ return CONSTRAINT_NONE;
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
|
|
/*
|
|
/*
|
|
* Simple selection loop. We chose the process with the highest
|
|
* Simple selection loop. We chose the process with the highest
|
|
@@ -613,7 +632,8 @@ rest_and_return:
|
|
* OR try to be smart about which process to kill. Note that we
|
|
* OR try to be smart about which process to kill. Note that we
|
|
* don't have to be perfect here, we just have to be good.
|
|
* don't have to be perfect here, we just have to be good.
|
|
*/
|
|
*/
|
|
-void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
|
|
|
|
|
|
+void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
|
|
|
|
+ int order, nodemask_t *nodemask)
|
|
{
|
|
{
|
|
unsigned long freed = 0;
|
|
unsigned long freed = 0;
|
|
enum oom_constraint constraint;
|
|
enum oom_constraint constraint;
|
|
@@ -632,7 +652,7 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
|
|
* Check if there were limitations on the allocation (only relevant for
|
|
* Check if there were limitations on the allocation (only relevant for
|
|
* NUMA) that may require different handling.
|
|
* NUMA) that may require different handling.
|
|
*/
|
|
*/
|
|
- constraint = constrained_alloc(zonelist, gfp_mask);
|
|
|
|
|
|
+ constraint = constrained_alloc(zonelist, gfp_mask, nodemask);
|
|
read_lock(&tasklist_lock);
|
|
read_lock(&tasklist_lock);
|
|
|
|
|
|
switch (constraint) {
|
|
switch (constraint) {
|