[libvirt] [PATCH 02/12] Add JSON serialization of virLockSpacePtr objects for process re-exec()
Michal Privoznik
mprivozn at redhat.com
Fri Oct 5 11:25:51 UTC 2012
On 12.09.2012 18:28, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange" <berrange at redhat.com>
>
> 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 at redhat.com>
> ---
> src/libvirt_private.syms | 2 +
> src/util/virlockspace.c | 236 +++++++++++++++++++++++++++++++++++++++++++++++
> src/util/virlockspace.h | 4 +
> 3 files changed, 242 insertions(+)
>
ACK but see my comments below
> 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)))
s/10/VIR_LOCK_SPACE_RESOURCE_HASH_TABLE_SIZE/ or the name you invent
> + 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;
This is useless ...
> +
> + 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;
> + }
... since we require 'fd' attribute anyway.
> + 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;
> + }
> +
Since we already know the res->owners size, wouldn't it be better to
allocate it here instead of ...
> + 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;
... doing this?
> + }
> +
> + 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);
>
>
More information about the libvir-list
mailing list