Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp1503735imm; Wed, 23 May 2018 18:01:35 -0700 (PDT) X-Google-Smtp-Source: AB8JxZpLtMOv4npBS+azQD7wESf8NDBNho+8Jbs4WpF1/oS07c1L4xLdWLwLuNRrPokIJUGRSeO1 X-Received: by 2002:a63:6807:: with SMTP id d7-v6mr4018901pgc.332.1527123695457; Wed, 23 May 2018 18:01:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527123695; cv=none; d=google.com; s=arc-20160816; b=Lyw3XmwJyV1sArCF8kdwWsiWgV7FrFLRN+5qpnWw0eDdIIlotssS0K2OZZzgPTNyYO klaWf0+03QlrSuQt9VGlQbP5dMX4IFP9gHI3wkI+vpyCC8AObw5e/B9PGnLbxESPZWUf Jl77sNQ1ZsmvQzDWo7/ejZwe5aT7NYyZZE3rEurPtxBWimQPoJiK8SsR6WIPTaitb7U0 I90cbEXiWMKfFq5Dor22ZUP6D4fAnbAoZtpW2Eh7o8JAG4a6PL+24hc+tw0grB8NZWfm mSxTdcjS2NJFpCMzOtr04BOovHEZOxg9MHPlMm+H90wRTsLoOs9l0Rddi2A7johXmnCc uTJg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=iwN8nISYsFeJQvNhik795GdHaspYG22RCiPRU1540zI=; b=dqgT2dOgd+r7xfCgXHGLKu8pLidLISW658/yIT9/NAZHFOrHXirXfqUaA7zIa48lTp gr7vHrpvGW41ltq+1favqEgSHHozmCBDvSHX2fpqLrnijEOz0p6pYFFeCMH+A2As+Zwo 1/ewk/Xtpk/HkJhLTSf9dZZQSa70W8A8kL6C6gjUsXojmkxSUdSGugdPNfEk5TegQbYp AahmX/NVXbDA0Y+tCfxWZfXz6P1ksxKLvHrB3gCNh7OZyXcuzd6u4oYTRu5YTWIttcHC 0TVBkroqHoci+F75nP+Ct0riIAQcBLm/NVl4f5nHRHKLCz0ZSUpdtNLVnhbiW8fN99hn 0nkA== 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a3-v6si19864283pfh.365.2018.05.23.18.01.20; Wed, 23 May 2018 18:01:35 -0700 (PDT) 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935387AbeEXBAj (ORCPT + 99 others); Wed, 23 May 2018 21:00:39 -0400 Received: from mga07.intel.com ([134.134.136.100]:34349 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935280AbeEXBAa (ORCPT ); Wed, 23 May 2018 21:00:30 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 23 May 2018 18:00:30 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,435,1520924400"; d="scan'208";a="42362529" Received: from yhuang6-ux31a.sh.intel.com ([10.239.197.97]) by fmsmga008.fm.intel.com with ESMTP; 23 May 2018 18:00:27 -0700 From: "Huang, Ying" To: Andrew Morton Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Huang Ying , Andi Kleen , Jan Kara , Michal Hocko , Andrea Arcangeli , "Kirill A. Shutemov" , Matthew Wilcox , Hugh Dickins , Minchan Kim , Shaohua Li , Christopher Lameter , Mike Kravetz Subject: [PATCH -V2 -mm 1/4] mm, clear_huge_page: Move order algorithm into a separate function Date: Thu, 24 May 2018 08:58:48 +0800 Message-Id: <20180524005851.4079-2-ying.huang@intel.com> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180524005851.4079-1-ying.huang@intel.com> References: <20180524005851.4079-1-ying.huang@intel.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Huang Ying In commit c79b57e462b5d ("mm: hugetlb: clear target sub-page last when clearing huge page"), to keep the cache lines of the target subpage hot, the order to clear the subpages in the huge page in clear_huge_page() is changed to clearing the subpage which is furthest from the target subpage firstly, and the target subpage last. This optimization could be applied to copying huge page too with the same order algorithm. To avoid code duplication and reduce maintenance overhead, in this patch, the order algorithm is moved out of clear_huge_page() into a separate function: process_huge_page(). So that we can use it for copying huge page too. This will change the direct calls to clear_user_highpage() into the indirect calls. But with the proper inline support of the compilers, the indirect call will be optimized to be the direct call. Our tests show no performance change with the patch. This patch is a code cleanup without functionality change. Signed-off-by: "Huang, Ying" Suggested-by: Mike Kravetz Cc: Andi Kleen Cc: Jan Kara Cc: Michal Hocko Cc: Andrea Arcangeli Cc: "Kirill A. Shutemov" Cc: Matthew Wilcox Cc: Hugh Dickins Cc: Minchan Kim Cc: Shaohua Li Cc: Christopher Lameter --- mm/memory.c | 90 ++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 34 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 14578158ed20..b9f573a81bbd 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4569,71 +4569,93 @@ EXPORT_SYMBOL(__might_fault); #endif #if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLBFS) -static void clear_gigantic_page(struct page *page, - unsigned long addr, - unsigned int pages_per_huge_page) -{ - int i; - struct page *p = page; - - might_sleep(); - for (i = 0; i < pages_per_huge_page; - i++, p = mem_map_next(p, page, i)) { - cond_resched(); - clear_user_highpage(p, addr + i * PAGE_SIZE); - } -} -void clear_huge_page(struct page *page, - unsigned long addr_hint, unsigned int pages_per_huge_page) +/* + * Process all subpages of the specified huge page with the specified + * operation. The target subpage will be processed last to keep its + * cache lines hot. + */ +static inline void process_huge_page( + unsigned long addr_hint, unsigned int pages_per_huge_page, + void (*process_subpage)(unsigned long addr, int idx, void *arg), + void *arg) { int i, n, base, l; unsigned long addr = addr_hint & ~(((unsigned long)pages_per_huge_page << PAGE_SHIFT) - 1); - if (unlikely(pages_per_huge_page > MAX_ORDER_NR_PAGES)) { - clear_gigantic_page(page, addr, pages_per_huge_page); - return; - } - - /* Clear sub-page to access last to keep its cache lines hot */ + /* Process target subpage last to keep its cache lines hot */ might_sleep(); n = (addr_hint - addr) / PAGE_SIZE; if (2 * n <= pages_per_huge_page) { - /* If sub-page to access in first half of huge page */ + /* If target subpage in first half of huge page */ base = 0; l = n; - /* Clear sub-pages at the end of huge page */ + /* Process subpages at the end of huge page */ for (i = pages_per_huge_page - 1; i >= 2 * n; i--) { cond_resched(); - clear_user_highpage(page + i, addr + i * PAGE_SIZE); + process_subpage(addr + i * PAGE_SIZE, i, arg); } } else { - /* If sub-page to access in second half of huge page */ + /* If target subpage in second half of huge page */ base = pages_per_huge_page - 2 * (pages_per_huge_page - n); l = pages_per_huge_page - n; - /* Clear sub-pages at the begin of huge page */ + /* Process subpages at the begin of huge page */ for (i = 0; i < base; i++) { cond_resched(); - clear_user_highpage(page + i, addr + i * PAGE_SIZE); + process_subpage(addr + i * PAGE_SIZE, i, arg); } } /* - * Clear remaining sub-pages in left-right-left-right pattern - * towards the sub-page to access + * Process remaining subpages in left-right-left-right pattern + * towards the target subpage */ for (i = 0; i < l; i++) { int left_idx = base + i; int right_idx = base + 2 * l - 1 - i; cond_resched(); - clear_user_highpage(page + left_idx, - addr + left_idx * PAGE_SIZE); + process_subpage(addr + left_idx * PAGE_SIZE, left_idx, arg); cond_resched(); - clear_user_highpage(page + right_idx, - addr + right_idx * PAGE_SIZE); + process_subpage(addr + right_idx * PAGE_SIZE, right_idx, arg); } } +static void clear_gigantic_page(struct page *page, + unsigned long addr, + unsigned int pages_per_huge_page) +{ + int i; + struct page *p = page; + + might_sleep(); + for (i = 0; i < pages_per_huge_page; + i++, p = mem_map_next(p, page, i)) { + cond_resched(); + clear_user_highpage(p, addr + i * PAGE_SIZE); + } +} + +static void clear_subpage(unsigned long addr, int idx, void *arg) +{ + struct page *page = arg; + + clear_user_highpage(page + idx, addr); +} + +void clear_huge_page(struct page *page, + unsigned long addr_hint, unsigned int pages_per_huge_page) +{ + unsigned long addr = addr_hint & + ~(((unsigned long)pages_per_huge_page << PAGE_SHIFT) - 1); + + if (unlikely(pages_per_huge_page > MAX_ORDER_NR_PAGES)) { + clear_gigantic_page(page, addr, pages_per_huge_page); + return; + } + + process_huge_page(addr_hint, pages_per_huge_page, clear_subpage, page); +} + static void copy_user_gigantic_page(struct page *dst, struct page *src, unsigned long addr, struct vm_area_struct *vma, -- 2.16.1