@@ -446,6 +446,28 @@ static int virtio_mem_mb_remove(struct virtio_mem *vm, unsigned long mb_id)
446
446
return remove_memory (nid , addr , memory_block_size_bytes ());
447
447
}
448
448
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
+
449
471
/*
450
472
* Trigger the workqueue so the device can perform its magic.
451
473
*/
@@ -537,7 +559,13 @@ static void virtio_mem_notify_offline(struct virtio_mem *vm,
537
559
break ;
538
560
}
539
561
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
+ */
541
569
virtio_mem_retry (vm );
542
570
}
543
571
@@ -1284,7 +1312,8 @@ static int virtio_mem_mb_unplug_any_sb_offline(struct virtio_mem *vm,
1284
1312
* Unplug the desired number of plugged subblocks of an online memory block.
1285
1313
* Will skip subblock that are busy.
1286
1314
*
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.
1288
1317
*
1289
1318
* Note: Can fail after some subblocks were successfully unplugged. Can
1290
1319
* 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,
1340
1369
}
1341
1370
1342
1371
/*
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.
1345
1375
*/
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
+
1346
1385
return 0 ;
1347
1386
}
1348
1387
0 commit comments