From 8057c04e8d8ed4b371d3eb67ade34ef7ff55e08a Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 9 Aug 2012 11:54:37 +0100 Subject: [PATCH] Add JSON serialization of virLockSpacePtr objects for process re-exec() Add two new APIs virLockSpaceNewPostExecRestart and virLockSpacePreExecRestart which allow a virLockSpacePtr object to be created from a JSON object and saved to a JSON object, for the purposes of re-exec'ing a process. As well as saving the state in JSON format, the second method will disable the O_CLOEXEC flag so that the open file descriptors are preserved across the process re-exec() Signed-off-by: Daniel P. Berrange --- src/libvirt_private.syms | 2 + src/util/virlockspace.c | 237 +++++++++++++++++++++++++++++++++++++++ src/util/virlockspace.h | 4 + 3 files changed, 243 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b5a5948ce2..5a11368efa 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1362,6 +1362,8 @@ virLockSpaceDeleteResource; virLockSpaceFree; virLockSpaceGetDirectory; virLockSpaceNew; +virLockSpaceNewPostExecRestart; +virLockSpacePreExecRestart; virLockSpaceReleaseResource; virLockSpaceReleaseResourcesForOwner; diff --git a/src/util/virlockspace.c b/src/util/virlockspace.c index e525331d74..7e8c0a74f6 100644 --- a/src/util/virlockspace.c +++ b/src/util/virlockspace.c @@ -297,6 +297,243 @@ error: } + +virLockSpacePtr virLockSpaceNewPostExecRestart(virJSONValuePtr object) +{ + virLockSpacePtr lockspace; + virJSONValuePtr resources; + int n; + size_t i; + + VIR_DEBUG("object=%p", object); + + if (VIR_ALLOC(lockspace) < 0) + return NULL; + + if (virMutexInit(&lockspace->lock) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to initialize lockspace mutex")); + VIR_FREE(lockspace); + return NULL; + } + + if (!(lockspace->resources = virHashCreate(VIR_LOCKSPACE_TABLE_SIZE, + virLockSpaceResourceDataFree))) + goto error; + + if (virJSONValueObjectHasKey(object, "directory")) { + const char *dir = virJSONValueObjectGetString(object, "directory"); + if (!(lockspace->dir = strdup(dir))) { + virReportOOMError(); + goto error; + } + } + + if (!(resources = virJSONValueObjectGet(object, "resources"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing resources value in JSON document")); + goto error; + } + + if ((n = virJSONValueArraySize(resources)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Malformed resources value in JSON document")); + goto error; + } + + for (i = 0 ; i < n ; i++) { + virJSONValuePtr child = virJSONValueArrayGet(resources, i); + virLockSpaceResourcePtr res; + const char *tmp; + virJSONValuePtr owners; + size_t j; + int m; + + if (VIR_ALLOC(res) < 0) { + virReportOOMError(); + goto error; + } + res->fd = -1; + + if (!(tmp = virJSONValueObjectGetString(child, "name"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing resource name in JSON document")); + virLockSpaceResourceFree(res); + goto error; + } + if (!(res->name = strdup(tmp))) { + virReportOOMError(); + virLockSpaceResourceFree(res); + goto error; + } + + if (!(tmp = virJSONValueObjectGetString(child, "path"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing resource path in JSON document")); + virLockSpaceResourceFree(res); + goto error; + } + if (!(res->path = strdup(tmp))) { + virReportOOMError(); + virLockSpaceResourceFree(res); + goto error; + } + if (virJSONValueObjectGetNumberInt(child, "fd", &res->fd) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing resource fd in JSON document")); + virLockSpaceResourceFree(res); + goto error; + } + if (virSetInherit(res->fd, false) < 0) { + virReportSystemError(errno, "%s", + _("Cannot enable close-on-exec flag")); + goto error; + } + if (virJSONValueObjectGetBoolean(child, "lockHeld", &res->lockHeld) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing resource lockHeld in JSON document")); + virLockSpaceResourceFree(res); + goto error; + } + + if (virJSONValueObjectGetNumberUint(child, "flags", &res->flags) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing resource flags in JSON document")); + virLockSpaceResourceFree(res); + goto error; + } + + if (!(owners = virJSONValueObjectGet(child, "owners"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing resource owners in JSON document")); + virLockSpaceResourceFree(res); + goto error; + } + + if ((m = virJSONValueArraySize(owners)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Malformed owners value in JSON document")); + virLockSpaceResourceFree(res); + goto error; + } + + res->nOwners = m; + if (VIR_ALLOC_N(res->owners, res->nOwners) < 0) { + virReportOOMError(); + virLockSpaceResourceFree(res); + goto error; + } + + for (j = 0 ; j < res->nOwners ; j++) { + unsigned long long int owner; + virJSONValuePtr ownerval = virJSONValueArrayGet(owners, j); + + if (virJSONValueGetNumberUlong(ownerval, &owner) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Malformed owner value in JSON document")); + virLockSpaceResourceFree(res); + goto error; + } + + res->owners[res->nOwners-1] = (pid_t)owner; + } + + if (virHashAddEntry(lockspace->resources, res->name, res) < 0) { + virLockSpaceResourceFree(res); + goto error; + } + } + + return lockspace; + +error: + virLockSpaceFree(lockspace); + return NULL; +} + + +virJSONValuePtr virLockSpacePreExecRestart(virLockSpacePtr lockspace) +{ + virJSONValuePtr object = virJSONValueNewObject(); + virJSONValuePtr resources; + virHashKeyValuePairPtr pairs = NULL, tmp; + + if (!object) + return NULL; + + virMutexLock(&lockspace->lock); + + if (lockspace->dir && + virJSONValueObjectAppendString(object, "directory", lockspace->dir) < 0) + goto error; + + if (!(resources = virJSONValueNewArray())) + goto error; + + if (virJSONValueObjectAppend(object, "resources", resources) < 0) { + virJSONValueFree(resources); + goto error; + } + + tmp = pairs = virHashGetItems(lockspace->resources, NULL); + while (tmp && tmp->value) { + virLockSpaceResourcePtr res = (virLockSpaceResourcePtr)tmp->value; + virJSONValuePtr child = virJSONValueNewObject(); + virJSONValuePtr owners = NULL; + size_t i; + + if (virJSONValueArrayAppend(resources, child) < 0) { + virJSONValueFree(child); + goto error; + } + + if (virJSONValueObjectAppendString(child, "name", res->name) < 0 || + virJSONValueObjectAppendString(child, "path", res->path) < 0 || + virJSONValueObjectAppendNumberInt(child, "fd", res->fd) < 0 || + virJSONValueObjectAppendBoolean(child, "lockHeld", res->lockHeld) < 0 || + virJSONValueObjectAppendNumberUint(child, "flags", res->flags) < 0) + goto error; + + if (virSetInherit(res->fd, true) < 0) { + virReportSystemError(errno, "%s", + _("Cannot disable close-on-exec flag")); + goto error; + } + + if (!(owners = virJSONValueNewArray())) + goto error; + + if (virJSONValueObjectAppend(child, "owners", owners) < 0) { + virJSONValueFree(owners); + goto error; + } + + for (i = 0 ; i < res->nOwners ; i++) { + virJSONValuePtr owner = virJSONValueNewNumberUlong(res->owners[i]); + if (!owner) + goto error; + + if (virJSONValueArrayAppend(owners, owner) < 0) { + virJSONValueFree(owner); + goto error; + } + } + + tmp++; + } + VIR_FREE(pairs); + + virMutexUnlock(&lockspace->lock); + return object; + + error: + VIR_FREE(pairs); + virJSONValueFree(object); + virMutexUnlock(&lockspace->lock); + return NULL; +} + + void virLockSpaceFree(virLockSpacePtr lockspace) { if (!lockspace) diff --git a/src/util/virlockspace.h b/src/util/virlockspace.h index bd8f91c095..9c5128bdc3 100644 --- a/src/util/virlockspace.h +++ b/src/util/virlockspace.h @@ -23,11 +23,15 @@ # define __VIR_LOCK_SPACE_H__ # include "internal.h" +# include "json.h" typedef struct _virLockSpace virLockSpace; typedef virLockSpace *virLockSpacePtr; virLockSpacePtr virLockSpaceNew(const char *directory); +virLockSpacePtr virLockSpaceNewPostExecRestart(virJSONValuePtr object); + +virJSONValuePtr virLockSpacePreExecRestart(virLockSpacePtr lockspace); void virLockSpaceFree(virLockSpacePtr lockspace); -- GitLab