|
@@ -69,6 +69,7 @@
|
|
|
|
|
|
/* prevent >1 _updater_ of zone percpu pageset ->high and ->batch fields */
|
|
/* prevent >1 _updater_ of zone percpu pageset ->high and ->batch fields */
|
|
static DEFINE_MUTEX(pcp_batch_high_lock);
|
|
static DEFINE_MUTEX(pcp_batch_high_lock);
|
|
|
|
+#define MIN_PERCPU_PAGELIST_FRACTION (8)
|
|
|
|
|
|
#ifdef CONFIG_USE_PERCPU_NUMA_NODE_ID
|
|
#ifdef CONFIG_USE_PERCPU_NUMA_NODE_ID
|
|
DEFINE_PER_CPU(int, numa_node);
|
|
DEFINE_PER_CPU(int, numa_node);
|
|
@@ -4145,7 +4146,7 @@ static void __meminit zone_init_free_lists(struct zone *zone)
|
|
memmap_init_zone((size), (nid), (zone), (start_pfn), MEMMAP_EARLY)
|
|
memmap_init_zone((size), (nid), (zone), (start_pfn), MEMMAP_EARLY)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
-static int __meminit zone_batchsize(struct zone *zone)
|
|
|
|
|
|
+static int zone_batchsize(struct zone *zone)
|
|
{
|
|
{
|
|
#ifdef CONFIG_MMU
|
|
#ifdef CONFIG_MMU
|
|
int batch;
|
|
int batch;
|
|
@@ -4261,8 +4262,8 @@ static void pageset_set_high(struct per_cpu_pageset *p,
|
|
pageset_update(&p->pcp, high, batch);
|
|
pageset_update(&p->pcp, high, batch);
|
|
}
|
|
}
|
|
|
|
|
|
-static void __meminit pageset_set_high_and_batch(struct zone *zone,
|
|
|
|
- struct per_cpu_pageset *pcp)
|
|
|
|
|
|
+static void pageset_set_high_and_batch(struct zone *zone,
|
|
|
|
+ struct per_cpu_pageset *pcp)
|
|
{
|
|
{
|
|
if (percpu_pagelist_fraction)
|
|
if (percpu_pagelist_fraction)
|
|
pageset_set_high(pcp,
|
|
pageset_set_high(pcp,
|
|
@@ -5881,23 +5882,38 @@ int percpu_pagelist_fraction_sysctl_handler(struct ctl_table *table, int write,
|
|
void __user *buffer, size_t *length, loff_t *ppos)
|
|
void __user *buffer, size_t *length, loff_t *ppos)
|
|
{
|
|
{
|
|
struct zone *zone;
|
|
struct zone *zone;
|
|
- unsigned int cpu;
|
|
|
|
|
|
+ int old_percpu_pagelist_fraction;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
|
|
+ mutex_lock(&pcp_batch_high_lock);
|
|
|
|
+ old_percpu_pagelist_fraction = percpu_pagelist_fraction;
|
|
|
|
+
|
|
ret = proc_dointvec_minmax(table, write, buffer, length, ppos);
|
|
ret = proc_dointvec_minmax(table, write, buffer, length, ppos);
|
|
- if (!write || (ret < 0))
|
|
|
|
- return ret;
|
|
|
|
|
|
+ if (!write || ret < 0)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ /* Sanity checking to avoid pcp imbalance */
|
|
|
|
+ if (percpu_pagelist_fraction &&
|
|
|
|
+ percpu_pagelist_fraction < MIN_PERCPU_PAGELIST_FRACTION) {
|
|
|
|
+ percpu_pagelist_fraction = old_percpu_pagelist_fraction;
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* No change? */
|
|
|
|
+ if (percpu_pagelist_fraction == old_percpu_pagelist_fraction)
|
|
|
|
+ goto out;
|
|
|
|
|
|
- mutex_lock(&pcp_batch_high_lock);
|
|
|
|
for_each_populated_zone(zone) {
|
|
for_each_populated_zone(zone) {
|
|
- unsigned long high;
|
|
|
|
- high = zone->managed_pages / percpu_pagelist_fraction;
|
|
|
|
|
|
+ unsigned int cpu;
|
|
|
|
+
|
|
for_each_possible_cpu(cpu)
|
|
for_each_possible_cpu(cpu)
|
|
- pageset_set_high(per_cpu_ptr(zone->pageset, cpu),
|
|
|
|
- high);
|
|
|
|
|
|
+ pageset_set_high_and_batch(zone,
|
|
|
|
+ per_cpu_ptr(zone->pageset, cpu));
|
|
}
|
|
}
|
|
|
|
+out:
|
|
mutex_unlock(&pcp_batch_high_lock);
|
|
mutex_unlock(&pcp_batch_high_lock);
|
|
- return 0;
|
|
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
int hashdist = HASHDIST_DEFAULT;
|
|
int hashdist = HASHDIST_DEFAULT;
|