Commit f55484fd authored by David Hildenbrand's avatar David Hildenbrand Committed by Michael S. Tsirkin
Browse files

virtio-mem: check if the config changed before fake offlining memory



If we repeatedly fail to fake offline memory to unplug it, we won't be
sending any unplug requests to the device. However, we only check if the
config changed when sending such (un)plug requests.

We could end up trying for a long time to unplug memory, even though
the config changed already and we're not supposed to unplug memory
anymore. For example, the hypervisor might detect a low-memory situation
while unplugging memory and decide to replug some memory. Continuing
trying to unplug memory in that case can be problematic.

So let's check on a more regular basis.

Signed-off-by: default avatarDavid Hildenbrand <david@redhat.com>
Message-Id: <20230713145551.2824980-5-david@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent a31648fd
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -1189,7 +1189,8 @@ static void virtio_mem_fake_online(unsigned long pfn, unsigned long nr_pages)
 * Try to allocate a range, marking pages fake-offline, effectively
 * fake-offlining them.
 */
static int virtio_mem_fake_offline(unsigned long pfn, unsigned long nr_pages)
static int virtio_mem_fake_offline(struct virtio_mem *vm, unsigned long pfn,
				   unsigned long nr_pages)
{
	const bool is_movable = is_zone_movable_page(pfn_to_page(pfn));
	int rc, retry_count;
@@ -1202,6 +1203,14 @@ static int virtio_mem_fake_offline(unsigned long pfn, unsigned long nr_pages)
	 * some guarantees.
	 */
	for (retry_count = 0; retry_count < 5; retry_count++) {
		/*
		 * If the config changed, stop immediately and go back to the
		 * main loop: avoid trying to keep unplugging if the device
		 * might have decided to not remove any more memory.
		 */
		if (atomic_read(&vm->config_changed))
			return -EAGAIN;

		rc = alloc_contig_range(pfn, pfn + nr_pages, MIGRATE_MOVABLE,
					GFP_KERNEL);
		if (rc == -ENOMEM)
@@ -1951,7 +1960,7 @@ static int virtio_mem_sbm_unplug_sb_online(struct virtio_mem *vm,
	start_pfn = PFN_DOWN(virtio_mem_mb_id_to_phys(mb_id) +
			     sb_id * vm->sbm.sb_size);

	rc = virtio_mem_fake_offline(start_pfn, nr_pages);
	rc = virtio_mem_fake_offline(vm, start_pfn, nr_pages);
	if (rc)
		return rc;

@@ -2149,7 +2158,7 @@ static int virtio_mem_bbm_offline_remove_and_unplug_bb(struct virtio_mem *vm,
		if (!page)
			continue;

		rc = virtio_mem_fake_offline(pfn, PAGES_PER_SECTION);
		rc = virtio_mem_fake_offline(vm, pfn, PAGES_PER_SECTION);
		if (rc) {
			end_pfn = pfn;
			goto rollback;