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 24B61C001DF for ; Wed, 2 Aug 2023 14:21:10 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 647DA280182; Wed, 2 Aug 2023 10:21:09 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 5F7E6280143; Wed, 2 Aug 2023 10:21:09 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 4BFDF280182; Wed, 2 Aug 2023 10:21:09 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 3D1B2280143 for ; Wed, 2 Aug 2023 10:21:09 -0400 (EDT) Received: from smtpin20.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id 7B32E160F2C for ; Wed, 2 Aug 2023 14:21:08 +0000 (UTC) X-FDA: 81079376616.20.E5122AE Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) by imf01.hostedemail.com (Postfix) with ESMTP id 1A26C4001A for ; Wed, 2 Aug 2023 14:21:04 +0000 (UTC) Authentication-Results: imf01.hostedemail.com; dkim=none; dmarc=pass (policy=quarantine) header.from=huawei.com; spf=pass (imf01.hostedemail.com: domain of jonathan.cameron@huawei.com designates 185.176.79.56 as permitted sender) smtp.mailfrom=jonathan.cameron@huawei.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1690986065; a=rsa-sha256; cv=none; b=4x3VhQuXVTT25eVtYPQunhKJCmEu7oBom0BhJpR3/qWcV5tbkMMuworPdKAQpBGp30UwXN t5CEEvofVGBnhsNqei0ASfpC4mabbZ1SNy9mbVRIxNCf2Kn3xhbXcAG1Raw8QTXfF+7bsC CDS1RnNHPUlbpnwSZg92yC1ywl47600= ARC-Authentication-Results: i=1; imf01.hostedemail.com; dkim=none; dmarc=pass (policy=quarantine) header.from=huawei.com; spf=pass (imf01.hostedemail.com: domain of jonathan.cameron@huawei.com designates 185.176.79.56 as permitted sender) smtp.mailfrom=jonathan.cameron@huawei.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1690986065; 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-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Wp6uh41wIlI+n1yeQ+oiePVMAAd57e0RcxONQWMkTJU=; b=fxy+kSMLkKxUy/cYfQSK7cbhLNkiodvbPaccgihXH9GjHJdx/B1D1AjfaIfX+MgB7OGEsz RDgXqg+urBKy4kd4QjxiWNKxiwjHQiteNpkuu6Q4t6AYvE3iDA6m0hcByoq5ixN15Wgfyo sewFckEG3lbI/G4M+qVSpzmFOIiJWl4= Received: from lhrpeml500005.china.huawei.com (unknown [172.18.147.201]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4RGDZT4Q37z67GZK; Wed, 2 Aug 2023 22:17:21 +0800 (CST) Received: from localhost (10.202.227.76) by lhrpeml500005.china.huawei.com (7.191.163.240) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Wed, 2 Aug 2023 15:20:59 +0100 Date: Wed, 2 Aug 2023 15:20:58 +0100 From: Jonathan Cameron To: Vishal Verma CC: Andrew Morton , David Hildenbrand , Oscar Salvador , Dan Williams , Dave Jiang , , , , , Huang Ying , Dave Hansen , Aneesh Kumar K.V , Michal Hocko , Jeff Moyer Subject: Re: [PATCH v3 1/2] mm/memory_hotplug: split memmap_on_memory requests across memblocks Message-ID: <20230802152058.000030ed@Huawei.com> In-Reply-To: <20230801-vv-kmem_memmap-v3-1-406e9aaf5689@intel.com> References: <20230801-vv-kmem_memmap-v3-0-406e9aaf5689@intel.com> <20230801-vv-kmem_memmap-v3-1-406e9aaf5689@intel.com> Organization: Huawei Technologies Research and Development (UK) Ltd. X-Mailer: Claws Mail 4.1.0 (GTK 3.24.33; x86_64-w64-mingw32) MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit X-Originating-IP: [10.202.227.76] X-ClientProxiedBy: lhrpeml100001.china.huawei.com (7.191.160.183) To lhrpeml500005.china.huawei.com (7.191.163.240) X-CFilter-Loop: Reflected X-Rspamd-Server: rspam08 X-Rspamd-Queue-Id: 1A26C4001A X-Stat-Signature: 33tbohmi1bowzjf7bueu947wm7ryxw11 X-Rspam-User: X-HE-Tag: 1690986064-235393 X-HE-Meta: U2FsdGVkX1/wt+hVC5tKhLVcca+02+HT5ftRgFTAU4BOBySzlSop4bwYbIQyO4VMbdeytOMLOABc/y3/+5UVtHusXI/hJYUQpOR5K3PjB1y+S9Y2msQg3CuU0tICa4nguIKNR+JB2VTdFEBF+z0EBVjtdwX9A2cIxIMMv3G1HinemUwN1oM2jox2gFc1z7I09OSVdovRaEIY928YFvJpgfoJwfvmlQ7k8UPnIl4CjrXJDp2ipheiD/tILN6sbxg5pYGXta6KZv7N9WdIpOPO4kc+tjqPDoatakkbTLVcVvsXJOutKTYNggFf7OYU7m2fciUp40WQJmZ1+H7sA1ACQeSDvRhyoVyxb0KFIQYh9lW9/95BCRoID0DHGaEaMg01kvqTl0ACCiLUCVv+wbLlvf/Y5n2ym72yPjru2SH6tqVKBf6e2Eit6olW65oVZL5FOi2pDbcvO0IHPUohl5d3HqDwfBevoL2zCscCREBFkUwQIzrymsQAtseoFn1B3/DtAamEjcQ/OzZFsxldZBjW0Ub8jSFEhpqSdnsuq3WgOv/k53XspWCF8RpmQdL2D1XWAN9eG2AsiGF0vmHv6Luptyl2JNk7bB391I22jze7Y+Z7kPwTUs/cM4FOTL3c2J4R1ips/hG3hwrs+NGZ1l/iu9dgJX2YptEb0S/bCrovgVu/psJ6PQUC8o7QSCv5brCkx0qFIX2o4iRAfuFHPMXTlq2cSS2jZHU07QEGhJZBVCenLwWZ5/ke5TW5IaEvF++MRAfUMi5/VLm/kS5hMrJ3noQSjIGbgt9oQh1MwVw9jMS6dPYfp9asQ0C3Y9F1evcElbhmRmkrgMqEgeoH8mZKsE9SeasNJUPSWP/CJENa3qTltBOP64buICLvIDFbQNBv2vX7H+8XgLZsGd/h3/WiTPz9TDPxfGfeKjQDLwdwV3TWEaVgAOxFZOrbCSfuDWI7YRSNKvrphCC+mn0LgdS 2TJ9bB50 b0u8N80rSvshMZAW3/4pJ81Wf9KF8a4bdLOFYR2yO1sZwi5LwH9bAq27sed/5Rj9eauG+oaWwRtuCwqyUKjrMI81NCmZQbEXwFa3GQmxYBYTMvMUKZz08GnT+LHViFDAfw89B0AoeHHC5877Hokh3wr/q+GQtVEIKz+TM8UJMfkKXigzUhVnhumR0kfE2b9h4Pg+8/j3ZAONM9PJXN9fcEI99cFIKxnSSTsG4KurDc9GatS9yF7lruRABuF3KaqlavAmoxu6BxbXP+9bbTcwvb9cgLHYLHfiyZ57PE9BHxY5SC2nBICRBnSSdnxPs/7O0GdGENeyWDWiWhhNSq/z6ukYqFkkUiSOr4Izzc55rLoPV4SbWwuB5Nn3kVqZvSDiM3cZDRDvm20whVRztzf4CwbqWlKkWcgJ76soL X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: On Tue, 01 Aug 2023 23:55:37 -0600 Vishal Verma wrote: > The MHP_MEMMAP_ON_MEMORY flag for hotplugged memory is restricted to > 'memblock_size' chunks of memory being added. Adding a larger span of > memory precludes memmap_on_memory semantics. > > For users of hotplug such as kmem, large amounts of memory might get > added from the CXL subsystem. In some cases, this amount may exceed the > available 'main memory' to store the memmap for the memory being added. > In this case, it is useful to have a way to place the memmap on the > memory being added, even if it means splitting the addition into > memblock-sized chunks. > > Change add_memory_resource() to loop over memblock-sized chunks of > memory if caller requested memmap_on_memory, and if other conditions for > it are met. Teach try_remove_memory() to also expect that a memory > range being removed might have been split up into memblock sized chunks, > and to loop through those as needed. > > Cc: Andrew Morton > Cc: David Hildenbrand > Cc: Michal Hocko > Cc: Oscar Salvador > Cc: Dan Williams > Cc: Dave Jiang > Cc: Dave Hansen > Cc: Huang Ying > Suggested-by: David Hildenbrand > Signed-off-by: Vishal Verma A couple of trivial comments inline. > --- > mm/memory_hotplug.c | 150 ++++++++++++++++++++++++++++++++-------------------- > 1 file changed, 93 insertions(+), 57 deletions(-) > > diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c > index d282664f558e..cae03c8d4bbf 100644 > --- a/mm/memory_hotplug.c > +++ b/mm/memory_hotplug.c > @@ -1383,6 +1383,44 @@ static bool mhp_supports_memmap_on_memory(unsigned long size) > return arch_supports_memmap_on_memory(vmemmap_size); > } > > +static int add_memory_create_devices(int nid, struct memory_group *group, > + u64 start, u64 size, mhp_t mhp_flags) > +{ > + struct mhp_params params = { .pgprot = pgprot_mhp(PAGE_KERNEL) }; > + struct vmem_altmap mhp_altmap = { > + .base_pfn = PHYS_PFN(start), > + .end_pfn = PHYS_PFN(start + size - 1), > + }; > + int ret; > + > + if ((mhp_flags & MHP_MEMMAP_ON_MEMORY)) { > + mhp_altmap.free = memory_block_memmap_on_memory_pages(); > + params.altmap = kmalloc(sizeof(struct vmem_altmap), GFP_KERNEL); > + if (!params.altmap) > + return -ENOMEM; > + > + memcpy(params.altmap, &mhp_altmap, sizeof(mhp_altmap)); > + } > + > + /* call arch's memory hotadd */ > + ret = arch_add_memory(nid, start, size, ¶ms); > + if (ret < 0) > + goto error; > + > + /* create memory block devices after memory was added */ > + ret = create_memory_block_devices(start, size, params.altmap, group); > + if (ret) { > + arch_remove_memory(start, size, NULL); Maybe push this down to a second label? > + goto error; > + } > + > + return 0; > + > +error: > + kfree(params.altmap); > + return ret; > +} > + > /* > * NOTE: The caller must call lock_device_hotplug() to serialize hotplug > * and online/offline operations (triggered e.g. by sysfs). > @@ -1391,14 +1429,10 @@ static bool mhp_supports_memmap_on_memory(unsigned long size) > */ > int __ref add_memory_resource(int nid, struct resource *res, mhp_t mhp_flags) > { > - struct mhp_params params = { .pgprot = pgprot_mhp(PAGE_KERNEL) }; > + unsigned long memblock_size = memory_block_size_bytes(); > enum memblock_flags memblock_flags = MEMBLOCK_NONE; > - struct vmem_altmap mhp_altmap = { > - .base_pfn = PHYS_PFN(res->start), > - .end_pfn = PHYS_PFN(res->end), > - }; > struct memory_group *group = NULL; > - u64 start, size; > + u64 start, size, cur_start; > bool new_node = false; > int ret; > > @@ -1439,28 +1473,21 @@ int __ref add_memory_resource(int nid, struct resource *res, mhp_t mhp_flags) > /* > * Self hosted memmap array > */ > - if (mhp_flags & MHP_MEMMAP_ON_MEMORY) { > - if (mhp_supports_memmap_on_memory(size)) { > - mhp_altmap.free = memory_block_memmap_on_memory_pages(); > - params.altmap = kmalloc(sizeof(struct vmem_altmap), GFP_KERNEL); > - if (!params.altmap) > + if ((mhp_flags & MHP_MEMMAP_ON_MEMORY) && > + mhp_supports_memmap_on_memory(memblock_size)) { > + for (cur_start = start; cur_start < start + size; > + cur_start += memblock_size) { > + ret = add_memory_create_devices(nid, group, cur_start, > + memblock_size, > + mhp_flags); > + if (ret) > goto error; > - > - memcpy(params.altmap, &mhp_altmap, sizeof(mhp_altmap)); > } > - /* fallback to not using altmap */ > - } > - > - /* call arch's memory hotadd */ > - ret = arch_add_memory(nid, start, size, ¶ms); > - if (ret < 0) > - goto error_free; > - > - /* create memory block devices after memory was added */ > - ret = create_memory_block_devices(start, size, params.altmap, group); > - if (ret) { > - arch_remove_memory(start, size, NULL); > - goto error_free; > + } else { > + ret = add_memory_create_devices(nid, group, start, size, > + mhp_flags); > + if (ret) > + goto error; > } > > if (new_node) { > @@ -1497,8 +1524,6 @@ int __ref add_memory_resource(int nid, struct resource *res, mhp_t mhp_flags) > walk_memory_blocks(start, size, NULL, online_memory_block); > > return ret; > -error_free: > - kfree(params.altmap); > error: > if (IS_ENABLED(CONFIG_ARCH_KEEP_MEMBLOCK)) > memblock_remove(start, size); > @@ -2149,40 +2174,14 @@ void try_offline_node(int nid) > } > EXPORT_SYMBOL(try_offline_node); > > -static int __ref try_remove_memory(u64 start, u64 size) > +static void __ref __try_remove_memory(int nid, u64 start, u64 size) > { > - int ret; > - struct memory_block *mem; > - int rc = 0, nid = NUMA_NO_NODE; > struct vmem_altmap *altmap = NULL; > + struct memory_block *mem; > + int ret; > > - BUG_ON(check_hotplug_memory_range(start, size)); > - > - /* > - * All memory blocks must be offlined before removing memory. Check > - * whether all memory blocks in question are offline and return error > - * if this is not the case. > - * > - * While at it, determine the nid. Note that if we'd have mixed nodes, > - * we'd only try to offline the last determined one -- which is good > - * enough for the cases we care about. > - */ > - rc = walk_memory_blocks(start, size, &nid, check_memblock_offlined_cb); > - if (rc) > - return rc; > - > - /* > - * We only support removing memory added with MHP_MEMMAP_ON_MEMORY in > - * the same granularity it was added - a single memory block. > - */ > ret = walk_memory_blocks(start, size, &mem, test_has_altmap_cb); > if (ret) { > - if (size != memory_block_size_bytes()) { > - pr_warn("Refuse to remove %#llx - %#llx," > - "wrong granularity\n", > - start, start + size); > - return -EINVAL; > - } > altmap = mem->altmap; > /* > * Mark altmap NULL so that we can add a debug > @@ -2221,6 +2220,43 @@ static int __ref try_remove_memory(u64 start, u64 size) > try_offline_node(nid); > > mem_hotplug_done(); > +} > + > +static int __ref try_remove_memory(u64 start, u64 size) > +{ > + int ret, nid = NUMA_NO_NODE; I'm not overly keen to see the trivial rename of rc -> ret in here. Just makes it ever so slightly harder to compare old code and new code. > + > + BUG_ON(check_hotplug_memory_range(start, size)); > + > + /* > + * All memory blocks must be offlined before removing memory. Check > + * whether all memory blocks in question are offline and return error > + * if this is not the case. > + * > + * While at it, determine the nid. Note that if we'd have mixed nodes, > + * we'd only try to offline the last determined one -- which is good > + * enough for the cases we care about. > + */ > + ret = walk_memory_blocks(start, size, &nid, check_memblock_offlined_cb); > + if (ret) > + return ret; > + > + /* > + * For memmap_on_memory, the altmaps could have been added on > + * a per-memblock basis. Loop through the entire range if so, > + * and remove each memblock and its altmap. > + */ > + if (mhp_memmap_on_memory()) { > + unsigned long memblock_size = memory_block_size_bytes(); > + u64 cur_start; > + > + for (cur_start = start; cur_start < start + size; > + cur_start += memblock_size) > + __try_remove_memory(nid, cur_start, memblock_size); > + } else { > + __try_remove_memory(nid, start, size); > + } > + > return 0; > } > >