Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752475AbcDRDmw (ORCPT ); Sun, 17 Apr 2016 23:42:52 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:35677 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751902AbcDRCa0 (ORCPT ); Sun, 17 Apr 2016 22:30:26 -0400 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Gerald Schaefer , Martin Schwidefsky Subject: [PATCH 4.5 015/124] s390/mm: handle PTE-mapped tail pages in fast gup Date: Mon, 18 Apr 2016 11:28:07 +0900 Message-Id: <20160418022616.512265438@linuxfoundation.org> X-Mailer: git-send-email 2.8.0 In-Reply-To: <20160418022615.726954227@linuxfoundation.org> References: <20160418022615.726954227@linuxfoundation.org> User-Agent: quilt/0.64 MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-15 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2031 Lines: 60 4.5-stable review patch. If anyone has any objections, please let me know. ------------------ From: Gerald Schaefer commit fc897c95e91451271cd707ee0f71022b9b201ce9 upstream. With the THP refcounting rework it is possible to see THP compound tail pages mapped with PTEs during a THP split. This needs to be considered when using page_cache_get_speculative(), which will always fail on tail pages because ->_count is always zero. commit 7aef4172 "mm: handle PTE-mapped tail pages in gerneric fast gup implementaiton" fixed it for the generic fast gup code by using compound_head(page) instead of page, but not for s390. This patch is a 1:1 adaption of commit 7aef4172 for the s390 fast gup code. Without this fix, gup will fall back to the slow path or fail in the unlikely scenario that we hit a THP under splitting in-between the page table split and the compound page split. Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/mm/gup.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c @@ -20,9 +20,9 @@ static inline int gup_pte_range(pmd_t *pmdp, pmd_t pmd, unsigned long addr, unsigned long end, int write, struct page **pages, int *nr) { + struct page *head, *page; unsigned long mask; pte_t *ptep, pte; - struct page *page; mask = (write ? _PAGE_PROTECT : 0) | _PAGE_INVALID | _PAGE_SPECIAL; @@ -37,12 +37,14 @@ static inline int gup_pte_range(pmd_t *p return 0; VM_BUG_ON(!pfn_valid(pte_pfn(pte))); page = pte_page(pte); - if (!page_cache_get_speculative(page)) + head = compound_head(page); + if (!page_cache_get_speculative(head)) return 0; if (unlikely(pte_val(pte) != pte_val(*ptep))) { - put_page(page); + put_page(head); return 0; } + VM_BUG_ON_PAGE(compound_head(page) != head, page); pages[*nr] = page; (*nr)++;