On 12.09.2012 18:28, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange(a)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(a)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);