diff --git a/exec.c b/exec.c index 11e0328095..997ef6a5a8 100644 --- a/exec.c +++ b/exec.c @@ -1016,7 +1016,8 @@ static long gethugepagesize(const char *path) static void *file_ram_alloc(RAMBlock *block, ram_addr_t memory, - const char *path) + const char *path, + Error **errp) { char *filename; char *sanitized_name; @@ -1035,7 +1036,8 @@ static void *file_ram_alloc(RAMBlock *block, } if (kvm_enabled() && !kvm_has_sync_mmu()) { - fprintf(stderr, "host lacks kvm mmu notifiers, -mem-path unsupported\n"); + error_setg(errp, + "host lacks kvm mmu notifiers, -mem-path unsupported"); goto error; } @@ -1052,7 +1054,8 @@ static void *file_ram_alloc(RAMBlock *block, fd = mkstemp(filename); if (fd < 0) { - perror("unable to create backing store for hugepages"); + error_setg_errno(errp, errno, + "unable to create backing store for hugepages"); g_free(filename); goto error; } @@ -1067,12 +1070,14 @@ static void *file_ram_alloc(RAMBlock *block, * If anything goes wrong with it under other filesystems, * mmap will fail. */ - if (ftruncate(fd, memory)) + if (ftruncate(fd, memory)) { perror("ftruncate"); + } area = mmap(0, memory, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (area == MAP_FAILED) { - perror("file_ram_alloc: can't mmap RAM pages"); + error_setg_errno(errp, errno, + "unable to map backing store for hugepages"); close(fd); goto error; } @@ -1281,13 +1286,14 @@ static ram_addr_t ram_block_add(RAMBlock *new_block) #ifdef __linux__ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, - const char *mem_path) + const char *mem_path, + Error **errp) { RAMBlock *new_block; if (xen_enabled()) { - fprintf(stderr, "-mem-path not supported with Xen\n"); - exit(1); + error_setg(errp, "-mem-path not supported with Xen"); + return -1; } if (phys_mem_alloc != qemu_anon_ram_alloc) { @@ -1296,16 +1302,22 @@ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, * phys_mem_alloc, but we haven't bothered to provide * a hook there. */ - fprintf(stderr, - "-mem-path not supported with this accelerator\n"); - exit(1); + error_setg(errp, + "-mem-path not supported with this accelerator"); + return -1; } size = TARGET_PAGE_ALIGN(size); new_block = g_malloc0(sizeof(*new_block)); new_block->mr = mr; new_block->length = size; - new_block->host = file_ram_alloc(new_block, size, mem_path); + new_block->host = file_ram_alloc(new_block, size, + mem_path, errp); + if (!new_block->host) { + g_free(new_block); + return -1; + } + return ram_block_add(new_block); } #endif diff --git a/include/exec/memory.h b/include/exec/memory.h index 65ddb7a2a8..4c7bacf959 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -31,6 +31,7 @@ #include "qemu/queue.h" #include "qemu/int128.h" #include "qemu/notify.h" +#include "qapi/error.h" #define MAX_PHYS_ADDR_SPACE_BITS 62 #define MAX_PHYS_ADDR (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1) @@ -321,12 +322,14 @@ void memory_region_init_ram(MemoryRegion *mr, * @name: the name of the region. * @size: size of the region. * @path: the path in which to allocate the RAM. + * @errp: pointer to Error*, to store an error if it happens. */ void memory_region_init_ram_from_file(MemoryRegion *mr, struct Object *owner, const char *name, uint64_t size, - const char *path); + const char *path, + Error **errp); #endif /** diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 9b00638505..deafcebac0 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -23,7 +23,7 @@ #include "hw/xen/xen.h" ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, - const char *mem_path); + const char *mem_path, Error **errp); ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr); ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr); diff --git a/memory.c b/memory.c index 09f98fcbe6..5ef7167848 100644 --- a/memory.c +++ b/memory.c @@ -1038,13 +1038,14 @@ void memory_region_init_ram_from_file(MemoryRegion *mr, struct Object *owner, const char *name, uint64_t size, - const char *path) + const char *path, + Error **errp) { memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - mr->ram_addr = qemu_ram_alloc_from_file(size, mr, path); + mr->ram_addr = qemu_ram_alloc_from_file(size, mr, path, errp); } #endif diff --git a/numa.c b/numa.c index 7c36bb5b60..8af9c916ac 100644 --- a/numa.c +++ b/numa.c @@ -230,7 +230,18 @@ static void allocate_system_memory_nonnuma(MemoryRegion *mr, Object *owner, { if (mem_path) { #ifdef __linux__ - memory_region_init_ram_from_file(mr, owner, name, ram_size, mem_path); + Error *err = NULL; + memory_region_init_ram_from_file(mr, owner, name, ram_size, + mem_path, &err); + + /* Legacy behavior: if allocation failed, fall back to + * regular RAM allocation. + */ + if (!memory_region_size(mr)) { + qerror_report_err(err); + error_free(err); + memory_region_init_ram(mr, owner, name, ram_size); + } #else fprintf(stderr, "-mem-path not supported on this host\n"); exit(1);