From patchwork Fri May 19 15:50:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Ostrovsky X-Patchwork-Id: 9737501 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A66226020B for ; Fri, 19 May 2017 15:52:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A7AB526AE3 for ; Fri, 19 May 2017 15:52:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9B95928174; Fri, 19 May 2017 15:52:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 0C462287EC for ; Fri, 19 May 2017 15:52:18 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dBkA5-0000mx-VH; Fri, 19 May 2017 15:49:53 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dBkA4-0000iR-Fq for xen-devel@lists.xen.org; Fri, 19 May 2017 15:49:52 +0000 Received: from [85.158.139.211] by server-16.bemta-5.messagelabs.com id BE/3D-01752-F141F195; Fri, 19 May 2017 15:49:51 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrNLMWRWlGSWpSXmKPExsUyZ7p8oK6kiHy kwfH35hZLPi5mcWD0OLr7N1MAYxRrZl5SfkUCa8bRJQYFDywrdj14ydTAeFyzi5GLQ0hgMpPE r1tX2CCc34wSP/fOZ4FwNjBKPNk1gRHC6WGUeLS1EaiMk4NNwEji7NHpjCC2iIC0xLXPl8GKm AUamCSenzsI5HBwCAt4S6x7pw9isgioStzpdgMp5xXwktjydDJYq4SAgsSUh++ZQWxOoOo3k2 axgthCQDW/ZvWxQtQYS7S/vcg2gZFvASPDKkaN4tSistQiXSNTvaSizPSMktzEzBxdQwNTvdz U4uLE9NScxKRiveT83E2MwECpZ2Bg3MG4q93vEKMkB5OSKK/jYblIIb6k/JTKjMTijPii0pzU 4kOMMhwcShK8DkLykUKCRanpqRVpmTnAkIVJS3DwKInw8oGkeYsLEnOLM9MhUqcYFaXEebNAE gIgiYzSPLg2WJxcYpSVEuZlZGBgEOIpSC3KzSxBlX/FKM7BqCTMewNkCk9mXgnc9FdAi5mAFj c/kAZZXJKIkJJqYFzD7/Cr6MfeOT7i3zp3nOj4M81cj2+xlHHhwqsXV+edV5T76mz91ePjskv Njo4r7uic+pH5+7CBjdaN7qOaM6SdImfM3HslZkJcf8iBk8r8sU2bpJ4VzZtcEcw2SeeCm4tj 0O0tmeb6T6L0psnZyeR9uTppzXzhgCoGCe/YwLATnA9/sk5rrlViKc5INNRiLipOBADa2Z4Ij gIAAA== X-Env-Sender: boris.ostrovsky@oracle.com X-Msg-Ref: server-14.tower-206.messagelabs.com!1495208983!60403069!1 X-Originating-IP: [156.151.31.81] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogMTU2LjE1MS4zMS44MSA9PiAyODgzMzk=\n X-StarScan-Received: X-StarScan-Version: 9.4.12; banners=-,-,- X-VirusChecked: Checked Received: (qmail 28721 invoked from network); 19 May 2017 15:49:45 -0000 Received: from userp1040.oracle.com (HELO userp1040.oracle.com) (156.151.31.81) by server-14.tower-206.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 19 May 2017 15:49:45 -0000 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id v4JFncrY032585 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 19 May 2017 15:49:39 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.14.4/8.14.4) with ESMTP id v4JFnc4L029668 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 19 May 2017 15:49:38 GMT Received: from abhmp0001.oracle.com (abhmp0001.oracle.com [141.146.116.7]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id v4JFnbDs003543; Fri, 19 May 2017 15:49:37 GMT Received: from ovs104.us.oracle.com (/10.149.76.204) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 19 May 2017 08:49:37 -0700 From: Boris Ostrovsky To: xen-devel@lists.xen.org Date: Fri, 19 May 2017 11:50:34 -0400 Message-Id: <1495209040-11101-3-git-send-email-boris.ostrovsky@oracle.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1495209040-11101-1-git-send-email-boris.ostrovsky@oracle.com> References: <1495209040-11101-1-git-send-email-boris.ostrovsky@oracle.com> X-Source-IP: aserv0022.oracle.com [141.146.126.234] Cc: sstabellini@kernel.org, wei.liu2@citrix.com, George.Dunlap@eu.citrix.com, andrew.cooper3@citrix.com, ian.jackson@eu.citrix.com, tim@xen.org, jbeulich@suse.com, Boris Ostrovsky Subject: [Xen-devel] [PATCH v4 2/8] mm: Extract allocation loop from alloc_heap_pages() X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP This will make code a bit more readable, especially with changes that will be introduced in subsequent patches. Signed-off-by: Boris Ostrovsky Acked-by: Jan Beulich --- Change in v4: * New patch xen/common/page_alloc.c | 132 +++++++++++++++++++++++++++--------------------- 1 file changed, 74 insertions(+), 58 deletions(-) diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index c65d214..1e57885 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -694,22 +694,15 @@ static void page_list_add_scrub(struct page_info *pg, unsigned int node, page_list_add(pg, &heap(node, zone, order)); } -/* Allocate 2^@order contiguous pages. */ -static struct page_info *alloc_heap_pages( - unsigned int zone_lo, unsigned int zone_hi, - unsigned int order, unsigned int memflags, - struct domain *d) +static struct page_info *get_free_buddy(unsigned int zone_lo, + unsigned int zone_hi, + unsigned int order, unsigned int memflags, + struct domain *d) { - unsigned int i, j, zone = 0, nodemask_retry = 0; nodeid_t first_node, node = MEMF_get_node(memflags), req_node = node; - unsigned long request = 1UL << order; + nodemask_t nodemask = d ? d->node_affinity : node_online_map; + unsigned int j, zone, nodemask_retry = 0, request = 1UL << order; struct page_info *pg; - nodemask_t nodemask = (d != NULL ) ? d->node_affinity : node_online_map; - bool need_scrub, need_tlbflush = 0; - uint32_t tlbflush_timestamp = 0; - - /* Make sure there are enough bits in memflags for nodeID. */ - BUILD_BUG_ON((_MEMF_bits - _MEMF_node) < (8 * sizeof(nodeid_t))); if ( node == NUMA_NO_NODE ) { @@ -725,36 +718,8 @@ static struct page_info *alloc_heap_pages( first_node = node; ASSERT(node < MAX_NUMNODES); - ASSERT(zone_lo <= zone_hi); - ASSERT(zone_hi < NR_ZONES); - - if ( unlikely(order > MAX_ORDER) ) - return NULL; - - spin_lock(&heap_lock); - - /* - * Claimed memory is considered unavailable unless the request - * is made by a domain with sufficient unclaimed pages. - */ - if ( (outstanding_claims + request > - total_avail_pages + tmem_freeable_pages()) && - ((memflags & MEMF_no_refcount) || - !d || d->outstanding_pages < request) ) - goto not_found; - - /* - * TMEM: When available memory is scarce due to tmem absorbing it, allow - * only mid-size allocations to avoid worst of fragmentation issues. - * Others try tmem pools then fail. This is a workaround until all - * post-dom0-creation-multi-page allocations can be eliminated. - */ - if ( ((order == 0) || (order >= 9)) && - (total_avail_pages <= midsize_alloc_zone_pages) && - tmem_freeable_pages() ) - goto try_tmem; - /* + /* * Start with requested node, but exhaust all node memory in requested * zone before failing, only calc new node value if we fail to find memory * in target node, this avoids needless computation on fast-path. @@ -770,11 +735,11 @@ static struct page_info *alloc_heap_pages( /* Find smallest order which can satisfy the request. */ for ( j = order; j <= MAX_ORDER; j++ ) if ( (pg = page_list_remove_head(&heap(node, zone, j))) ) - goto found; + return pg; } while ( zone-- > zone_lo ); /* careful: unsigned zone may wrap */ if ( (memflags & MEMF_exact_node) && req_node != NUMA_NO_NODE ) - goto not_found; + return NULL; /* Pick next node. */ if ( !node_isset(node, nodemask) ) @@ -791,42 +756,93 @@ static struct page_info *alloc_heap_pages( { /* When we have tried all in nodemask, we fall back to others. */ if ( (memflags & MEMF_exact_node) || nodemask_retry++ ) - goto not_found; + return NULL; nodes_andnot(nodemask, node_online_map, nodemask); first_node = node = first_node(nodemask); if ( node >= MAX_NUMNODES ) - goto not_found; + return NULL; } } +} + +/* Allocate 2^@order contiguous pages. */ +static struct page_info *alloc_heap_pages( + unsigned int zone_lo, unsigned int zone_hi, + unsigned int order, unsigned int memflags, + struct domain *d) +{ + nodeid_t node; + unsigned int i, buddy_order, zone; + unsigned long request = 1UL << order; + struct page_info *pg; + bool need_scrub, need_tlbflush = false; + uint32_t tlbflush_timestamp = 0; + + /* Make sure there are enough bits in memflags for nodeID. */ + BUILD_BUG_ON((_MEMF_bits - _MEMF_node) < (8 * sizeof(nodeid_t))); + + ASSERT(zone_lo <= zone_hi); + ASSERT(zone_hi < NR_ZONES); + + if ( unlikely(order > MAX_ORDER) ) + return NULL; + + spin_lock(&heap_lock); + + /* + * Claimed memory is considered unavailable unless the request + * is made by a domain with sufficient unclaimed pages. + */ + if ( (outstanding_claims + request > + total_avail_pages + tmem_freeable_pages()) && + ((memflags & MEMF_no_refcount) || + !d || d->outstanding_pages < request) ) + { + spin_unlock(&heap_lock); + return NULL; + } - try_tmem: - /* Try to free memory from tmem */ - if ( (pg = tmem_relinquish_pages(order, memflags)) != NULL ) + /* + * TMEM: When available memory is scarce due to tmem absorbing it, allow + * only mid-size allocations to avoid worst of fragmentation issues. + * Others try tmem pools then fail. This is a workaround until all + * post-dom0-creation-multi-page allocations can be eliminated. + */ + if ( ((order == 0) || (order >= 9)) && + (total_avail_pages <= midsize_alloc_zone_pages) && + tmem_freeable_pages() ) { - /* reassigning an already allocated anonymous heap page */ + /* Try to free memory from tmem. */ + pg = tmem_relinquish_pages(order, memflags); spin_unlock(&heap_lock); return pg; } - not_found: - /* No suitable memory blocks. Fail the request. */ - spin_unlock(&heap_lock); - return NULL; + pg = get_free_buddy(zone_lo, zone_hi, order, memflags, d); + if ( !pg ) + { + /* No suitable memory blocks. Fail the request. */ + spin_unlock(&heap_lock); + return NULL; + } + + node = phys_to_nid(page_to_maddr(pg)); + zone = page_to_zone(pg); + buddy_order = PFN_ORDER(pg); - found: need_scrub = (pg->u.free.first_dirty != INVALID_DIRTY_IDX); /* We may have to halve the chunk a number of times. */ - while ( j != order ) + while ( buddy_order != order ) { /* * Some of the sub-chunks may be clean but we will mark them * as dirty (if need_scrub is set) to avoid traversing the * list here. */ - page_list_add_scrub(pg, node, zone, --j, + page_list_add_scrub(pg, node, zone, --buddy_order, need_scrub ? 0 : INVALID_DIRTY_IDX); - pg += 1 << j; + pg += 1 << buddy_order; } ASSERT(avail[node][zone] >= request);