From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> 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 <berrange@xxxxxxxxxx> --- src/libvirt_private.syms | 2 + src/util/virlockspace.c | 236 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virlockspace.h | 4 + 3 files changed, 242 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 58a9520..6c94584 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1328,6 +1328,8 @@ virLockSpaceDeleteResource; virLockSpaceFree; virLockSpaceGetDirectory; virLockSpaceNew; +virLockSpaceNewPostExecRestart; +virLockSpacePreExecRestart; virLockSpaceReleaseResource; virLockSpaceReleaseResourcesForOwner; diff --git a/src/util/virlockspace.c b/src/util/virlockspace.c index 611592a..786513f 100644 --- a/src/util/virlockspace.c +++ b/src/util/virlockspace.c @@ -295,6 +295,242 @@ 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(10, + 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; + } + + for (j = 0 ; j < m ; 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; + } + + if (VIR_EXPAND_N(res->owners, res->nOwners, 1) < 0) { + virReportOOMError(); + 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 bd8f91c..9c5128b 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); -- 1.7.11.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list