From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BF70C330B3E for ; Thu, 22 Jan 2026 11:43:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769082202; cv=none; b=Mj7AS4up++z6m5l/scq7zRNUms7l2DVYwfP0k+4dDWsuGpBWJw5gxyCy+PVvX/r+mc9wg+6BxGHB8W3XaRbg2y1AT15/Fy98ap6wlxUyqnE3ZlZxwhL3Tpv/+JLbYBKXGGB5vAJPLAQWO9KoqtE/IIr0ZdI+5WeWthz+OVFzcXA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769082202; c=relaxed/simple; bh=OPdZB6MSp5meiziqBd6t9/xT7dgKfhbqXbbraGT13Mg=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=YpBs6Nf2o4y3jpB8Ug4BbHpnbW/9aOTYoUWiUVr69cr+HaYGgvaIaoh3fJF+S/thRzJLh9iHsO9IK1nqfHc2zSj+PfQ/Us4gihdehJdoK4I8W/nsuCp5sweLQiWpdrpJSAZq4X1vN3RiDNcHmj7EawU7f3zkT9ZJxIrNn3T8GKs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mIpB13tS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mIpB13tS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7445BC116C6; Thu, 22 Jan 2026 11:43:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769082202; bh=OPdZB6MSp5meiziqBd6t9/xT7dgKfhbqXbbraGT13Mg=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=mIpB13tSBsQHZYqWrcmRadmhOe9cDmU9RxlZ8RaFNt76xFzjjJ1XDWs2tQDj/WBbB FLqq54Rgvexxb24IGs9cCmrmIix/Np5so7G7P4j4VFW9yjtCIS6/ttCze+Ft+S2V8x 9YyAP4tTIG9Ttx4NF27XfG9EYhTc5GHnAWCFj8kAYWK5UCiXciBGJRM6TGYEKyUX6H AuMRKYj2BFmP7p6bm6urjlBiCE93iq9u2r0+KgC47aqrs4pcMGGBHY+v0lQ9QJ0vCc ziNJPBRRNA5DH1rgBnyrffz9SOSVQAAfM4IoglJMgJFPDhSDzbpBU7qVxafqtiIRWo GgIcZJ9Ar+ahg== Date: Thu, 22 Jan 2026 13:43:13 +0200 From: Mike Rapoport To: Tianyou Li Cc: David Hildenbrand , Oscar Salvador , Wei Yang , Michal Hocko , linux-mm@kvack.org, Yong Hu , Nanhai Zou , Yuan Liu , Tim Chen , Qiuxu Zhuo , Yu C Chen , Pan Deng , Chen Zhang , linux-kernel@vger.kernel.org Subject: Re: [PATCH v8 3/3] mm/memory hotplug/unplug: Optimize zone->contiguous update when changes pfn range Message-ID: References: <20260120143346.1427837-1-tianyou.li@intel.com> <20260120143346.1427837-4-tianyou.li@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20260120143346.1427837-4-tianyou.li@intel.com> Hi, On Tue, Jan 20, 2026 at 10:33:46PM +0800, Tianyou Li wrote: > When invoke move_pfn_range_to_zone or remove_pfn_range_from_zone, it will > update the zone->contiguous by checking the new zone's pfn range from the > beginning to the end, regardless the previous state of the old zone. When > the zone's pfn range is large, the cost of traversing the pfn range to > update the zone->contiguous could be significant. > > Add fast paths to quickly detect cases where zone is definitely not > contiguous without scanning the new zone. The cases are: when the new range > did not overlap with previous range, the contiguous should be false; if the > new range adjacent with the previous range, just need to check the new > range; if the new added pages could not fill the hole of previous zone, the > contiguous should be false. > > The following test cases of memory hotplug for a VM [1], tested in the > environment [2], show that this optimization can significantly reduce the > memory hotplug time [3]. > > +----------------+------+---------------+--------------+----------------+ > | | Size | Time (before) | Time (after) | Time Reduction | > | +------+---------------+--------------+----------------+ > | Plug Memory | 256G | 10s | 2s | 80% | > | +------+---------------+--------------+----------------+ > | | 512G | 33s | 6s | 81% | > +----------------+------+---------------+--------------+----------------+ > > +----------------+------+---------------+--------------+----------------+ > | | Size | Time (before) | Time (after) | Time Reduction | > | +------+---------------+--------------+----------------+ > | Unplug Memory | 256G | 10s | 2s | 80% | > | +------+---------------+--------------+----------------+ > | | 512G | 34s | 6s | 82% | > +----------------+------+---------------+--------------+----------------+ > > [1] Qemu commands to hotplug 256G/512G memory for a VM: > object_add memory-backend-ram,id=hotmem0,size=256G/512G,share=on > device_add virtio-mem-pci,id=vmem1,memdev=hotmem0,bus=port1 > qom-set vmem1 requested-size 256G/512G (Plug Memory) > qom-set vmem1 requested-size 0G (Unplug Memory) > > [2] Hardware : Intel Icelake server > Guest Kernel : v6.18-rc2 > Qemu : v9.0.0 > > Launch VM : > qemu-system-x86_64 -accel kvm -cpu host \ > -drive file=./Centos10_cloud.qcow2,format=qcow2,if=virtio \ > -drive file=./seed.img,format=raw,if=virtio \ > -smp 3,cores=3,threads=1,sockets=1,maxcpus=3 \ > -m 2G,slots=10,maxmem=2052472M \ > -device pcie-root-port,id=port1,bus=pcie.0,slot=1,multifunction=on \ > -device pcie-root-port,id=port2,bus=pcie.0,slot=2 \ > -nographic -machine q35 \ > -nic user,hostfwd=tcp::3000-:22 > > Guest kernel auto-onlines newly added memory blocks: > echo online > /sys/devices/system/memory/auto_online_blocks > > [3] The time from typing the QEMU commands in [1] to when the output of > 'grep MemTotal /proc/meminfo' on Guest reflects that all hotplugged > memory is recognized. > > Reported-by: Nanhai Zou > Reported-by: Chen Zhang > Tested-by: Yuan Liu > Reviewed-by: Tim Chen > Reviewed-by: Qiuxu Zhuo > Reviewed-by: Yu C Chen > Reviewed-by: Pan Deng > Reviewed-by: Nanhai Zou > Reviewed-by: Yuan Liu > Signed-off-by: Tianyou Li > --- ... > +int online_memory_block_pages(unsigned long start_pfn, unsigned long nr_pages, > + unsigned long nr_vmemmap_pages, struct zone *zone, > + struct memory_group *group) > { > + const bool contiguous = zone->contiguous; > + enum zone_contig_state new_contiguous_state; > int ret; > > + /* > + * Calculate the new zone contig state before move_pfn_range_to_zone() > + * sets the zone temporarily to non-contiguous. > + */ > + new_contiguous_state = zone_contig_state_after_growing(zone, start_pfn, > + nr_pages); > + > if (nr_vmemmap_pages) { > ret = mhp_init_memmap_on_memory(start_pfn, nr_vmemmap_pages, zone); > if (ret) > - return ret; > + goto restore_zone_contig; But zone_contig_state_after_growing() does not change zone->contiguous. Why do we need to save and restore it? > } > > ret = online_pages(start_pfn + nr_vmemmap_pages, > @@ -1271,7 +1320,7 @@ int online_memory_block_pages(unsigned long start_pfn, > if (ret) { > if (nr_vmemmap_pages) > mhp_deinit_memmap_on_memory(start_pfn, nr_vmemmap_pages); > - return ret; > + goto restore_zone_contig; > } > > /* > @@ -1282,6 +1331,15 @@ int online_memory_block_pages(unsigned long start_pfn, > adjust_present_page_count(pfn_to_page(start_pfn), group, > nr_vmemmap_pages); > > + /* > + * Now that the ranges are indicated as online, check whether the whole > + * zone is contiguous. > + */ > + set_zone_contiguous(zone, new_contiguous_state); > + return 0; > + > +restore_zone_contig: > + zone->contiguous = contiguous; > return ret; > } -- Sincerely yours, Mike.