Signed-off-by: Luyao Huang <lhuang(a)redhat.com>
---
configure.ac | 10 +
po/POTFILES.in | 3 +-
src/Makefile.am | 7 +-
src/libvirt_private.syms | 24 ++
src/util/virshm.c | 739 +++++++++++++++++++++++++++++++++++++++++++++++
src/util/virshm.h | 92 ++++++
6 files changed, 872 insertions(+), 3 deletions(-)
create mode 100644 src/util/virshm.c
create mode 100644 src/util/virshm.h
diff --git a/configure.ac b/configure.ac
index 08a0f93..ce4908d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1176,6 +1176,16 @@ if test "$with_linux" = "yes"; then
]])
fi
+dnl
+dnl check for POSIX share memory functions
+dnl
+LIBRT_LIBS=""
+AC_CHECK_LIB([rt],[shm_open],[LIBRT_LIBS="-lrt"])
+old_libs="$LIBS"
+LIBS="$old_libs $LIBRT_LIBS"
+AC_CHECK_FUNCS([shm_open])
+LIBS="$old_libs"
+AC_SUBST([LIBRT_LIBS])
dnl Need to test if pkg-config exists
PKG_PROG_PKG_CONFIG
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 46220f7..189699d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -216,8 +216,9 @@ src/util/virpolkit.c
src/util/virportallocator.c
src/util/virprocess.c
src/util/virrandom.c
-src/util/virsexpr.c
src/util/virscsi.c
+src/util/virsexpr.c
+src/util/virshm.c
src/util/virsocketaddr.c
src/util/virstats.c
src/util/virstorageencryption.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 57a06e8..3158b32 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -152,6 +152,7 @@ UTIL_SOURCES = \
util/virscsi.c util/virscsi.h \
util/virseclabel.c util/virseclabel.h \
util/virsexpr.c util/virsexpr.h \
+ util/virshm.c util/virshm.h \
util/virsocketaddr.h util/virsocketaddr.c \
util/virstats.c util/virstats.h \
util/virstorageencryption.c util/virstorageencryption.h \
@@ -1049,7 +1050,7 @@ libvirt_util_la_LIBADD = $(CAPNG_LIBS) $(YAJL_LIBS) $(LIBNL_LIBS) \
$(THREAD_LIBS) $(AUDIT_LIBS) $(DEVMAPPER_LIBS) \
$(LIB_CLOCK_GETTIME) $(DBUS_LIBS) $(MSCOM_LIBS) $(LIBXML_LIBS) \
$(SECDRIVER_LIBS) $(NUMACTL_LIBS) $(SYSTEMD_DAEMON_LIBS) \
- $(POLKIT_LIBS)
+ $(POLKIT_LIBS) $(LIBRT_LIBS)
noinst_LTLIBRARIES += libvirt_conf.la
@@ -1282,9 +1283,10 @@ libvirt_driver_qemu_impl_la_CFLAGS = \
$(AM_CFLAGS)
libvirt_driver_qemu_impl_la_LDFLAGS = $(AM_LDFLAGS)
libvirt_driver_qemu_impl_la_LIBADD = $(CAPNG_LIBS) \
- $(GNUTLS_LIBS) \
+ $(GNUTLS_LIBS) \
$(LIBNL_LIBS) \
$(LIBXML_LIBS) \
+ $(LIBRT_LIBS) \
$(NULL)
libvirt_driver_qemu_impl_la_SOURCES = $(QEMU_DRIVER_SOURCES)
@@ -2286,6 +2288,7 @@ libvirt_setuid_rpc_client_la_LDFLAGS = \
$(AM_LDFLAGS) \
$(LIBXML_LIBS) \
$(SECDRIVER_LIBS) \
+ $(LIBRT_LIBS) \
$(NULL)
libvirt_setuid_rpc_client_la_CFLAGS = \
-DLIBVIRT_SETUID_RPC_CLIENT \
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d57bf5b..e25ef6b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2089,6 +2089,30 @@ sexpr_u64;
string2sexpr;
+# util/virshm.h
+virShmBuildPath;
+virShmCreate;
+virShmObjectFindByName;
+virShmObjectFree;
+virShmObjectGetName;
+virShmObjectGetOtherCreate;
+virShmObjectGetShareable;
+virShmObjectGetSize;
+virShmObjectGetType;
+virShmObjectGetUsedDomainNumber;
+virShmObjectGetUsedDriverName;
+virShmObjectListAdd;
+virShmObjectListDel;
+virShmObjectListGetDefault;
+virShmObjectListGetStateFilePath;
+virShmObjectNew;
+virShmObjectRemoveStateFile;
+virShmObjectSaveState;
+virShmOpen;
+virShmRemoveUsedDomain;
+virShmSetUsedDomain;
+virShmUnlink;
+
# util/virsocketaddr.h
virSocketAddrBroadcast;
virSocketAddrBroadcastByPrefix;
diff --git a/src/util/virshm.c b/src/util/virshm.c
new file mode 100644
index 0000000..bec9dd2
--- /dev/null
+++ b/src/util/virshm.c
@@ -0,0 +1,739 @@
+/*
+ * virshm.c: helper API for POSIX share memory
+ *
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#ifdef HAVE_SHM_OPEN
+# include <sys/mman.h>
+#endif
+
+#include "virshm.h"
+#include "virxml.h"
+#include "virbuffer.h"
+#include "virerror.h"
+#include "virstring.h"
+#include "virlog.h"
+#include "virutil.h"
+#include "viralloc.h"
+#include "virfile.h"
+#include "configmake.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_LOG_INIT("util.shm");
+
+#define SHMEM_STATE_DIR LOCALSTATEDIR "/run/libvirt/shmem"
+
+VIR_ENUM_IMPL(virShmObject, VIR_SHM_TYPE_LAST,
+ "shm",
+ "server");
+
+struct _virShmObject {
+ char *name; /* shmem object name */
+ int type; /* shmem object type */
+ unsigned long long size; /* size of shmem object */
+ char *path; /* shmem path */
+ bool othercreate; /* a bool parameter record if the shm is created by
libvirt */
+ bool shareable; /* a bool parameter record if the shm is shared between
domains */
+
+ char *drvname; /* which driver */
+ char **domains; /* domain(s) using this shm */
+ size_t ndomains; /* number of useds */
+};
+
+struct _virShmObjectList {
+ virObjectLockable parent;
+ char *stateDir;
+ size_t nshmobjs;
+ virShmObjectPtr *shmobjs;
+};
+
+static virClassPtr virShmObjectListClass;
+
+static virShmObjectListPtr mainlist; /* global shm object list */
+
+static void virShmObjectListDispose(void *obj);
+
+static int
+virShmObjectListLoadState(virShmObjectPtr *shmobj,
+ const char *stateDir,
+ const char *name)
+{
+ char *stateFile = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ xmlDocPtr xml = NULL;
+ virShmObjectPtr tmpshm;
+ xmlNodePtr *usagenode = NULL;
+ int ret = -1;
+ char *drivername = NULL;
+ char *shmtype = NULL;
+ int nusages;
+
+ if (VIR_ALLOC(tmpshm) < 0)
+ return -1;
+
+ if (!(stateFile = virFileBuildPath(stateDir, name, ".xml")))
+ goto cleanup;
+
+ if (!(xml = virXMLParseFileCtxt(stateFile, &ctxt)))
+ goto cleanup;
+
+ tmpshm->name = virXPathString("string(./name)", ctxt);
+ if (!tmpshm->name) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("shmem missing name attribute"));
+ goto cleanup;
+ }
+
+ shmtype = virXPathString("string(./type)", ctxt);
+ if (!shmtype) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("shmem missing type attribute"));
+ goto cleanup;
+ }
+ if ((tmpshm->type = virShmObjectTypeFromString(shmtype)) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("invalid shmem object type %s"), shmtype);
+ goto cleanup;
+ }
+
+ if (virXPathULongLong("string(./size)", ctxt, &tmpshm->size) < 0)
{
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("shmem missing or have invalid size attribute"));
+ goto cleanup;
+ }
+
+ tmpshm->path = virXPathString("string(./path)", ctxt);
+ if (virXPathBoolean("boolean(./othercreate)", ctxt))
+ tmpshm->othercreate = true;
+
+ if (virXPathBoolean("boolean(./shareable)", ctxt))
+ tmpshm->shareable = true;
+
+ if (!(drivername = virXPathString("string(./driver)", ctxt))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("shmem usage element missing driver attribute"));
+ goto cleanup;
+ }
+ nusages = virXPathNodeSet("./domain", ctxt, &usagenode);
+ if (nusages < 0)
+ goto cleanup;
+
+ if (nusages > 0) {
+ size_t i;
+
+ for (i = 0; i < nusages; i++) {
+ char *domainname;
+ xmlNodePtr save = NULL;
+
+ save = ctxt->node;
+ ctxt->node = usagenode[i];
+
+ if (!(domainname = virXPathString("string(./@name)", ctxt))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("shmem domain element missing name
attribute"));
+ goto cleanup;
+ }
+
+ if (virShmSetUsedDomain(tmpshm, drivername, domainname) < 0) {
+ VIR_FREE(domainname);
+ goto cleanup;
+ }
+ VIR_FREE(domainname);
+ ctxt->node = save;
+ }
+ }
+ *shmobj = tmpshm;
+ tmpshm = NULL;
+ ret = 0;
+
+ cleanup:
+ virShmObjectFree(tmpshm);
+ VIR_FREE(stateFile);
+ VIR_FREE(drivername);
+ VIR_FREE(shmtype);
+ xmlFreeDoc(xml);
+ xmlXPathFreeContext(ctxt);
+ return ret;
+}
+
+static int
+virShmObjectListLoadAllState(virShmObjectListPtr list)
+{
+ DIR *dir;
+ struct dirent *entry;
+
+ if (!(dir = opendir(list->stateDir))) {
+ if (errno == ENOENT)
+ return 0;
+ virReportSystemError(errno, _("Failed to open dir '%s'"),
list->stateDir);
+ return -1;
+ }
+
+ while (virDirRead(dir, &entry, list->stateDir) > 0) {
+ virShmObjectPtr shmobj;
+
+ if (entry->d_name[0] == '.' ||
+ !virFileStripSuffix(entry->d_name, ".xml"))
+ continue;
+ if (virShmObjectListLoadState(&shmobj, list->stateDir, entry->d_name)
< 0)
+ continue;
+ if (virShmObjectListAdd(list, shmobj) < 0)
+ continue;
+ }
+ closedir(dir);
+ return 0;
+}
+
+static virShmObjectListPtr
+virShmObjectListNew(void)
+{
+ virShmObjectListPtr list;
+ bool privileged = geteuid() == 0;
+
+ if (!(list = virObjectLockableNew(virShmObjectListClass)))
+ return NULL;
+
+ if (privileged) {
+ if (VIR_STRDUP(list->stateDir, SHMEM_STATE_DIR) < 0)
+ goto error;
+ } else {
+ char *rundir = NULL;
+
+ if (!(rundir = virGetUserRuntimeDirectory()))
+ goto error;
+
+ if (virAsprintf(&list->stateDir, "%s/shmem", rundir) < 0) {
+ VIR_FREE(rundir);
+ goto error;
+ }
+ VIR_FREE(rundir);
+ }
+ if (virFileMakePath(list->stateDir) < 0) {
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("Failed to create state dir '%s'"),
+ list->stateDir);
+ goto error;
+ }
+ if (virShmObjectListLoadAllState(list) < 0)
+ goto error;
+
+ return list;
+
+ error:
+ virObjectUnref(list);
+ return NULL;
+}
+
+static int
+virShmOnceInit(void)
+{
+ if (!(virShmObjectListClass = virClassNew(virClassForObjectLockable(),
+ "virShmObjectList",
+ sizeof(virShmObjectList),
+ virShmObjectListDispose)))
+ return -1;
+
+ if (!(mainlist = virShmObjectListNew()))
+ return -1;
+
+ return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(virShm)
+
+virShmObjectListPtr
+virShmObjectListGetDefault(void)
+{
+ if (virShmInitialize() < 0)
+ return NULL;
+
+ return virObjectRef(mainlist);
+}
+
+int
+virShmSetUsedDomain(virShmObjectPtr shmobj,
+ const char *drvname,
+ const char *domname)
+{
+ char *tmpdomain = NULL;
+ bool remove_drvname = false;
+
+ if (shmobj->drvname) {
+ if (STRNEQ(drvname, shmobj->drvname)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot use one shmem for different driver"));
+ goto error;
+ }
+ } else {
+ if (VIR_STRDUP(shmobj->drvname, drvname) < 0)
+ goto error;
+ remove_drvname = true;
+ }
+
+ if (VIR_STRDUP(tmpdomain, domname) < 0)
+ goto error;
+
+ if (VIR_APPEND_ELEMENT(shmobj->domains, shmobj->ndomains, tmpdomain) < 0)
+ goto error;
+
+ return 0;
+
+ error:
+ if (remove_drvname)
+ VIR_FREE(shmobj->drvname);
+ VIR_FREE(tmpdomain);
+ return -1;
+}
+
+void
+virShmObjectFree(virShmObjectPtr shmobj)
+{
+ size_t i;
+
+ if (!shmobj)
+ return;
+
+ VIR_FREE(shmobj->name);
+ VIR_FREE(shmobj->path);
+ VIR_FREE(shmobj->drvname);
+ for (i = 0; i < shmobj->ndomains; i++)
+ VIR_FREE(shmobj->domains[i]);
+ VIR_FREE(shmobj->domains);
+ VIR_FREE(shmobj);
+}
+
+virShmObjectPtr
+virShmObjectNew(const char *name,
+ unsigned long long size,
+ const char *path,
+ int type,
+ bool othercreate,
+ bool shareable,
+ const char *drvname,
+ const char *domname)
+{
+ virShmObjectPtr shmobj;
+
+ if (VIR_ALLOC(shmobj) < 0)
+ return NULL;
+
+ shmobj->size = size;
+ shmobj->type = type;
+
+ if (VIR_STRDUP(shmobj->name, name) < 0)
+ goto error;
+
+ if (path) {
+ if (VIR_STRDUP(shmobj->path, path) < 0)
+ goto error;
+ } else {
+ VIR_FREE(shmobj->path);
+ }
+
+ shmobj->othercreate = othercreate;
+ shmobj->shareable = shareable;
+
+ if (virShmSetUsedDomain(shmobj, drvname, domname) < 0)
+ goto error;
+
+ return shmobj;
+
+ error:
+ virShmObjectFree(shmobj);
+ return NULL;
+}
+
+static void
+virShmObjectListDispose(void *obj)
+{
+ virShmObjectListPtr list = obj;
+ size_t i;
+
+ for (i = 0; i < list->nshmobjs; i++)
+ virShmObjectFree(list->shmobjs[i]);
+
+ VIR_FREE(list->shmobjs);
+}
+
+int
+virShmObjectSaveState(virShmObjectPtr shmobj,
+ const char *stateDir)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ int ret = -1;
+ size_t i;
+ char *xml = NULL;
+ char *stateFile = NULL;
+
+ virBufferAddLit(&buf, "<shmem>\n");
+ virBufferAdjustIndent(&buf, 2);
+
+ virBufferAsprintf(&buf, "<name>%s</name>\n",
shmobj->name);
+
+ virBufferAsprintf(&buf, "<type>%s</type>\n",
virShmObjectTypeToString(shmobj->type));
+
+ virBufferAsprintf(&buf, "<size>%llu</size>\n",
shmobj->size);
+ if (shmobj->path)
+ virBufferAsprintf(&buf, "<path>%s</path>\n",
shmobj->path);
+ if (shmobj->othercreate)
+ virBufferAddLit(&buf, "<othercreate/>\n");
+ if (shmobj->shareable)
+ virBufferAddLit(&buf, "<shareable/>\n");
+ virBufferAsprintf(&buf, "<driver>%s</driver>\n",
shmobj->drvname);
+ for (i = 0; i < shmobj->ndomains; i++)
+ virBufferAsprintf(&buf, "<domain name='%s'/>\n",
shmobj->domains[i]);
+
+ virBufferAdjustIndent(&buf, -2);
+ virBufferAddLit(&buf, "</shmem>\n");
+
+ if (virBufferCheckError(&buf) < 0)
+ goto cleanup;
+
+ if (!(xml = virBufferContentAndReset(&buf)))
+ goto cleanup;
+
+ if (!(stateFile = virFileBuildPath(stateDir, shmobj->name, ".xml")))
+ goto cleanup;
+
+ if (virXMLSaveFile(stateFile, NULL, NULL, xml) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(stateFile);
+ VIR_FREE(xml);
+ return ret;
+}
+
+int
+virShmRemoveUsedDomain(virShmObjectPtr shmobj,
+ const char *drvname,
+ const char *domname)
+{
+ size_t i;
+
+ if (shmobj->drvname) {
+ if (STRNEQ(drvname, shmobj->drvname)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot use one shmem for different driver"));
+ return -1;
+ }
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get shmem object driver name"));
+ return -1;
+ }
+
+ for (i = 0; i < shmobj->ndomains; i++) {
+ if (STREQ(shmobj->domains[i], domname)) {
+ VIR_FREE(shmobj->domains[i]);
+ VIR_DELETE_ELEMENT(shmobj->domains, i, shmobj->ndomains);
+ return 0;
+ }
+ }
+
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot find domname in shmem object domain list"));
+ return -1;
+}
+
+const char *
+virShmObjectListGetStateFilePath(virShmObjectListPtr list)
+{
+ return list->stateDir;
+}
+
+int
+virShmObjectRemoveStateFile(virShmObjectListPtr list,
+ const char *name)
+{
+ char *stateFile = NULL;
+
+ if (!(stateFile = virFileBuildPath(list->stateDir, name, ".xml")))
+ return -1;
+ unlink(stateFile);
+ VIR_FREE(stateFile);
+ return 0;
+}
+
+int
+virShmObjectListDel(virShmObjectListPtr list,
+ virShmObjectPtr shmobj)
+{
+ size_t i;
+
+ for (i = 0; i < list->nshmobjs; i++) {
+ virShmObjectPtr tmp = list->shmobjs[i];
+
+ if (STREQ(tmp->name, shmobj->name)) {
+ VIR_DELETE_ELEMENT(list->shmobjs, i, list->nshmobjs);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+const char *
+virShmObjectGetName(virShmObjectPtr shmobj)
+{
+ return shmobj->name;
+}
+
+unsigned long long
+virShmObjectGetSize(virShmObjectPtr shmobj)
+{
+ return shmobj->size;
+}
+
+int
+virShmObjectGetType(virShmObjectPtr shmobj)
+{
+ return shmobj->type;
+}
+
+int
+virShmObjectGetUsedDomainNumber(virShmObjectPtr shmobj)
+{
+ return shmobj->ndomains;
+}
+
+const char *
+virShmObjectGetUsedDriverName(virShmObjectPtr shmobj)
+{
+ return shmobj->drvname;
+}
+
+bool
+virShmObjectGetOtherCreate(virShmObjectPtr shmobj)
+{
+ return shmobj->othercreate;
+}
+
+bool
+virShmObjectGetShareable(virShmObjectPtr shmobj)
+{
+ return shmobj->shareable;
+}
+
+virShmObjectPtr
+virShmObjectFindByName(virShmObjectListPtr list,
+ const char *name)
+{
+ size_t i;
+
+ for (i = 0; i < list->nshmobjs; i++) {
+ if (STREQ_NULLABLE(list->shmobjs[i]->name, name))
+ return list->shmobjs[i];
+ }
+
+ return NULL;
+}
+
+int
+virShmObjectListAdd(virShmObjectListPtr list,
+ virShmObjectPtr shmobj)
+{
+ if (virShmObjectFindByName(list, shmobj->name)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("A share memory object named '%s' already
exists"),
+ shmobj->name);
+ return -1;
+ }
+
+ return VIR_APPEND_ELEMENT(list->shmobjs, list->nshmobjs, shmobj);
+}
+
+#ifdef HAVE_SHM_OPEN
+int
+virShmOpen(const char *name,
+ unsigned long long size,
+ mode_t mode)
+{
+ int fd = -1;
+ struct stat sb;
+
+ if ((fd = shm_open(name, O_RDWR, mode)) < 0) {
+ virReportSystemError(errno,
+ _("Unable to open shared memory"
+ " objects '%s'"),
+ name);
+ return -1;
+ }
+
+ if (fstat(fd, &sb) < 0) {
+ virReportSystemError(errno,
+ _("cannot stat file '%s'"), name);
+ goto error;
+ }
+
+ if (sb.st_size != size) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("already exist shared memory object"
+ " size %ju is not equal the required size %llu"),
+ (uintmax_t)sb.st_size, size);
+ goto error;
+ }
+
+ return fd;
+
+ error:
+ VIR_FORCE_CLOSE(fd);
+ return -1;
+}
+
+int
+virShmCreate(const char *name,
+ unsigned long long size,
+ bool outerr,
+ bool *othercreate,
+ mode_t mode)
+{
+ int fd = -1;
+
+ fd = shm_open(name, O_RDWR|O_CREAT|O_EXCL, mode);
+
+ if (fd > 0) {
+ if (ftruncate(fd, size) != 0) {
+ virReportSystemError(errno,
+ _("Unable to truncate"
+ " file descriptor to %llu"),
+ size);
+ ignore_value(shm_unlink(name));
+ VIR_FORCE_CLOSE(fd);
+ return -1;
+ }
+ } else if (errno == EEXIST) {
+ if (outerr) {
+ virReportSystemError(errno,
+ _("shared memory objects"
+ " '%s' is already exist"),
+ name);
+ return -1;
+ }
+
+ VIR_WARN("shared memory objects '%s' is already exist", name);
+ *othercreate = true;
+
+ return virShmOpen(name, size, mode);
+ } else {
+ virReportSystemError(errno,
+ _("Unable to create shared memory"
+ " objects '%s'"),
+ name);
+ return -1;
+ }
+
+ return fd;
+}
+
+int
+virShmUnlink(const char *name)
+{
+ int ret;
+
+ if ((ret = shm_unlink(name)) < 0) {
+ virReportSystemError(errno,
+ _("Unable to delete shared memory"
+ " objects '%s'"),
+ name);
+ }
+ return ret;
+}
+
+# if defined(__linux__)
+# define SHM_DEFAULT_PATH "/dev/shm"
+
+int
+virShmBuildPath(const char *name, char **path)
+{
+
+ if (virAsprintf(path, "%s/%s", SHM_DEFAULT_PATH, name) < 0)
+ return -1;
+
+ if (!virFileExists(*path)) {
+ virReportSystemError(errno,
+ _("could not access %s"),
+ *path);
+ VIR_FREE(*path);
+ return -1;
+ }
+ return 0;
+}
+
+# else
+
+int
+virShmBuildPath(const char *name ATTRIBUTE_UNUSED,
+ char **path ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS, "%s",
+ _("Cannot get share memory object path on this
platform"));
+ return -1;
+}
+
+# endif
+#else /* !HAVE_SHM_OPEN */
+int
+virShmOpen(const char *name ATTRIBUTE_UNUSED,
+ unsigned long long size ATTRIBUTE_UNUSED,
+ mode_t mode ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS, "%s",
+ _("Cannot open share memory object on this
platform"));
+ return -1;
+}
+
+int
+virShmCreate(const char *name ATTRIBUTE_UNUSED,
+ unsigned long long size ATTRIBUTE_UNUSED,
+ bool outerr ATTRIBUTE_UNUSED,
+ bool *othercreate ATTRIBUTE_UNUSED,
+ mode_t mode ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS, "%s",
+ _("Cannot create share memory object on this
platform"));
+ return -1;
+}
+
+int
+virShmUnlink(const char *name ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS, "%s",
+ _("Cannot unlink share memory object on this
platform"));
+ return -1;
+}
+
+int
+virShmBuildPath(const char *name ATTRIBUTE_UNUSED,
+ char **path ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS, "%s",
+ _("Cannot get share memory object path on this
platform"));
+ return -1;
+}
+
+#endif /* !HAVE_SHM_OPEN */
diff --git a/src/util/virshm.h b/src/util/virshm.h
new file mode 100644
index 0000000..ad94fd4
--- /dev/null
+++ b/src/util/virshm.h
@@ -0,0 +1,92 @@
+/*
+ * virshm.h: helper API for POSIX share memory
+ *
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __VIR_SHM_H__
+# define __VIR_SHM_H__
+
+# include "internal.h"
+# include "virutil.h"
+# include "virobject.h"
+
+typedef enum {
+ VIR_SHM_TYPE_SHM = 0,
+ VIR_SHM_TYPE_SERVER,
+
+ VIR_SHM_TYPE_LAST
+} virShmObjectType;
+
+VIR_ENUM_DECL(virShmObject);
+
+typedef struct _virShmObject virShmObject;
+typedef virShmObject *virShmObjectPtr;
+typedef struct _virShmObjectList virShmObjectList;
+typedef virShmObjectList *virShmObjectListPtr;
+
+virShmObjectListPtr virShmObjectListGetDefault(void);
+
+int virShmSetUsedDomain(virShmObjectPtr shmobj,
+ const char *drvname,
+ const char *domname)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+int virShmRemoveUsedDomain(virShmObjectPtr shmobj,
+ const char *drvname,
+ const char *domname)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+void virShmObjectFree(virShmObjectPtr shmobj);
+virShmObjectPtr virShmObjectNew(const char *name, unsigned long long size,
+ const char *path, int type, bool othercreate,
+ bool shareable, const char *drvname, const char
*domname)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(7) ATTRIBUTE_NONNULL(8);
+int virShmObjectSaveState(virShmObjectPtr shmobj,
+ const char *stateDir)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+const char * virShmObjectListGetStateFilePath(virShmObjectListPtr list);
+int virShmObjectRemoveStateFile(virShmObjectListPtr list,
+ const char *name)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+int virShmObjectListAdd(virShmObjectListPtr list,
+ virShmObjectPtr shmobj)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+int virShmObjectListDel(virShmObjectListPtr list,
+ virShmObjectPtr shmobj)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+virShmObjectPtr virShmObjectFindByName(virShmObjectListPtr list,
+ const char *name)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+const char * virShmObjectGetName(virShmObjectPtr shmobj);
+unsigned long long virShmObjectGetSize(virShmObjectPtr shmobj);
+int virShmObjectGetType(virShmObjectPtr shmobj);
+int virShmObjectGetUsedDomainNumber(virShmObjectPtr shmobj);
+const char * virShmObjectGetUsedDriverName(virShmObjectPtr shmobj);
+bool virShmObjectGetOtherCreate(virShmObjectPtr shmobj);
+bool virShmObjectGetShareable(virShmObjectPtr shmobj);
+
+int virShmCreate(const char *name, unsigned long long size,
+ bool outerr, bool *othercreate, mode_t mode)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4);
+int virShmOpen(const char *name,
+ unsigned long long size,
+ mode_t mode)
+ ATTRIBUTE_NONNULL(1);
+int virShmUnlink(const char *name);
+int virShmBuildPath(const char *name, char **path)
+ ATTRIBUTE_NONNULL(2);
+#endif /* __VIR_SHM_H__ */
--
1.8.3.1