From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
stable@vger.kernel.org, Mel Gorman <mgorman@suse.de>,
Rob van der Heij <rvdheij@gmail.com>,
Andrew Morton <akpm@linux-foundation.org>,
Linus Torvalds <torvalds@linux-foundation.org>
Subject: [ 38/58] mm/fadvise.c: drain all pagevecs if POSIX_FADV_DONTNEED fails to discard all pages
Date: Mon, 25 Feb 2013 14:19:34 -0800 [thread overview]
Message-ID: <20130225221644.442769166@linuxfoundation.org> (raw)
In-Reply-To: <20130225221636.018756060@linuxfoundation.org>
3.7-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mel Gorman <mgorman@suse.de>
commit 67d46b296a1ba1477c0df8ff3bc5e0167a0b0732 upstream.
Rob van der Heij reported the following (paraphrased) on private mail.
The scenario is that I want to avoid backups to fill up the page
cache and purge stuff that is more likely to be used again (this is
with s390x Linux on z/VM, so I don't give it as much memory that
we don't care anymore). So I have something with LD_PRELOAD that
intercepts the close() call (from tar, in this case) and issues
a posix_fadvise() just before closing the file.
This mostly works, except for small files (less than 14 pages)
that remains in page cache after the face.
Unfortunately Rob has not had a chance to test this exact patch but the
test program below should be reproducing the problem he described.
The issue is the per-cpu pagevecs for LRU additions. If the pages are
added by one CPU but fadvise() is called on another then the pages
remain resident as the invalidate_mapping_pages() only drains the local
pagevecs via its call to pagevec_release(). The user-visible effect is
that a program that uses fadvise() properly is not obeyed.
A possible fix for this is to put the necessary smarts into
invalidate_mapping_pages() to globally drain the LRU pagevecs if a
pagevec page could not be discarded. The downside with this is that an
inode cache shrink would send a global IPI and memory pressure
potentially causing global IPI storms is very undesirable.
Instead, this patch adds a check during fadvise(POSIX_FADV_DONTNEED) to
check if invalidate_mapping_pages() discarded all the requested pages.
If a subset of pages are discarded it drains the LRU pagevecs and tries
again. If the second attempt fails, it assumes it is due to the pages
being mapped, locked or dirty and does not care. With this patch, an
application using fadvise() correctly will be obeyed but there is a
downside that a malicious application can force the kernel to send
global IPIs and increase overhead.
If accepted, I would like this to be considered as a -stable candidate.
It's not an urgent issue but it's a system call that is not working as
advertised which is weak.
The following test program demonstrates the problem. It should never
report that pages are still resident but will without this patch. It
assumes that CPU 0 and 1 exist.
int main() {
int fd;
int pagesize = getpagesize();
ssize_t written = 0, expected;
char *buf;
unsigned char *vec;
int resident, i;
cpu_set_t set;
/* Prepare a buffer for writing */
expected = FILESIZE_PAGES * pagesize;
buf = malloc(expected + 1);
if (buf == NULL) {
printf("ENOMEM\n");
exit(EXIT_FAILURE);
}
buf[expected] = 0;
memset(buf, 'a', expected);
/* Prepare the mincore vec */
vec = malloc(FILESIZE_PAGES);
if (vec == NULL) {
printf("ENOMEM\n");
exit(EXIT_FAILURE);
}
/* Bind ourselves to CPU 0 */
CPU_ZERO(&set);
CPU_SET(0, &set);
if (sched_setaffinity(getpid(), sizeof(set), &set) == -1) {
perror("sched_setaffinity");
exit(EXIT_FAILURE);
}
/* open file, unlink and write buffer */
fd = open("fadvise-test-file", O_CREAT|O_EXCL|O_RDWR);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
unlink("fadvise-test-file");
while (written < expected) {
ssize_t this_write;
this_write = write(fd, buf + written, expected - written);
if (this_write == -1) {
perror("write");
exit(EXIT_FAILURE);
}
written += this_write;
}
free(buf);
/*
* Force ourselves to another CPU. If fadvise only flushes the local
* CPUs pagevecs then the fadvise will fail to discard all file pages
*/
CPU_ZERO(&set);
CPU_SET(1, &set);
if (sched_setaffinity(getpid(), sizeof(set), &set) == -1) {
perror("sched_setaffinity");
exit(EXIT_FAILURE);
}
/* sync and fadvise to discard the page cache */
fsync(fd);
if (posix_fadvise(fd, 0, expected, POSIX_FADV_DONTNEED) == -1) {
perror("posix_fadvise");
exit(EXIT_FAILURE);
}
/* map the file and use mincore to see which parts of it are resident */
buf = mmap(NULL, expected, PROT_READ, MAP_SHARED, fd, 0);
if (buf == NULL) {
perror("mmap");
exit(EXIT_FAILURE);
}
if (mincore(buf, expected, vec) == -1) {
perror("mincore");
exit(EXIT_FAILURE);
}
/* Check residency */
for (i = 0, resident = 0; i < FILESIZE_PAGES; i++) {
if (vec[i])
resident++;
}
if (resident != 0) {
printf("Nr unexpected pages resident: %d\n", resident);
exit(EXIT_FAILURE);
}
munmap(buf, expected);
close(fd);
free(vec);
exit(EXIT_SUCCESS);
}
Signed-off-by: Mel Gorman <mgorman@suse.de>
Reported-by: Rob van der Heij <rvdheij@gmail.com>
Tested-by: Rob van der Heij <rvdheij@gmail.com>
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@linuxfoundation.org>
---
mm/fadvise.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -17,6 +17,7 @@
#include <linux/fadvise.h>
#include <linux/writeback.h>
#include <linux/syscalls.h>
+#include <linux/swap.h>
#include <asm/unistd.h>
@@ -120,9 +121,22 @@ SYSCALL_DEFINE(fadvise64_64)(int fd, lof
start_index = (offset+(PAGE_CACHE_SIZE-1)) >> PAGE_CACHE_SHIFT;
end_index = (endbyte >> PAGE_CACHE_SHIFT);
- if (end_index >= start_index)
- invalidate_mapping_pages(mapping, start_index,
+ if (end_index >= start_index) {
+ unsigned long count = invalidate_mapping_pages(mapping,
+ start_index, end_index);
+
+ /*
+ * If fewer pages were invalidated than expected then
+ * it is possible that some of the pages were on
+ * a per-cpu pagevec for a remote CPU. Drain all
+ * pagevecs and try again.
+ */
+ if (count < (end_index - start_index + 1)) {
+ lru_add_drain_all();
+ invalidate_mapping_pages(mapping, start_index,
end_index);
+ }
+ }
break;
default:
ret = -EINVAL;
next prev parent reply other threads:[~2013-02-25 22:20 UTC|newest]
Thread overview: 65+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-02-25 22:18 [ 00/58] 3.7.10-stable review Greg Kroah-Hartman
2013-02-25 22:18 ` [ 01/58] drm/nouveau/vm: fix memory corruption when pgt allocation fails Greg Kroah-Hartman
2013-02-25 22:18 ` [ 02/58] x86-32, mm: Rip out x86_32 NUMA remapping code Greg Kroah-Hartman
2013-02-25 22:18 ` [ 03/58] x86-32, mm: Remove reference to resume_map_numa_kva() Greg Kroah-Hartman
2013-02-25 22:19 ` [ 04/58] x86-32, mm: Remove reference to alloc_remap() Greg Kroah-Hartman
2013-02-25 22:19 ` [ 05/58] perf tools: Fix build with bison 2.3 and older Greg Kroah-Hartman
2013-02-25 22:19 ` [ 06/58] perf hists: Fix period symbol_conf.field_sep display Greg Kroah-Hartman
2013-02-25 22:19 ` [ 07/58] mm: fix pageblock bitmap allocation Greg Kroah-Hartman
2013-02-25 22:19 ` [ 08/58] timeconst.pl: Eliminate Perl warning Greg Kroah-Hartman
2013-02-25 22:19 ` [ 09/58] genirq: Avoid deadlock in spurious handling Greg Kroah-Hartman
2013-02-25 22:19 ` [ 10/58] posix-cpu-timers: Fix nanosleep task_struct leak Greg Kroah-Hartman
2013-02-25 22:19 ` [ 11/58] hrtimer: Prevent hrtimer_enqueue_reprogram race Greg Kroah-Hartman
2013-02-25 22:19 ` [ 12/58] x86: Hyper-V: register clocksource only if its advertised Greg Kroah-Hartman
2013-02-25 22:19 ` [ 13/58] workqueue: un-GPL function delayed_work_timer_fn() Greg Kroah-Hartman
2013-02-25 22:19 ` [ 14/58] ALSA: ali5451: remove irq enabling in pointer callback Greg Kroah-Hartman
2013-02-25 22:19 ` [ 15/58] ALSA: rme32.c irq enabling after spin_lock_irq Greg Kroah-Hartman
2013-02-25 22:19 ` [ 16/58] tty: Prevent deadlock in n_gsm driver Greg Kroah-Hartman
2013-02-25 22:19 ` [ 17/58] tty: set_termios/set_termiox should not return -EINTR Greg Kroah-Hartman
2013-02-25 22:19 ` [ 18/58] USB: serial: fix null-pointer dereferences on disconnect Greg Kroah-Hartman
2013-02-25 22:19 ` [ 19/58] serial: imx: Fix recursive locking bug Greg Kroah-Hartman
2013-02-25 22:19 ` [ 20/58] serial_core: Fix type definition for PORT_BRCM_TRUMANAGE Greg Kroah-Hartman
2013-02-25 22:19 ` [ 21/58] b43: Increase number of RX DMA slots Greg Kroah-Hartman
2013-02-25 22:19 ` [ 22/58] rtlwifi: rtl8192cu: Add new USB ID Greg Kroah-Hartman
2013-02-25 22:19 ` [ 23/58] rtlwifi: usb: allocate URB control message setup_packet and data buffer separately Greg Kroah-Hartman
2013-02-25 22:19 ` [ 24/58] tty vt: fix character insertion overflow Greg Kroah-Hartman
2013-02-25 22:19 ` [ 25/58] xen: Send spinlock IPI to all waiters Greg Kroah-Hartman
2013-02-25 22:19 ` [ 26/58] xen: close evtchn port if binding to irq fails Greg Kroah-Hartman
2013-02-25 22:19 ` [ 27/58] zram: Fix deadlock bug in partial read/write Greg Kroah-Hartman
2013-02-25 22:19 ` [ 28/58] Driver core: treat unregistered bus_types as having no devices Greg Kroah-Hartman
2013-02-25 22:19 ` [ 29/58] mmu_notifier_unregister NULL Pointer deref and multiple ->release() callouts Greg Kroah-Hartman
2013-02-25 22:19 ` [ 30/58] KVM: s390: Handle hosts not supporting s390-virtio Greg Kroah-Hartman
2013-02-25 22:19 ` [ 31/58] s390/kvm: Fix store status for ACRS/FPRS Greg Kroah-Hartman
2013-02-25 22:19 ` [ 32/58] futex: Revert "futex: Mark get_robust_list as deprecated" Greg Kroah-Hartman
2013-02-25 22:19 ` [ 33/58] inotify: remove broken mask checks causing unmount to be EINVAL Greg Kroah-Hartman
2013-02-25 22:19 ` [ 34/58] fs/block_dev.c: page cache wrongly left invalidated after revalidate_disk() Greg Kroah-Hartman
2013-02-25 22:19 ` [ 35/58] ocfs2: unlock super lock if lockres refresh failed Greg Kroah-Hartman
2013-02-25 22:19 ` [ 36/58] drivers/video/backlight/adp88?0_bl.c: fix resume Greg Kroah-Hartman
2013-02-25 22:19 ` [ 37/58] tmpfs: fix use-after-free of mempolicy object Greg Kroah-Hartman
2013-02-25 22:19 ` Greg Kroah-Hartman [this message]
2013-02-25 22:19 ` [ 39/58] xen-pciback: rate limit error messages from xen_pcibk_enable_msi{,x}() Greg Kroah-Hartman
2013-02-25 22:19 ` [ 40/58] drivercore: Fix ordering between deferred_probe and exiting initcalls Greg Kroah-Hartman
2013-02-25 22:19 ` [ 41/58] umount oops when remove blocklayoutdriver first Greg Kroah-Hartman
2013-02-25 22:19 ` [ 42/58] NLM: Ensure that we resend all pending blocking locks after a reclaim Greg Kroah-Hartman
2013-02-25 22:19 ` [ 43/58] NFSv4.1: Dont decode skipped layoutgets Greg Kroah-Hartman
2013-02-25 22:19 ` [ 44/58] p54usb: corrected USB ID for T-Com Sinus 154 data II Greg Kroah-Hartman
2013-02-25 22:19 ` [ 45/58] ALSA: usb-audio: fix Roland A-PRO support Greg Kroah-Hartman
2013-02-25 22:19 ` [ 46/58] ALSA: usb: Fix Processing Unit Descriptor parsers Greg Kroah-Hartman
2013-02-25 22:19 ` [ 47/58] ALSA: hda - Release assigned pin/cvt at error path of hdmi_pcm_open() Greg Kroah-Hartman
2013-02-25 22:19 ` [ 48/58] ALSA: hda - Fix default multichannel HDMI mapping regression Greg Kroah-Hartman
2013-02-25 22:19 ` [ 49/58] ALSA: hda - Workaround for silent output on Sony Vaio VGC-LN51JGB with ALC889 Greg Kroah-Hartman
2013-02-25 22:19 ` [ 50/58] ALSA: hda - hdmi: ELD shouldnt be valid after unplug Greg Kroah-Hartman
2013-02-25 22:19 ` [ 51/58] GFS2: Get a block reservation before resizing a file Greg Kroah-Hartman
2013-02-25 22:34 ` Bob Peterson
2013-02-25 22:19 ` [ 52/58] sunvdc: Fix off-by-one in generic_request() Greg Kroah-Hartman
2013-02-25 22:19 ` [ 53/58] sparc64: Add missing HAVE_ARCH_TRANSPARENT_HUGEPAGE Greg Kroah-Hartman
2013-02-25 22:19 ` [ 54/58] sparc64: Fix get_user_pages_fast() wrt. THP Greg Kroah-Hartman
2013-02-25 22:19 ` [ 55/58] sparc64: Fix gfp_flags setting in tsb_grow() Greg Kroah-Hartman
2013-02-25 22:19 ` [ 56/58] sparc64: Handle hugepage TSB being NULL Greg Kroah-Hartman
2013-02-25 22:19 ` [ 57/58] sparc64: Fix tsb_grow() in atomic context Greg Kroah-Hartman
2013-02-25 22:19 ` [ 58/58] sparc64: Fix huge PMD to PTE translation for sun4u in TLB miss handler Greg Kroah-Hartman
2013-02-26 0:47 ` [ 00/58] 3.7.10-stable review Shuah Khan
2013-02-26 1:02 ` Greg Kroah-Hartman
2013-02-26 17:37 ` Andre Tomt
2013-02-26 17:48 ` Josh Boyer
2013-02-26 17:52 ` David Miller
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=20130225221644.442769166@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=rvdheij@gmail.com \
--cc=stable@vger.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