in virtio_mem.c [2809:2872]
static void virtio_mem_deinit_hotplug(struct virtio_mem *vm)
{
unsigned long mb_id;
int rc;
/*
* Make sure the workqueue won't be triggered anymore and no memory
* blocks can be onlined/offlined until we're finished here.
*/
mutex_lock(&vm->hotplug_mutex);
spin_lock_irq(&vm->removal_lock);
vm->removing = true;
spin_unlock_irq(&vm->removal_lock);
mutex_unlock(&vm->hotplug_mutex);
/* wait until the workqueue stopped */
cancel_work_sync(&vm->wq);
hrtimer_cancel(&vm->retry_timer);
if (vm->in_sbm) {
/*
* After we unregistered our callbacks, user space can online
* partially plugged offline blocks. Make sure to remove them.
*/
virtio_mem_sbm_for_each_mb(vm, mb_id,
VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL) {
rc = virtio_mem_sbm_remove_mb(vm, mb_id);
BUG_ON(rc);
virtio_mem_sbm_set_mb_state(vm, mb_id,
VIRTIO_MEM_SBM_MB_UNUSED);
}
/*
* After we unregistered our callbacks, user space can no longer
* offline partially plugged online memory blocks. No need to
* worry about them.
*/
}
/* unregister callbacks */
unregister_virtio_mem_device(vm);
unregister_memory_notifier(&vm->memory_notifier);
/*
* There is no way we could reliably remove all memory we have added to
* the system. And there is no way to stop the driver/device from going
* away. Warn at least.
*/
if (virtio_mem_has_memory_added(vm)) {
dev_warn(&vm->vdev->dev,
"device still has system memory added\n");
} else {
virtio_mem_delete_resource(vm);
kfree_const(vm->resource_name);
memory_group_unregister(vm->mgid);
}
/* remove all tracking data - no locking needed */
if (vm->in_sbm) {
vfree(vm->sbm.mb_states);
vfree(vm->sbm.sb_states);
} else {
vfree(vm->bbm.bb_states);
}
}