mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
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 <pankaj.gupta.linux@gmail.com> Tested-by: Pankaj Gupta <pankaj.gupta.linux@gmail.com> Cc: "Michael S. Tsirkin" <mst@redhat.com> Cc: Jason Wang <jasowang@redhat.com> Cc: Oscar Salvador <osalvador@suse.de> Cc: Michal Hocko <mhocko@kernel.org> Cc: Igor Mammedov <imammedo@redhat.com> Cc: Dave Young <dyoung@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Dan Williams <dan.j.williams@intel.com> Cc: Pavel Tatashin <pasha.tatashin@soleen.com> Cc: Stefan Hajnoczi <stefanha@redhat.com> Cc: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: David Hildenbrand <david@redhat.com> Link: https://lore.kernel.org/r/20200507140139.17083-10-david@redhat.com Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
08b3acd7a6
commit
a573238786
@ -446,6 +446,28 @@ static int virtio_mem_mb_remove(struct virtio_mem *vm, unsigned long mb_id)
|
||||
return remove_memory(nid, addr, memory_block_size_bytes());
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to offline and remove a memory block from Linux.
|
||||
*
|
||||
* Must not be called with the vm->hotplug_mutex held (possible deadlock with
|
||||
* onlining code).
|
||||
*
|
||||
* Will not modify the state of the memory block.
|
||||
*/
|
||||
static int virtio_mem_mb_offline_and_remove(struct virtio_mem *vm,
|
||||
unsigned long mb_id)
|
||||
{
|
||||
const uint64_t addr = virtio_mem_mb_id_to_phys(mb_id);
|
||||
int nid = vm->nid;
|
||||
|
||||
if (nid == NUMA_NO_NODE)
|
||||
nid = memory_add_physaddr_to_nid(addr);
|
||||
|
||||
dev_dbg(&vm->vdev->dev, "offlining and removing memory block: %lu\n",
|
||||
mb_id);
|
||||
return offline_and_remove_memory(nid, addr, memory_block_size_bytes());
|
||||
}
|
||||
|
||||
/*
|
||||
* Trigger the workqueue so the device can perform its magic.
|
||||
*/
|
||||
@ -537,7 +559,13 @@ static void virtio_mem_notify_offline(struct virtio_mem *vm,
|
||||
break;
|
||||
}
|
||||
|
||||
/* trigger the workqueue, maybe we can now unplug memory. */
|
||||
/*
|
||||
* Trigger the workqueue, maybe we can now unplug memory. Also,
|
||||
* when we offline and remove a memory block, this will re-trigger
|
||||
* us immediately - which is often nice because the removal of
|
||||
* the memory block (e.g., memmap) might have freed up memory
|
||||
* on other memory blocks we manage.
|
||||
*/
|
||||
virtio_mem_retry(vm);
|
||||
}
|
||||
|
||||
@ -1284,7 +1312,8 @@ static int virtio_mem_mb_unplug_any_sb_offline(struct virtio_mem *vm,
|
||||
* Unplug the desired number of plugged subblocks of an online memory block.
|
||||
* Will skip subblock that are busy.
|
||||
*
|
||||
* Will modify the state of the memory block.
|
||||
* Will modify the state of the memory block. Might temporarily drop the
|
||||
* hotplug_mutex.
|
||||
*
|
||||
* Note: Can fail after some subblocks were successfully unplugged. Can
|
||||
* 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,
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Once all subblocks of a memory block were unplugged, we want
|
||||
* to offline the memory block and remove it.
|
||||
* Once all subblocks of a memory block were unplugged, offline and
|
||||
* remove it. This will usually not fail, as no memory is in use
|
||||
* anymore - however some other notifiers might NACK the request.
|
||||
*/
|
||||
if (virtio_mem_mb_test_sb_unplugged(vm, mb_id, 0, vm->nb_sb_per_mb)) {
|
||||
mutex_unlock(&vm->hotplug_mutex);
|
||||
rc = virtio_mem_mb_offline_and_remove(vm, mb_id);
|
||||
mutex_lock(&vm->hotplug_mutex);
|
||||
if (!rc)
|
||||
virtio_mem_mb_set_state(vm, mb_id,
|
||||
VIRTIO_MEM_MB_STATE_UNUSED);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user