[RFC 24/26] plugins/amdgpu: Store VMA data in shared memory
Tvrtko Ursulin <[email protected]> Fri, 20 Feb 2026 12:05:12 +0000
| Newsgroups | dev.linux.lists.criu |
|---|---|
| Message-ID | <[email protected]> |
If a process mmap()'s a device VMA and then forks it will currently fail to restore because the saved VMA metadata is populated after the target processes are forked. That is, only one process will see the list of struct vma_metadata needed to correctly restore. The other one will see an empty list and fail the whole process. Lets move the VMA metadata into the shared memory, protected by the existing mutex. This enables both processes to see the full list. Caveat is that at the moment we only allow for 128 total VMAs. Problem being is how to allocate a dynamicly size shared memory area at this stage of the restore process. Shmalloc() helper is out of reach, being already marked as private, and allocating anonymous shared memory appears to mess up the process state leading to crashes during restore. Signed-off-by: Tvrtko Ursulin <[email protected]> --- plugins/amdgpu/amdgpu_plugin.c | 41 +++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/plugins/amdgpu/amdgpu_plugin.c b/plugins/amdgpu/amdgpu_plugin.c index f4bda11b3de5..83d16272237f 100644 --- a/plugins/amdgpu/amdgpu_plugin.c +++ b/plugins/amdgpu/amdgpu_plugin.c @@ -50,7 +50,6 @@ #include "util.h" struct vma_metadata { - struct list_head list; uint64_t old_pgoff; uint64_t new_pgoff; uint64_t vma_entry; @@ -59,8 +58,6 @@ struct vma_metadata { /************************************ Global Variables ********************************************/ -static LIST_HEAD(update_vma_info_list); - size_t kfd_max_buffer_size; bool plugin_added_to_inventory = false; @@ -76,6 +73,8 @@ static struct shared_memory { mutex_t mutex; int num_handles; struct handle_id *handles; + int num_vmas; + struct vma_metadata vma[128]; } *shared_memory; /* @@ -1245,6 +1244,7 @@ int amdgpu_restore_init(void) mutex_init(&shared_memory->mutex); shared_memory->num_handles = num_handles; + shared_memory->num_vmas = 0; return 0; } @@ -1686,12 +1686,19 @@ int save_vma_updates(uint64_t offset, uint64_t addr, uint64_t restored_offset, int fd) { struct vma_metadata *vma_md; + int ret = 0; - vma_md = xmalloc(sizeof(*vma_md)); - if (!vma_md) { - return -ENOMEM; + if (!shared_memory) + return -ENXIO; + + mutex_lock(&shared_memory->mutex); + + if (shared_memory->num_vmas == ARRAY_SIZE(shared_memory->vma)) { + ret = -E2BIG; + goto out; } + vma_md = &shared_memory->vma[shared_memory->num_vmas++]; vma_md->old_pgoff = offset; vma_md->vma_entry = addr; vma_md->new_pgoff = restored_offset; @@ -1701,9 +1708,10 @@ int save_vma_updates(uint64_t offset, uint64_t addr, uint64_t restored_offset, vma_md->vma_entry, vma_md->old_pgoff, vma_md->new_pgoff, vma_md->fd); - list_add_tail(&vma_md->list, &update_vma_info_list); +out: + mutex_unlock(&shared_memory->mutex); - return 0; + return ret; } static int restore_bo_data(int id, struct kfd_criu_bo_bucket *bo_buckets, CriuKfd *e) @@ -2144,15 +2152,17 @@ CR_PLUGIN_REGISTER_HOOK(CR_PLUGIN_HOOK__RESTORE_EXT_FILE, amdgpu_plugin_restore_ int amdgpu_plugin_update_vmamap(const char *in_path, const uint64_t addr, const uint64_t old_offset, uint64_t *new_offset, int *updated_fd) { - struct vma_metadata *vma_md; - char path[PATH_MAX]; - char *p_begin; - char *p_end; bool is_kfd = false, is_renderD = false; + char *p_begin, *p_end; + char path[PATH_MAX]; + int i; if (plugin_disabled) return -ENOTSUP; + if (!shared_memory) + return -ENXIO; + pr_debug("Enter %s\n", __func__); strncpy(path, in_path, sizeof(path)); @@ -2182,7 +2192,10 @@ int amdgpu_plugin_update_vmamap(const char *in_path, const uint64_t addr, const return 0; } - list_for_each_entry(vma_md, &update_vma_info_list, list) { + mutex_lock(&shared_memory->mutex); + for (i = 0; i < shared_memory->num_vmas; i++) { + struct vma_metadata *vma_md = &shared_memory->vma[i]; + if (old_offset != vma_md->old_pgoff) continue; if (is_kfd && addr != vma_md->vma_entry) @@ -2201,11 +2214,13 @@ int amdgpu_plugin_update_vmamap(const char *in_path, const uint64_t addr, const *updated_fd = -1; } + mutex_unlock(&shared_memory->mutex); pr_debug("old_pgoff=0x%lx new_pgoff=0x%lx fd=%d\n", vma_md->old_pgoff, vma_md->new_pgoff, *updated_fd); return 1; } + mutex_unlock(&shared_memory->mutex); pr_info("No match for addr:0x%lx offset:%lx\n", addr, old_offset); return 0; } -- 2.52.0