From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9BD9FE7F14B for ; Wed, 27 Sep 2023 01:38:11 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 9EC0A8D0066; Tue, 26 Sep 2023 21:38:10 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 99C3A8D0002; Tue, 26 Sep 2023 21:38:10 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 864EF8D0066; Tue, 26 Sep 2023 21:38:10 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 79FF78D0002 for ; Tue, 26 Sep 2023 21:38:10 -0400 (EDT) Received: from smtpin03.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id 488AF40D9A for ; Wed, 27 Sep 2023 01:38:10 +0000 (UTC) X-FDA: 81280666740.03.247E15B Received: from out-193.mta1.migadu.com (out-193.mta1.migadu.com [95.215.58.193]) by imf28.hostedemail.com (Postfix) with ESMTP id 89842C000A for ; Wed, 27 Sep 2023 01:38:08 +0000 (UTC) Authentication-Results: imf28.hostedemail.com; dkim=pass header.d=linux.dev header.s=key1 header.b=F+C2wGLK; spf=pass (imf28.hostedemail.com: domain of yajun.deng@linux.dev designates 95.215.58.193 as permitted sender) smtp.mailfrom=yajun.deng@linux.dev; dmarc=pass (policy=none) header.from=linux.dev ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1695778688; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:references:dkim-signature; bh=Nz6caoQZVPJenPUxtn5KQteC75zflIiT4pdokHAsttw=; b=XgkTbtmHytpXXDq/HInZj95ZLx0/V+JLAKe7QO5+mZ5bZRIIIb0wQZjCyEpTivwIFrCQu4 3YMArrJ2Ne5EKJyMM2ZJtpEKVSz/OUPNT1g23PfTnhoEd6z6EIlJ9YoCiGqsZtP1WvHg4c OLtRmgbvwKzIsmGNAjuHkFBJpKpQeY4= ARC-Authentication-Results: i=1; imf28.hostedemail.com; dkim=pass header.d=linux.dev header.s=key1 header.b=F+C2wGLK; spf=pass (imf28.hostedemail.com: domain of yajun.deng@linux.dev designates 95.215.58.193 as permitted sender) smtp.mailfrom=yajun.deng@linux.dev; dmarc=pass (policy=none) header.from=linux.dev ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1695778688; a=rsa-sha256; cv=none; b=69VbSMPXiW1qyrtuNyltp6vdEbmEYQ0LrSYbCBu9O5qmfoSuyytVP/pqwYF2IIm9+RFvkI 7VoojWDDiFDncfnaEywP11OPq8PNPWXjFIJc52TjdJs+6PQfYtz80n3VNpiS/hIy4lmKgX u9l09MSxvJOFAcp3mAttjh82KavOcZY= X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1695778686; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=Nz6caoQZVPJenPUxtn5KQteC75zflIiT4pdokHAsttw=; b=F+C2wGLKKtN0ueSSw//MQ/ZSjyS6aCRiZyJ6YlOb1fuekh72Nu5ff5Z6H39On8vrOt6mxj rhBzAklP1gljRJdrJg3BZS4d6PV4hLD8FHKRZo0RTFybBUTBwUnNJ3lcX5+4e4TwLKRzZ2 t5Kg4LL9wEzupxrNacEixn6KSw4KXgo= From: Yajun Deng To: rppt@kernel.org, akpm@linux-foundation.org Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Yajun Deng Subject: [PATCH] memblock: don't run loop in memblock_add_range() twice Date: Wed, 27 Sep 2023 09:37:52 +0800 Message-Id: <20230927013752.2515238-1-yajun.deng@linux.dev> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT X-Rspamd-Queue-Id: 89842C000A X-Rspam-User: X-Stat-Signature: sshjs143oxa3fc4eexkz8ygznzekpxbp X-Rspamd-Server: rspam01 X-HE-Tag: 1695778688-864633 X-HE-Meta: U2FsdGVkX18Yu715/CF+SWJCsYb+4/gqwUObr6BEav/iyaiKWzFLvOSeLGxXZnL26uc7TZWZDpXhhNJLZTehv9b59LboC2hQ3ntNP0XJonNHge0i0lLbxGFck+OkGkLKfZdfWoomKXpb62vX5dzMZJS+YNItb+SDBLvFI/wvEiZE4YIhtTCyxCBCR4GCvjJwOiwPxXKWjXFyqNFbmxafkIi3PWaTbe+JLRHYE8m3qS3ZSBWuKlWgrI2ezFS9GqQtG35BlPlqCxF2QxW6gADPeslkLjGlgDyXuynSiMgiMQBuOEGPIlStsfltXOW0OOZKu/QltPfnrrq7i9mXQHCwsIeZ7U0hAK0r6lqNPqcHTRXYPVNNbD1GYaBIVH58ss7+ewBgfvP8r0EDLYLtNrX7cX7zPPSiUr//zZ8Xg8kDlTItmWvCfu24/yN/ecyK6AXguDc8pWKWTRxatjyLAkERPiUMO6wXGbTCK5eJEkxB0nX5ujk4NmFPCcr0mUmICrlynAz8qaeUjOItC+HbUBExDDHTfoExOcATsLqpuItYsjaDgii7ZpjdGUr5SpmhzDhs7394QJGSqiZeYWChXSCEL5B12nv2oHRLGkjxvVIQDZSMqfesu6Hc/Wj80I3T8QLz8IcNjRgDRqyHAZ3V/nKxTZeKjuaY5b9c5GghmFyACvd7S57ZcITJonxWAGMqa5/+ZnyyOoOHmPKTgIHwQkrHsPp/TXWGADAotmuumGBOrcMMLjInt1qp5DNNEL0lsr/Mlpu/wMsPqeU3S+2T/4RNP6/UgG8WksWCUtEX0MGjTsUwhPdF2qSwxOrgvM8MuGLO8misccDRD5BQRZphtUClige2kvNvdqsGDVSfJCWoVbuILltvPGZ9sDZCDQcY+NPapGeRwM7b1PB4vnr3JkXt9sHUAH5rc2OssScJBOBcqNhDC5JBenk/6qcmLw7ymsR34cgJntwM0CAlrsIQxk1 H/rJvyI4 ZaRfDZNx8ptF8RaAmslBSP00XvEEYRiwx5A0b0pykrMw8KebAKw4IEFbHQuvLw+/1t1VPY06VnHeAhixb5lqDKRr726PxJoKdK+BRbYPdPIkYPqqM1OsIoAhs/EDTM5aIyfJ4 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000066, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: There is round twice in memblock_add_range(). The first counts the number of regions needed to accommodate the new area. The second actually inserts them. But the first round isn't really needed, we just need to check the counts before inserting them. Check the count before calling memblock_insert_region(). If the count is equal to the maximum value, it needs to resize the array. Otherwise, insert it directly. To avoid nested calls to memblock_add_range(), we need to call memblock_reserve() out of memblock_double_array(). Signed-off-by: Yajun Deng --- mm/memblock.c | 117 ++++++++++++++++++++++++-------------------------- 1 file changed, 57 insertions(+), 60 deletions(-) diff --git a/mm/memblock.c b/mm/memblock.c index 5a88d6d24d79..3f44c84f5d0b 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -400,6 +400,8 @@ void __init memblock_discard(void) * @type: memblock type of the regions array being doubled * @new_area_start: starting address of memory range to avoid overlap with * @new_area_size: size of memory range to avoid overlap with + * @new_reserve_base: starting address of new array + * @new_reserve_size: size of new array * * Double the size of the @type regions array. If memblock is being used to * allocate memory for a new reserved regions array and there is a previously @@ -412,7 +414,9 @@ void __init memblock_discard(void) */ static int __init_memblock memblock_double_array(struct memblock_type *type, phys_addr_t new_area_start, - phys_addr_t new_area_size) + phys_addr_t new_area_size, + phys_addr_t *new_reserve_base, + phys_addr_t *new_reserve_size) { struct memblock_region *new_array, *old_array; phys_addr_t old_alloc_size, new_alloc_size; @@ -490,11 +494,13 @@ static int __init_memblock memblock_double_array(struct memblock_type *type, memblock_free(old_array, old_alloc_size); /* - * Reserve the new array if that comes from the memblock. Otherwise, we - * needn't do it + * Keep the address and size if that comes from the memblock. Otherwise, + * we needn't do it. */ - if (!use_slab) - BUG_ON(memblock_reserve(addr, new_alloc_size)); + if (!use_slab) { + *new_reserve_base = addr; + *new_reserve_size = new_alloc_size; + } /* Update slab flag */ *in_slab = use_slab; @@ -588,11 +594,12 @@ static int __init_memblock memblock_add_range(struct memblock_type *type, phys_addr_t base, phys_addr_t size, int nid, enum memblock_flags flags) { - bool insert = false; phys_addr_t obase = base; phys_addr_t end = base + memblock_cap_size(base, &size); - int idx, nr_new, start_rgn = -1, end_rgn; + phys_addr_t new_base = 0, new_size; + int idx, start_rgn = -1, end_rgn; struct memblock_region *rgn; + unsigned long ocnt = type->cnt; if (!size) return 0; @@ -608,25 +615,6 @@ static int __init_memblock memblock_add_range(struct memblock_type *type, return 0; } - /* - * The worst case is when new range overlaps all existing regions, - * then we'll need type->cnt + 1 empty regions in @type. So if - * type->cnt * 2 + 1 is less than or equal to type->max, we know - * that there is enough empty regions in @type, and we can insert - * regions directly. - */ - if (type->cnt * 2 + 1 <= type->max) - insert = true; - -repeat: - /* - * The following is executed twice. Once with %false @insert and - * then with %true. The first counts the number of regions needed - * to accommodate the new area. The second actually inserts them. - */ - base = obase; - nr_new = 0; - for_each_memblock_type(idx, type, rgn) { phys_addr_t rbase = rgn->base; phys_addr_t rend = rbase + rgn->size; @@ -644,15 +632,23 @@ static int __init_memblock memblock_add_range(struct memblock_type *type, WARN_ON(nid != memblock_get_region_node(rgn)); #endif WARN_ON(flags != rgn->flags); - nr_new++; - if (insert) { - if (start_rgn == -1) - start_rgn = idx; - end_rgn = idx + 1; - memblock_insert_region(type, idx++, base, - rbase - base, nid, - flags); - } + + /* + * If type->cnt is equal to type->max, it means there's + * not enough empty region and the array needs to be + * resized. Otherwise, insert it directly. + */ + if ((type->cnt == type->max) && + memblock_double_array(type, obase, size, + &new_base, &new_size)) + return -ENOMEM; + + if (start_rgn == -1) + start_rgn = idx; + end_rgn = idx + 1; + memblock_insert_region(type, idx++, base, + rbase - base, nid, + flags); } /* area below @rend is dealt with, forget about it */ base = min(rend, end); @@ -660,33 +656,28 @@ static int __init_memblock memblock_add_range(struct memblock_type *type, /* insert the remaining portion */ if (base < end) { - nr_new++; - if (insert) { - if (start_rgn == -1) - start_rgn = idx; - end_rgn = idx + 1; - memblock_insert_region(type, idx, base, end - base, - nid, flags); - } + if ((type->cnt == type->max) && + memblock_double_array(type, obase, size, + &new_base, &new_size)) + return -ENOMEM; + + if (start_rgn == -1) + start_rgn = idx; + end_rgn = idx + 1; + memblock_insert_region(type, idx, base, end - base, + nid, flags); } - if (!nr_new) + if (ocnt == type->cnt) return 0; - /* - * If this was the first round, resize array and repeat for actual - * insertions; otherwise, merge and return. - */ - if (!insert) { - while (type->cnt + nr_new > type->max) - if (memblock_double_array(type, obase, size) < 0) - return -ENOMEM; - insert = true; - goto repeat; - } else { - memblock_merge_regions(type, start_rgn, end_rgn); - return 0; - } + memblock_merge_regions(type, start_rgn, end_rgn); + + /* Reserve the new array */ + if (new_base) + memblock_reserve(new_base, new_size); + + return 0; } /** @@ -755,6 +746,7 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, int *start_rgn, int *end_rgn) { phys_addr_t end = base + memblock_cap_size(base, &size); + phys_addr_t new_base = 0, new_size; int idx; struct memblock_region *rgn; @@ -764,10 +756,15 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, return 0; /* we'll create at most two more regions */ - while (type->cnt + 2 > type->max) - if (memblock_double_array(type, base, size) < 0) + if (type->cnt + 2 > type->max) { + if (memblock_double_array(type, base, size, + &new_base, &new_size)) return -ENOMEM; + if (new_base) + memblock_reserve(new_base, new_size); + } + for_each_memblock_type(idx, type, rgn) { phys_addr_t rbase = rgn->base; phys_addr_t rend = rbase + rgn->size; -- 2.25.1