linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@kernel.org
Cc: stable-review@kernel.org, torvalds@linux-foundation.org,
	akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk,
	Christoph Lameter <cl@linux.com>, Mel Gorman <mel@csn.ul.ie>
Subject: [74/80] mm: page allocator: calculate a better estimate of NR_FREE_PAGES when memory is low and kswapd is awake
Date: Fri, 24 Sep 2010 09:25:02 -0700	[thread overview]
Message-ID: <20100924162621.373149171@clark.site> (raw)
In-Reply-To: <20100924162706.GA7381@kroah.com>

2.6.35-stable review patch.  If anyone has any objections, please let us know.

------------------

From: Christoph Lameter <cl@linux.com>

commit aa45484031ddee09b06350ab8528bfe5b2c76d1c upstream.

Ordinarily watermark checks are based on the vmstat NR_FREE_PAGES as it is
cheaper than scanning a number of lists.  To avoid synchronization
overhead, counter deltas are maintained on a per-cpu basis and drained
both periodically and when the delta is above a threshold.  On large CPU
systems, the difference between the estimated and real value of
NR_FREE_PAGES can be very high.  If NR_FREE_PAGES is much higher than
number of real free page in buddy, the VM can allocate pages below min
watermark, at worst reducing the real number of pages to zero.  Even if
the OOM killer kills some victim for freeing memory, it may not free
memory if the exit path requires a new page resulting in livelock.

This patch introduces a zone_page_state_snapshot() function (courtesy of
Christoph) that takes a slightly more accurate view of an arbitrary vmstat
counter.  It is used to read NR_FREE_PAGES while kswapd is awake to avoid
the watermark being accidentally broken.  The estimate is not perfect and
may result in cache line bounces but is expected to be lighter than the
IPI calls necessary to continually drain the per-cpu counters while kswapd
is awake.

Signed-off-by: Christoph Lameter <cl@linux.com>
Signed-off-by: Mel Gorman <mel@csn.ul.ie>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 include/linux/mmzone.h |   13 +++++++++++++
 include/linux/vmstat.h |   22 ++++++++++++++++++++++
 mm/mmzone.c            |   21 +++++++++++++++++++++
 mm/page_alloc.c        |    4 ++--
 mm/vmstat.c            |   15 ++++++++++++++-
 5 files changed, 72 insertions(+), 3 deletions(-)

--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -284,6 +284,13 @@ struct zone {
 	unsigned long watermark[NR_WMARK];
 
 	/*
+	 * When free pages are below this point, additional steps are taken
+	 * when reading the number of free pages to avoid per-cpu counter
+	 * drift allowing watermarks to be breached
+	 */
+	unsigned long percpu_drift_mark;
+
+	/*
 	 * We don't know if the memory that we're going to allocate will be freeable
 	 * or/and it will be released eventually, so to avoid totally wasting several
 	 * GB of ram we must reserve some of the lower zone memory (otherwise we risk
@@ -456,6 +463,12 @@ static inline int zone_is_oom_locked(con
 	return test_bit(ZONE_OOM_LOCKED, &zone->flags);
 }
 
+#ifdef CONFIG_SMP
+unsigned long zone_nr_free_pages(struct zone *zone);
+#else
+#define zone_nr_free_pages(zone) zone_page_state(zone, NR_FREE_PAGES)
+#endif /* CONFIG_SMP */
+
 /*
  * The "priority" of VM scanning is how much of the queues we will scan in one
  * go. A value of 12 for DEF_PRIORITY implies that we will scan 1/4096th of the
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -170,6 +170,28 @@ static inline unsigned long zone_page_st
 	return x;
 }
 
+/*
+ * More accurate version that also considers the currently pending
+ * deltas. For that we need to loop over all cpus to find the current
+ * deltas. There is no synchronization so the result cannot be
+ * exactly accurate either.
+ */
+static inline unsigned long zone_page_state_snapshot(struct zone *zone,
+					enum zone_stat_item item)
+{
+	long x = atomic_long_read(&zone->vm_stat[item]);
+
+#ifdef CONFIG_SMP
+	int cpu;
+	for_each_online_cpu(cpu)
+		x += per_cpu_ptr(zone->pageset, cpu)->vm_stat_diff[item];
+
+	if (x < 0)
+		x = 0;
+#endif
+	return x;
+}
+
 extern unsigned long global_reclaimable_pages(void);
 extern unsigned long zone_reclaimable_pages(struct zone *zone);
 
--- a/mm/mmzone.c
+++ b/mm/mmzone.c
@@ -87,3 +87,24 @@ int memmap_valid_within(unsigned long pf
 	return 1;
 }
 #endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */
+
+#ifdef CONFIG_SMP
+/* Called when a more accurate view of NR_FREE_PAGES is needed */
+unsigned long zone_nr_free_pages(struct zone *zone)
+{
+	unsigned long nr_free_pages = zone_page_state(zone, NR_FREE_PAGES);
+
+	/*
+	 * While kswapd is awake, it is considered the zone is under some
+	 * memory pressure. Under pressure, there is a risk that
+	 * per-cpu-counter-drift will allow the min watermark to be breached
+	 * potentially causing a live-lock. While kswapd is awake and
+	 * free pages are low, get a better estimate for free pages
+	 */
+	if (nr_free_pages < zone->percpu_drift_mark &&
+			!waitqueue_active(&zone->zone_pgdat->kswapd_wait))
+		return zone_page_state_snapshot(zone, NR_FREE_PAGES);
+
+	return nr_free_pages;
+}
+#endif /* CONFIG_SMP */
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1461,7 +1461,7 @@ int zone_watermark_ok(struct zone *z, in
 {
 	/* free_pages my go negative - that's OK */
 	long min = mark;
-	long free_pages = zone_page_state(z, NR_FREE_PAGES) - (1 << order) + 1;
+	long free_pages = zone_nr_free_pages(z) - (1 << order) + 1;
 	int o;
 
 	if (alloc_flags & ALLOC_HIGH)
@@ -2424,7 +2424,7 @@ void show_free_areas(void)
 			" all_unreclaimable? %s"
 			"\n",
 			zone->name,
-			K(zone_page_state(zone, NR_FREE_PAGES)),
+			K(zone_nr_free_pages(zone)),
 			K(min_wmark_pages(zone)),
 			K(low_wmark_pages(zone)),
 			K(high_wmark_pages(zone)),
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -138,11 +138,24 @@ static void refresh_zone_stat_thresholds
 	int threshold;
 
 	for_each_populated_zone(zone) {
+		unsigned long max_drift, tolerate_drift;
+
 		threshold = calculate_threshold(zone);
 
 		for_each_online_cpu(cpu)
 			per_cpu_ptr(zone->pageset, cpu)->stat_threshold
 							= threshold;
+
+		/*
+		 * Only set percpu_drift_mark if there is a danger that
+		 * NR_FREE_PAGES reports the low watermark is ok when in fact
+		 * the min watermark could be breached by an allocation
+		 */
+		tolerate_drift = low_wmark_pages(zone) - min_wmark_pages(zone);
+		max_drift = num_online_cpus() * threshold;
+		if (max_drift > tolerate_drift)
+			zone->percpu_drift_mark = high_wmark_pages(zone) +
+					max_drift;
 	}
 }
 
@@ -813,7 +826,7 @@ static void zoneinfo_show_print(struct s
 		   "\n        scanned  %lu"
 		   "\n        spanned  %lu"
 		   "\n        present  %lu",
-		   zone_page_state(zone, NR_FREE_PAGES),
+		   zone_nr_free_pages(zone),
 		   min_wmark_pages(zone),
 		   low_wmark_pages(zone),
 		   high_wmark_pages(zone),



  parent reply	other threads:[~2010-09-24 16:30 UTC|newest]

Thread overview: 99+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-09-24 16:27 [00/80] 2.6.35.6 stable review Greg KH
2010-09-24 16:23 ` [01/80] usb: musb_debugfs: dont use the struct file private_data field with seq_files Greg KH
2010-09-24 16:23 ` [02/80] USB: serial/mos*: prevent reading uninitialized stack memory Greg KH
2010-09-24 16:23 ` [03/80] bridge: Clear INET control block of SKBs passed into ip_fragment() Greg KH
2010-09-24 16:23 ` [04/80] gro: fix different skb headrooms Greg KH
2010-09-24 16:23 ` [05/80] gro: Re-fix " Greg KH
2010-09-24 16:23 ` [06/80] irda: Correctly clean up self->ias_obj on irda_bind() failure Greg KH
2010-09-24 16:23 ` [07/80] rds: fix a leak of kernel memory Greg KH
2010-09-24 16:23 ` [08/80] net: RPS needs to depend upon USE_GENERIC_SMP_HELPERS Greg KH
2010-09-24 16:23 ` [09/80] tcp: Combat per-cpu skew in orphan tests Greg KH
2010-09-24 16:23 ` [10/80] tcp: fix three tcp sysctls tuning Greg KH
2010-09-24 16:23 ` [11/80] tcp: select(writefds) dont hang up when a peer close connection Greg KH
2010-09-24 16:24 ` [12/80] tcp: Prevent overzealous packetization by SWS logic Greg KH
2010-09-24 16:24 ` [13/80] udp: add rehash on connect() Greg KH
2010-09-24 16:24 ` [14/80] UNIX: Do not loop forever at unix_autobind() Greg KH
2010-09-24 16:24 ` [15/80] l2tp: test for ethernet header in l2tp_eth_dev_recv() Greg KH
2010-09-24 16:24 ` [16/80] net: blackhole route should always be recalculated Greg KH
2010-09-24 16:24 ` [17/80] sparc64: Get rid of indirect p1275 PROM call buffer Greg KH
2010-09-24 16:24 ` [18/80] drivers/net/usb/hso.c: prevent reading uninitialized memory Greg KH
2010-09-24 16:24 ` [19/80] drivers/net/cxgb3/cxgb3_main.c: prevent reading uninitialized stack memory Greg KH
2010-09-24 16:24 ` [20/80] drivers/net/eql.c: " Greg KH
2010-09-24 16:24 ` [21/80] bonding: correctly process non-linear skbs Greg KH
2010-09-24 16:24 ` [22/80] Staging: vt6655: fix buffer overflow Greg KH
2010-09-24 16:24 ` [23/80] net/llc: make opt unsigned in llc_ui_setsockopt() Greg KH
2010-09-24 16:24 ` [24/80] mm: fix swapin race condition Greg KH
2010-09-24 16:24 ` [25/80] mm: further " Greg KH
2010-09-24 16:24 ` [26/80] virtio: console: Prevent userspace from submitting NULL buffers Greg KH
2010-09-24 16:24 ` [27/80] virtio: console: Fix poll blocking even though there is data to read Greg KH
2010-09-24 16:24 ` [28/80] intel_agp, drm/i915: Add all sandybridge graphics devices support Greg KH
2010-09-24 16:24 ` [29/80] agp/intel: fix physical address mask bits for sandybridge Greg KH
2010-09-24 16:24 ` [30/80] agp/intel: fix dma mask bits on sandybridge Greg KH
2010-09-24 16:24 ` [31/80] hw breakpoints: Fix pid namespace bug Greg KH
2010-09-24 16:24 ` [32/80] pid: make setpgid() system call use RCU read-side critical section Greg KH
2010-09-24 16:24 ` [33/80] sched: Fix user time incorrectly accounted as system time on 32-bit Greg KH
2010-09-24 16:24 ` [34/80] oprofile: Add Support for Intel CPU Family 6 / Model 22 (Intel Celeron 540) Greg KH
2010-09-24 16:24 ` [35/80] drm/i915,agp/intel: Add second set of PCI-IDs for B43 Greg KH
2010-09-24 16:24 ` [36/80] bdi: Initialize noop_backing_dev_info properly Greg KH
2010-09-24 16:24 ` [37/80] bdi: Fix warnings in __mark_inode_dirty for /dev/zero and friends Greg KH
2010-09-24 16:24 ` [38/80] char: Mark /dev/zero and /dev/kmem as not capable of writeback Greg KH
2010-09-24 16:24 ` [39/80] drivers/pci/intel-iommu.c: fix build with older gccs Greg KH
2010-09-24 16:24 ` [40/80] mmap: call unlink_anon_vmas() in __split_vma() in case of error Greg KH
2010-09-24 16:24 ` [41/80] drivers/video/sis/sis_main.c: prevent reading uninitialized stack memory Greg KH
2010-09-24 16:24 ` [42/80] rtc: s3c: balance state changes of wakeup flag Greg KH
2010-09-24 16:24 ` [43/80] Prevent freeing uninitialized pointer in compat_do_readv_writev Greg KH
2010-09-24 16:24 ` [44/80] /proc/vmcore: fix seeking Greg KH
2010-09-24 16:24 ` [45/80] vmscan: check all_unreclaimable in direct reclaim path Greg KH
2010-09-24 16:24 ` [46/80] percpu: fix pcpu_last_unit_cpu Greg KH
2010-09-24 16:24 ` [47/80] aio: do not return ERESTARTSYS as a result of AIO Greg KH
2010-09-24 16:24 ` [48/80] aio: check for multiplication overflow in do_io_submit Greg KH
2010-09-24 16:24 ` [49/80] x86 platform drivers: hp-wmi Reorder event id processing Greg KH
2010-09-24 16:24 ` [50/80] GFS2: gfs2_logd should be using interruptible waits Greg KH
2010-09-24 16:24 ` [51/80] drm/nv50: initialize ramht_refs list for faked 0 channel Greg KH
2010-09-24 16:24 ` [52/80] inotify: send IN_UNMOUNT events Greg KH
2010-09-24 16:24 ` [53/80] SCSI: mptsas: fix hangs caused by ATA pass-through Greg KH
2010-09-27 17:47   ` John Drescher
2010-09-24 16:24 ` [54/80] KVM: Keep slot ID in memory slot structure Greg KH
2010-09-24 16:24 ` [55/80] KVM: Prevent internal slots from being COWed Greg KH
2010-09-24 16:24 ` [56/80] KVM: MMU: fix direct sps access corrupted Greg KH
2010-09-24 16:24 ` [57/80] KVM: x86: emulator: inc/dec can have lock prefix Greg KH
2010-09-24 16:24 ` [58/80] KVM: MMU: fix mmu notifier invalidate handler for huge spte Greg KH
2010-09-24 16:24 ` [59/80] KVM: VMX: Fix host GDT.LIMIT corruption Greg KH
2010-09-24 16:24 ` [60/80] IA64: fix siglock Greg KH
2010-09-24 16:24 ` [61/80] IA64: Optimize ticket spinlocks in fsys_rt_sigprocmask Greg KH
2010-09-24 16:24 ` [62/80] KEYS: Fix RCU no-lock warning in keyctl_session_to_parent() Greg KH
2010-09-24 16:24 ` [63/80] KEYS: Fix bug in keyctl_session_to_parent() if parent has no session keyring Greg KH
2010-09-24 16:24 ` [64/80] xfs: prevent reading uninitialized stack memory Greg KH
2010-09-24 16:24 ` [65/80] drivers/video/via/ioctl.c: " Greg KH
2010-09-24 16:24 ` [66/80] AT91: change dma resource index Greg KH
2010-09-24 16:24 ` [67/80] PM: Prevent waiting forever on asynchronous resume after failing suspend Greg KH
2010-09-24 16:24 ` [68/80] PM / Hibernate: Avoid hitting OOM during preallocation of memory Greg KH
2010-09-24 16:24 ` [69/80] x86, asm: Use a lower case name for the end macro in atomic64_386_32.S Greg KH
2010-09-24 16:24 ` [70/80] ALSA: hda - Fix beep frequency on IDT 92HD73xx and 92HD71Bxx codecs Greg KH
2010-09-24 16:24 ` [71/80] Fix call to replaced SuperIO functions Greg KH
2010-09-24 16:25 ` [72/80] dell-wmi: Add support for eject key on Dell Studio 1555 Greg KH
2010-09-24 16:25 ` [73/80] mm: page allocator: drain per-cpu lists after direct reclaim allocation fails Greg KH
2010-09-24 16:25 ` Greg KH [this message]
2010-09-24 16:25 ` [75/80] mm: page allocator: update free page counters after pages are placed on the free list Greg KH
2010-09-24 16:25 ` [76/80] guard page for stacks that grow upwards Greg KH
2010-09-24 16:25 ` [77/80] Fix unprotected access to task credentials in waitid() Greg KH
2010-09-24 16:25 ` [78/80] sctp: Do not reset the packet during sctp_packet_config() Greg KH
2010-09-24 16:25 ` [79/80] drm/i915: Ensure that the crtcinfo is populated during mode_fixup() Greg KH
2010-09-24 16:25 ` [80/80] alpha: Fix printk format errors Greg KH
2010-09-24 20:49 ` [00/80] 2.6.35.6 stable review Gene Heskett
2010-09-25 15:02   ` Greg KH
2010-09-25 15:16     ` Gene Heskett
2010-09-25 23:52       ` Gene Heskett
2010-09-25 16:49 ` Piotr Hosowicz
2010-09-25 17:24   ` Greg KH
2010-09-25 17:30     ` Piotr Hosowicz
2010-09-25 17:42       ` Greg KH
2010-09-25 17:52         ` Piotr Hosowicz
2010-09-26 11:32           ` Greg KH
2010-09-26 13:02             ` Piotr Hosowicz
2010-09-26 13:10               ` Sven Joachim
2010-09-26 13:15                 ` Piotr Hosowicz
2010-09-25 17:34     ` Piotr Hosowicz
2010-09-25 17:41       ` Greg KH
2010-09-25 17:47         ` Piotr Hosowicz
2010-09-25 17:49         ` Piotr Hosowicz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100924162621.373149171@clark.site \
    --to=gregkh@suse.de \
    --cc=akpm@linux-foundation.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=cl@linux.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mel@csn.ul.ie \
    --cc=stable-review@kernel.org \
    --cc=stable@kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).