From: Ben Hutchings <ben@decadent.org.uk>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: akpm@linux-foundation.org, "Khalid Aziz" <khalid.aziz@oracle.com>,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Christoph Lameter" <cl@linux.com>,
"Ben Hutchings" <bhutchings@solarflare.com>,
"Minchan Kim" <minchan@kernel.org>,
"Andi Kleen" <andi@firstfloor.org>,
"Pravin Shelar" <pshelar@nicira.com>,
"Andrea Arcangeli" <aarcange@redhat.com>,
"Mel Gorman" <mgorman@suse.de>,
"Linus Torvalds" <torvalds@linux-foundation.org>,
"Johannes Weiner" <jweiner@redhat.com>,
"Rik van Riel" <riel@redhat.com>
Subject: [PATCH 3.2 75/79] mm: hugetlbfs: fix hugetlbfs optimization
Date: Wed, 12 Feb 2014 08:10:12 +0000 [thread overview]
Message-ID: <lsq.1392192612.133215022@decadent.org.uk> (raw)
In-Reply-To: <lsq.1392192611.998273004@decadent.org.uk>
3.2.55-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Andrea Arcangeli <aarcange@redhat.com>
commit 27c73ae759774e63313c1fbfeb17ba076cea64c5 upstream.
Commit 7cb2ef56e6a8 ("mm: fix aio performance regression for database
caused by THP") can cause dereference of a dangling pointer if
split_huge_page runs during PageHuge() if there are updates to the
tail_page->private field.
Also it is repeating compound_head twice for hugetlbfs and it is running
compound_head+compound_trans_head for THP when a single one is needed in
both cases.
The new code within the PageSlab() check doesn't need to verify that the
THP page size is never bigger than the smallest hugetlbfs page size, to
avoid memory corruption.
A longstanding theoretical race condition was found while fixing the
above (see the change right after the skip_unlock label, that is
relevant for the compound_lock path too).
By re-establishing the _mapcount tail refcounting for all compound
pages, this also fixes the below problem:
echo 0 >/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
BUG: Bad page state in process bash pfn:59a01
page:ffffea000139b038 count:0 mapcount:10 mapping: (null) index:0x0
page flags: 0x1c00000000008000(tail)
Modules linked in:
CPU: 6 PID: 2018 Comm: bash Not tainted 3.12.0+ #25
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
Call Trace:
dump_stack+0x55/0x76
bad_page+0xd5/0x130
free_pages_prepare+0x213/0x280
__free_pages+0x36/0x80
update_and_free_page+0xc1/0xd0
free_pool_huge_page+0xc2/0xe0
set_max_huge_pages.part.58+0x14c/0x220
nr_hugepages_store_common.isra.60+0xd0/0xf0
nr_hugepages_store+0x13/0x20
kobj_attr_store+0xf/0x20
sysfs_write_file+0x189/0x1e0
vfs_write+0xc5/0x1f0
SyS_write+0x55/0xb0
system_call_fastpath+0x16/0x1b
Signed-off-by: Khalid Aziz <khalid.aziz@oracle.com>
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Tested-by: Khalid Aziz <khalid.aziz@oracle.com>
Cc: Pravin Shelar <pshelar@nicira.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Johannes Weiner <jweiner@redhat.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Rik van Riel <riel@redhat.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Minchan Kim <minchan@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[Khalid Aziz: Backported to 3.4]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
include/linux/hugetlb.h | 6 +++
mm/hugetlb.c | 17 ++++++++
mm/swap.c | 107 ++++++++++++++++++++++++++++++++++-------------
3 files changed, 101 insertions(+), 29 deletions(-)
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -24,6 +24,7 @@ struct hugepage_subpool *hugepage_new_su
void hugepage_put_subpool(struct hugepage_subpool *spool);
int PageHuge(struct page *page);
+int PageHeadHuge(struct page *page_head);
void reset_vma_resv_huge_pages(struct vm_area_struct *vma);
int hugetlb_sysctl_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *);
@@ -87,6 +88,11 @@ static inline int PageHuge(struct page *
{
return 0;
}
+
+static inline int PageHeadHuge(struct page *page_head)
+{
+ return 0;
+}
static inline void reset_vma_resv_huge_pages(struct vm_area_struct *vma)
{
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -679,6 +679,23 @@ int PageHuge(struct page *page)
}
EXPORT_SYMBOL_GPL(PageHuge);
+/*
+ * PageHeadHuge() only returns true for hugetlbfs head page, but not for
+ * normal or transparent huge pages.
+ */
+int PageHeadHuge(struct page *page_head)
+{
+ compound_page_dtor *dtor;
+
+ if (!PageHead(page_head))
+ return 0;
+
+ dtor = get_compound_page_dtor(page_head);
+
+ return dtor == free_huge_page;
+}
+EXPORT_SYMBOL_GPL(PageHeadHuge);
+
pgoff_t __basepage_index(struct page *page)
{
struct page *page_head = compound_head(page);
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -78,18 +78,6 @@ static void __put_compound_page(struct p
static void put_compound_page(struct page *page)
{
- /*
- * hugetlbfs pages cannot be split from under us. If this is a
- * hugetlbfs page, check refcount on head page and release the page if
- * the refcount becomes zero.
- */
- if (PageHuge(page)) {
- page = compound_head(page);
- if (put_page_testzero(page))
- __put_compound_page(page);
- return;
- }
-
if (unlikely(PageTail(page))) {
/* __split_huge_page_refcount can run under us */
struct page *page_head = compound_trans_head(page);
@@ -97,6 +85,35 @@ static void put_compound_page(struct pag
if (likely(page != page_head &&
get_page_unless_zero(page_head))) {
unsigned long flags;
+
+ if (PageHeadHuge(page_head)) {
+ if (likely(PageTail(page))) {
+ /*
+ * __split_huge_page_refcount
+ * cannot race here.
+ */
+ VM_BUG_ON(!PageHead(page_head));
+ atomic_dec(&page->_mapcount);
+ if (put_page_testzero(page_head))
+ VM_BUG_ON(1);
+ if (put_page_testzero(page_head))
+ __put_compound_page(page_head);
+ return;
+ } else {
+ /*
+ * __split_huge_page_refcount
+ * run before us, "page" was a
+ * THP tail. The split
+ * page_head has been freed
+ * and reallocated as slab or
+ * hugetlbfs page of smaller
+ * order (only possible if
+ * reallocated as slab on
+ * x86).
+ */
+ goto skip_lock;
+ }
+ }
/*
* page_head wasn't a dangling pointer but it
* may not be a head page anymore by the time
@@ -108,9 +125,29 @@ static void put_compound_page(struct pag
/* __split_huge_page_refcount run before us */
compound_unlock_irqrestore(page_head, flags);
VM_BUG_ON(PageHead(page_head));
- if (put_page_testzero(page_head))
- __put_single_page(page_head);
- out_put_single:
+skip_lock:
+ if (put_page_testzero(page_head)) {
+ /*
+ * The head page may have been
+ * freed and reallocated as a
+ * compound page of smaller
+ * order and then freed again.
+ * All we know is that it
+ * cannot have become: a THP
+ * page, a compound page of
+ * higher order, a tail page.
+ * That is because we still
+ * hold the refcount of the
+ * split THP tail and
+ * page_head was the THP head
+ * before the split.
+ */
+ if (PageHead(page_head))
+ __put_compound_page(page_head);
+ else
+ __put_single_page(page_head);
+ }
+out_put_single:
if (put_page_testzero(page))
__put_single_page(page);
return;
@@ -174,21 +211,34 @@ bool __get_page_tail(struct page *page)
*/
unsigned long flags;
bool got = false;
- struct page *page_head;
+ struct page *page_head = compound_trans_head(page);
- /*
- * If this is a hugetlbfs page it cannot be split under us. Simply
- * increment refcount for the head page.
- */
- if (PageHuge(page)) {
- page_head = compound_head(page);
- atomic_inc(&page_head->_count);
- got = true;
- goto out;
- }
-
- page_head = compound_trans_head(page);
if (likely(page != page_head && get_page_unless_zero(page_head))) {
+ /* Ref to put_compound_page() comment. */
+ if (PageHeadHuge(page_head)) {
+ if (likely(PageTail(page))) {
+ /*
+ * This is a hugetlbfs
+ * page. __split_huge_page_refcount
+ * cannot race here.
+ */
+ VM_BUG_ON(!PageHead(page_head));
+ __get_page_tail_foll(page, false);
+ return true;
+ } else {
+ /*
+ * __split_huge_page_refcount run
+ * before us, "page" was a THP
+ * tail. The split page_head has been
+ * freed and reallocated as slab or
+ * hugetlbfs page of smaller order
+ * (only possible if reallocated as
+ * slab on x86).
+ */
+ put_page(page_head);
+ return false;
+ }
+ }
/*
* page_head wasn't a dangling pointer but it
* may not be a head page anymore by the time
@@ -205,7 +255,6 @@ bool __get_page_tail(struct page *page)
if (unlikely(!got))
put_page(page_head);
}
-out:
return got;
}
EXPORT_SYMBOL(__get_page_tail);
next prev parent reply other threads:[~2014-02-12 8:15 UTC|newest]
Thread overview: 83+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-12 8:10 [PATCH 3.2 00/79] 3.2.55-rc1 review Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 37/79] xhci: Limit the spurious wakeup fix only to HP machines Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 44/79] libata: disable a disk via libata.force params Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 57/79] drm/radeon: 0x9649 is SUMO2 not SUMO Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 34/79] ext4: check for overlapping extents in ext4_valid_extent_entries() Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 23/79] hpfs: fix warnings when the filesystem fills up Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 65/79] ahci: add PCI ID for Marvell 88SE9170 SATA controller Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 79/79] sched/rt: Avoid updating RT entry timeout twice within one tick period Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 17/79] net: avoid reference counter overflows on fib_rules in multicast forwarding Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 42/79] radiotap: fix bitmap-end-finding buffer overrun Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 10/79] rds: prevent dereference of a NULL device Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 32/79] ext4: call ext4_error_inode() if jbd2_journal_dirty_metadata() fails Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 50/79] ath9k: Fix interrupt handling for the AR9002 family Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 62/79] ahci: Use PCI_VENDOR_ID_MARVELL_EXT for 0x1b4b Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 30/79] sh: always link in helper functions extracted from libgcc Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 28/79] ceph: cleanup aborted requests when re-sending requests Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 20/79] mm/memory-failure.c: recheck PageHuge() after hugetlb page migrate successfully Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 19/79] PCI: Enable ARI if dev and upstream bridge support it; disable otherwise Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 33/79] ext4: fix use-after-free in ext4_mb_new_blocks Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 09/79] hamradio/yam: fix info leak in ioctl Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 15/79] bnx2x: fix DMA unmapping of TSO split BDs Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 61/79] powerpc: Fix bad stack check in exception entry Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 35/79] ext2: Fix oops in ext2_get_block() called from ext2_quota_write() Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 41/79] gpio: msm: Fix irq mask/unmask by writing bits instead of numbers Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 48/79] drm/i915: Use the correct GMCH_CTRL register for Sandybridge+ Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 70/79] md/raid10: fix bug when raid10 recovery fails to recover a block Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 67/79] SELinux: Fix possible NULL pointer dereference in selinux_inode_permission() Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 04/79] net: drop_monitor: fix the value of maxattr Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 54/79] dm9601: fix reception of full size ethernet frames on dm9620/dm9621a Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 49/79] rtlwifi: pci: Fix oops on driver unload Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 03/79] ipv6: don't count addrconf generated routes against gc limit Ben Hutchings
2014-02-12 8:10 ` Ben Hutchings [this message]
2014-02-12 8:10 ` [PATCH 3.2 53/79] net_dma: mark broken Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 73/79] perf/x86/amd/ibs: Fix waking up from S3 for AMD family 10h Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 46/79] sched/rt: Fix rq's cpupri leak while enqueue/dequeue child RT entities Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 26/79] x86, fpu, amd: Clear exceptions in AMD FXSAVE workaround Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 43/79] ftrace: Initialize the ftrace profiler for each possible cpu Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 08/79] drivers/net/hamradio: Integer overflow in hdlcdrv_ioctl() Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 64/79] pci: Add PCI_DEVICE_SUB() macro Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 39/79] drm/radeon: Fix sideport problems on certain RS690 boards Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 38/79] iscsi-target: Fix-up all zero data-length CDBs with R/W_BIT set Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 31/79] libata: add ATA_HORKAGE_BROKEN_FPDMA_AA quirk for Seagate Momentus SpinPoint M8 Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 12/79] vlan: Fix header ops passthru when doing TX VLAN offload Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 52/79] ASoC: wm8904: fix DSP mode B configuration Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 69/79] md/raid10: fix two bugs in handling of known-bad-blocks Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 55/79] dm9601: work around tx fifo sync issue on dm962x Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 72/79] nilfs2: fix segctor bug that causes file system corruption Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 68/79] md/raid5: Fix possible confusion when multiple write errors occur Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 14/79] bridge: use spin_lock_bh() in br_multicast_set_hash_max Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 27/79] mm: ensure get_unmapped_area() returns higher address than mmap_min_addr Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 02/79] rds: prevent BUG_ON triggered on congestion update to loopback Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 56/79] ext4: add explicit casts when masking cluster sizes Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 24/79] ath9k_htc: properly set MAC address and BSSID mask Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 51/79] cpupower: Fix segfault due to incorrect getopt_long arugments Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 71/79] hwmon: (coretemp) Fix truncated name of alarm attributes Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 74/79] mm: fix aio performance regression for database caused by THP Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 06/79] net: unix: allow bind to fail on mutex lock Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 16/79] inet_diag: fix inet_diag_dump_icsk() timewait socket state logic Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 60/79] ARM: fix footbridge clockevent device Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 47/79] ALSA: Add SNDRV_PCM_STATE_PAUSED case in wait_for_avail function Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 78/79] sched: Unthrottle rt runqueues in __disable_runtime() Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 21/79] staging: comedi: cb_pcidio: fix for newer PCI-DIO48H Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 45/79] drm/ttm: Fix accesses through vmas with only partial coverage Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 40/79] ALSA: hda - Add enable_msi=0 workaround for four HP machines Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 58/79] selinux: fix broken peer recv check Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 13/79] net: llc: fix use after free in llc_ui_recvmsg Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 59/79] selinux: selinux_setprocattr()->ptrace_parent() needs rcu_read_lock() Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 07/79] net: inet_diag: zero out uninitialized idiag_{src,dst} fields Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 76/79] sched/rt: Fix SCHED_RR across cgroups Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 11/79] net: rose: restore old recvmsg behavior Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 18/79] xfs: Account log unmount transaction correctly Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 66/79] ARM: fix "bad mode in ... handler" message for undefined instructions Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 77/79] sched,rt: fix isolated CPUs leaving root_task_group indefinitely throttled Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 05/79] tg3: Initialize REG_BASE_ADDR at PCI config offset 120 to 0 Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 22/79] [IA64] Fix warning from machine_kexec.c Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 29/79] ceph: wake up 'safe' waiters when unregistering request Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 36/79] ext4: fix del_timer() misuse for ->s_err_report Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 63/79] ahci: add an observed PCI ID for Marvell 88se9172 SATA controller Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 01/79] net: do not pretend FRAGLIST support Ben Hutchings
2014-02-12 8:10 ` [PATCH 3.2 25/79] KVM: x86: Convert vapic synchronization to _cached functions (CVE-2013-6368) Ben Hutchings
2014-02-12 8:16 ` [PATCH 3.2 00/79] 3.2.55-rc1 review Ben Hutchings
2014-02-12 11:50 ` Guenter Roeck
2014-02-12 18:14 ` Ben Hutchings
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=lsq.1392192612.133215022@decadent.org.uk \
--to=ben@decadent.org.uk \
--cc=aarcange@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=andi@firstfloor.org \
--cc=bhutchings@solarflare.com \
--cc=cl@linux.com \
--cc=gregkh@linuxfoundation.org \
--cc=jweiner@redhat.com \
--cc=khalid.aziz@oracle.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=minchan@kernel.org \
--cc=pshelar@nicira.com \
--cc=riel@redhat.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
all inboxes | Powered by JetHome®