* [PATCH 1/2] mm: drop bogus VM_BUG_ON_PAGE assert in put_page() codepath
2015-04-28 16:24 [PATCH 0/2] Reintroduce picky __compound_tail_refcounted() Kirill A. Shutemov
@ 2015-04-28 16:24 ` Kirill A. Shutemov
2015-04-28 16:24 ` [PATCH 2/2] mm: avoid tail page refcounting on non-THP compound pages Kirill A. Shutemov
2015-05-05 7:29 ` [PATCH 0/2] Reintroduce picky __compound_tail_refcounted() Kirill A. Shutemov
2 siblings, 0 replies; 4+ messages in thread
From: Kirill A. Shutemov @ 2015-04-28 16:24 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-mm, linux-kernel, Andrea Arcangeli, Borislav Petkov,
Hugh Dickins, Linus Torvalds, Kirill A. Shutemov
My patch 8d63d99a5dfb which was merged during 4.1 merge window caused
regression:
page:ffffea0010a15040 count:0 mapcount:1 mapping: (null) index:0x0
flags: 0x8000000000008014(referenced|dirty|tail)
page dumped because: VM_BUG_ON_PAGE(page_mapcount(page) != 0)
------------[ cut here ]------------
kernel BUG at mm/swap.c:134!
The problem can be reproduced by playing *two* audio files at the same
time and then stopping one of players. I used two mplayers to trigger
this.
The VM_BUG_ON_PAGE() which triggers the bug is bogus:
Sound subsystem uses compound pages for its buffers, but unlike most
__GFP_COMP sound maps compound pages to userspace with PTEs.
In our case with two players map the buffer twice and therefore elevates
page_mapcount() on tail pages by two. When one of players exits it
unmaps the VMA and drops page_mapcount() to one and try to release
reference on the page with put_page().
My commit changes which path it takes under put_compound_page(). It hits
put_unrefcounted_compound_page() where VM_BUG_ON_PAGE() is. It sees
page_mapcount() == 1. The function wrongly assumes that subpages of
compound page cannot be be mapped by itself with PTEs..
The solution is simply drop the VM_BUG_ON_PAGE().
Note: there's no need to move the check under put_page_testzero().
Allocator will check the mapcount by itself before putting on free
list.
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Reported-by: Andrea Arcangeli <aarcange@redhat.com>
Reviewed-by: Andrea Arcangeli <aarcange@redhat.com>
Reported-by: Borislav Petkov <bp@alien8.de>
Cc: Hugh Dickins <hughd@google.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
mm/swap.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/mm/swap.c b/mm/swap.c
index a7251a8ed532..a3a0a2f1f7c3 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -131,7 +131,6 @@ void put_unrefcounted_compound_page(struct page *page_head, struct page *page)
* here, see the comment above this function.
*/
VM_BUG_ON_PAGE(!PageHead(page_head), page_head);
- VM_BUG_ON_PAGE(page_mapcount(page) != 0, page);
if (put_page_testzero(page_head)) {
/*
* If this is the tail of a slab THP page,
--
2.1.4
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/2] mm: avoid tail page refcounting on non-THP compound pages
2015-04-28 16:24 [PATCH 0/2] Reintroduce picky __compound_tail_refcounted() Kirill A. Shutemov
2015-04-28 16:24 ` [PATCH 1/2] mm: drop bogus VM_BUG_ON_PAGE assert in put_page() codepath Kirill A. Shutemov
@ 2015-04-28 16:24 ` Kirill A. Shutemov
2015-05-05 7:29 ` [PATCH 0/2] Reintroduce picky __compound_tail_refcounted() Kirill A. Shutemov
2 siblings, 0 replies; 4+ messages in thread
From: Kirill A. Shutemov @ 2015-04-28 16:24 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-mm, linux-kernel, Andrea Arcangeli, Borislav Petkov,
Hugh Dickins, Linus Torvalds, Kirill A. Shutemov
[ kirill.shutemov: re-introduce 8d63d99a5dfb after removing bogus
VM_BUG_ON_PAGE() in put_unrefcounted_compound_page() ]
THP uses tail page refcounting to be able to split huge pages at any time.
Tail page refcounting is not needed for other users of compound pages and
it's harmful because of overhead.
We try to exclude non-THP pages from tail page refcounting using
__compound_tail_refcounted() check. It excludes most common non-THP
compound pages: SL*B and hugetlb, but it doesn't catch rest of __GFP_COMP
users -- drivers.
And it's not only about overhead.
Drivers might want to use compound pages to get refcounting semantics
suitable for mapping high-order pages to userspace. But tail page
refcounting breaks it.
Tail page refcounting uses ->_mapcount in tail pages to store GUP pins on
them. It means GUP pins would affect page_mapcount() for tail pages.
It's not a problem for THP, because it never maps tail pages. But unlike
THP, drivers map parts of compound pages with PTEs and it makes
page_mapcount() be called for tail pages.
In particular, GUP pins would shift PSS up and affect /proc/kpagecount for
such pages. But, I'm not aware about anything which can lead to crash or
other serious misbehaviour.
Since currently all THP pages are anonymous and all drivers pages are not,
we can fix the __compound_tail_refcounted() check by requiring PageAnon()
to enable tail page refcounting.
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Acked-by: Hugh Dickins <hughd@google.com>
Reviewed-by: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
include/linux/mm.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0755b9fd03a7..8b086070c3a5 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -499,7 +499,7 @@ static inline int page_count(struct page *page)
static inline bool __compound_tail_refcounted(struct page *page)
{
- return !PageSlab(page) && !PageHeadHuge(page);
+ return PageAnon(page) && !PageSlab(page) && !PageHeadHuge(page);
}
/*
--
2.1.4
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH 0/2] Reintroduce picky __compound_tail_refcounted()
2015-04-28 16:24 [PATCH 0/2] Reintroduce picky __compound_tail_refcounted() Kirill A. Shutemov
2015-04-28 16:24 ` [PATCH 1/2] mm: drop bogus VM_BUG_ON_PAGE assert in put_page() codepath Kirill A. Shutemov
2015-04-28 16:24 ` [PATCH 2/2] mm: avoid tail page refcounting on non-THP compound pages Kirill A. Shutemov
@ 2015-05-05 7:29 ` Kirill A. Shutemov
2 siblings, 0 replies; 4+ messages in thread
From: Kirill A. Shutemov @ 2015-05-05 7:29 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-mm, linux-kernel, Andrea Arcangeli, Borislav Petkov,
Hugh Dickins, Linus Torvalds
On Tue, Apr 28, 2015 at 07:24:56PM +0300, Kirill A. Shutemov wrote:
> Hi Andrew,
>
> My patch 8d63d99a5dfb which was merged during 4.1 merge window caused
> regression:
>
> page:ffffea0010a15040 count:0 mapcount:1 mapping: (null) index:0x0
> flags: 0x8000000000008014(referenced|dirty|tail)
> page dumped because: VM_BUG_ON_PAGE(page_mapcount(page) != 0)
> ------------[ cut here ]------------
> kernel BUG at mm/swap.c:134!
>
> The patch was reverted by Linus.
>
> This VM_BUG_ON_PAGE() is bogus. The first patch explains why the assert is
> wrong and removes it. The second re-introduces original patch.
>
> Kirill A. Shutemov (2):
> mm: drop bogus VM_BUG_ON_PAGE assert in put_page() codepath
> mm: avoid tail page refcounting on non-THP compound pages
>
> include/linux/mm.h | 2 +-
> mm/swap.c | 1 -
> 2 files changed, 1 insertion(+), 2 deletions(-)
Ping?
--
Kirill A. Shutemov
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 4+ messages in thread