Provide a function to clone a context. This is necessary
because simply copying the structs will eventually
corrup the GC: maxsize is updated in the cloned context
but not in the originating, yet they have the same array
of referenced pointers alloc_ptrs.
Signed-off-by: Andres Lagar-Cavilla <andres@xxxxxxxxxxxxxxxx>
# HG changeset patch
# User Andres Lagar-Cavilla <andres@xxxxxxxxxxxxxxxx>
# Date 1259848013 18000
# Node ID eeb2f35cd9a7a5a6c4e38c1ec5995524035375fa
# Parent 684a4d0abc86dbded4ceda68f7b5e1b4806ff1d7
Provide a function to clone a context. This is necessary
because simply copying the structs will eventually
corrup the GC: maxsize is updated in the cloned context
but not in the originating, yet they have the same array
of referenced pointers alloc_ptrs.
Signed-off-by: Andres Lagar-Cavilla <andres@xxxxxxxxxxxxxxxx>
diff -r 684a4d0abc86 -r eeb2f35cd9a7 libxl.c
--- a/libxl.c
+++ b/libxl.c
@@ -656,10 +656,17 @@ void dm_xenstore_record_pid(struct libxl
struct libxl_device_model_starting *starting = for_spawn;
struct libxl_ctx clone;
char *kvs[3];
- int rc;
+ int rc, cloned;
- clone = *ctx;
- clone.xsh = xs_daemon_open();
+ if (libxl_clone_context_xs(ctx, &clone)) {
+ XL_LOG(ctx, XL_LOG_ERROR, "Out of memory when cloning context");
+ /* Throw a prayer fallback */
+ clone = *ctx;
+ clone.xsh = xs_daemon_open();
+ cloned = 0;
+ } else {
+ cloned = 1;
+ }
/* we mustn't use the parent's handle in the child */
kvs[0] = "image/device-model-pid";
@@ -669,7 +676,11 @@ void dm_xenstore_record_pid(struct libxl
if (rc) XL_LOG_ERRNO(&clone, XL_LOG_ERROR,
"Couldn't record device model pid %ld at %s/%s",
(unsigned long)innerchild, starting->dom_path, kvs);
- xs_daemon_close(clone.xsh);
+ if (cloned) {
+ libxl_discard_cloned_context_xs(&clone);
+ } else {
+ xs_daemon_close(clone.xsh);
+ }
}
static int libxl_vfb_and_vkb_from_device_model_info(struct libxl_ctx *ctx,
diff -r 684a4d0abc86 -r eeb2f35cd9a7 libxl_device.c
--- a/libxl_device.c
+++ b/libxl_device.c
@@ -212,15 +212,19 @@ int libxl_devices_destroy(struct libxl_c
fd_set rfds;
struct timeval tv;
flexarray_t *toremove;
- struct libxl_ctx clone = *ctx;
+ struct libxl_ctx clone;
- clone.xsh = xs_daemon_open();
+ if (libxl_clone_context_xs(ctx, &clone)) {
+ XL_LOG(ctx, XL_LOG_ERROR, "Out of memory when cloning context");
+ return ERROR_NOMEM;
+ }
+
toremove = flexarray_make(16, 1);
path = libxl_sprintf(&clone, "/local/domain/%d/device", domid);
l1 = libxl_xs_directory(&clone, XBT_NULL, path, &num1);
if (!l1) {
XL_LOG(&clone, XL_LOG_ERROR, "%s is empty", path);
- xs_daemon_close(clone.xsh);
+ libxl_discard_cloned_context_xs(&clone);
return -1;
}
for (i = 0; i < num1; i++) {
@@ -269,7 +273,7 @@ int libxl_devices_destroy(struct libxl_c
xs_rm(clone.xsh, XBT_NULL, path);
}
flexarray_free(toremove);
- xs_daemon_close(clone.xsh);
+ libxl_discard_cloned_context_xs(&clone);
return 0;
}
diff -r 684a4d0abc86 -r eeb2f35cd9a7 libxl_internal.c
--- a/libxl_internal.c
+++ b/libxl_internal.c
@@ -28,6 +28,28 @@ int libxl_error_set(struct libxl_ctx *ct
return 0;
}
+int libxl_clone_context(struct libxl_ctx *from, struct libxl_ctx *to)
+{
+ /* We could just copy the structs, but since
+ * maxsize is not a pointer we need to take care
+ * of our own GC. */
+ *to = *from;
+ to->alloc_ptrs = NULL;
+ to->alloc_maxsize = 256;
+ to->alloc_ptrs = calloc(to->alloc_maxsize, sizeof(void *));
+ if (!to->alloc_ptrs)
+ return ERROR_NOMEM;
+ return 0;
+}
+
+void libxl_discard_cloned_context(struct libxl_ctx *ctx)
+{
+ /* We only need to worry about GC-related fields */
+ (void)libxl_ctx_free(ctx);
+ if (ctx->alloc_ptrs)
+ free(ctx->alloc_ptrs);
+}
+
int libxl_ptr_add(struct libxl_ctx *ctx, void *ptr)
{
int i;
diff -r 684a4d0abc86 -r eeb2f35cd9a7 libxl_internal.h
--- a/libxl_internal.h
+++ b/libxl_internal.h
@@ -63,6 +63,23 @@ typedef struct {
#define PRINTF_ATTRIBUTE(x, y) __attribute__((format(printf, x, y)))
/* memory allocation tracking/helpers */
+int libxl_clone_context(struct libxl_ctx *from, struct libxl_ctx *to);
+static inline int libxl_clone_context_xs(
+ struct libxl_ctx *from, struct libxl_ctx *to)
+{
+ int rc;
+ rc = libxl_clone_context(from, to);
+ if (rc) return rc;
+ to->xsh = xs_daemon_open();
+ return 0;
+}
+void libxl_discard_cloned_context(struct libxl_ctx *ctx);
+static inline void libxl_discard_cloned_context_xs(
+ struct libxl_ctx *ctx)
+{
+ libxl_discard_cloned_context(ctx);
+ xs_daemon_close(ctx->xsh);
+}
int libxl_ptr_add(struct libxl_ctx *ctx, void *ptr);
int libxl_free(struct libxl_ctx *ctx, void *ptr);
int libxl_free_all(struct libxl_ctx *ctx);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|