hostmem: add property to map memory with MAP_SHARED

A new "share" property can be used with the "memory-file" backend to
map memory with MAP_SHARED instead of MAP_PRIVATE.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
master
Paolo Bonzini 2014-06-10 19:15:24 +08:00 committed by Michael S. Tsirkin
parent a35ba7be4b
commit dbcb898118
6 changed files with 42 additions and 12 deletions

View File

@ -28,6 +28,8 @@ typedef struct HostMemoryBackendFile HostMemoryBackendFile;
struct HostMemoryBackendFile { struct HostMemoryBackendFile {
HostMemoryBackend parent_obj; HostMemoryBackend parent_obj;
bool share;
char *mem_path; char *mem_path;
}; };
@ -51,7 +53,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
backend->force_prealloc = mem_prealloc; backend->force_prealloc = mem_prealloc;
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
object_get_canonical_path(OBJECT(backend)), object_get_canonical_path(OBJECT(backend)),
backend->size, backend->size, fb->share,
fb->mem_path, errp); fb->mem_path, errp);
} }
#endif #endif
@ -87,9 +89,31 @@ static void set_mem_path(Object *o, const char *str, Error **errp)
fb->mem_path = g_strdup(str); fb->mem_path = g_strdup(str);
} }
static bool file_memory_backend_get_share(Object *o, Error **errp)
{
HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
return fb->share;
}
static void file_memory_backend_set_share(Object *o, bool value, Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(o);
HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
if (memory_region_size(&backend->mr)) {
error_setg(errp, "cannot change property value");
return;
}
fb->share = value;
}
static void static void
file_backend_instance_init(Object *o) file_backend_instance_init(Object *o)
{ {
object_property_add_bool(o, "share",
file_memory_backend_get_share,
file_memory_backend_set_share, NULL);
object_property_add_str(o, "mem-path", get_mem_path, object_property_add_str(o, "mem-path", get_mem_path,
set_mem_path, NULL); set_mem_path, NULL);
} }

18
exec.c
View File

@ -73,6 +73,9 @@ static MemoryRegion io_mem_unassigned;
/* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */ /* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */
#define RAM_PREALLOC (1 << 0) #define RAM_PREALLOC (1 << 0)
/* RAM is mmap-ed with MAP_SHARED */
#define RAM_SHARED (1 << 1)
#endif #endif
struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus); struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
@ -1074,7 +1077,9 @@ static void *file_ram_alloc(RAMBlock *block,
perror("ftruncate"); perror("ftruncate");
} }
area = mmap(0, memory, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); area = mmap(0, memory, PROT_READ | PROT_WRITE,
(block->flags & RAM_SHARED ? MAP_SHARED : MAP_PRIVATE),
fd, 0);
if (area == MAP_FAILED) { if (area == MAP_FAILED) {
error_setg_errno(errp, errno, error_setg_errno(errp, errno,
"unable to map backing store for hugepages"); "unable to map backing store for hugepages");
@ -1286,7 +1291,7 @@ static ram_addr_t ram_block_add(RAMBlock *new_block)
#ifdef __linux__ #ifdef __linux__
ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
const char *mem_path, bool share, const char *mem_path,
Error **errp) Error **errp)
{ {
RAMBlock *new_block; RAMBlock *new_block;
@ -1311,6 +1316,7 @@ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
new_block = g_malloc0(sizeof(*new_block)); new_block = g_malloc0(sizeof(*new_block));
new_block->mr = mr; new_block->mr = mr;
new_block->length = size; new_block->length = size;
new_block->flags = share ? RAM_SHARED : 0;
new_block->host = file_ram_alloc(new_block, size, new_block->host = file_ram_alloc(new_block, size,
mem_path, errp); mem_path, errp);
if (!new_block->host) { if (!new_block->host) {
@ -1413,12 +1419,8 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
flags = MAP_FIXED; flags = MAP_FIXED;
munmap(vaddr, length); munmap(vaddr, length);
if (block->fd >= 0) { if (block->fd >= 0) {
#ifdef MAP_POPULATE flags |= (block->flags & RAM_SHARED ?
flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED : MAP_SHARED : MAP_PRIVATE);
MAP_PRIVATE;
#else
flags |= MAP_PRIVATE;
#endif
area = mmap(vaddr, length, PROT_READ | PROT_WRITE, area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
flags, block->fd, offset); flags, block->fd, offset);
} else { } else {

View File

@ -321,6 +321,7 @@ void memory_region_init_ram(MemoryRegion *mr,
* @owner: the object that tracks the region's reference count * @owner: the object that tracks the region's reference count
* @name: the name of the region. * @name: the name of the region.
* @size: size of the region. * @size: size of the region.
* @share: %true if memory must be mmaped with the MAP_SHARED flag
* @path: the path in which to allocate the RAM. * @path: the path in which to allocate the RAM.
* @errp: pointer to Error*, to store an error if it happens. * @errp: pointer to Error*, to store an error if it happens.
*/ */
@ -328,6 +329,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
struct Object *owner, struct Object *owner,
const char *name, const char *name,
uint64_t size, uint64_t size,
bool share,
const char *path, const char *path,
Error **errp); Error **errp);
#endif #endif

View File

@ -23,7 +23,8 @@
#include "hw/xen/xen.h" #include "hw/xen/xen.h"
ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
const char *mem_path, Error **errp); bool share, const char *mem_path,
Error **errp);
ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
MemoryRegion *mr); MemoryRegion *mr);
ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr); ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr);

View File

@ -1038,6 +1038,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
struct Object *owner, struct Object *owner,
const char *name, const char *name,
uint64_t size, uint64_t size,
bool share,
const char *path, const char *path,
Error **errp) Error **errp)
{ {
@ -1045,7 +1046,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
mr->ram = true; mr->ram = true;
mr->terminates = true; mr->terminates = true;
mr->destructor = memory_region_destructor_ram; mr->destructor = memory_region_destructor_ram;
mr->ram_addr = qemu_ram_alloc_from_file(size, mr, path, errp); mr->ram_addr = qemu_ram_alloc_from_file(size, mr, share, path, errp);
} }
#endif #endif

2
numa.c
View File

@ -231,7 +231,7 @@ static void allocate_system_memory_nonnuma(MemoryRegion *mr, Object *owner,
if (mem_path) { if (mem_path) {
#ifdef __linux__ #ifdef __linux__
Error *err = NULL; Error *err = NULL;
memory_region_init_ram_from_file(mr, owner, name, ram_size, memory_region_init_ram_from_file(mr, owner, name, ram_size, false,
mem_path, &err); mem_path, &err);
/* Legacy behavior: if allocation failed, fall back to /* Legacy behavior: if allocation failed, fall back to