qemu/backends/hostmem-file.c
<<
>>
Prefs
   1/*
   2 * QEMU Host Memory Backend for hugetlbfs
   3 *
   4 * Copyright (C) 2013-2014 Red Hat Inc
   5 *
   6 * Authors:
   7 *   Paolo Bonzini <pbonzini@redhat.com>
   8 *
   9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10 * See the COPYING file in the top-level directory.
  11 */
  12#include "qemu/osdep.h"
  13#include "qapi/error.h"
  14#include "qemu-common.h"
  15#include "sysemu/hostmem.h"
  16#include "sysemu/sysemu.h"
  17#include "qom/object_interfaces.h"
  18
  19/* hostmem-file.c */
  20/**
  21 * @TYPE_MEMORY_BACKEND_FILE:
  22 * name of backend that uses mmap on a file descriptor
  23 */
  24#define TYPE_MEMORY_BACKEND_FILE "memory-backend-file"
  25
  26#define MEMORY_BACKEND_FILE(obj) \
  27    OBJECT_CHECK(HostMemoryBackendFile, (obj), TYPE_MEMORY_BACKEND_FILE)
  28
  29typedef struct HostMemoryBackendFile HostMemoryBackendFile;
  30
  31struct HostMemoryBackendFile {
  32    HostMemoryBackend parent_obj;
  33
  34    bool share;
  35    bool discard_data;
  36    char *mem_path;
  37};
  38
  39static void
  40file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
  41{
  42    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(backend);
  43
  44    if (!backend->size) {
  45        error_setg(errp, "can't create backend with size 0");
  46        return;
  47    }
  48    if (!fb->mem_path) {
  49        error_setg(errp, "mem-path property not set");
  50        return;
  51    }
  52#ifndef CONFIG_LINUX
  53    error_setg(errp, "-mem-path not supported on this host");
  54#else
  55    if (!host_memory_backend_mr_inited(backend)) {
  56        gchar *path;
  57        backend->force_prealloc = mem_prealloc;
  58        path = object_get_canonical_path(OBJECT(backend));
  59        memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
  60                                 path,
  61                                 backend->size, fb->share,
  62                                 fb->mem_path, errp);
  63        g_free(path);
  64    }
  65#endif
  66}
  67
  68static char *get_mem_path(Object *o, Error **errp)
  69{
  70    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
  71
  72    return g_strdup(fb->mem_path);
  73}
  74
  75static void set_mem_path(Object *o, const char *str, Error **errp)
  76{
  77    HostMemoryBackend *backend = MEMORY_BACKEND(o);
  78    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
  79
  80    if (host_memory_backend_mr_inited(backend)) {
  81        error_setg(errp, "cannot change property value");
  82        return;
  83    }
  84    g_free(fb->mem_path);
  85    fb->mem_path = g_strdup(str);
  86}
  87
  88static bool file_memory_backend_get_share(Object *o, Error **errp)
  89{
  90    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
  91
  92    return fb->share;
  93}
  94
  95static void file_memory_backend_set_share(Object *o, bool value, Error **errp)
  96{
  97    HostMemoryBackend *backend = MEMORY_BACKEND(o);
  98    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
  99
 100    if (host_memory_backend_mr_inited(backend)) {
 101        error_setg(errp, "cannot change property value");
 102        return;
 103    }
 104    fb->share = value;
 105}
 106
 107static bool file_memory_backend_get_discard_data(Object *o, Error **errp)
 108{
 109    return MEMORY_BACKEND_FILE(o)->discard_data;
 110}
 111
 112static void file_memory_backend_set_discard_data(Object *o, bool value,
 113                                               Error **errp)
 114{
 115    MEMORY_BACKEND_FILE(o)->discard_data = value;
 116}
 117
 118static void file_backend_unparent(Object *obj)
 119{
 120    HostMemoryBackend *backend = MEMORY_BACKEND(obj);
 121    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(obj);
 122
 123    if (host_memory_backend_mr_inited(backend) && fb->discard_data) {
 124        void *ptr = memory_region_get_ram_ptr(&backend->mr);
 125        uint64_t sz = memory_region_size(&backend->mr);
 126
 127        qemu_madvise(ptr, sz, QEMU_MADV_REMOVE);
 128    }
 129}
 130
 131static void
 132file_backend_class_init(ObjectClass *oc, void *data)
 133{
 134    HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
 135
 136    bc->alloc = file_backend_memory_alloc;
 137    oc->unparent = file_backend_unparent;
 138
 139    object_class_property_add_bool(oc, "share",
 140        file_memory_backend_get_share, file_memory_backend_set_share,
 141        &error_abort);
 142    object_class_property_add_bool(oc, "discard-data",
 143        file_memory_backend_get_discard_data, file_memory_backend_set_discard_data,
 144        &error_abort);
 145    object_class_property_add_str(oc, "mem-path",
 146        get_mem_path, set_mem_path,
 147        &error_abort);
 148}
 149
 150static void file_backend_instance_finalize(Object *o)
 151{
 152    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
 153
 154    g_free(fb->mem_path);
 155}
 156
 157static const TypeInfo file_backend_info = {
 158    .name = TYPE_MEMORY_BACKEND_FILE,
 159    .parent = TYPE_MEMORY_BACKEND,
 160    .class_init = file_backend_class_init,
 161    .instance_finalize = file_backend_instance_finalize,
 162    .instance_size = sizeof(HostMemoryBackendFile),
 163};
 164
 165static void register_types(void)
 166{
 167    type_register_static(&file_backend_info);
 168}
 169
 170type_init(register_types);
 171