Received: by 2002:a25:31c3:0:0:0:0:0 with SMTP id x186csp2224252ybx; Fri, 8 Nov 2019 01:39:40 -0800 (PST) X-Google-Smtp-Source: APXvYqy3RMjGhYYjJimAqjFZE5W0Nx9PHc7b3Mxz/MPr1qKpJf4mEXDUKxGSi8RZLcAODhBPVYd/ X-Received: by 2002:a17:906:234e:: with SMTP id m14mr7456852eja.94.1573205980516; Fri, 08 Nov 2019 01:39:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1573205980; cv=none; d=google.com; s=arc-20160816; b=L8K0Ohob3bBxbEt0HsJO9gE/r/0J19h2uLZaIR09OQQxsLprqQ0utLzT055gPddEOK tNnD4tZUPxBEV8P7U5qV/pWdYL9ufGSC07rEyuNwXwaz0LrMHOjrwaSLMKb76/gY3kp1 JiKeEWOWmq4zCkBnGrOHNj+CTur5NUXgMEG31CWwb+CoLFApkbl1xNq507aAk1cv/kW0 54I8F8HVr5dJmP1pusA5btLPXanI2od8C0BydZ/TYSgCcs3xk/Q7/G5XoG0EAqqsWmWS X5k0dPfGnFopgt4MnItrS/ABiWo/e5y8FfudIgIGzip4pWbpWZPHVkwAJdexmEojyGcM 6TVg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=FCBU0fu6DmCKmaE87i6H72N+61EDXWZou14B3URupbo=; b=nJUX1POzEvFjNDRcY2MoQSesq2Mohi4IVQwsZoVmTlbYnEk8Et1+OoUcIYrchL1get cUP11qNmV/qHoPnu3j0XVKBqkuiEHOpbxGWFUHgO5C0qkp5vOjP/0dLYJIgfafn3UAPC aOYkwMA5N2bpREVFmqUdI5RuOm/hRLrb67/gX+HFZkuZfLLFIwBbrk6onvP3Pt5ylDm3 0/AtH9C+3mdmIaEgUE29eF8ATIoO1NXvzNNEjBfWwX1xQqibMgtrJgiRxvzNV5cDrHxf pI5lGv3sSi8COqDcTDREcqeVSUzSL0SAvlr5Q8B4S6UdfLm8PBcEm9GGIVoPI1NKQM7w Dcbg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id dv23si3178225ejb.338.2019.11.08.01.39.17; Fri, 08 Nov 2019 01:39:40 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731528AbfKHJi3 (ORCPT + 99 others); Fri, 8 Nov 2019 04:38:29 -0500 Received: from mx2.suse.de ([195.135.220.15]:39776 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1731476AbfKHJi2 (ORCPT ); Fri, 8 Nov 2019 04:38:28 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 0B21BAE7F; Fri, 8 Nov 2019 09:38:24 +0000 (UTC) From: Vlastimil Babka To: stable@vger.kernel.org Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Ajay Kaher , Punit Agrawal , Steve Capper , Michal Hocko , "Kirill A. Shutemov" , "Aneesh Kumar K . V" , Catalin Marinas , Will Deacon , Naoya Horiguchi , Mark Rutland , Hillf Danton , Mike Kravetz , Andrew Morton , Linus Torvalds , Vlastimil Babka Subject: [PATCH STABLE 4.4 2/8] mm, gup: ensure real head page is ref-counted when using hugepages Date: Fri, 8 Nov 2019 10:38:08 +0100 Message-Id: <20191108093814.16032-3-vbabka@suse.cz> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191108093814.16032-1-vbabka@suse.cz> References: <20191108093814.16032-1-vbabka@suse.cz> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Punit Agrawal commit d63206ee32b6e64b0e12d46e5d6004afd9913713 upstream. When speculatively taking references to a hugepage using page_cache_add_speculative() in gup_huge_pmd(), it is assumed that the page returned by pmd_page() is the head page. Although normally true, this assumption doesn't hold when the hugepage comprises of successive page table entries such as when using contiguous bit on arm64 at PTE or PMD levels. This can be addressed by ensuring that the page passed to page_cache_add_speculative() is the real head or by de-referencing the head page within the function. We take the first approach to keep the usage pattern aligned with page_cache_get_speculative() where users already pass the appropriate page, i.e., the de-referenced head. Apply the same logic to fix gup_huge_[pud|pgd]() as well. [punit.agrawal@arm.com: fix arm64 ltp failure] Link: http://lkml.kernel.org/r/20170619170145.25577-5-punit.agrawal@arm.com Link: http://lkml.kernel.org/r/20170522133604.11392-3-punit.agrawal@arm.com Signed-off-by: Punit Agrawal Acked-by: Steve Capper Cc: Michal Hocko Cc: "Kirill A. Shutemov" Cc: Aneesh Kumar K.V Cc: Catalin Marinas Cc: Will Deacon Cc: Naoya Horiguchi Cc: Mark Rutland Cc: Hillf Danton Cc: Mike Kravetz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Vlastimil Babka --- mm/gup.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mm/gup.c b/mm/gup.c index 6f9088cb8ebe..71e9d0093a35 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1130,8 +1130,7 @@ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, return 0; refs = 0; - head = pmd_page(orig); - page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT); + page = pmd_page(orig) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); tail = page; do { pages[*nr] = page; @@ -1140,6 +1139,7 @@ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, refs++; } while (addr += PAGE_SIZE, addr != end); + head = compound_head(pmd_page(orig)); if (!page_cache_add_speculative(head, refs)) { *nr -= refs; return 0; @@ -1176,8 +1176,7 @@ static int gup_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr, return 0; refs = 0; - head = pud_page(orig); - page = head + ((addr & ~PUD_MASK) >> PAGE_SHIFT); + page = pud_page(orig) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); tail = page; do { pages[*nr] = page; @@ -1186,6 +1185,7 @@ static int gup_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr, refs++; } while (addr += PAGE_SIZE, addr != end); + head = compound_head(pud_page(orig)); if (!page_cache_add_speculative(head, refs)) { *nr -= refs; return 0; @@ -1218,8 +1218,7 @@ static int gup_huge_pgd(pgd_t orig, pgd_t *pgdp, unsigned long addr, return 0; refs = 0; - head = pgd_page(orig); - page = head + ((addr & ~PGDIR_MASK) >> PAGE_SHIFT); + page = pgd_page(orig) + ((addr & ~PGDIR_MASK) >> PAGE_SHIFT); tail = page; do { pages[*nr] = page; @@ -1228,6 +1227,7 @@ static int gup_huge_pgd(pgd_t orig, pgd_t *pgdp, unsigned long addr, refs++; } while (addr += PAGE_SIZE, addr != end); + head = compound_head(pgd_page(orig)); if (!page_cache_add_speculative(head, refs)) { *nr -= refs; return 0; -- 2.23.0