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 "qemu/error-report.h"
  16#include "sysemu/hostmem.h"
  17#include "sysemu/sysemu.h"
  18#include "qom/object_interfaces.h"
  19
  20/* hostmem-file.c */
  21/**
  22 * @TYPE_MEMORY_BACKEND_FILE:
  23 * name of backend that uses mmap on a file descriptor
  24 */
  25#define TYPE_MEMORY_BACKEND_FILE "memory-backend-file"
  26
  27#define MEMORY_BACKEND_FILE(obj) \
  28    OBJECT_CHECK(HostMemoryBackendFile, (obj), TYPE_MEMORY_BACKEND_FILE)
  29
  30typedef struct HostMemoryBackendFile HostMemoryBackendFile;
  31
  32struct HostMemoryBackendFile {
  33    HostMemoryBackend parent_obj;
  34
  35    char *mem_path;
  36    uint64_t align;
  37    bool discard_data;
  38    bool is_pmem;
  39};
  40
  41static void
  42file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
  43{
  44    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(backend);
  45#ifdef CONFIG_POSIX
  46    gchar *path;
  47#endif
  48
  49    if (!backend->size) {
  50        error_setg(errp, "can't create backend with size 0");
  51        return;
  52    }
  53    if (!fb->mem_path) {
  54        error_setg(errp, "mem-path property not set");
  55        return;
  56    }
  57#ifndef CONFIG_POSIX
  58    error_setg(errp, "-mem-path not supported on this host");
  59#else
  60    backend->force_prealloc = mem_prealloc;
  61    path = object_get_canonical_path(OBJECT(backend));
  62    memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
  63                                     path,
  64                                     backend->size, fb->align,
  65                                     (backend->share ? RAM_SHARED : 0) |
  66                                     (fb->is_pmem ? RAM_PMEM : 0),
  67                                     fb->mem_path, errp);
  68    g_free(path);
  69#endif
  70}
  71
  72static char *get_mem_path(Object *o, Error **errp)
  73{
  74    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
  75
  76    return g_strdup(fb->mem_path);
  77}
  78
  79static void set_mem_path(Object *o, const char *str, Error **errp)
  80{
  81    HostMemoryBackend *backend = MEMORY_BACKEND(o);
  82    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
  83
  84    if (host_memory_backend_mr_inited(backend)) {
  85        error_setg(errp, "cannot change property value");
  86        return;
  87    }
  88    g_free(fb->mem_path);
  89    fb->mem_path = g_strdup(str);
  90}
  91
  92static bool file_memory_backend_get_discard_data(Object *o, Error **errp)
  93{
  94    return MEMORY_BACKEND_FILE(o)->discard_data;
  95}
  96
  97static void file_memory_backend_set_discard_data(Object *o, bool value,
  98                                               Error **errp)
  99{
 100    MEMORY_BACKEND_FILE(o)->discard_data = value;
 101}
 102
 103static void file_memory_backend_get_align(Object *o, Visitor *v,
 104                                          const char *name, void *opaque,
 105                                          Error **errp)
 106{
 107    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
 108    uint64_t val = fb->align;
 109
 110    visit_type_size(v, name, &val, errp);
 111}
 112
 113static void file_memory_backend_set_align(Object *o, Visitor *v,
 114                                          const char *name, void *opaque,
 115                                          Error **errp)
 116{
 117    HostMemoryBackend *backend = MEMORY_BACKEND(o);
 118    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
 119    Error *local_err = NULL;
 120    uint64_t val;
 121
 122    if (host_memory_backend_mr_inited(backend)) {
 123        error_setg(&local_err, "cannot change property value");
 124        goto out;
 125    }
 126
 127    visit_type_size(v, name, &val, &local_err);
 128    if (local_err) {
 129        goto out;
 130    }
 131    fb->align = val;
 132
 133 out:
 134    error_propagate(errp, local_err);
 135}
 136
 137static bool file_memory_backend_get_pmem(Object *o, Error **errp)
 138{
 139    return MEMORY_BACKEND_FILE(o)->is_pmem;
 140}
 141
 142static void file_memory_backend_set_pmem(Object *o, bool value, Error **errp)
 143{
 144    HostMemoryBackend *backend = MEMORY_BACKEND(o);
 145    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
 146
 147    if (host_memory_backend_mr_inited(backend)) {
 148        char *path = object_get_canonical_path_component(o);
 149
 150        error_setg(errp, "cannot change property 'pmem' of %s '%s'",
 151                   object_get_typename(o),
 152                   path);
 153        g_free(path);
 154        return;
 155    }
 156
 157#ifndef CONFIG_LIBPMEM
 158    if (value) {
 159        Error *local_err = NULL;
 160        char *path = object_get_canonical_path_component(o);
 161
 162        error_setg(&local_err,
 163                   "Lack of libpmem support while setting the 'pmem=on'"
 164                   " of %s '%s'. We can't ensure data persistence.",
 165                   object_get_typename(o),
 166                   path);
 167        g_free(path);
 168        error_propagate(errp, local_err);
 169        return;
 170    }
 171#endif
 172
 173    fb->is_pmem = value;
 174}
 175
 176static void file_backend_unparent(Object *obj)
 177{
 178    HostMemoryBackend *backend = MEMORY_BACKEND(obj);
 179    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(obj);
 180
 181    if (host_memory_backend_mr_inited(backend) && fb->discard_data) {
 182        void *ptr = memory_region_get_ram_ptr(&backend->mr);
 183        uint64_t sz = memory_region_size(&backend->mr);
 184
 185        qemu_madvise(ptr, sz, QEMU_MADV_REMOVE);
 186    }
 187}
 188
 189static void
 190file_backend_class_init(ObjectClass *oc, void *data)
 191{
 192    HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
 193
 194    bc->alloc = file_backend_memory_alloc;
 195    oc->unparent = file_backend_unparent;
 196
 197    object_class_property_add_bool(oc, "discard-data",
 198        file_memory_backend_get_discard_data, file_memory_backend_set_discard_data,
 199        &error_abort);
 200    object_class_property_add_str(oc, "mem-path",
 201        get_mem_path, set_mem_path,
 202        &error_abort);
 203    object_class_property_add(oc, "align", "int",
 204        file_memory_backend_get_align,
 205        file_memory_backend_set_align,
 206        NULL, NULL, &error_abort);
 207    object_class_property_add_bool(oc, "pmem",
 208        file_memory_backend_get_pmem, file_memory_backend_set_pmem,
 209        &error_abort);
 210}
 211
 212static void file_backend_instance_finalize(Object *o)
 213{
 214    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
 215
 216    g_free(fb->mem_path);
 217}
 218
 219static const TypeInfo file_backend_info = {
 220    .name = TYPE_MEMORY_BACKEND_FILE,
 221    .parent = TYPE_MEMORY_BACKEND,
 222    .class_init = file_backend_class_init,
 223    .instance_finalize = file_backend_instance_finalize,
 224    .instance_size = sizeof(HostMemoryBackendFile),
 225};
 226
 227static void register_types(void)
 228{
 229    type_register_static(&file_backend_info);
 230}
 231
 232type_init(register_types);
 233