Skip to content

Commit a573238

Browse files
davidhildenbrandmstsirkin
authored andcommitted
virtio-mem: Offline and remove completely unplugged memory blocks
Let's offline+remove memory blocks once all subblocks are unplugged. We can use the new Linux MM interface for that. As no memory is in use anymore, this shouldn't take a long time and shouldn't fail. There might be corner cases where the offlining could still fail (especially, if another notifier NACKs the offlining request). Acked-by: Pankaj Gupta <[email protected]> Tested-by: Pankaj Gupta <[email protected]> Cc: "Michael S. Tsirkin" <[email protected]> Cc: Jason Wang <[email protected]> Cc: Oscar Salvador <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Igor Mammedov <[email protected]> Cc: Dave Young <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Dan Williams <[email protected]> Cc: Pavel Tatashin <[email protected]> Cc: Stefan Hajnoczi <[email protected]> Cc: Vlastimil Babka <[email protected]> Signed-off-by: David Hildenbrand <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 08b3acd commit a573238

File tree

1 file changed

+43
-4
lines changed

1 file changed

+43
-4
lines changed

drivers/virtio/virtio_mem.c

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,28 @@ static int virtio_mem_mb_remove(struct virtio_mem *vm, unsigned long mb_id)
446446
return remove_memory(nid, addr, memory_block_size_bytes());
447447
}
448448

449+
/*
450+
* Try to offline and remove a memory block from Linux.
451+
*
452+
* Must not be called with the vm->hotplug_mutex held (possible deadlock with
453+
* onlining code).
454+
*
455+
* Will not modify the state of the memory block.
456+
*/
457+
static int virtio_mem_mb_offline_and_remove(struct virtio_mem *vm,
458+
unsigned long mb_id)
459+
{
460+
const uint64_t addr = virtio_mem_mb_id_to_phys(mb_id);
461+
int nid = vm->nid;
462+
463+
if (nid == NUMA_NO_NODE)
464+
nid = memory_add_physaddr_to_nid(addr);
465+
466+
dev_dbg(&vm->vdev->dev, "offlining and removing memory block: %lu\n",
467+
mb_id);
468+
return offline_and_remove_memory(nid, addr, memory_block_size_bytes());
469+
}
470+
449471
/*
450472
* Trigger the workqueue so the device can perform its magic.
451473
*/
@@ -537,7 +559,13 @@ static void virtio_mem_notify_offline(struct virtio_mem *vm,
537559
break;
538560
}
539561

540-
/* trigger the workqueue, maybe we can now unplug memory. */
562+
/*
563+
* Trigger the workqueue, maybe we can now unplug memory. Also,
564+
* when we offline and remove a memory block, this will re-trigger
565+
* us immediately - which is often nice because the removal of
566+
* the memory block (e.g., memmap) might have freed up memory
567+
* on other memory blocks we manage.
568+
*/
541569
virtio_mem_retry(vm);
542570
}
543571

@@ -1284,7 +1312,8 @@ static int virtio_mem_mb_unplug_any_sb_offline(struct virtio_mem *vm,
12841312
* Unplug the desired number of plugged subblocks of an online memory block.
12851313
* Will skip subblock that are busy.
12861314
*
1287-
* Will modify the state of the memory block.
1315+
* Will modify the state of the memory block. Might temporarily drop the
1316+
* hotplug_mutex.
12881317
*
12891318
* Note: Can fail after some subblocks were successfully unplugged. Can
12901319
* return 0 even if subblocks were busy and could not get unplugged.
@@ -1340,9 +1369,19 @@ static int virtio_mem_mb_unplug_any_sb_online(struct virtio_mem *vm,
13401369
}
13411370

13421371
/*
1343-
* TODO: Once all subblocks of a memory block were unplugged, we want
1344-
* to offline the memory block and remove it.
1372+
* Once all subblocks of a memory block were unplugged, offline and
1373+
* remove it. This will usually not fail, as no memory is in use
1374+
* anymore - however some other notifiers might NACK the request.
13451375
*/
1376+
if (virtio_mem_mb_test_sb_unplugged(vm, mb_id, 0, vm->nb_sb_per_mb)) {
1377+
mutex_unlock(&vm->hotplug_mutex);
1378+
rc = virtio_mem_mb_offline_and_remove(vm, mb_id);
1379+
mutex_lock(&vm->hotplug_mutex);
1380+
if (!rc)
1381+
virtio_mem_mb_set_state(vm, mb_id,
1382+
VIRTIO_MEM_MB_STATE_UNUSED);
1383+
}
1384+
13461385
return 0;
13471386
}
13481387

0 commit comments

Comments
 (0)