As a side-effect, it also checks for negative totals (elsewhere reported
as 0) and "fails" with EINVAL if any are found, with a warning in dmesg.
-(At time of writing, a few stats are known sometimes to be found negative,
-with no ill effects: errors and warnings on these stats are suppressed.)
+(On a SMP machine some stats can temporarily become negative, with no ill
+effects: errors and warnings on these stats are suppressed.)
numa_stat
#ifdef CONFIG_SMP
+#define MAX_THRESHOLD 125
+
int calculate_pressure_threshold(struct zone *zone)
{
int threshold;
threshold = max(1, (int)(watermark_distance / num_online_cpus()));
/*
- * Maximum threshold is 125
+ * Threshold is capped by MAX_THRESHOLD
*/
- threshold = min(125, threshold);
-
- return threshold;
+ return min(MAX_THRESHOLD, threshold);
}
int calculate_normal_threshold(struct zone *zone)
}
EXPORT_SYMBOL(dec_node_page_state);
#else
+
+#define MAX_THRESHOLD 0
+
/*
* Use interrupt disable to serialize counter updates
*/
int vmstat_refresh(struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
- long val;
+ long val, max_drift;
int err;
int i;
* pages, immediately after running a test. /proc/sys/vm/stat_refresh,
* which can equally be echo'ed to or cat'ted from (by root),
* can be used to update the stats just before reading them.
- *
- * Oh, and since global_zone_page_state() etc. are so careful to hide
- * transiently negative values, report an error here if any of
- * the stats is negative, so we know to go looking for imbalance.
*/
err = schedule_on_each_cpu(refresh_vm_stats);
if (err)
return err;
+
+ /*
+ * Since global_zone_page_state() etc. are so careful to hide
+ * transiently negative values, report an error here if any of
+ * the stats is negative and are less than the maximum drift value,
+ * so we know to go looking for imbalance.
+ */
+ max_drift = num_online_cpus() * MAX_THRESHOLD;
+
for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) {
val = atomic_long_read(&vm_zone_stat[i]);
- if (val < 0) {
+ if (val < -max_drift) {
pr_warn("%s: %s %ld\n",
__func__, zone_stat_name(i), val);
err = -EINVAL;
#ifdef CONFIG_NUMA
for (i = 0; i < NR_VM_NUMA_STAT_ITEMS; i++) {
val = atomic_long_read(&vm_numa_stat[i]);
- if (val < 0) {
+ if (val < -max_drift) {
pr_warn("%s: %s %ld\n",
__func__, numa_stat_name(i), val);
err = -EINVAL;