[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH, v2]: xl: Implement per-API-call garbage-collection lifetime



Changes since v1:
 - Fix a double-free bug introduced by v1, pointed out by Stefano
   where internal pointer was being passed back to caller from
   libxl_create_stubdom()

8<----------------------------------------------------------------------
Currently scratch variables allocated by libxl have the same lifetime as
the context. While this is suitable for one off invocations of xl. It is
not so great for a daemon process linking to libxl. In that case there
will be prolific leakage of heap memory.

My proposed solution involves create a new libxl_gc structure, which
contains a pointer to an owning context as well as the garbage
collection data. Top-level library functions which expect to do a lot of
scratch allocations put gc struct on the stack and initialize it with a
macro. Before returning they then call libxl_free_all on this struct.
This means that static helper functions called by such functions will
usually take a gc instead of a ctx as a first parameter.

The patch touches almost every code-path so a close review and testing
would be much appreciated. I have tested with valgrind all of the parts
I could which looked non-straightforward. Suffice to say that it seems
crash-free even if we have exposed a few real memory leaks. These are
for cases where we return eg. block list to an xl caller but there is no
appropriate block_list_free() function to call. Ian Campbells work in
this area should sew up all these loose ends.

Signed-off-by: Gianni Tedesco <gianni.tedesco@xxxxxxxxxx>

diff -r 7b144fe8c528 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c       Wed Aug 11 14:39:44 2010 +0100
+++ b/tools/libxl/libxl.c       Thu Aug 12 15:22:56 2010 +0100
@@ -45,17 +45,12 @@ int libxl_ctx_init(libxl_ctx *ctx, int v
         return ERROR_VERSION;
     memset(ctx, 0, sizeof(libxl_ctx));
     ctx->lg = lg;
-    ctx->alloc_maxsize = 256;
-    ctx->alloc_ptrs = calloc(ctx->alloc_maxsize, sizeof(void *));
-    if (!ctx->alloc_ptrs)
-        return ERROR_NOMEM;
     memset(&ctx->version_info, 0, sizeof(libxl_version_info));
 
     ctx->xch = xc_interface_open(lg,lg,0);
     if (!ctx->xch) {
         XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno, 
                         "cannot open libxc handle");
-        free(ctx->alloc_ptrs);
         return ERROR_FAIL;
     }
 
@@ -64,7 +59,6 @@ int libxl_ctx_init(libxl_ctx *ctx, int v
         XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno, 
                         "cannot connect to xenstore");
         xc_interface_close(ctx->xch);
-        free(ctx->alloc_ptrs);
         return ERROR_FAIL;
     }
     return 0;
@@ -73,8 +67,6 @@ int libxl_ctx_init(libxl_ctx *ctx, int v
 static void do_free_version_info(libxl_version_info *info);
 int libxl_ctx_free(libxl_ctx *ctx)
 {
-    libxl_free_all(ctx);
-    free(ctx->alloc_ptrs);
     xc_interface_close(ctx->xch);
     do_free_version_info(&ctx->version_info);
     if (ctx->xsh) xs_daemon_close(ctx->xsh); 
@@ -86,6 +78,7 @@ int libxl_ctx_free(libxl_ctx *ctx)
 int libxl_domain_make(libxl_ctx *ctx, libxl_domain_create_info *info,
                        uint32_t *domid)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     int flags, ret, i, rc;
     char *uuid_string;
     char *rw_paths[] = { "device", "device/suspend/event-channel" , "data"};
@@ -98,7 +91,10 @@ int libxl_domain_make(libxl_ctx *ctx, li
     xen_domain_handle_t handle;
 
     uuid_string = libxl_uuid2string(ctx, info->uuid);
-    if (!uuid_string) return ERROR_NOMEM;
+    if (!uuid_string) {
+        libxl_free_all(&gc);
+        return ERROR_NOMEM;
+    }
 
     flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0;
     flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0;
@@ -111,22 +107,27 @@ int libxl_domain_make(libxl_ctx *ctx, li
     ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid);
     if (ret < 0) {
         XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "domain creation fail");
+        libxl_free_all(&gc);
         return ERROR_FAIL;
     }
 
     ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid);
     if (ret < 0) {
         XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "domain move fail");
+        libxl_free_all(&gc);
         return ERROR_FAIL;
     }
 
-    dom_path = libxl_xs_get_dompath(ctx, *domid);
-    if (!dom_path)
+    dom_path = libxl_xs_get_dompath(&gc, *domid);
+    if (!dom_path) {
+        libxl_free_all(&gc);
         return ERROR_FAIL;
-
-    vm_path = libxl_sprintf(ctx, "/vm/%s", uuid_string);
+    }
+
+    vm_path = libxl_sprintf(&gc, "/vm/%s", uuid_string);
     if (!vm_path) {
         XL_LOG(ctx, XL_LOG_ERROR, "cannot allocate create paths");
+        libxl_free_all(&gc);
         return ERROR_FAIL;
     }
 
@@ -147,42 +148,47 @@ retry_transaction:
     xs_mkdir(ctx->xsh, t, vm_path);
     xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
 
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vm", dom_path), vm_path, 
strlen(vm_path));
+    xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/vm", dom_path), vm_path, 
strlen(vm_path));
     rc = libxl_domain_rename(ctx, *domid, 0, info->name, t);
-    if (rc) return rc;
+    if (rc) {
+        libxl_free_all(&gc);
+        return rc;
+    }
 
     for (i = 0; i < ARRAY_SIZE(rw_paths); i++) {
-        char *path = libxl_sprintf(ctx, "%s/%s", dom_path, rw_paths[i]);
+        char *path = libxl_sprintf(&gc, "%s/%s", dom_path, rw_paths[i]);
         xs_mkdir(ctx->xsh, t, path);
         xs_set_permissions(ctx->xsh, t, path, rwperm, ARRAY_SIZE(rwperm));
-        libxl_free(ctx, path);
     }
     for (i = 0; i < ARRAY_SIZE(ro_paths); i++) {
-        char *path = libxl_sprintf(ctx, "%s/%s", dom_path, ro_paths[i]);
+        char *path = libxl_sprintf(&gc, "%s/%s", dom_path, ro_paths[i]);
         xs_mkdir(ctx->xsh, t, path);
         xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
-        libxl_free(ctx, path);
     }
 
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/uuid", vm_path), uuid_string, 
strlen(uuid_string));
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", vm_path), info->name, 
strlen(info->name));
+    xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/uuid", vm_path), uuid_string, 
strlen(uuid_string));
+    xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/name", vm_path), info->name, 
strlen(info->name));
     if (info->poolname)
-        xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/pool_name", vm_path), 
info->poolname, strlen(info->poolname));
-
-    libxl_xs_writev(ctx, t, dom_path, info->xsdata);
-    libxl_xs_writev(ctx, t, libxl_sprintf(ctx, "%s/platform", dom_path), 
info->platformdata);
-
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, 
"%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1);
+        xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/pool_name", vm_path), 
info->poolname, strlen(info->poolname));
+
+    libxl_xs_writev(&gc, t, dom_path, info->xsdata);
+    libxl_xs_writev(&gc, t, libxl_sprintf(&gc, "%s/platform", dom_path), 
info->platformdata);
+
+    xs_write(ctx->xsh, t, libxl_sprintf(&gc, 
"%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1);
 
     if (!xs_transaction_end(ctx->xsh, t, 0))
         if (errno == EAGAIN)
             goto retry_transaction;
+
+    libxl_free_all(&gc);
     return 0;
 }
 
 int libxl_domain_rename(libxl_ctx *ctx, uint32_t domid,
                         const char *old_name, const char *new_name,
-                        xs_transaction_t trans) {
+                        xs_transaction_t trans)
+{
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *dom_path = 0;
     const char *name_path;
     char *got_old_name;
@@ -190,10 +196,10 @@ int libxl_domain_rename(libxl_ctx *ctx, 
     xs_transaction_t our_trans = 0;
     int rc;
 
-    dom_path = libxl_xs_get_dompath(ctx, domid);
+    dom_path = libxl_xs_get_dompath(&gc, domid);
     if (!dom_path) goto x_nomem;
 
-    name_path= libxl_sprintf(ctx, "%s/name", dom_path);
+    name_path= libxl_sprintf(&gc, "%s/name", dom_path);
     if (!name_path) goto x_nomem;
 
  retry_transaction:
@@ -250,8 +256,8 @@ int libxl_domain_rename(libxl_ctx *ctx, 
 
     rc = 0;
  x_rc:
-    if (dom_path) libxl_free(ctx, dom_path);
     if (our_trans) xs_transaction_end(ctx->xsh, our_trans, 1);
+    libxl_free_all(&gc);
     return rc;
 
  x_fail:  rc = ERROR_FAIL;  goto x_rc;
@@ -260,38 +266,42 @@ int libxl_domain_rename(libxl_ctx *ctx, 
 
 int libxl_domain_build(libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t 
domid, libxl_domain_build_state *state)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char **vments = NULL, **localents = NULL;
     struct timeval start_time;
     int i, ret;
 
     ret = build_pre(ctx, domid, info, state);
-    if (ret) goto out;
+    if (ret)
+        goto out;
 
     gettimeofday(&start_time, NULL);
 
     if (info->hvm) {
         ret = build_hvm(ctx, domid, info, state);
-        if (ret) goto out;
-
-        vments = libxl_calloc(ctx, 7, sizeof(char *));
+        if (ret)
+            goto out;
+
+        vments = libxl_calloc(&gc, 7, sizeof(char *));
         vments[0] = "rtc/timeoffset";
         vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
         vments[2] = "image/ostype";
         vments[3] = "hvm";
         vments[4] = "start_time";
-        vments[5] = libxl_sprintf(ctx, "%lu.%02d", 
start_time.tv_sec,(int)start_time.tv_usec/10000);
+        vments[5] = libxl_sprintf(&gc, "%lu.%02d", 
start_time.tv_sec,(int)start_time.tv_usec/10000);
     } else {
         ret = build_pv(ctx, domid, info, state);
-        if (ret) goto out;
-
-        vments = libxl_calloc(ctx, 11, sizeof(char *));
+        if (ret)
+            goto out;
+
+        vments = libxl_calloc(&gc, 11, sizeof(char *));
         i = 0;
         vments[i++] = "image/ostype";
         vments[i++] = "linux";
         vments[i++] = "image/kernel";
         vments[i++] = (char*) info->kernel.path;
         vments[i++] = "start_time";
-        vments[i++] = libxl_sprintf(ctx, "%lu.%02d", 
start_time.tv_sec,(int)start_time.tv_usec/10000);
+        vments[i++] = libxl_sprintf(&gc, "%lu.%02d", 
start_time.tv_sec,(int)start_time.tv_usec/10000);
         if (info->u.pv.ramdisk.path) {
             vments[i++] = "image/ramdisk";
             vments[i++] = (char*) info->u.pv.ramdisk.path;
@@ -307,6 +317,7 @@ out:
     if (!info->hvm)
            libxl_file_reference_unmap(ctx, &info->u.pv.ramdisk);
 
+    libxl_free_all(&gc);
     return ret;
 }
 
@@ -314,35 +325,38 @@ int libxl_domain_restore(libxl_ctx *ctx,
                          uint32_t domid, int fd, libxl_domain_build_state 
*state,
                          libxl_device_model_info *dm_info)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char **vments = NULL, **localents = NULL;
     struct timeval start_time;
     int i, ret, esave, flags;
 
     ret = build_pre(ctx, domid, info, state);
-    if (ret) goto out;
+    if (ret)
+        goto out;
 
     ret = restore_common(ctx, domid, info, state, fd);
-    if (ret) goto out;
+    if (ret)
+        goto out;
 
     gettimeofday(&start_time, NULL);
 
     if (info->hvm) {
-        vments = libxl_calloc(ctx, 7, sizeof(char *));
+        vments = libxl_calloc(&gc, 7, sizeof(char *));
         vments[0] = "rtc/timeoffset";
         vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
         vments[2] = "image/ostype";
         vments[3] = "hvm";
         vments[4] = "start_time";
-        vments[5] = libxl_sprintf(ctx, "%lu.%02d", 
start_time.tv_sec,(int)start_time.tv_usec/10000);
+        vments[5] = libxl_sprintf(&gc, "%lu.%02d", 
start_time.tv_sec,(int)start_time.tv_usec/10000);
     } else {
-        vments = libxl_calloc(ctx, 11, sizeof(char *));
+        vments = libxl_calloc(&gc, 11, sizeof(char *));
         i = 0;
         vments[i++] = "image/ostype";
         vments[i++] = "linux";
         vments[i++] = "image/kernel";
         vments[i++] = (char*) info->kernel.path;
         vments[i++] = "start_time";
-        vments[i++] = libxl_sprintf(ctx, "%lu.%02d", 
start_time.tv_sec,(int)start_time.tv_usec/10000);
+        vments[i++] = libxl_sprintf(&gc, "%lu.%02d", 
start_time.tv_sec,(int)start_time.tv_usec/10000);
         if (info->u.pv.ramdisk.path) {
             vments[i++] = "image/ramdisk";
             vments[i++] = (char*) info->u.pv.ramdisk.path;
@@ -353,7 +367,8 @@ int libxl_domain_restore(libxl_ctx *ctx,
         }
     }
     ret = build_post(ctx, domid, info, state, vments, localents);
-    if (ret) goto out;
+    if (ret)
+        goto out;
 
     dm_info->saved_state = NULL;
     if (info->hvm) {
@@ -380,28 +395,36 @@ out:
     }
 
     errno = esave;
+    libxl_free_all(&gc);
     return ret;
 }
 
 int libxl_domain_resume(libxl_ctx *ctx, uint32_t domid)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
+    int rc = 0;
+    
     if (is_hvm(ctx, domid)) {
         XL_LOG(ctx, XL_LOG_DEBUG, "Called domain_resume on "
                 "non-cooperative hvm domain %u", domid);
-        return ERROR_NI;
+        rc = ERROR_NI;
+        goto out;
     }
     if (xc_domain_resume(ctx->xch, domid, 1)) {
         XL_LOG_ERRNO(ctx, XL_LOG_ERROR, 
                         "xc_domain_resume failed for domain %u", 
                         domid);
-        return ERROR_FAIL;
+        rc = ERROR_FAIL;
+        goto out;
     }
     if (!xs_resume_domain(ctx->xsh, domid)) {
         XL_LOG_ERRNO(ctx, XL_LOG_ERROR, 
                         "xs_resume_domain failed for domain %u", 
                         domid);
-        return ERROR_FAIL;
+        rc = ERROR_FAIL;
     }
+out:
+    libxl_free_all(&gc);
     return 0;
 }
 
@@ -414,6 +437,7 @@ int libxl_domain_resume(libxl_ctx *ctx, 
 int libxl_domain_preserve(libxl_ctx *ctx, uint32_t domid,
                           libxl_domain_create_info *info, const char 
*name_suffix, libxl_uuid new_uuid)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     struct xs_permissions roperm[2];
     xs_transaction_t t;
     char *preserved_name;
@@ -423,17 +447,29 @@ int libxl_domain_preserve(libxl_ctx *ctx
 
     int rc;
 
-    preserved_name = libxl_sprintf(ctx, "%s%s", info->name, name_suffix);
-    if (!preserved_name) return ERROR_NOMEM;
+    preserved_name = libxl_sprintf(&gc, "%s%s", info->name, name_suffix);
+    if (!preserved_name) {
+        libxl_free_all(&gc);
+        return ERROR_NOMEM;
+    }
 
     uuid_string = libxl_uuid2string(ctx, new_uuid);
-    if (!uuid_string) return ERROR_NOMEM;
-
-    dom_path = libxl_xs_get_dompath(ctx, domid);
-    if (!dom_path) return ERROR_FAIL;
-
-    vm_path = libxl_sprintf(ctx, "/vm/%s", uuid_string);
-    if (!vm_path) return ERROR_FAIL;
+    if (!uuid_string) {
+        libxl_free_all(&gc);
+        return ERROR_NOMEM;
+    }
+
+    dom_path = libxl_xs_get_dompath(&gc, domid);
+    if (!dom_path) {
+        libxl_free_all(&gc);
+        return ERROR_FAIL;
+    }
+
+    vm_path = libxl_sprintf(&gc, "/vm/%s", uuid_string);
+    if (!vm_path) {
+        libxl_free_all(&gc);
+        return ERROR_FAIL;
+    }
 
     roperm[0].id = 0;
     roperm[0].perms = XS_PERM_NONE;
@@ -447,16 +483,17 @@ int libxl_domain_preserve(libxl_ctx *ctx
     xs_mkdir(ctx->xsh, t, vm_path);
     xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
 
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vm", dom_path), vm_path, 
strlen(vm_path));
+    xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/vm", dom_path), vm_path, 
strlen(vm_path));
     rc = libxl_domain_rename(ctx, domid, info->name, preserved_name, t);
     if (rc) return rc;
 
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/uuid", vm_path), uuid_string, 
strlen(uuid_string));
+    xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/uuid", vm_path), uuid_string, 
strlen(uuid_string));
 
     if (!xs_transaction_end(ctx->xsh, t, 0))
         if (errno == EAGAIN)
             goto retry_transaction;
 
+    libxl_free_all(&gc);
     return 0;
 }
 
@@ -586,11 +623,12 @@ int libxl_domain_suspend(libxl_ctx *ctx,
     int hvm = is_hvm(ctx, domid);
     int live = info != NULL && info->flags & XL_SUSPEND_LIVE;
     int debug = info != NULL && info->flags & XL_SUSPEND_DEBUG;
+    int rc = 0;
 
     core_suspend(ctx, domid, fd, hvm, live, debug);
     if (hvm)
-        return save_device_model(ctx, domid, fd);
-    return 0;
+        rc = save_device_model(ctx, domid, fd);
+    return rc;
 }
 
 int libxl_domain_pause(libxl_ctx *ctx, uint32_t domid)
@@ -619,24 +657,26 @@ int libxl_domain_core_dump(libxl_ctx *ct
 
 int libxl_domain_unpause(libxl_ctx *ctx, uint32_t domid)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *path;
     char *state;
-    int ret;
+    int ret, rc = 0;
 
     if (is_hvm(ctx, domid)) {
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", 
domid);
-        state = libxl_xs_read(ctx, XBT_NULL, path);
+        path = libxl_sprintf(&gc, "/local/domain/0/device-model/%d/state", 
domid);
+        state = libxl_xs_read(&gc, XBT_NULL, path);
         if (state != NULL && !strcmp(state, "paused")) {
-            libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, 
"/local/domain/0/device-model/%d/command", domid), "continue");
+            libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, 
"/local/domain/0/device-model/%d/command", domid), "continue");
             libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL);
         }
     }
     ret = xc_domain_unpause(ctx->xch, domid);
     if (ret<0) {
         XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unpausing domain %d", domid);
-        return ERROR_FAIL;
+        rc = ERROR_FAIL;
     }
-    return 0;
+    libxl_free_all(&gc);
+    return rc;
 }
 
 static char *req_table[] = {
@@ -649,17 +689,22 @@ static char *req_table[] = {
 
 int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid, int req)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *shutdown_path;
     char *dom_path;
 
-    if (req > ARRAY_SIZE(req_table))
+    if (req > ARRAY_SIZE(req_table)) {
+        libxl_free_all(&gc);
         return ERROR_INVAL;
-
-    dom_path = libxl_xs_get_dompath(ctx, domid);
-    if (!dom_path)
+    }
+
+    dom_path = libxl_xs_get_dompath(&gc, domid);
+    if (!dom_path) {
+        libxl_free_all(&gc);
         return ERROR_FAIL;
-
-    shutdown_path = libxl_sprintf(ctx, "%s/control/shutdown", dom_path);
+    }
+
+    shutdown_path = libxl_sprintf(&gc, "%s/control/shutdown", dom_path);
 
     xs_write(ctx->xsh, XBT_NULL, shutdown_path, req_table[req], 
strlen(req_table[req]));
     if (is_hvm(ctx,domid)) {
@@ -684,6 +729,7 @@ int libxl_domain_shutdown(libxl_ctx *ctx
             }
        }
     }
+    libxl_free_all(&gc);
     return 0;
 }
 
@@ -705,7 +751,8 @@ int libxl_wait_for_domain_death(libxl_ct
 
 int libxl_wait_for_disk_ejects(libxl_ctx *ctx, uint32_t guest_domid, 
libxl_device_disk *disks, int num_disks, libxl_waiter *waiter)
 {
-    int i;
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
+    int i, rc = -1;
     uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid);
 
     if (!domid)
@@ -713,14 +760,17 @@ int libxl_wait_for_disk_ejects(libxl_ctx
 
     for (i = 0; i < num_disks; i++) {
         if (asprintf(&(waiter[i].path), "%s/device/vbd/%d/eject",
-                     libxl_xs_get_dompath(ctx, domid),
+                     libxl_xs_get_dompath(&gc, domid),
                      device_disk_dev_number(disks[i].virtpath)) < 0)
-            return -1;
+            goto out;
         if (asprintf(&(waiter[i].token), "%d", LIBXL_EVENT_DISK_EJECT) < 0)
-            return -1;
+            goto out;
         xs_watch(ctx->xsh, waiter->path, waiter->token);
     }
-    return 0;
+    rc = 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 int libxl_get_event(libxl_ctx *ctx, libxl_event *event)
@@ -773,49 +823,56 @@ int libxl_event_get_domain_death_info(li
 
 int libxl_event_get_disk_eject_info(libxl_ctx *ctx, uint32_t domid, 
libxl_event *event, libxl_device_disk *disk)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *path;
     char *backend;
     char *value;
 
-    value = libxl_xs_read(ctx, XBT_NULL, event->path);
-
-    if (!value || strcmp(value,  "eject"))
+    value = libxl_xs_read(&gc, XBT_NULL, event->path);
+
+    if (!value || strcmp(value,  "eject")) {
+        libxl_free_all(&gc);
         return 0;
+    }
 
     path = strdup(event->path);
     path[strlen(path) - 6] = '\0';
-    backend = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend", 
path));
+    backend = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend", 
path));
 
     disk->backend_domid = 0;
     disk->domid = domid;
     disk->physpath = NULL;
     disk->phystype = 0;
     /* this value is returned to the user: do not free right away */
-    disk->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev", 
backend));
+    disk->virtpath = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/dev", 
backend));
     disk->unpluggable = 1;
     disk->readwrite = 0;
     disk->is_cdrom = 1;
 
     free(path);
+    libxl_free_all(&gc);
     return 1;
 }
 
 static int libxl_destroy_device_model(libxl_ctx *ctx, uint32_t domid)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *pid;
     int ret;
 
-    pid = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"/local/domain/%d/image/device-model-pid", domid));
+    pid = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"/local/domain/%d/image/device-model-pid", domid));
     if (!pid) {
         int stubdomid = libxl_get_stubdom_id(ctx, domid);
         if (!stubdomid) {
             XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't find device model's 
pid");
-            return ERROR_INVAL;
+            ret = ERROR_INVAL;
+            goto out;
         }
         XL_LOG(ctx, XL_LOG_ERROR, "Device model is a stubdom, domid=%d\n", 
stubdomid);
-        return libxl_domain_destroy(ctx, stubdomid, 0);
+        ret = libxl_domain_destroy(ctx, stubdomid, 0);
+        goto out;
     }
-    xs_rm(ctx->xsh, XBT_NULL, libxl_sprintf(ctx, 
"/local/domain/0/device-model/%d", domid));
+    xs_rm(ctx->xsh, XBT_NULL, libxl_sprintf(&gc, 
"/local/domain/0/device-model/%d", domid));
 
     ret = kill(atoi(pid), SIGHUP);
     if (ret < 0 && errno == ESRCH) {
@@ -828,11 +885,14 @@ static int libxl_destroy_device_model(li
         XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to kill Device Model [%d]",
                      atoi(pid));
     }
+out:
+    libxl_free_all(&gc);
     return ret;
 }
 
 int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid, int force)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *dom_path;
     char *vm_path;
     int rc, dm_present;
@@ -841,20 +901,21 @@ int libxl_domain_destroy(libxl_ctx *ctx,
         dm_present = 1;
     } else {
         char *pid;
-        pid = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"/local/domain/%d/image/device-model-pid", domid));
+        pid = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"/local/domain/%d/image/device-model-pid", domid));
         dm_present = (pid != NULL);
-        libxl_free(ctx, pid);
     }
 
-    dom_path = libxl_xs_get_dompath(ctx, domid);
-    if (!dom_path)
-        return ERROR_FAIL;
+    dom_path = libxl_xs_get_dompath(&gc, domid);
+    if (!dom_path) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
 
     if (libxl_device_pci_shutdown(ctx, domid) < 0)
         XL_LOG(ctx, XL_LOG_ERROR, "pci shutdown failed for domid %d", domid);
     if (dm_present) {
         xs_write(ctx->xsh, XBT_NULL,
-                 libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", 
domid),
+                 libxl_sprintf(&gc, "/local/domain/0/device-model/%d/command", 
domid),
                  "shutdown", strlen("shutdown"));
     }
     rc = xc_domain_pause(ctx->xch, domid);
@@ -868,7 +929,7 @@ int libxl_domain_destroy(libxl_ctx *ctx,
     if (libxl_devices_destroy(ctx, domid, force) < 0)
         XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_devices failed for %d", 
domid);
 
-    vm_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vm", 
dom_path));
+    vm_path = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/vm", 
dom_path));
     if (vm_path)
         if (!xs_rm(ctx->xsh, XBT_NULL, vm_path))
             XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", vm_path);
@@ -881,17 +942,24 @@ int libxl_domain_destroy(libxl_ctx *ctx,
     rc = xc_domain_destroy(ctx->xch, domid);
     if (rc < 0) {
         XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_destroy failed for 
%d", domid);
-        return ERROR_FAIL;
+        rc = ERROR_FAIL;
+        goto out;
     }
+    rc = 0;
+out:
+    libxl_free_all(&gc);
     return 0;
 }
 
 int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num)
 {
-    char *p = libxl_sprintf(ctx, "%s/xenconsole", libxl_private_bindir_path());
-    char *domid_s = libxl_sprintf(ctx, "%d", domid);
-    char *cons_num_s = libxl_sprintf(ctx, "%d", cons_num);
-    return execl(p, p, domid_s, "--num", cons_num_s, (void *)NULL) == 0 ? 0 : 
ERROR_FAIL;
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
+    char *p = libxl_sprintf(&gc, "%s/xenconsole", libxl_private_bindir_path());
+    char *domid_s = libxl_sprintf(&gc, "%d", domid);
+    char *cons_num_s = libxl_sprintf(&gc, "%d", cons_num);
+    execl(p, p, domid_s, "--num", cons_num_s, (void *)NULL);
+    libxl_free_all(&gc);
+    return ERROR_FAIL;
 }
 
 int libxl_primary_console_exec(libxl_ctx *ctx, uint32_t domid_vm)
@@ -905,6 +973,7 @@ int libxl_primary_console_exec(libxl_ctx
 
 int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     const char *vnc_port, *vfb_back;
     const char *vnc_listen = NULL, *vnc_pass = NULL;
     int port = 0, autopass_fd = -1;
@@ -915,22 +984,22 @@ int libxl_vncviewer_exec(libxl_ctx *ctx,
         NULL,
     };
 
-    vnc_port = libxl_xs_read(ctx, XBT_NULL,
-                            libxl_sprintf(ctx,
+    vnc_port = libxl_xs_read(&gc, XBT_NULL,
+                            libxl_sprintf(&gc,
                             "/local/domain/%d/console/vnc-port", domid));
     if ( vnc_port )
         port = atoi(vnc_port) - 5900;
 
-    vfb_back = libxl_xs_read(ctx, XBT_NULL,
-                            libxl_sprintf(ctx,
+    vfb_back = libxl_xs_read(&gc, XBT_NULL,
+                            libxl_sprintf(&gc,
                             "/local/domain/%d/device/vfb/0/backend", domid));
     if ( vfb_back ) {
-        vnc_listen = libxl_xs_read(ctx, XBT_NULL,
-                            libxl_sprintf(ctx,
+        vnc_listen = libxl_xs_read(&gc, XBT_NULL,
+                            libxl_sprintf(&gc,
                             "/local/domain/%d/console/vnc-listen", domid));
         if ( autopass )
-            vnc_pass = libxl_xs_read(ctx, XBT_NULL,
-                            libxl_sprintf(ctx,
+            vnc_pass = libxl_xs_read(&gc, XBT_NULL,
+                            libxl_sprintf(&gc,
                             "/local/domain/%d/console/vnc-pass", domid));
     }
 
@@ -940,7 +1009,7 @@ int libxl_vncviewer_exec(libxl_ctx *ctx,
     if ( (vnc_bin = getenv("VNCVIEWER")) )
         args[0] = vnc_bin;
 
-    args[1] = libxl_sprintf(ctx, "%s:%d", vnc_listen, port);
+    args[1] = libxl_sprintf(&gc, "%s:%d", vnc_listen, port);
 
     if ( vnc_pass ) {
         char tmpname[] = "/tmp/vncautopass.XXXXXX";
@@ -962,11 +1031,12 @@ int libxl_vncviewer_exec(libxl_ctx *ctx,
     }
 
 skip_autopass:
+    libxl_free_all(&gc);
     libxl_exec(autopass_fd, -1, -1, args[0], args);
     return 0;
 }
 
-static char ** libxl_build_device_model_args_old(libxl_ctx *ctx,
+static char ** libxl_build_device_model_args_old(libxl_gc *gc,
                                              libxl_device_model_info *info,
                                              libxl_device_nic *vifs,
                                              int num_vifs)
@@ -974,13 +1044,14 @@ static char ** libxl_build_device_model_
     int num = 0, i;
     flexarray_t *dm_args;
     dm_args = flexarray_make(16, 1);
+
     if (!dm_args)
         return NULL;
 
     flexarray_set(dm_args, num++, "qemu-dm");
     flexarray_set(dm_args, num++, "-d");
 
-    flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->domid));
+    flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", info->domid));
 
     if (info->dom_name) {
         flexarray_set(dm_args, num++, "-domain-name");
@@ -992,18 +1063,18 @@ static char ** libxl_build_device_model_
             if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
                 flexarray_set(
                     dm_args, num++,
-                    libxl_sprintf(ctx, "%s:%d%s",
+                    libxl_sprintf(gc, "%s:%d%s",
                                   info->vnclisten,
                                   info->vncdisplay,
                                   info->vncpasswd ? ",password" : ""));
             } else {
-                flexarray_set(dm_args, num++, libxl_sprintf(ctx, 
"127.0.0.1:%d", info->vncdisplay));
+                flexarray_set(dm_args, num++, libxl_sprintf(gc, 
"127.0.0.1:%d", info->vncdisplay));
             }
         } else if (info->vnclisten) {
             if (strchr(info->vnclisten, ':') != NULL) {
                 flexarray_set(dm_args, num++, info->vnclisten);
             } else {
-                flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s:0", 
info->vnclisten));
+                flexarray_set(dm_args, num++, libxl_sprintf(gc, "%s:0", 
info->vnclisten));
             }
         } else {
             flexarray_set(dm_args, num++, "127.0.0.1:0");
@@ -1034,7 +1105,7 @@ static char ** libxl_build_device_model_
 
         if (info->videoram) {
             flexarray_set(dm_args, num++, "-videoram");
-            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", 
info->videoram));
+            flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", 
info->videoram));
         }
         if (info->stdvga) {
             flexarray_set(dm_args, num++, "-std-vga");
@@ -1060,24 +1131,24 @@ static char ** libxl_build_device_model_
         }
         if (info->vcpus > 1) {
             flexarray_set(dm_args, num++, "-vcpus");
-            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", 
info->vcpus));
+            flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", 
info->vcpus));
         }
         if (info->vcpu_avail) {
             flexarray_set(dm_args, num++, "-vcpu_avail");
-            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "0x%x", 
info->vcpu_avail));
+            flexarray_set(dm_args, num++, libxl_sprintf(gc, "0x%x", 
info->vcpu_avail));
         }
         for (i = 0; i < num_vifs; i++) {
             if (vifs[i].nictype == NICTYPE_IOEMU) {
-                char *smac = libxl_sprintf(ctx, 
"%02x:%02x:%02x:%02x:%02x:%02x",
+                char *smac = libxl_sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x",
                                            vifs[i].mac[0], vifs[i].mac[1], 
vifs[i].mac[2],
                                            vifs[i].mac[3], vifs[i].mac[4], 
vifs[i].mac[5]);
                 if (!vifs[i].ifname)
-                    vifs[i].ifname = libxl_sprintf(ctx, "tap%d.%d", 
info->domid, vifs[i].devid);
+                    vifs[i].ifname = libxl_sprintf(gc, "tap%d.%d", 
info->domid, vifs[i].devid);
                 flexarray_set(dm_args, num++, "-net");
-                flexarray_set(dm_args, num++, libxl_sprintf(ctx, 
"nic,vlan=%d,macaddr=%s,model=%s",
+                flexarray_set(dm_args, num++, libxl_sprintf(gc, 
"nic,vlan=%d,macaddr=%s,model=%s",
                             vifs[i].devid, smac, vifs[i].model));
                 flexarray_set(dm_args, num++, "-net");
-                flexarray_set(dm_args, num++, libxl_sprintf(ctx, 
"tap,vlan=%d,ifname=%s,bridge=%s,script=no",
+                flexarray_set(dm_args, num++, libxl_sprintf(gc, 
"tap,vlan=%d,ifname=%s,bridge=%s,script=no",
                             vifs[i].devid, vifs[i].ifname, vifs[i].bridge));
                 ioemu_vifs++;
             }
@@ -1103,7 +1174,7 @@ static char ** libxl_build_device_model_
     return (char **) flexarray_contents(dm_args);
 }
 
-static char ** libxl_build_device_model_args_new(libxl_ctx *ctx,
+static char ** libxl_build_device_model_args_new(libxl_gc *gc,
                                              libxl_device_model_info *info,
                                              libxl_device_nic *vifs,
                                              int num_vifs)
@@ -1120,7 +1191,7 @@ static char ** libxl_build_device_model_
     flexarray_set(dm_args, num++, "qemu-system-xen");
     flexarray_set(dm_args, num++, "-xen-domid");
 
-    flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->domid));
+    flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", info->domid));
 
     if (info->dom_name) {
         flexarray_set(dm_args, num++, "-name");
@@ -1143,11 +1214,11 @@ static char ** libxl_build_device_model_
 
         if (strchr(listen, ':') != NULL)
             flexarray_set(dm_args, num++,
-                    libxl_sprintf(ctx, "%s%s", listen,
+                    libxl_sprintf(gc, "%s%s", listen,
                         info->vncunused ? ",to=99" : ""));
         else
             flexarray_set(dm_args, num++,
-                    libxl_sprintf(ctx, "%s:%d%s", listen, display,
+                    libxl_sprintf(gc, "%s:%d%s", listen, display,
                         info->vncunused ? ",to=99" : ""));
     }
     if (info->sdl) {
@@ -1174,7 +1245,7 @@ static char ** libxl_build_device_model_
 
         if (info->boot) {
             flexarray_set(dm_args, num++, "-boot");
-            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "order=%s", 
info->boot));
+            flexarray_set(dm_args, num++, libxl_sprintf(gc, "order=%s", 
info->boot));
         }
         if (info->usb || info->usbdevice) {
             flexarray_set(dm_args, num++, "-usb");
@@ -1193,22 +1264,22 @@ static char ** libxl_build_device_model_
         if (info->vcpus > 1) {
             flexarray_set(dm_args, num++, "-smp");
             if (info->vcpu_avail)
-                flexarray_set(dm_args, num++, libxl_sprintf(ctx, 
"%d,maxcpus=%d", info->vcpus, info->vcpu_avail));
+                flexarray_set(dm_args, num++, libxl_sprintf(gc, 
"%d,maxcpus=%d", info->vcpus, info->vcpu_avail));
             else
-                flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", 
info->vcpus));
+                flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", 
info->vcpus));
         }
         for (i = 0; i < num_vifs; i++) {
             if (vifs[i].nictype == NICTYPE_IOEMU) {
-                char *smac = libxl_sprintf(ctx, 
"%02x:%02x:%02x:%02x:%02x:%02x",
+                char *smac = libxl_sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x",
                                            vifs[i].mac[0], vifs[i].mac[1], 
vifs[i].mac[2],
                                            vifs[i].mac[3], vifs[i].mac[4], 
vifs[i].mac[5]);
                 if (!vifs[i].ifname)
-                    vifs[i].ifname = libxl_sprintf(ctx, "tap%d.%d", 
info->domid, vifs[i].devid);
+                    vifs[i].ifname = libxl_sprintf(gc, "tap%d.%d", 
info->domid, vifs[i].devid);
                 flexarray_set(dm_args, num++, "-net");
-                flexarray_set(dm_args, num++, libxl_sprintf(ctx, 
"nic,vlan=%d,macaddr=%s,model=%s",
+                flexarray_set(dm_args, num++, libxl_sprintf(gc, 
"nic,vlan=%d,macaddr=%s,model=%s",
                             vifs[i].devid, smac, vifs[i].model));
                 flexarray_set(dm_args, num++, "-net");
-                flexarray_set(dm_args, num++, libxl_sprintf(ctx, 
"tap,vlan=%d,ifname=%s,script=no",
+                flexarray_set(dm_args, num++, libxl_sprintf(gc, 
"tap,vlan=%d,ifname=%s,script=no",
                             vifs[i].devid, vifs[i].ifname));
                 ioemu_vifs++;
             }
@@ -1231,34 +1302,36 @@ static char ** libxl_build_device_model_
     else
         flexarray_set(dm_args, num++, "xenfv");
 
-    disks = libxl_device_disk_list(ctx, info->domid, &nb);
+    disks = libxl_device_disk_list(libxl_gc_owner(gc), info->domid, &nb);
     for (; nb > 0; --nb, ++disks) {
         if ( disks->is_cdrom ) {
             flexarray_set(dm_args, num++, "-cdrom");
             flexarray_set(dm_args, num++, disks->physpath);
         }else{
-            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-%s", 
disks->virtpath));
+            flexarray_set(dm_args, num++, libxl_sprintf(gc, "-%s", 
disks->virtpath));
             flexarray_set(dm_args, num++, disks->physpath);
         }
     }
+    free(disks);
 
     flexarray_set(dm_args, num++, NULL);
     return (char **) flexarray_contents(dm_args);
 }
 
-static char ** libxl_build_device_model_args(libxl_ctx *ctx,
+static char ** libxl_build_device_model_args(libxl_gc *gc,
                                              libxl_device_model_info *info,
                                              libxl_device_nic *vifs,
                                              int num_vifs)
 {
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     int new_qemu;
 
     new_qemu = libxl_check_device_model_version(ctx, info->device_model);
 
     if (new_qemu == 1) {
-        return libxl_build_device_model_args_new(ctx, info, vifs, num_vifs);
+        return libxl_build_device_model_args_new(gc, info, vifs, num_vifs);
     } else {
-        return libxl_build_device_model_args_old(ctx, info, vifs, num_vifs);
+        return libxl_build_device_model_args_old(gc, info, vifs, num_vifs);
     }
 }
 
@@ -1309,6 +1382,7 @@ static int libxl_vfb_and_vkb_from_device
 
 static int libxl_write_dmargs(libxl_ctx *ctx, int domid, int guest_domid, char 
**args)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     int i;
     char *vm_path;
     char *dmargs, *path;
@@ -1321,7 +1395,7 @@ static int libxl_write_dmargs(libxl_ctx 
     roperm[1].id = domid;
     roperm[1].perms = XS_PERM_READ;
 
-    vm_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"/local/domain/%d/vm", guest_domid));
+    vm_path = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"/local/domain/%d/vm", guest_domid));
 
     i = 0;
     dmargs_size = 0;
@@ -1340,17 +1414,18 @@ static int libxl_write_dmargs(libxl_ctx 
         }
         i++;
     }
-    path = libxl_sprintf(ctx, "%s/image/dmargs", vm_path);
+    path = libxl_sprintf(&gc, "%s/image/dmargs", vm_path);
 
 retry_transaction:
     t = xs_transaction_start(ctx->xsh);
     xs_write(ctx->xsh, t, path, dmargs, strlen(dmargs));
     xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
-    xs_set_permissions(ctx->xsh, t, libxl_sprintf(ctx, "%s/rtc/timeoffset", 
vm_path), roperm, ARRAY_SIZE(roperm));
+    xs_set_permissions(ctx->xsh, t, libxl_sprintf(&gc, "%s/rtc/timeoffset", 
vm_path), roperm, ARRAY_SIZE(roperm));
     if (!xs_transaction_end(ctx->xsh, t, 0))
         if (errno == EAGAIN)
             goto retry_transaction;
     free(dmargs);
+    libxl_free_all(&gc);
     return 0;
 }
 
@@ -1362,6 +1437,7 @@ static int libxl_create_stubdom(libxl_ct
                                 libxl_device_vkb *vkb,
                                 libxl_device_model_starting **starting_r)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     int i, num_console = 1, ret;
     libxl_device_console *console;
     libxl_domain_create_info c_info;
@@ -1373,13 +1449,15 @@ static int libxl_create_stubdom(libxl_ct
     xs_transaction_t t;
     libxl_device_model_starting *dm_starting = 0;
 
-    args = libxl_build_device_model_args(ctx, info, vifs, num_vifs);
-    if (!args)
-        return ERROR_FAIL;
+    args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
+    if (!args) {
+        ret = ERROR_FAIL;
+        goto out;
+    }
 
     memset(&c_info, 0x00, sizeof(libxl_domain_create_info));
     c_info.hvm = 0;
-    c_info.name = libxl_sprintf(ctx, "%s-dm", _libxl_domid_to_name(ctx, 
info->domid));
+    c_info.name = libxl_sprintf(&gc, "%s-dm", _libxl_domid_to_name(&gc, 
info->domid));
     for (i = 0; i < 16; i++)
         c_info.uuid[i] = info->uuid[i];
 
@@ -1387,28 +1465,31 @@ static int libxl_create_stubdom(libxl_ct
     b_info.max_vcpus = 1;
     b_info.max_memkb = 32 * 1024;
     b_info.target_memkb = b_info.max_memkb;
-    b_info.kernel.path = libxl_abs_path(ctx, "ioemu-stubdom.gz", 
libxl_xenfirmwaredir_path());
-    b_info.u.pv.cmdline = libxl_sprintf(ctx, " -d %d", info->domid);
+    b_info.kernel.path = libxl_abs_path(&gc, "ioemu-stubdom.gz", 
libxl_xenfirmwaredir_path());
+    b_info.u.pv.cmdline = libxl_sprintf(&gc, " -d %d", info->domid);
     b_info.u.pv.ramdisk.path = "";
     b_info.u.pv.features = "";
     b_info.hvm = 0;
 
     ret = libxl_domain_make(ctx, &c_info, &domid);
-    if (ret) return ret;
+    if (ret)
+        goto out_free;
     ret = libxl_domain_build(ctx, &b_info, domid, &state);
-    if (ret) return ret;
+    if (ret)
+        goto out_free;
 
     libxl_write_dmargs(ctx, domid, info->domid, args);
-    libxl_xs_write(ctx, XBT_NULL,
-                   libxl_sprintf(ctx, "%s/image/device-model-domid", 
libxl_xs_get_dompath(ctx, info->domid)),
+    libxl_xs_write(&gc, XBT_NULL,
+                   libxl_sprintf(&gc, "%s/image/device-model-domid", 
libxl_xs_get_dompath(&gc, info->domid)),
                    "%d", domid);
-    libxl_xs_write(ctx, XBT_NULL,
-                   libxl_sprintf(ctx, "%s/target", libxl_xs_get_dompath(ctx, 
domid)),
+    libxl_xs_write(&gc, XBT_NULL,
+                   libxl_sprintf(&gc, "%s/target", libxl_xs_get_dompath(&gc, 
domid)),
                    "%d", info->domid);
     ret = xc_domain_set_target(ctx->xch, domid, info->domid);
     if (ret<0) {
         XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "setting target domain %d -> %d", 
domid, info->domid);
-        return ERROR_FAIL;
+        ret = ERROR_FAIL;
+        goto out_free;
     }
     xs_set_target(ctx->xsh, domid, info->domid);
 
@@ -1418,10 +1499,10 @@ static int libxl_create_stubdom(libxl_ct
     perm[1].perms = XS_PERM_READ;
 retry_transaction:
     t = xs_transaction_start(ctx->xsh);
-    xs_mkdir(ctx->xsh, t, libxl_sprintf(ctx, 
"/local/domain/0/device-model/%d", info->domid));
-    xs_set_permissions(ctx->xsh, t, libxl_sprintf(ctx, 
"/local/domain/0/device-model/%d", info->domid), perm, ARRAY_SIZE(perm));
-    xs_mkdir(ctx->xsh, t, libxl_sprintf(ctx, "/local/domain/%d/device/vfs", 
domid));
-    xs_set_permissions(ctx->xsh, t, libxl_sprintf(ctx, 
"/local/domain/%d/device/vfs",domid), perm, ARRAY_SIZE(perm));
+    xs_mkdir(ctx->xsh, t, libxl_sprintf(&gc, 
"/local/domain/0/device-model/%d", info->domid));
+    xs_set_permissions(ctx->xsh, t, libxl_sprintf(&gc, 
"/local/domain/0/device-model/%d", info->domid), perm, ARRAY_SIZE(perm));
+    xs_mkdir(ctx->xsh, t, libxl_sprintf(&gc, "/local/domain/%d/device/vfs", 
domid));
+    xs_set_permissions(ctx->xsh, t, libxl_sprintf(&gc, 
"/local/domain/%d/device/vfs",domid), perm, ARRAY_SIZE(perm));
     if (!xs_transaction_end(ctx->xsh, t, 0))
         if (errno == EAGAIN)
             goto retry_transaction;
@@ -1429,26 +1510,32 @@ retry_transaction:
     for (i = 0; i < num_disks; i++) {
         disks[i].domid = domid;
         ret = libxl_device_disk_add(ctx, domid, &disks[i]);
-        if (ret) return ret;
+        if (ret)
+            goto out_free;
     }
     for (i = 0; i < num_vifs; i++) {
         vifs[i].domid = domid;
         ret = libxl_device_nic_add(ctx, domid, &vifs[i]);
-        if (ret) return ret;
+        if (ret)
+            goto out_free;
     }
     vfb->domid = domid;
     ret = libxl_device_vfb_add(ctx, domid, vfb);
-    if (ret) return ret;
+    if (ret)
+        goto out_free;
     vkb->domid = domid;
     ret = libxl_device_vkb_add(ctx, domid, vkb);
-    if (ret) return ret;
+    if (ret)
+        goto out_free;
 
     if (info->serial)
         num_console++;
 
-    console = libxl_calloc(ctx, num_console, sizeof(libxl_device_console));
-    if (!console)
-        return ERROR_NOMEM;
+    console = libxl_calloc(&gc, num_console, sizeof(libxl_device_console));
+    if (!console) {
+        ret = ERROR_NOMEM;
+        goto out_free;
+    }
 
     for (i = 0; i < num_console; i++) {
         console[i].devid = i;
@@ -1457,28 +1544,34 @@ retry_transaction:
         if (!i)
             console[i].build_state = &state;
         ret = libxl_device_console_add(ctx, domid, &console[i]);
-        if (ret) return ret;
+        if (ret)
+            goto out_free;
     }
     if (libxl_create_xenpv_qemu(ctx, vfb, num_console, console, &dm_starting) 
< 0) {
-        free(args);
-        return ERROR_FAIL;
+        ret = ERROR_FAIL;
+        goto out_free;
     }
     if (libxl_confirm_device_model_startup(ctx, dm_starting) < 0) {
-        free(args);
-        return ERROR_FAIL;
+        ret = ERROR_FAIL;
+        goto out_free;
     }
 
     libxl_domain_unpause(ctx, domid);
 
     if (starting_r) {
-        *starting_r = libxl_calloc(ctx, sizeof(libxl_device_model_starting), 
1);
+        *starting_r = calloc(gc, sizeof(libxl_device_model_starting), 1);
         (*starting_r)->domid = info->domid;
-        (*starting_r)->dom_path = libxl_xs_get_dompath(ctx, info->domid);
+        (*starting_r)->dom_path = libxl_xs_get_dompath(&gc, info->domid);
         (*starting_r)->for_spawn = NULL;
     }
 
+    ret = 0;
+
+out_free:
     free(args);
-    return 0;
+out:
+    libxl_free_all(&gc);
+    return ret;
 }
 
 int libxl_create_device_model(libxl_ctx *ctx,
@@ -1487,6 +1580,7 @@ int libxl_create_device_model(libxl_ctx 
                               libxl_device_nic *vifs, int num_vifs,
                               libxl_device_model_starting **starting_r)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *path, *logfile;
     int logfile_w, null;
     int rc;
@@ -1501,48 +1595,55 @@ int libxl_create_device_model(libxl_ctx 
         libxl_device_vkb vkb;
 
         libxl_vfb_and_vkb_from_device_model_info(ctx, info, &vfb, &vkb);
-        return libxl_create_stubdom(ctx, info, disks, num_disks, vifs, 
num_vifs, &vfb, &vkb, starting_r);
+        rc = libxl_create_stubdom(ctx, info, disks, num_disks, vifs, num_vifs, 
&vfb, &vkb, starting_r);
+        goto out;
     }
 
-    args = libxl_build_device_model_args(ctx, info, vifs, num_vifs);
-    if (!args)
-        return ERROR_FAIL;
-
-    path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid);
+    args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
+    if (!args) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    path = libxl_sprintf(&gc, "/local/domain/0/device-model/%d", info->domid);
     xs_mkdir(ctx->xsh, XBT_NULL, path);
-    libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/disable_pf", path), 
"%d", !info->xen_platform_pci);
-
-    libxl_create_logfile(ctx, libxl_sprintf(ctx, "qemu-dm-%s", 
info->dom_name), &logfile);
+    libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/disable_pf", path), 
"%d", !info->xen_platform_pci);
+
+    libxl_create_logfile(ctx, libxl_sprintf(&gc, "qemu-dm-%s", 
info->dom_name), &logfile);
     logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644);
     free(logfile);
     null = open("/dev/null", O_RDONLY);
 
     if (starting_r) {
         rc = ERROR_NOMEM;
-        *starting_r = libxl_calloc(ctx, sizeof(libxl_device_model_starting), 
1);
-        if (!*starting_r) goto xit;
+        *starting_r = calloc(sizeof(libxl_device_model_starting), 1);
+        if (!*starting_r)
+            goto out_close;
         p = *starting_r;
-        p->for_spawn = libxl_calloc(ctx, sizeof(libxl_spawn_starting), 1);
+        p->for_spawn = calloc(sizeof(libxl_spawn_starting), 1);
     } else {
         p = &buf_starting;
         p->for_spawn = NULL;
     }
 
     p->domid = info->domid;
-    p->dom_path = libxl_xs_get_dompath(ctx, info->domid);
-    if (!p->dom_path) { libxl_free(ctx, p); return ERROR_FAIL; }
+    p->dom_path = libxl_xs_get_dompath(&gc, info->domid);
+    if (!p->dom_path) {
+        rc = ERROR_FAIL;
+        goto out_close;
+    }
 
     if (info->vncpasswd) {
-    retry_transaction:
+retry_transaction:
         /* Find uuid and the write the vnc password to xenstore for qemu. */
         t = xs_transaction_start(ctx->xsh);
-        vm_path = libxl_xs_read(ctx,t,libxl_sprintf(ctx, "%s/vm", 
p->dom_path));
+        vm_path = libxl_xs_read(&gc,t,libxl_sprintf(&gc, "%s/vm", 
p->dom_path));
         if (vm_path) {
             /* Now write the vncpassword into it. */
-            pass_stuff = libxl_calloc(ctx, 2, sizeof(char *));
+            pass_stuff = libxl_calloc(&gc, 2, sizeof(char *));
             pass_stuff[0] = "vncpasswd";
             pass_stuff[1] = info->vncpasswd;
-            libxl_xs_writev(ctx,t,vm_path,pass_stuff);
+            libxl_xs_writev(&gc,t,vm_path,pass_stuff);
             if (!xs_transaction_end(ctx->xsh, t, 0))
                 if (errno == EAGAIN)
                     goto retry_transaction;
@@ -1550,19 +1651,22 @@ int libxl_create_device_model(libxl_ctx 
     }
 
     rc = libxl_spawn_spawn(ctx, p, "device model", dm_xenstore_record_pid);
-    if (rc < 0) goto xit;
+    if (rc < 0)
+        goto out_close;
     if (!rc) { /* inner child */
         libxl_exec(null, logfile_w, logfile_w,
-                   libxl_abs_path(ctx, info->device_model, 
libxl_private_bindir_path()),
+                   libxl_abs_path(&gc, info->device_model, 
libxl_private_bindir_path()),
                    args);
     }
 
     rc = 0;
- xit:
-    free(args);
+
+out_close:
     close(null);
     close(logfile_w);
-
+    free(args);
+out:
+    libxl_free_all(&gc);
     return rc;
 }
 
@@ -1571,8 +1675,9 @@ int libxl_detach_device_model(libxl_ctx 
 {
     int rc;
     rc = libxl_spawn_detach(ctx, starting->for_spawn);
-    if (starting->for_spawn) libxl_free(ctx, starting->for_spawn);
-    libxl_free(ctx, starting);
+    if (starting->for_spawn)
+        free(starting->for_spawn);
+    free(starting);
     return rc;
 }
 
@@ -1591,29 +1696,30 @@ int libxl_confirm_device_model_startup(l
 
 
/******************************************************************************/
 
-static char *get_blktap2_device(libxl_ctx *ctx,
+static char *get_blktap2_device(libxl_gc *gc,
                                const char *name, const char *type)
 {
     int minor = tap_ctl_find_minor(type, name);
     if (minor < 0)
         return NULL;
-    return libxl_sprintf(ctx, "/dev/xen/blktap-2/tapdev%d", minor);
+    return libxl_sprintf(gc, "/dev/xen/blktap-2/tapdev%d", minor);
 }
 
-static char *make_blktap2_device(libxl_ctx *ctx,
+static char *make_blktap2_device(libxl_gc *gc,
                                 const char *name, const char *type)
 {
     char *params, *devname = NULL;
     int err;
-    params = libxl_sprintf(ctx, "%s:%s", type, name);
+    params = libxl_sprintf(gc, "%s:%s", type, name);
     err = tap_ctl_create(params, &devname);
     if (!err)
-        libxl_ptr_add(ctx, devname);
+        libxl_ptr_add(gc, devname);
     return err ? NULL : devname;
 }
 
 int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk 
*disk)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     flexarray_t *front;
     flexarray_t *back;
     char *backend_type;
@@ -1621,21 +1727,26 @@ int libxl_device_disk_add(libxl_ctx *ctx
     unsigned int foffset = 0;
     int devid;
     libxl_device device;
-    int major, minor;
+    int major, minor, rc;
 
     front = flexarray_make(16, 1);
-    if (!front)
-        return ERROR_NOMEM;
+    if (!front) {
+        rc = ERROR_NOMEM;
+        goto out;
+    }
     back = flexarray_make(16, 1);
-    if (!back) /* leaks front if error */
-        return ERROR_NOMEM;
+    if (!back) {
+        rc = ERROR_NOMEM;
+        goto out_free;
+    }
 
     backend_type = device_disk_backend_type_of_phystype(disk->phystype);
     devid = device_disk_dev_number(disk->virtpath);
     if (devid==-1) {
         XL_LOG(ctx, XL_LOG_ERROR, "Invalid or unsupported"
                " virtual disk identifier %s", disk->virtpath);
-        return ERROR_INVAL;
+        rc = ERROR_INVAL;
+        goto out_free;
     }
 
     device.backend_devid = devid;
@@ -1649,7 +1760,7 @@ int libxl_device_disk_add(libxl_ctx *ctx
 
             device_physdisk_major_minor(disk->physpath, &major, &minor);
             flexarray_set(back, boffset++, "physical-device");
-            flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x:%x", major, 
minor));
+            flexarray_set(back, boffset++, libxl_sprintf(&gc, "%x:%x", major, 
minor));
 
             flexarray_set(back, boffset++, "params");
             flexarray_set(back, boffset++, disk->physpath);
@@ -1665,25 +1776,27 @@ int libxl_device_disk_add(libxl_ctx *ctx
             if (!tap_ctl_check(&msg)) {
                 const char *type = 
device_disk_string_of_phystype(disk->phystype);
                 char *dev;
-                dev = get_blktap2_device(ctx, disk->physpath, type);
+                dev = get_blktap2_device(&gc, disk->physpath, type);
                 if (!dev)
-                    dev = make_blktap2_device(ctx, disk->physpath, type);
-                if (!dev)
-                    return ERROR_FAIL;
+                    dev = make_blktap2_device(&gc, disk->physpath, type);
+                if (!dev) {
+                    rc = ERROR_FAIL;
+                    goto out_free;
+                }
                 flexarray_set(back, boffset++, "tapdisk-params");
-                flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s", 
device_disk_string_of_phystype(disk->phystype), disk->physpath));
+                flexarray_set(back, boffset++, libxl_sprintf(&gc, "%s:%s", 
device_disk_string_of_phystype(disk->phystype), disk->physpath));
                 flexarray_set(back, boffset++, "params");
-                flexarray_set(back, boffset++, libxl_strdup(ctx, dev));
+                flexarray_set(back, boffset++, libxl_strdup(&gc, dev));
                 backend_type = "phy";
                 device_physdisk_major_minor(dev, &major, &minor);
                 flexarray_set(back, boffset++, "physical-device");
-                flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x:%x", 
major, minor));
+                flexarray_set(back, boffset++, libxl_sprintf(&gc, "%x:%x", 
major, minor));
                 device.backend_kind = DEVICE_VBD;
 
                 break;
             }
             flexarray_set(back, boffset++, "params");
-            flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s",
+            flexarray_set(back, boffset++, libxl_sprintf(&gc, "%s:%s",
                           device_disk_string_of_phystype(disk->phystype), 
disk->physpath));
 
             device.backend_kind = DEVICE_TAP;
@@ -1691,19 +1804,20 @@ int libxl_device_disk_add(libxl_ctx *ctx
         }
         default:
             XL_LOG(ctx, XL_LOG_ERROR, "unrecognized disk physical type: %d\n", 
disk->phystype);
-            return ERROR_INVAL;
+            rc = ERROR_INVAL;
+            goto out_free;
     }
 
     flexarray_set(back, boffset++, "frontend-id");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", disk->domid));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", disk->domid));
     flexarray_set(back, boffset++, "online");
     flexarray_set(back, boffset++, "1");
     flexarray_set(back, boffset++, "removable");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 
(disk->unpluggable) ? 1 : 0));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 
(disk->unpluggable) ? 1 : 0));
     flexarray_set(back, boffset++, "bootable");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
     flexarray_set(back, boffset++, "state");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
     flexarray_set(back, boffset++, "dev");
     flexarray_set(back, boffset++, disk->virtpath);
     flexarray_set(back, boffset++, "type");
@@ -1712,11 +1826,11 @@ int libxl_device_disk_add(libxl_ctx *ctx
     flexarray_set(back, boffset++, disk->readwrite ? "w" : "r");
 
     flexarray_set(front, foffset++, "backend-id");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 
disk->backend_domid));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 
disk->backend_domid));
     flexarray_set(front, foffset++, "state");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
     flexarray_set(front, foffset++, "virtual-device");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", devid));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", devid));
     flexarray_set(front, foffset++, "device-type");
     flexarray_set(front, foffset++, disk->is_cdrom ? "cdrom" : "disk");
 
@@ -1726,11 +1840,17 @@ int libxl_device_disk_add(libxl_ctx *ctx
     }
 
     libxl_device_generic_add(ctx, &device,
-                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
-                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+                             libxl_xs_kvs_of_flexarray(&gc, back, boffset),
+                             libxl_xs_kvs_of_flexarray(&gc, front, foffset));
+
+    rc = 0;
+
+out_free:
     flexarray_free(back);
     flexarray_free(front);
-    return 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 int libxl_device_disk_del(libxl_ctx *ctx, 
@@ -1750,9 +1870,10 @@ int libxl_device_disk_del(libxl_ctx *ctx
     return libxl_device_del(ctx, &device, wait);
 }
 
-const char * libxl_device_disk_local_attach(libxl_ctx *ctx, libxl_device_disk 
*disk)
+char * libxl_device_disk_local_attach(libxl_ctx *ctx, libxl_device_disk *disk)
 {
-    char *dev = NULL;
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
+    char *dev = NULL, *ret;
     int phystype = disk->phystype;
     switch (phystype) {
         case PHYSTYPE_PHY: {
@@ -1767,9 +1888,9 @@ const char * libxl_device_disk_local_att
             const char *msg;
             if (!tap_ctl_check(&msg)) {
                 const char *type = device_disk_string_of_phystype(phystype);
-                dev = get_blktap2_device(ctx, disk->physpath, type);
+                dev = get_blktap2_device(&gc, disk->physpath, type);
                 if (!dev)
-                    dev = make_blktap2_device(ctx, disk->physpath, type);
+                    dev = make_blktap2_device(&gc, disk->physpath, type);
             }
             break;
         }
@@ -1777,7 +1898,9 @@ const char * libxl_device_disk_local_att
             XL_LOG(ctx, XL_LOG_ERROR, "unrecognized disk physical type: %d\n", 
phystype);
             break;
     }
-    return dev;
+    ret = strdup(dev);
+    libxl_free_all(&gc);
+    return ret;
 }
 
 int libxl_device_disk_local_detach(libxl_ctx *ctx, libxl_device_disk *disk)
@@ -1795,31 +1918,36 @@ int libxl_device_disk_local_detach(libxl
 
/******************************************************************************/
 int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     flexarray_t *front;
     flexarray_t *back;
     unsigned int boffset = 0;
     unsigned int foffset = 0;
     libxl_device device;
     char *dompath, **l;
-    unsigned int nb;
+    unsigned int nb, rc;
 
     front = flexarray_make(16, 1);
-    if (!front)
-        return ERROR_NOMEM;
+    if (!front) {
+        rc = ERROR_NOMEM;
+        goto out;
+    }
     back = flexarray_make(16, 1);
-    if (!back)
-        return ERROR_NOMEM;
+    if (!back) {
+        rc = ERROR_NOMEM;
+        goto out_free;
+    }
 
     if (nic->devid == -1) {
-        if (!(dompath = libxl_xs_get_dompath(ctx, domid))) {
-            return ERROR_FAIL;
+        if (!(dompath = libxl_xs_get_dompath(&gc, domid))) {
+            rc = ERROR_FAIL;
+            goto out_free;
         }
-        if (!(l = libxl_xs_directory(ctx, XBT_NULL,
-                                     libxl_sprintf(ctx, "%s/device/vif", 
dompath), &nb))) {
+        if (!(l = libxl_xs_directory(&gc, XBT_NULL,
+                                     libxl_sprintf(&gc, "%s/device/vif", 
dompath), &nb))) {
             nic->devid = 0;
         } else {
             nic->devid = strtoul(l[nb - 1], NULL, 10) + 1;
-            libxl_free(ctx, l);
         }
     }
 
@@ -1831,30 +1959,30 @@ int libxl_device_nic_add(libxl_ctx *ctx,
     device.kind = DEVICE_VIF;
 
     flexarray_set(back, boffset++, "frontend-id");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->domid));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", nic->domid));
     flexarray_set(back, boffset++, "online");
     flexarray_set(back, boffset++, "1");
     flexarray_set(back, boffset++, "state");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
     flexarray_set(back, boffset++, "script");
     flexarray_set(back, boffset++, nic->script);
     flexarray_set(back, boffset++, "mac");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, 
"%02x:%02x:%02x:%02x:%02x:%02x",
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, 
"%02x:%02x:%02x:%02x:%02x:%02x",
                                                  nic->mac[0], nic->mac[1], 
nic->mac[2],
                                                  nic->mac[3], nic->mac[4], 
nic->mac[5]));
     flexarray_set(back, boffset++, "bridge");
-    flexarray_set(back, boffset++, libxl_strdup(ctx, nic->bridge));
+    flexarray_set(back, boffset++, libxl_strdup(&gc, nic->bridge));
     flexarray_set(back, boffset++, "handle");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->devid));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", nic->devid));
 
     flexarray_set(front, foffset++, "backend-id");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 
nic->backend_domid));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 
nic->backend_domid));
     flexarray_set(front, foffset++, "state");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
     flexarray_set(front, foffset++, "handle");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->devid));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", nic->devid));
     flexarray_set(front, foffset++, "mac");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, 
"%02x:%02x:%02x:%02x:%02x:%02x",
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, 
"%02x:%02x:%02x:%02x:%02x:%02x",
                                                   nic->mac[0], nic->mac[1], 
nic->mac[2],
                                                   nic->mac[3], nic->mac[4], 
nic->mac[5]));
     if (0 /* protocol != native*/) {
@@ -1863,13 +1991,17 @@ int libxl_device_nic_add(libxl_ctx *ctx,
     }
 
     libxl_device_generic_add(ctx, &device,
-                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
-                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+                             libxl_xs_kvs_of_flexarray(&gc, back, boffset),
+                             libxl_xs_kvs_of_flexarray(&gc, front, foffset));
 
     /* FIXME: wait for plug */
+    rc = 0;
+out_free:
     flexarray_free(back);
     flexarray_free(front);
-    return 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 int libxl_device_nic_del(libxl_ctx *ctx, 
@@ -1900,87 +2032,94 @@ void libxl_free_nics_list(libxl_nicinfo 
 
 libxl_nicinfo *libxl_list_nics(libxl_ctx *ctx, uint32_t domid, unsigned int 
*nb)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *dompath, *nic_path_fe;
     char **l, **list;
     char *val, *tok;
     unsigned int nb_nics, i;
     libxl_nicinfo *res, *nics;
 
-    dompath = libxl_xs_get_dompath(ctx, domid);
-    if (!dompath) {
-        return NULL;
-    }
-    list = l = libxl_xs_directory(ctx, XBT_NULL,
-                           libxl_sprintf(ctx, "%s/device/vif", dompath), 
&nb_nics);
-    if (!l) {
-        return NULL;
-    }
+    dompath = libxl_xs_get_dompath(&gc, domid);
+    if (!dompath)
+        goto err;
+    list = l = libxl_xs_directory(&gc, XBT_NULL,
+                           libxl_sprintf(&gc, "%s/device/vif", dompath), 
&nb_nics);
+    if (!l)
+        goto err;
     nics = res = calloc(nb_nics, sizeof (libxl_device_nic));
-    if (!res) {
-        libxl_free(ctx, l);
-        return NULL;
-    }
+    if (!res)
+        goto err;
     for (*nb = nb_nics; nb_nics > 0; --nb_nics, ++l, ++nics) {
-        nic_path_fe = libxl_sprintf(ctx, "%s/device/vif/%s", dompath, *l);
+        nic_path_fe = libxl_sprintf(&gc, "%s/device/vif/%s", dompath, *l);
 
         nics->backend = xs_read(ctx->xsh, XBT_NULL,
-                                libxl_sprintf(ctx, "%s/backend", nic_path_fe), 
NULL);
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", 
nic_path_fe));
+                                libxl_sprintf(&gc, "%s/backend", nic_path_fe), 
NULL);
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend-id", 
nic_path_fe));
         nics->backend_id = val ? strtoul(val, NULL, 10) : -1;
 
         nics->devid = strtoul(*l, NULL, 10);
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", 
nic_path_fe));
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/state", 
nic_path_fe));
         nics->state = val ? strtoul(val, NULL, 10) : -1;
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mac", 
nic_path_fe));
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/mac", 
nic_path_fe));
         for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
              ++i, tok = strtok(NULL, ":")) {
             nics->mac[i] = strtoul(tok, NULL, 16);
         }
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/event-channel", nic_path_fe));
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/event-channel", nic_path_fe));
         nics->evtch = val ? strtol(val, NULL, 10) : -1;
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/tx-ring-ref", nic_path_fe));
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/tx-ring-ref", nic_path_fe));
         nics->rref_tx = val ? strtol(val, NULL, 10) : -1;
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/rx-ring-ref", nic_path_fe));
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/rx-ring-ref", nic_path_fe));
         nics->rref_rx = val ? strtol(val, NULL, 10) : -1;
         nics->frontend = xs_read(ctx->xsh, XBT_NULL,
-                                 libxl_sprintf(ctx, "%s/frontend", 
nics->backend), NULL);
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/frontend-id", nics->backend));
+                                 libxl_sprintf(&gc, "%s/frontend", 
nics->backend), NULL);
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/frontend-id", nics->backend));
         nics->frontend_id = val ? strtoul(val, NULL, 10) : -1;
         nics->script = xs_read(ctx->xsh, XBT_NULL,
-                               libxl_sprintf(ctx, "%s/script", nics->backend), 
NULL);
+                               libxl_sprintf(&gc, "%s/script", nics->backend), 
NULL);
     }
 
+    libxl_free_all(&gc);
     return res;
+err:
+    libxl_free_all(&gc);
+    return NULL;
 }
 
 
/******************************************************************************/
 int libxl_device_net2_add(libxl_ctx *ctx, uint32_t domid, libxl_device_net2 
*net2)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     flexarray_t *front, *back;
     unsigned int boffset = 0, foffset = 0;
     libxl_device device;
     char *dompath, *dom, **l;
     unsigned int nb;
+    int rc;
 
     front = flexarray_make(16, 1);
-    if (!front)
-        return ERROR_NOMEM;
+    if (!front) {
+        rc = ERROR_NOMEM;
+        goto err;
+    }
     back = flexarray_make(16, 1);
-    if (!back)
-        return ERROR_NOMEM;
-
-    if (!(dompath = libxl_xs_get_dompath(ctx, domid))) {
-        return ERROR_FAIL;
+    if (!back) {
+        rc = ERROR_NOMEM;
+        goto err_free;
     }
-    dom = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/name", dompath));
+
+    if (!(dompath = libxl_xs_get_dompath(&gc, domid))) {
+        rc = ERROR_FAIL;
+        goto err_free;
+    }
+    dom = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/name", dompath));
 
     if (net2->devid == -1) {
-        if (!(l = libxl_xs_directory(ctx, XBT_NULL,
-                                     libxl_sprintf(ctx, "%s/device/vif2", 
dompath), &nb))) {
+        if (!(l = libxl_xs_directory(&gc, XBT_NULL,
+                                     libxl_sprintf(&gc, "%s/device/vif2", 
dompath), &nb))) {
             net2->devid = 0;
         } else {
             net2->devid = strtoul(l[nb - 1], NULL, 10) + 1;
-            libxl_free(ctx, l);
         }
     }
 
@@ -1994,129 +2133,132 @@ int libxl_device_net2_add(libxl_ctx *ctx
     flexarray_set(back, boffset++, "domain");
     flexarray_set(back, boffset++, dom);
     flexarray_set(back, boffset++, "frontend-id");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->domid));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", net2->domid));
 
     flexarray_set(back, boffset++, "local-trusted");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 
net2->back_trusted));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 
net2->back_trusted));
     flexarray_set(back, boffset++, "mac");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, 
"%02x:%02x:%02x:%02x:%02x:%02x",
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, 
"%02x:%02x:%02x:%02x:%02x:%02x",
                                                  net2->back_mac[0], 
net2->back_mac[1],
                                                  net2->back_mac[2], 
net2->back_mac[3],
                                                  net2->back_mac[4], 
net2->back_mac[5]));
 
     flexarray_set(back, boffset++, "remote-trusted");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->trusted));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", net2->trusted));
     flexarray_set(back, boffset++, "remote-mac");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, 
"%02x:%02x:%02x:%02x:%02x:%02x",
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, 
"%02x:%02x:%02x:%02x:%02x:%02x",
                                                  net2->front_mac[0], 
net2->front_mac[1],
                                                  net2->front_mac[2], 
net2->front_mac[3],
                                                  net2->front_mac[4], 
net2->front_mac[5]));
 
     flexarray_set(back, boffset++, "max-bypasses");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 
net2->max_bypasses));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 
net2->max_bypasses));
     flexarray_set(back, boffset++, "filter-mac");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 
!!(net2->filter_mac)));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 
!!(net2->filter_mac)));
     flexarray_set(back, boffset++, "handle");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->devid));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", net2->devid));
     flexarray_set(back, boffset++, "online");
     flexarray_set(back, boffset++, "1");
     flexarray_set(back, boffset++, "state");
     flexarray_set(back, boffset++, "1");
 
     flexarray_set(front, foffset++, "backend-id");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 
net2->backend_domid));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 
net2->backend_domid));
 
     flexarray_set(front, foffset++, "local-trusted");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", net2->trusted));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", net2->trusted));
     flexarray_set(front, foffset++, "mac");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, 
"%02x:%02x:%02x:%02x:%02x:%02x",
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, 
"%02x:%02x:%02x:%02x:%02x:%02x",
                                                   net2->front_mac[0], 
net2->front_mac[1],
                                                   net2->front_mac[2], 
net2->front_mac[3],
                                                   net2->front_mac[4], 
net2->front_mac[5]));
 
     flexarray_set(front, foffset++, "remote-trusted");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 
net2->back_trusted));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 
net2->back_trusted));
     flexarray_set(front, foffset++, "remote-mac");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, 
"%02x:%02x:%02x:%02x:%02x:%02x",
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, 
"%02x:%02x:%02x:%02x:%02x:%02x",
                                                   net2->back_mac[0], 
net2->back_mac[1],
                                                   net2->back_mac[2], 
net2->back_mac[3],
                                                   net2->back_mac[4], 
net2->back_mac[5]));
 
     flexarray_set(front, foffset++, "filter-mac");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 
!!(net2->filter_mac)));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 
!!(net2->filter_mac)));
     flexarray_set(front, foffset++, "state");
     flexarray_set(front, foffset++, "1");
 
     libxl_device_generic_add(ctx, &device,
-                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
-                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+                             libxl_xs_kvs_of_flexarray(&gc, back, boffset),
+                             libxl_xs_kvs_of_flexarray(&gc, front, foffset));
 
     /* FIXME: wait for plug */
+    rc = 0;
+err_free:
     flexarray_free(back);
     flexarray_free(front);
-    return 0;
+err:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 libxl_net2info *libxl_device_net2_list(libxl_ctx *ctx, uint32_t domid, 
unsigned int *nb)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *dompath, *net2_path_fe;
     char **l;
     char *val, *tok;
     unsigned int nb_net2s, i;
     libxl_net2info *res, *net2s;
 
-    dompath = libxl_xs_get_dompath(ctx, domid);
-    if (!dompath) {
-        return NULL;
-    }
-    l = libxl_xs_directory(ctx, XBT_NULL,
-                           libxl_sprintf(ctx, "%s/device/vif2", dompath), 
&nb_net2s);
-    if (!l) {
-        return NULL;
-    }
-    res = libxl_calloc(ctx, nb_net2s, sizeof (libxl_net2info));
-    if (!res) {
-        libxl_free(ctx, l);
-        return NULL;
-    }
+    dompath = libxl_xs_get_dompath(&gc, domid);
+    if (!dompath)
+        goto err;
+    l = libxl_xs_directory(&gc, XBT_NULL,
+                           libxl_sprintf(&gc, "%s/device/vif2", dompath), 
&nb_net2s);
+    if (!l)
+        goto err;
+    res = calloc(nb_net2s, sizeof (libxl_net2info));
+    if (!res)
+        goto err;
     net2s = res;
     for (*nb = nb_net2s; nb_net2s > 0; --nb_net2s, ++l, ++net2s) {
-        net2_path_fe = libxl_sprintf(ctx, "%s/device/vif2/%s", dompath, *l);
-
-        net2s->backend = libxl_xs_read(ctx, XBT_NULL,
-                                       libxl_sprintf(ctx, "%s/backend", 
net2_path_fe));
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", 
net2_path_fe));
+        net2_path_fe = libxl_sprintf(&gc, "%s/device/vif2/%s", dompath, *l);
+
+        net2s->backend = libxl_xs_read(&gc, XBT_NULL,
+                                       libxl_sprintf(&gc, "%s/backend", 
net2_path_fe));
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend-id", 
net2_path_fe));
         net2s->backend_id = val ? strtoul(val, NULL, 10) : -1;
 
         net2s->devid = strtoul(*l, NULL, 10);
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", 
net2_path_fe));
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/state", 
net2_path_fe));
         net2s->state = val ? strtoul(val, NULL, 10) : -1;
 
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mac", 
net2_path_fe));
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/mac", 
net2_path_fe));
         for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
              ++i, tok = strtok(NULL, ":")) {
             net2s->mac[i] = strtoul(tok, NULL, 16);
         }
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/remote-trusted", net2_path_fe));
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/remote-trusted", net2_path_fe));
         net2s->trusted = val ? strtoul(val, NULL, 10) : -1;
 
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/remote-mac", 
net2_path_fe));
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/remote-mac", 
net2_path_fe));
         for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
              ++i, tok = strtok(NULL, ":")) {
             net2s->back_mac[i] = strtoul(tok, NULL, 16);
         }
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/filter-mac", 
net2_path_fe));
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/filter-mac", 
net2_path_fe));
         net2s->filter_mac = val ? strtoul(val, NULL, 10) : -1;
 
-        net2s->frontend = libxl_xs_read(ctx, XBT_NULL,
-                                        libxl_sprintf(ctx, "%s/frontend", 
net2s->backend));
-        val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/frontend-id", net2s->backend));
+        net2s->frontend = libxl_xs_read(&gc, XBT_NULL,
+                                        libxl_sprintf(&gc, "%s/frontend", 
net2s->backend));
+        val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/frontend-id", net2s->backend));
         net2s->frontend_id = val ? strtoul(val, NULL, 10) : -1;
-        libxl_free(ctx, net2_path_fe);
     }
 
-    libxl_free(ctx, l);
+    libxl_free_all(&gc);
     return res;
+err:
+    libxl_free_all(&gc);
+    return NULL;
 }
 
 int libxl_device_net2_del(libxl_ctx *ctx, libxl_device_net2 *net2, int wait)
@@ -2137,21 +2279,23 @@ int libxl_device_net2_del(libxl_ctx *ctx
 
/******************************************************************************/
 int libxl_device_console_add(libxl_ctx *ctx, uint32_t domid, 
libxl_device_console *console)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     flexarray_t *front;
     flexarray_t *back;
     unsigned int boffset = 0;
     unsigned int foffset = 0;
     libxl_device device;
+    int rc;
 
     if (console->build_state) {
         xs_transaction_t t;
-        char **ents = (char **) libxl_calloc(ctx, 9, sizeof(char *));
+        char **ents = (char **) libxl_calloc(&gc, 9, sizeof(char *));
         ents[0] = "console/port";
-        ents[1] = libxl_sprintf(ctx, "%"PRIu32, 
console->build_state->console_port);
+        ents[1] = libxl_sprintf(&gc, "%"PRIu32, 
console->build_state->console_port);
         ents[2] = "console/ring-ref";
-        ents[3] = libxl_sprintf(ctx, "%lu", console->build_state->console_mfn);
+        ents[3] = libxl_sprintf(&gc, "%lu", console->build_state->console_mfn);
         ents[4] = "console/limit";
-        ents[5] = libxl_sprintf(ctx, "%d", LIBXL_XENCONSOLE_LIMIT);
+        ents[5] = libxl_sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT);
         ents[6] = "console/type";
         if (console->constype == CONSTYPE_XENCONSOLED)
             ents[7] = "xenconsoled";
@@ -2159,18 +2303,22 @@ int libxl_device_console_add(libxl_ctx *
             ents[7] = "ioemu";
 retry_transaction:
         t = xs_transaction_start(ctx->xsh);
-        libxl_xs_writev(ctx, t, libxl_xs_get_dompath(ctx, console->domid), 
ents);
+        libxl_xs_writev(&gc, t, libxl_xs_get_dompath(&gc, console->domid), 
ents);
         if (!xs_transaction_end(ctx->xsh, t, 0))
             if (errno == EAGAIN)
                 goto retry_transaction;
     }
 
     front = flexarray_make(16, 1);
-    if (!front)
-        return ERROR_NOMEM;
+    if (!front) {
+        rc = ERROR_NOMEM;
+        goto out;
+    }
     back = flexarray_make(16, 1);
-    if (!back)
-        return ERROR_NOMEM;
+    if (!back) {
+        rc = ERROR_NOMEM;
+        goto out_free;
+    }
 
     device.backend_devid = console->devid;
     device.backend_domid = console->backend_domid;
@@ -2180,22 +2328,22 @@ retry_transaction:
     device.kind = DEVICE_CONSOLE;
 
     flexarray_set(back, boffset++, "frontend-id");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", console->domid));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", console->domid));
     flexarray_set(back, boffset++, "online");
     flexarray_set(back, boffset++, "1");
     flexarray_set(back, boffset++, "state");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
     flexarray_set(back, boffset++, "domain");
-    flexarray_set(back, boffset++, _libxl_domid_to_name(ctx, domid));
+    flexarray_set(back, boffset++, _libxl_domid_to_name(&gc, domid));
     flexarray_set(back, boffset++, "protocol");
     flexarray_set(back, boffset++, LIBXL_XENCONSOLE_PROTOCOL);
 
     flexarray_set(front, foffset++, "backend-id");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 
console->backend_domid));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 
console->backend_domid));
     flexarray_set(front, foffset++, "state");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
     flexarray_set(front, foffset++, "limit");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 
LIBXL_XENCONSOLE_LIMIT));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 
LIBXL_XENCONSOLE_LIMIT));
     flexarray_set(front, foffset++, "protocol");
     flexarray_set(front, foffset++, LIBXL_XENCONSOLE_PROTOCOL);
     flexarray_set(front, foffset++, "type");
@@ -2205,29 +2353,38 @@ retry_transaction:
         flexarray_set(front, foffset++, "ioemu");
 
     libxl_device_generic_add(ctx, &device,
-                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
-                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+                             libxl_xs_kvs_of_flexarray(&gc, back, boffset),
+                             libxl_xs_kvs_of_flexarray(&gc, front, foffset));
+    rc = 0;
+out_free:
     flexarray_free(back);
     flexarray_free(front);
-
-    return 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 
/******************************************************************************/
 int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     flexarray_t *front;
     flexarray_t *back;
     unsigned int boffset = 0;
     unsigned int foffset = 0;
     libxl_device device;
+    int rc;
 
     front = flexarray_make(16, 1);
-    if (!front)
-        return ERROR_NOMEM;
+    if (!front) {
+        rc = ERROR_NOMEM;
+        goto out;
+    }
     back = flexarray_make(16, 1);
-    if (!back)
-        return ERROR_NOMEM;
+    if (!back) {
+        rc = ERROR_NOMEM;
+        goto out_free;
+    }
 
     device.backend_devid = vkb->devid;
     device.backend_domid = vkb->backend_domid;
@@ -2237,26 +2394,29 @@ int libxl_device_vkb_add(libxl_ctx *ctx,
     device.kind = DEVICE_VKBD;
 
     flexarray_set(back, boffset++, "frontend-id");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vkb->domid));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vkb->domid));
     flexarray_set(back, boffset++, "online");
     flexarray_set(back, boffset++, "1");
     flexarray_set(back, boffset++, "state");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
     flexarray_set(back, boffset++, "domain");
-    flexarray_set(back, boffset++, _libxl_domid_to_name(ctx, domid));
+    flexarray_set(back, boffset++, _libxl_domid_to_name(&gc, domid));
 
     flexarray_set(front, foffset++, "backend-id");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 
vkb->backend_domid));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 
vkb->backend_domid));
     flexarray_set(front, foffset++, "state");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
 
     libxl_device_generic_add(ctx, &device,
-                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
-                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+                             libxl_xs_kvs_of_flexarray(&gc, back, boffset),
+                             libxl_xs_kvs_of_flexarray(&gc, front, foffset));
+    rc = 0;
+out_free:
     flexarray_free(back);
     flexarray_free(front);
-
-    return 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 int libxl_device_vkb_clean_shutdown(libxl_ctx *ctx, uint32_t domid)
@@ -2271,16 +2431,17 @@ int libxl_device_vkb_hard_shutdown(libxl
 
 libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int 
*num)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *be_path_tap, *be_path_vbd;
     libxl_device_disk *dend, *disks, *ret = NULL;
     char **b, **l = NULL;
     unsigned int numl;
     char *type;
 
-    be_path_vbd = libxl_sprintf(ctx, "%s/backend/vbd/%d", 
libxl_xs_get_dompath(ctx, 0), domid);
-    be_path_tap = libxl_sprintf(ctx, "%s/backend/tap/%d", 
libxl_xs_get_dompath(ctx, 0), domid);
-
-    b = l = libxl_xs_directory(ctx, XBT_NULL, be_path_vbd, &numl);
+    be_path_vbd = libxl_sprintf(&gc, "%s/backend/vbd/%d", 
libxl_xs_get_dompath(&gc, 0), domid);
+    be_path_tap = libxl_sprintf(&gc, "%s/backend/tap/%d", 
libxl_xs_get_dompath(&gc, 0), domid);
+
+    b = l = libxl_xs_directory(&gc, XBT_NULL, be_path_vbd, &numl);
     if (l) {
         ret = realloc(ret, sizeof(libxl_device_disk) * numl);
         disks = ret;
@@ -2289,20 +2450,19 @@ libxl_device_disk *libxl_device_disk_lis
         for (; disks < dend; ++disks, ++l) {
             disks->backend_domid = 0;
             disks->domid = domid;
-            disks->physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/params", be_path_vbd, *l));
-            libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/type", be_path_vbd, *l)), &(disks->phystype));
-            disks->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/dev", be_path_vbd, *l));
-            disks->unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/removable", be_path_vbd, *l)));
-            if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/mode", be_path_vbd, *l)), "w"))
+            disks->physpath = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/%s/params", be_path_vbd, *l));
+            libxl_string_to_phystype(ctx, libxl_xs_read(&gc, XBT_NULL, 
libxl_sprintf(&gc, "%s/%s/type", be_path_vbd, *l)), &(disks->phystype));
+            disks->virtpath = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/%s/dev", be_path_vbd, *l));
+            disks->unpluggable = atoi(libxl_xs_read(&gc, XBT_NULL, 
libxl_sprintf(&gc, "%s/%s/removable", be_path_vbd, *l)));
+            if (!strcmp(libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/%s/mode", be_path_vbd, *l)), "w"))
                 disks->readwrite = 1;
             else
                 disks->readwrite = 0;
-            type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/frontend", be_path_vbd, *l))));
+            type = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/device-type", libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/%s/frontend", be_path_vbd, *l))));
             disks->is_cdrom = !strcmp(type, "cdrom");
         }
-        libxl_free(ctx, b);
     }
-    b = l = libxl_xs_directory(ctx, XBT_NULL, be_path_tap, &numl);
+    b = l = libxl_xs_directory(&gc, XBT_NULL, be_path_tap, &numl);
     if (l) {
         ret = realloc(ret, sizeof(libxl_device_disk) * (*num + numl));
         disks = ret + *num;
@@ -2310,51 +2470,54 @@ libxl_device_disk *libxl_device_disk_lis
         for (dend = ret + *num; disks < dend; ++disks, ++l) {
             disks->backend_domid = 0;
             disks->domid = domid;
-            disks->physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/params", be_path_tap, *l));
-            libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/type", be_path_tap, *l)), &(disks->phystype));
-            disks->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/dev", be_path_tap, *l));
-            disks->unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/removable", be_path_tap, *l)));
-            if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/mode", be_path_tap, *l)), "w"))
+            disks->physpath = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/%s/params", be_path_tap, *l));
+            libxl_string_to_phystype(ctx, libxl_xs_read(&gc, XBT_NULL, 
libxl_sprintf(&gc, "%s/%s/type", be_path_tap, *l)), &(disks->phystype));
+            disks->virtpath = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/%s/dev", be_path_tap, *l));
+            disks->unpluggable = atoi(libxl_xs_read(&gc, XBT_NULL, 
libxl_sprintf(&gc, "%s/%s/removable", be_path_tap, *l)));
+            if (!strcmp(libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/%s/mode", be_path_tap, *l)), "w"))
                 disks->readwrite = 1;
             else
                 disks->readwrite = 0;
-            type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/frontend", be_path_tap, *l))));
+            type = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/device-type", libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/%s/frontend", be_path_tap, *l))));
             disks->is_cdrom = !strcmp(type, "cdrom");
         }
-        libxl_free(ctx, b);
     }
+    libxl_free_all(&gc);
     return ret;
 }
 
 int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
                               libxl_device_disk *disk, libxl_diskinfo 
*diskinfo)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *dompath, *diskpath;
     char *val;
 
-    dompath = libxl_xs_get_dompath(ctx, domid);
+    dompath = libxl_xs_get_dompath(&gc, domid);
     diskinfo->devid = device_disk_dev_number(disk->virtpath);
 
     /* tap devices entries in xenstore are written as vbd devices. */
-    diskpath = libxl_sprintf(ctx, "%s/device/vbd/%d", dompath, 
diskinfo->devid);
-    diskinfo->backend = libxl_xs_read(ctx, XBT_NULL,
-                                      libxl_sprintf(ctx, "%s/backend", 
diskpath));
+    diskpath = libxl_sprintf(&gc, "%s/device/vbd/%d", dompath, 
diskinfo->devid);
+    diskinfo->backend = libxl_xs_read(&gc, XBT_NULL,
+                                      libxl_sprintf(&gc, "%s/backend", 
diskpath));
     if (!diskinfo->backend) {
+        libxl_free_all(&gc);
         return ERROR_FAIL;
     }
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", 
diskpath));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend-id", 
diskpath));
     diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", 
diskpath));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/state", 
diskpath));
     diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/event-channel", 
diskpath));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/event-channel", 
diskpath));
     diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/ring-ref", 
diskpath));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/ring-ref", 
diskpath));
     diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
-    diskinfo->frontend = libxl_xs_read(ctx, XBT_NULL,
-                                       libxl_sprintf(ctx, "%s/frontend", 
diskinfo->backend));
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend-id", 
diskinfo->backend));
+    diskinfo->frontend = libxl_xs_read(&gc, XBT_NULL,
+                                       libxl_sprintf(&gc, "%s/frontend", 
diskinfo->backend));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/frontend-id", 
diskinfo->backend));
     diskinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
 
+    libxl_free_all(&gc);
     return 0;
 }
 
@@ -2376,6 +2539,7 @@ int libxl_cdrom_insert(libxl_ctx *ctx, u
     }
     if (i == num) {
         XL_LOG(ctx, XL_LOG_ERROR, "Virtual device not found");
+        free(disks);
         return ERROR_FAIL;
     }
     libxl_device_disk_del(ctx, disks + i, 1);
@@ -2388,28 +2552,30 @@ int libxl_cdrom_insert(libxl_ctx *ctx, u
         libxl_device_disk_add(ctx, stubdomid, disk);
         disk->domid = domid;
     }
+    free(disks);
     return 0;
 }
 
 
/******************************************************************************/
-static int libxl_build_xenpv_qemu_args(libxl_ctx *ctx,
+static int libxl_build_xenpv_qemu_args(libxl_gc *gc,
                                        libxl_device_vfb *vfb,
                                        int num_console,
                                        libxl_device_console *console,
                                        libxl_device_model_info *info)
 {
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     int i = 0, j = 0, num = 0;
     memset(info, 0x00, sizeof(libxl_device_model_info));
 
     info->vnc = vfb->vnc;
     if (vfb->vnclisten)
-        info->vnclisten = libxl_strdup(ctx, vfb->vnclisten);
+        info->vnclisten = libxl_strdup(gc, vfb->vnclisten);
     info->vncdisplay = vfb->vncdisplay;
     info->vncunused = vfb->vncunused;
     if (vfb->vncpasswd)
         info->vncpasswd = vfb->vncpasswd;
     if (vfb->keymap)
-        info->keymap = libxl_strdup(ctx, vfb->keymap);
+        info->keymap = libxl_strdup(gc, vfb->keymap);
     info->sdl = vfb->sdl;
     info->opengl = vfb->opengl;
     for (i = 0; i < num_console; i++) {
@@ -2420,9 +2586,9 @@ static int libxl_build_xenpv_qemu_args(l
         uint32_t guest_domid;
         if (libxl_is_stubdom(ctx, vfb->domid, &guest_domid)) {
             char *filename;
-            char *name = libxl_sprintf(ctx, "qemu-dm-%s", 
_libxl_domid_to_name(ctx, guest_domid));
+            char *name = libxl_sprintf(gc, "qemu-dm-%s", 
_libxl_domid_to_name(gc, guest_domid));
             libxl_create_logfile(ctx, name, &filename);
-            info->serial = libxl_sprintf(ctx, "file:%s", filename);
+            info->serial = libxl_sprintf(gc, "file:%s", filename);
             free(filename);
         } else {
             info->serial = "pty";
@@ -2430,7 +2596,7 @@ static int libxl_build_xenpv_qemu_args(l
         num--;
     }
     if (num > 0) {
-        info->extra = (char **) libxl_calloc(ctx, num * 2 + 1, sizeof(char *));
+        info->extra = (char **) libxl_calloc(gc, num * 2 + 1, sizeof(char *));
         for (j = 0; j < num * 2; j = j + 2) {
             info->extra[j] = "-serial";
             info->extra[j + 1] = "pty";
@@ -2438,8 +2604,8 @@ static int libxl_build_xenpv_qemu_args(l
         info->extra[j] = NULL;
     }
     info->domid = vfb->domid;
-    info->dom_name = _libxl_domid_to_name(ctx, vfb->domid);
-    info->device_model = libxl_abs_path(ctx, "qemu-dm", libxl_libexec_path());
+    info->dom_name = _libxl_domid_to_name(gc, vfb->domid);
+    info->device_model = libxl_abs_path(gc, "qemu-dm", libxl_libexec_path());
     info->type = XENPV;
     return 0;
 }
@@ -2448,27 +2614,35 @@ int libxl_create_xenpv_qemu(libxl_ctx *c
                             int num_console, libxl_device_console *console,
                             libxl_device_model_starting **starting_r)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     libxl_device_model_info info;
 
-    libxl_build_xenpv_qemu_args(ctx, vfb, num_console, console, &info);
+    libxl_build_xenpv_qemu_args(&gc, vfb, num_console, console, &info);
     libxl_create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r);
+    libxl_free_all(&gc);
     return 0;
 }
 
 int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     flexarray_t *front;
     flexarray_t *back;
     unsigned int boffset = 0;
     unsigned int foffset = 0;
     libxl_device device;
+    int rc;
 
     front = flexarray_make(16, 1);
-    if (!front)
-        return ERROR_NOMEM;
+    if (!front) {
+        rc = ERROR_NOMEM;
+        goto out;
+    }
     back = flexarray_make(16, 1);
-    if (!back)
-        return ERROR_NOMEM;
+    if (!back) {
+        rc = ERROR_NOMEM;
+        goto out_free;
+    }
 
     device.backend_devid = vfb->devid;
     device.backend_domid = vfb->backend_domid;
@@ -2478,27 +2652,27 @@ int libxl_device_vfb_add(libxl_ctx *ctx,
     device.kind = DEVICE_VFB;
 
     flexarray_set(back, boffset++, "frontend-id");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->domid));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->domid));
     flexarray_set(back, boffset++, "online");
     flexarray_set(back, boffset++, "1");
     flexarray_set(back, boffset++, "state");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
     flexarray_set(back, boffset++, "domain");
-    flexarray_set(back, boffset++, _libxl_domid_to_name(ctx, domid));
+    flexarray_set(back, boffset++, _libxl_domid_to_name(&gc, domid));
     flexarray_set(back, boffset++, "vnc");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vnc));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->vnc));
     flexarray_set(back, boffset++, "vnclisten");
     flexarray_set(back, boffset++, vfb->vnclisten);
     flexarray_set(back, boffset++, "vncpasswd");
     flexarray_set(back, boffset++, vfb->vncpasswd);
     flexarray_set(back, boffset++, "vncdisplay");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncdisplay));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->vncdisplay));
     flexarray_set(back, boffset++, "vncunused");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncunused));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->vncunused));
     flexarray_set(back, boffset++, "sdl");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->sdl));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->sdl));
     flexarray_set(back, boffset++, "opengl");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->opengl));
+    flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->opengl));
     if (vfb->xauthority) {
         flexarray_set(back, boffset++, "xauthority");
         flexarray_set(back, boffset++, vfb->xauthority);
@@ -2509,17 +2683,20 @@ int libxl_device_vfb_add(libxl_ctx *ctx,
     }
 
     flexarray_set(front, foffset++, "backend-id");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 
vfb->backend_domid));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 
vfb->backend_domid));
     flexarray_set(front, foffset++, "state");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
 
     libxl_device_generic_add(ctx, &device,
-                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
-                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+                             libxl_xs_kvs_of_flexarray(&gc, back, boffset),
+                             libxl_xs_kvs_of_flexarray(&gc, front, foffset));
+    rc = 0;
+out_free:
     flexarray_free(front);
     flexarray_free(back);
-
-    return 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 int libxl_device_vfb_clean_shutdown(libxl_ctx *ctx, uint32_t domid)
@@ -2536,81 +2713,90 @@ int libxl_device_vfb_hard_shutdown(libxl
 
 int libxl_domain_setmaxmem(libxl_ctx *ctx, uint32_t domid, uint32_t max_memkb)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *mem, *endptr;
     uint32_t memorykb;
-    char *dompath = libxl_xs_get_dompath(ctx, domid);
-
-    mem = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/target", 
dompath));
+    char *dompath = libxl_xs_get_dompath(&gc, domid);
+    int rc = 1;
+
+    mem = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/memory/target", 
dompath));
     if (!mem) {
         XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot get memory info from 
%s/memory/target\n", dompath);
-        return 1;
+        goto out;
     }
     memorykb = strtoul(mem, &endptr, 10);
     if (*endptr != '\0') {
         XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "invalid memory %s from 
%s/memory/target\n", mem, dompath);
-        return 1;
+        goto out;
     }
 
     if (max_memkb < memorykb) {
         XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "memory_static_max must be greater 
than or or equal to memory_dynamic_max\n");
-        return 1;
+        goto out;
     }
 
     if (domid != 0)
-        libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/memory/static-max", dompath), "%"PRIu32, max_memkb);
-
-    return 0;
+        libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/memory/static-max", dompath), "%"PRIu32, max_memkb);
+
+    rc = 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid, uint32_t 
target_memkb, int enforce)
 {
-    int rc = 0;
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
+    int rc = 1;
     uint32_t memorykb = 0, videoram = 0;
     char *memmax, *endptr, *videoram_s = NULL;
-    char *dompath = libxl_xs_get_dompath(ctx, domid);
+    char *dompath = libxl_xs_get_dompath(&gc, domid);
     xc_domaininfo_t info;
     libxl_dominfo ptr;
     char *uuid;
 
     if (domid) {
-        memmax = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/memory/static-max", dompath));
+        memmax = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/memory/static-max", dompath));
         if (!memmax) {
             XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
                 "cannot get memory info from %s/memory/static-max\n", dompath);
-            return 1;
+            goto out;
         }
         memorykb = strtoul(memmax, &endptr, 10);
         if (*endptr != '\0') {
             XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
                 "invalid max memory %s from %s/memory/static-max\n", memmax, 
dompath);
-            return 1;
+            goto out;
         }
 
         if (target_memkb > memorykb) {
             XL_LOG(ctx, XL_LOG_ERROR,
                 "memory_dynamic_max must be less than or equal to 
memory_static_max\n");
-            return 1;
+            goto out;
         }
     }
 
-    videoram_s = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/memory/videoram", dompath));
+    videoram_s = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/memory/videoram", dompath));
     videoram = videoram_s ? atoi(videoram_s) : 0;
 
-    libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/target", 
dompath), "%"PRIu32, target_memkb);
+    libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/memory/target", 
dompath), "%"PRIu32, target_memkb);
 
     rc = xc_domain_getinfolist(ctx->xch, domid, 1, &info);
     if (rc != 1 || info.domain != domid)
-        return rc;
+        goto out;
     xcinfo2xlinfo(&info, &ptr);
     uuid = libxl_uuid2string(ctx, ptr.uuid);
-    libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "/vm/%s/memory", uuid), 
"%"PRIu32, target_memkb / 1024);
+    libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "/vm/%s/memory", uuid), 
"%"PRIu32, target_memkb / 1024);
 
     if (enforce || !domid)
         memorykb = target_memkb;
     rc = xc_domain_setmaxmem(ctx->xch, domid, memorykb + 
LIBXL_MAXMEM_CONSTANT);
     if (rc != 0)
-        return rc;
+        goto out;
     rc = xc_domain_memory_set_pod_target(ctx->xch, domid, (target_memkb - 
videoram) / 4, NULL, NULL, NULL);
+
+out:
+    libxl_free_all(&gc);
     return rc;
 }
 
@@ -2784,26 +2970,31 @@ int libxl_set_vcpuaffinity(libxl_ctx *ct
 
 int libxl_set_vcpucount(libxl_ctx *ctx, uint32_t domid, uint32_t count)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     xc_domaininfo_t domaininfo;
     char *dompath;
-    int i;
+    int i, rc = ERROR_FAIL;
 
     if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
         XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting domain info list");
-        return ERROR_FAIL;
+        goto out;
     }
     if (!count || ((domaininfo.max_vcpu_id + 1) < count)) {
-        return ERROR_INVAL;
+        rc = ERROR_INVAL;
+        goto out;
     }
-    if (!(dompath = libxl_xs_get_dompath(ctx, domid)))
-        return ERROR_FAIL;
+    if (!(dompath = libxl_xs_get_dompath(&gc, domid)))
+        goto out;
 
     for (i = 0; i <= domaininfo.max_vcpu_id; ++i) {
-        libxl_xs_write(ctx, XBT_NULL,
-                       libxl_sprintf(ctx, "%s/cpu/%u/availability", dompath, 
i),
+        libxl_xs_write(&gc, XBT_NULL,
+                       libxl_sprintf(&gc, "%s/cpu/%u/availability", dompath, 
i),
                        "%s", ((1 << i) & ((1 << count) - 1)) ? "online" : 
"offline");
     }
-    return 0;
+    rc = 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 /*
@@ -2916,10 +3107,12 @@ int libxl_send_trigger(libxl_ctx *ctx, u
 
 int libxl_send_sysrq(libxl_ctx *ctx, uint32_t domid, char sysrq)
 {
-    char *dompath = libxl_xs_get_dompath(ctx, domid);
-
-    libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/control/sysrq", 
dompath), "%c", sysrq);
-
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
+    char *dompath = libxl_xs_get_dompath(&gc, domid);
+
+    libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/control/sysrq", 
dompath), "%c", sysrq);
+
+    libxl_free_all(&gc);
     return 0;
 }
 
@@ -3006,20 +3199,24 @@ void libxl_xen_console_read_finish(libxl
 
 uint32_t libxl_vm_get_start_time(libxl_ctx *ctx, uint32_t domid)
 {
-    char *dompath = libxl_xs_get_dompath(ctx, domid);
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
+    char *dompath = libxl_xs_get_dompath(&gc, domid);
     char *vm_path, *start_time;
+    uint32_t ret;
 
     vm_path = libxl_xs_read(
-        ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vm", dompath));
+        &gc, XBT_NULL, libxl_sprintf(&gc, "%s/vm", dompath));
     start_time = libxl_xs_read(
-        ctx, XBT_NULL, libxl_sprintf(ctx, "%s/start_time", vm_path));
+        &gc, XBT_NULL, libxl_sprintf(&gc, "%s/start_time", vm_path));
     if (start_time == NULL) {
         XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
                         "Can't get start time of domain '%d'", domid);
-        return -1;
+        ret = -1;
+    }else{
+        ret = strtoul(start_time, NULL, 10);
     }
-
-    return strtoul(start_time, NULL, 10);
+    libxl_free_all(&gc);
+    return ret;
 }
 
 char *libxl_tmem_list(libxl_ctx *ctx, uint32_t domid, int use_long)
diff -r 7b144fe8c528 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h       Wed Aug 11 14:39:44 2010 +0100
+++ b/tools/libxl/libxl.h       Thu Aug 12 15:22:56 2010 +0100
@@ -78,10 +78,6 @@ typedef struct {
     xc_interface *xch;
     struct xs_handle *xsh;
 
-    /* mini-GC */
-    int alloc_maxsize;
-    void **alloc_ptrs;
-
     /* for callers who reap children willy-nilly; caller must only
      * set this after libxl_init and before any other call - or
      * may leave them untouched */
@@ -491,7 +487,7 @@ int libxl_cdrom_insert(libxl_ctx *ctx, u
 /*
  * Make a disk available in this domain. Returns path to a device.
  */
-const char * libxl_device_disk_local_attach(libxl_ctx *ctx, libxl_device_disk 
*disk);
+char * libxl_device_disk_local_attach(libxl_ctx *ctx, libxl_device_disk *disk);
 int libxl_device_disk_local_detach(libxl_ctx *ctx, libxl_device_disk *disk);
 
 typedef struct {
diff -r 7b144fe8c528 tools/libxl/libxl_bootloader.c
--- a/tools/libxl/libxl_bootloader.c    Wed Aug 11 14:39:44 2010 +0100
+++ b/tools/libxl/libxl_bootloader.c    Thu Aug 12 15:22:56 2010 +0100
@@ -30,7 +30,7 @@
 #define XENCONSOLED_BUF_SIZE 16
 #define BOOTLOADER_BUF_SIZE 1024
 
-static char **make_bootloader_args(libxl_ctx *ctx,
+static char **make_bootloader_args(libxl_gc *gc,
                                    libxl_domain_build_info *info,
                                    uint32_t domid,
                                    const char *fifo, const char *disk)
@@ -45,20 +45,20 @@ static char **make_bootloader_args(libxl
     flexarray_set(args, nr++, (char *)info->u.pv.bootloader);
 
     if (info->kernel.path)
-        flexarray_set(args, nr++, libxl_sprintf(ctx, "--kernel=%s", 
info->kernel.path));
+        flexarray_set(args, nr++, libxl_sprintf(gc, "--kernel=%s", 
info->kernel.path));
     if (info->u.pv.ramdisk.path)
-        flexarray_set(args, nr++, libxl_sprintf(ctx, "--ramdisk=%s", 
info->u.pv.ramdisk.path));
+        flexarray_set(args, nr++, libxl_sprintf(gc, "--ramdisk=%s", 
info->u.pv.ramdisk.path));
     if (info->u.pv.cmdline && *info->u.pv.cmdline != '\0')
-        flexarray_set(args, nr++, libxl_sprintf(ctx, "--args=%s", 
info->u.pv.cmdline));
+        flexarray_set(args, nr++, libxl_sprintf(gc, "--args=%s", 
info->u.pv.cmdline));
 
-    flexarray_set(args, nr++, libxl_sprintf(ctx, "--output=%s", fifo));
+    flexarray_set(args, nr++, libxl_sprintf(gc, "--output=%s", fifo));
     flexarray_set(args, nr++, "--output-format=simple0");
-    flexarray_set(args, nr++, libxl_sprintf(ctx, "--output-directory=%s", 
"/var/run/libxl/"));
+    flexarray_set(args, nr++, libxl_sprintf(gc, "--output-directory=%s", 
"/var/run/libxl/"));
 
     if (info->u.pv.bootloader_args) {
         char *saveptr;
         /* Operate on a duplicate since strtok modifes the argument */
-        char *dup = libxl_strdup(ctx, info->u.pv.bootloader_args);
+        char *dup = libxl_strdup(gc, info->u.pv.bootloader_args);
         char *t = strtok_r(dup, " \t\n", &saveptr);
         do {
             flexarray_set(args, nr++, t);
@@ -161,7 +161,7 @@ static pid_t fork_exec_bootloader(int *m
  * if there is actual data to write, otherwise this would loop too fast,
  * eating up CPU time.
  */
-static char * bootloader_interact(libxl_ctx *ctx, int xenconsoled_fd, int 
bootloader_fd, int fifo_fd)
+static char * bootloader_interact(libxl_gc *gc, int xenconsoled_fd, int 
bootloader_fd, int fifo_fd)
 {
     int ret;
 
@@ -263,7 +263,7 @@ static char * bootloader_interact(libxl_
         }
     }
 
-    libxl_ptr_add(ctx, output);
+    libxl_ptr_add(gc, output);
     return output;
 
 out_err:
@@ -300,8 +300,8 @@ int libxl_run_bootloader(libxl_ctx *ctx,
                          libxl_device_disk *disk,
                          uint32_t domid)
 {
-    int ret;
-
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
+    int ret, rc = 0;
     char *fifo = NULL;
     const char *diskpath = NULL;
     char **args = NULL;
@@ -322,49 +322,48 @@ int libxl_run_bootloader(libxl_ctx *ctx,
     struct stat st_buf;
 
     if (info->hvm || !info->u.pv.bootloader)
-        return 0;
+        goto out;
 
+    rc = ERROR_INVAL;
     if (!disk)
-        return ERROR_INVAL;
+        goto out;
 
+    rc = ERROR_FAIL;
     ret = mkdir("/var/run/libxl/", S_IRWXU);
     if (ret < 0 && errno != EEXIST)
-        return ERROR_FAIL;
+        goto out;
 
     ret = stat("/var/run/libxl/", &st_buf);
     if (ret < 0)
-        return ERROR_FAIL;
+        goto out;
 
     if (!S_ISDIR(st_buf.st_mode))
-        return ERROR_FAIL;
+        goto out;
 
     tempdir = mkdtemp(tempdir_template);
     if (tempdir == NULL)
-        return ERROR_FAIL;
+        goto out;
 
     ret = asprintf(&fifo, "%s/fifo", tempdir);
     if (ret < 0) {
-        ret = ERROR_FAIL;
         fifo = NULL;
-        goto out;
+        goto out_close;
     }
 
     ret = mkfifo(fifo, 0600);
     if (ret < 0) {
-        ret = ERROR_FAIL;
-        goto out;
+        goto out_close;
     }
 
     diskpath = libxl_device_disk_local_attach(ctx, disk);
     if (!diskpath) {
-        ret = ERROR_FAIL;
-        goto out;
+        goto out_close;
     }
 
-    args = make_bootloader_args(ctx, info, domid, fifo, diskpath);
+    args = make_bootloader_args(&gc, info, domid, fifo, diskpath);
     if (args == NULL) {
-        ret = ERROR_NOMEM;
-        goto out;
+        rc = ERROR_NOMEM;
+        goto out_close;
     }
 
     /*
@@ -381,17 +380,15 @@ int libxl_run_bootloader(libxl_ctx *ctx,
                                &dom_console_slave_tty_path[0],
                                sizeof(dom_console_slave_tty_path));
     if (ret < 0) {
-        ret = ERROR_FAIL;
-        goto out;
+        goto out_close;
     }
 
-    dom_console_xs_path = libxl_sprintf(ctx, "%s/serial/0/tty", 
libxl_xs_get_dompath(ctx, domid));
-    libxl_xs_write(ctx, XBT_NULL, dom_console_xs_path, "%s", 
dom_console_slave_tty_path);
+    dom_console_xs_path = libxl_sprintf(&gc, "%s/serial/0/tty", 
libxl_xs_get_dompath(&gc, domid));
+    libxl_xs_write(&gc, XBT_NULL, dom_console_xs_path, "%s", 
dom_console_slave_tty_path);
 
     pid = fork_exec_bootloader(&bootloader_fd, (char *)info->u.pv.bootloader, 
args);
     if (pid < 0) {
-        ret = ERROR_FAIL;
-        goto out;
+        goto out_close;
     }
 
     while (1) {
@@ -402,30 +399,27 @@ int libxl_run_bootloader(libxl_ctx *ctx,
         if (errno == EINTR)
             continue;
 
-        ret = ERROR_FAIL;
-        goto out;
+        goto out_close;
     }
 
     fcntl(fifo_fd, F_SETFL, O_NDELAY);
 
-    blout = bootloader_interact(ctx, xenconsoled_fd, bootloader_fd, fifo_fd);
+    blout = bootloader_interact(&gc, xenconsoled_fd, bootloader_fd, fifo_fd);
     if (blout == NULL) {
-        ret = ERROR_FAIL;
-        goto out;
+        goto out_close;
     }
 
     pid = waitpid(pid, &blrc, 0);
     if (pid == -1 || (pid > 0 && WIFEXITED(blrc) && WEXITSTATUS(blrc) != 0)) {
-        ret = ERROR_FAIL;
-        goto out;
+        goto out_close;
     }
 
     libxl_device_disk_local_detach(ctx, disk);
 
     parse_bootloader_result(ctx, info, blout);
 
-    ret = 0;
-out:
+    rc = 0;
+out_close:
     if (fifo_fd > -1)
         close(fifo_fd);
     if (bootloader_fd > -1)
@@ -444,6 +438,8 @@ out:
 
     free(args);
 
-    return ret;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
diff -r 7b144fe8c528 tools/libxl/libxl_device.c
--- a/tools/libxl/libxl_device.c        Wed Aug 11 14:39:44 2010 +0100
+++ b/tools/libxl/libxl_device.c        Thu Aug 12 15:22:56 2010 +0100
@@ -42,20 +42,24 @@ static const char *string_of_kinds[] = {
 int libxl_device_generic_add(libxl_ctx *ctx, libxl_device *device,
                              char **bents, char **fents)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *dom_path_backend, *dom_path, *frontend_path, *backend_path;
     xs_transaction_t t;
     struct xs_permissions frontend_perms[2];
     struct xs_permissions backend_perms[2];
+    int rc;
 
-    if (!is_valid_device_kind(device->backend_kind) || 
!is_valid_device_kind(device->kind))
-        return ERROR_INVAL;
+    if (!is_valid_device_kind(device->backend_kind) || 
!is_valid_device_kind(device->kind)) {
+        rc = ERROR_INVAL;
+        goto out;
+    }
 
-    dom_path_backend = libxl_xs_get_dompath(ctx, device->backend_domid);
-    dom_path = libxl_xs_get_dompath(ctx, device->domid);
+    dom_path_backend = libxl_xs_get_dompath(&gc, device->backend_domid);
+    dom_path = libxl_xs_get_dompath(&gc, device->domid);
 
-    frontend_path = libxl_sprintf(ctx, "%s/device/%s/%d",
+    frontend_path = libxl_sprintf(&gc, "%s/device/%s/%d",
                                   dom_path, string_of_kinds[device->kind], 
device->devid);
-    backend_path = libxl_sprintf(ctx, "%s/backend/%s/%u/%d",
+    backend_path = libxl_sprintf(&gc, "%s/backend/%s/%u/%d",
                                  dom_path_backend, 
string_of_kinds[device->backend_kind], device->domid, device->devid);
 
     frontend_perms[0].id = device->domid;
@@ -81,12 +85,12 @@ retry_transaction:
     xs_mkdir(ctx->xsh, t, backend_path);
     xs_set_permissions(ctx->xsh, t, backend_path, backend_perms, 
ARRAY_SIZE(backend_perms));
 
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/backend", frontend_path), 
backend_path, strlen(backend_path));
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/frontend", backend_path), 
frontend_path, strlen(frontend_path));
+    xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/backend", frontend_path), 
backend_path, strlen(backend_path));
+    xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/frontend", backend_path), 
frontend_path, strlen(frontend_path));
 
     /* and write frontend kvs and backend kvs */
-    libxl_xs_writev(ctx, t, backend_path, bents);
-    libxl_xs_writev(ctx, t, frontend_path, fents);
+    libxl_xs_writev(&gc, t, backend_path, bents);
+    libxl_xs_writev(&gc, t, frontend_path, fents);
 
     if (!xs_transaction_end(ctx->xsh, t, 0)) {
         if (errno == EAGAIN)
@@ -94,7 +98,10 @@ retry_transaction:
         else
             XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs transaction failed");
     }
-    return 0;
+    rc = 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 char *device_disk_string_of_phystype(libxl_disk_phystype phystype)
@@ -221,35 +228,43 @@ int device_disk_dev_number(char *virtpat
 
 int libxl_device_destroy(libxl_ctx *ctx, char *be_path, int force)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     xs_transaction_t t;
-    char *state_path = libxl_sprintf(ctx, "%s/state", be_path);
-    char *state = libxl_xs_read(ctx, XBT_NULL, state_path);
+    char *state_path = libxl_sprintf(&gc, "%s/state", be_path);
+    char *state = libxl_xs_read(&gc, XBT_NULL, state_path);
+    int rc = 0;
+
     if (!state)
-        return 0;
+        goto out;
     if (atoi(state) != 4) {
         xs_rm(ctx->xsh, XBT_NULL, be_path);
-        return 0;
+        goto out;
     }
 
 retry_transaction:
     t = xs_transaction_start(ctx->xsh);
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/online", be_path), "0", 
strlen("0"));
+    xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/online", be_path), "0", 
strlen("0"));
     xs_write(ctx->xsh, t, state_path, "5", strlen("5"));
     if (!xs_transaction_end(ctx->xsh, t, 0)) {
         if (errno == EAGAIN)
             goto retry_transaction;
-        else
-            return -1;
+        else {
+            rc = -1;
+            goto out;
+        }
     }
     if (!force) {
         xs_watch(ctx->xsh, state_path, be_path);
-        return 1;
-    } else
-        return 0;
+        rc = 1;
+    }
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 int wait_for_dev_destroy(libxl_ctx *ctx, struct timeval *tv)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     int nfds, rc;
     unsigned int n;
     fd_set rfds;
@@ -262,57 +277,52 @@ int wait_for_dev_destroy(libxl_ctx *ctx,
     if (select(nfds, &rfds, NULL, NULL, tv) > 0) {
         l1 = xs_read_watch(ctx->xsh, &n);
         if (l1 != NULL) {
-            char *state = libxl_xs_read(ctx, XBT_NULL, l1[XS_WATCH_PATH]);
+            char *state = libxl_xs_read(&gc, XBT_NULL, l1[XS_WATCH_PATH]);
             if (!state || atoi(state) == 6) {
                 xs_unwatch(ctx->xsh, l1[0], l1[1]);
                 xs_rm(ctx->xsh, XBT_NULL, l1[XS_WATCH_TOKEN]);
                 XL_LOG(ctx, XL_LOG_DEBUG, "Destroyed device backend at %s", 
l1[XS_WATCH_TOKEN]);
                 rc = 0;
             }
-            libxl_free(ctx, state);
             free(l1);
         }
     }
+    libxl_free_all(&gc);
     return rc;
 }
 
 int libxl_devices_destroy(libxl_ctx *ctx, uint32_t domid, int force)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *path, *be_path, *fe_path;
     unsigned int num1, num2;
     char **l1 = NULL, **l2 = NULL;
     int i, j, n = 0, n_watches = 0;
     flexarray_t *toremove;
-    libxl_ctx clone;
-
-    if (libxl_ctx_init(&clone, LIBXL_VERSION, ctx->lg)) {
-        return -1;
-    }
 
     toremove = flexarray_make(16, 1);
-    path = libxl_sprintf(&clone, "/local/domain/%d/device", domid);
-    l1 = libxl_xs_directory(&clone, XBT_NULL, path, &num1);
+    path = libxl_sprintf(&gc, "/local/domain/%d/device", domid);
+    l1 = libxl_xs_directory(&gc, XBT_NULL, path, &num1);
     if (!l1) {
-        XL_LOG(&clone, XL_LOG_ERROR, "%s is empty", path);
-        libxl_ctx_free(&clone);
-        return 0;
+        XL_LOG(ctx, XL_LOG_ERROR, "%s is empty", path);
+        goto out;
     }
     for (i = 0; i < num1; i++) {
         if (!strcmp("vfs", l1[i]))
             continue;
-        path = libxl_sprintf(&clone, "/local/domain/%d/device/%s", domid, 
l1[i]);
-        l2 = libxl_xs_directory(&clone, XBT_NULL, path, &num2);
+        path = libxl_sprintf(&gc, "/local/domain/%d/device/%s", domid, l1[i]);
+        l2 = libxl_xs_directory(&gc, XBT_NULL, path, &num2);
         if (!l2)
             continue;
         for (j = 0; j < num2; j++) {
-            fe_path = libxl_sprintf(&clone, "/local/domain/%d/device/%s/%s", 
domid, l1[i], l2[j]);
-            be_path = libxl_xs_read(&clone, XBT_NULL, libxl_sprintf(&clone, 
"%s/backend", fe_path));
+            fe_path = libxl_sprintf(&gc, "/local/domain/%d/device/%s/%s", 
domid, l1[i], l2[j]);
+            be_path = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/backend", fe_path));
             if (be_path != NULL) {
-                if (libxl_device_destroy(&clone, be_path, force) > 0)
+                if (libxl_device_destroy(ctx, be_path, force) > 0)
                     n_watches++;
-                flexarray_set(toremove, n++, libxl_dirname(&clone, be_path));
+                flexarray_set(toremove, n++, libxl_dirname(&gc, be_path));
             } else {
-                xs_rm(clone.xsh, XBT_NULL, path);
+                xs_rm(ctx->xsh, XBT_NULL, path);
             }
         }
     }
@@ -326,7 +336,7 @@ int libxl_devices_destroy(libxl_ctx *ctx
         tv.tv_sec = LIBXL_DESTROY_TIMEOUT;
         tv.tv_usec = 0;
         while (n_watches > 0) {
-            if (wait_for_dev_destroy(&clone, &tv)) {
+            if (wait_for_dev_destroy(ctx, &tv)) {
                 break;
             } else {
                 n_watches--;
@@ -335,46 +345,44 @@ int libxl_devices_destroy(libxl_ctx *ctx
     }
     for (i = 0; i < n; i++) {
         flexarray_get(toremove, i, (void**) &path);
-        xs_rm(clone.xsh, XBT_NULL, path);
+        xs_rm(ctx->xsh, XBT_NULL, path);
     }
+out:
     flexarray_free(toremove);
-    libxl_ctx_free(&clone);
+    libxl_free_all(&gc);
     return 0;
 }
 
 int libxl_device_del(libxl_ctx *ctx, libxl_device *dev, int wait)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *dom_path_backend, *backend_path;
     int rc;
-    libxl_ctx clone;
-
-    if (libxl_ctx_init(&clone, LIBXL_VERSION, ctx->lg)) {
-        return -1;
-    }
 
     /* Create strings */
-    dom_path_backend    = libxl_xs_get_dompath(&clone, dev->backend_domid);
-    backend_path        = libxl_sprintf(&clone, "%s/backend/%s/%u/%d",
+    dom_path_backend    = libxl_xs_get_dompath(&gc, dev->backend_domid);
+    backend_path        = libxl_sprintf(&gc, "%s/backend/%s/%u/%d",
                                     dom_path_backend, 
                                     string_of_kinds[dev->backend_kind], 
                                     dev->domid, dev->devid);
-    libxl_free(&clone, dom_path_backend);
-
-    rc = libxl_device_destroy(&clone, backend_path, !wait);
+    rc = libxl_device_destroy(ctx, backend_path, !wait);
     if (rc == -1) {
-        libxl_ctx_free(&clone);
-        return ERROR_FAIL;
+        rc = ERROR_FAIL;
+        goto out;
     }
 
     if (wait) {
         struct timeval tv;
         tv.tv_sec = LIBXL_DESTROY_TIMEOUT;
         tv.tv_usec = 0;
-        (void)wait_for_dev_destroy(&clone, &tv);
+        (void)wait_for_dev_destroy(ctx, &tv);
     }
 
-    libxl_ctx_free(&clone);
-    return 0;
+    rc = 0;
+
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 int libxl_wait_for_device_model(libxl_ctx *ctx,
@@ -385,6 +393,7 @@ int libxl_wait_for_device_model(libxl_ct
                                                       void *userdata),
                                 void *check_callback_userdata)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *path;
     char *p;
     unsigned int len;
@@ -397,7 +406,7 @@ int libxl_wait_for_device_model(libxl_ct
     char **l = NULL;
 
     xsh = xs_daemon_open();
-    path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
+    path = libxl_sprintf(&gc, "/local/domain/0/device-model/%d/state", domid);
     xs_watch(xsh, path, path);
     tv.tv_sec = LIBXL_DEVICE_MODEL_START_TIMEOUT;
     tv.tv_usec = 0;
@@ -419,6 +428,7 @@ int libxl_wait_for_device_model(libxl_ct
         free(p);
         xs_unwatch(xsh, path, path);
         xs_daemon_close(xsh);
+        libxl_free_all(&gc);
         return rc;
 again:
         free(p);
@@ -436,15 +446,17 @@ again:
     xs_unwatch(xsh, path, path);
     xs_daemon_close(xsh);
     XL_LOG(ctx, XL_LOG_ERROR, "Device Model not ready");
+    libxl_free_all(&gc);
     return -1;
 }
 
 int libxl_wait_for_backend(libxl_ctx *ctx, char *be_path, char *state)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     int watchdog = 100;
     unsigned int len;
     char *p;
-    char *path = libxl_sprintf(ctx, "%s/state", be_path);
+    char *path = libxl_sprintf(&gc, "%s/state", be_path);
 
     while (watchdog > 0) {
         p = xs_read(ctx->xsh, XBT_NULL, path, &len);
@@ -467,6 +479,7 @@ int libxl_wait_for_backend(libxl_ctx *ct
         }
     }
     XL_LOG(ctx, XL_LOG_ERROR, "Backend %s not ready", be_path);
+    libxl_free_all(&gc);
     return -1;
 }
 
diff -r 7b144fe8c528 tools/libxl/libxl_dom.c
--- a/tools/libxl/libxl_dom.c   Wed Aug 11 14:39:44 2010 +0100
+++ b/tools/libxl/libxl_dom.c   Thu Aug 12 15:22:56 2010 +0100
@@ -86,6 +86,7 @@ int build_post(libxl_ctx *ctx, uint32_t 
                libxl_domain_build_info *info, libxl_domain_build_state *state,
                char **vms_ents, char **local_ents)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *dom_path, *vm_path;
     xs_transaction_t t;
     char **ents;
@@ -95,44 +96,43 @@ int build_post(libxl_ctx *ctx, uint32_t 
     xc_cpuid_apply_policy(ctx->xch, domid);
 #endif
 
-    ents = libxl_calloc(ctx, 12 + (info->max_vcpus * 2) + 2, sizeof(char *));
+    ents = libxl_calloc(&gc, 12 + (info->max_vcpus * 2) + 2, sizeof(char *));
     ents[0] = "memory/static-max";
-    ents[1] = libxl_sprintf(ctx, "%d", info->max_memkb);
+    ents[1] = libxl_sprintf(&gc, "%d", info->max_memkb);
     ents[2] = "memory/target";
-    ents[3] = libxl_sprintf(ctx, "%d", info->target_memkb);
+    ents[3] = libxl_sprintf(&gc, "%d", info->target_memkb);
     ents[4] = "memory/videoram";
-    ents[5] = libxl_sprintf(ctx, "%d", info->video_memkb);
+    ents[5] = libxl_sprintf(&gc, "%d", info->video_memkb);
     ents[6] = "domid";
-    ents[7] = libxl_sprintf(ctx, "%d", domid);
+    ents[7] = libxl_sprintf(&gc, "%d", domid);
     ents[8] = "store/port";
-    ents[9] = libxl_sprintf(ctx, "%"PRIu32, state->store_port);
+    ents[9] = libxl_sprintf(&gc, "%"PRIu32, state->store_port);
     ents[10] = "store/ring-ref";
-    ents[11] = libxl_sprintf(ctx, "%lu", state->store_mfn);
+    ents[11] = libxl_sprintf(&gc, "%lu", state->store_mfn);
     for (i = 0; i < info->max_vcpus; i++) {
-        ents[12+(i*2)]   = libxl_sprintf(ctx, "cpu/%d/availability", i);
+        ents[12+(i*2)]   = libxl_sprintf(&gc, "cpu/%d/availability", i);
         ents[12+(i*2)+1] = (i && info->cur_vcpus && !(info->cur_vcpus & (1 << 
i)))
                             ? "offline" : "online";
     }
 
-    dom_path = libxl_xs_get_dompath(ctx, domid);
+    dom_path = libxl_xs_get_dompath(&gc, domid);
     if (!dom_path)
         return ERROR_FAIL;
 
-    vm_path = xs_read(ctx->xsh, XBT_NULL, libxl_sprintf(ctx, "%s/vm", 
dom_path), NULL);
+    vm_path = xs_read(ctx->xsh, XBT_NULL, libxl_sprintf(&gc, "%s/vm", 
dom_path), NULL);
 retry_transaction:
     t = xs_transaction_start(ctx->xsh);
 
-    libxl_xs_writev(ctx, t, dom_path, ents);
-    libxl_xs_writev(ctx, t, dom_path, local_ents);
-    libxl_xs_writev(ctx, t, vm_path, vms_ents);
+    libxl_xs_writev(&gc, t, dom_path, ents);
+    libxl_xs_writev(&gc, t, dom_path, local_ents);
+    libxl_xs_writev(&gc, t, vm_path, vms_ents);
 
     if (!xs_transaction_end(ctx->xsh, t, 0))
         if (errno == EAGAIN)
             goto retry_transaction;
     xs_introduce_domain(ctx->xsh, domid, state->store_mfn, state->store_port);
     free(vm_path);
-    libxl_free(ctx, ents);
-    libxl_free(ctx, dom_path);
+    libxl_free_all(&gc);
     return 0;
 }
 
@@ -218,30 +218,35 @@ out:
 int build_hvm(libxl_ctx *ctx, uint32_t domid,
               libxl_domain_build_info *info, libxl_domain_build_state *state)
 {
-    int ret;
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
+    int ret, rc = ERROR_INVAL;
 
     if (info->kernel.mapped) {
         XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "build_hvm kernel cannot be mmapped");
-        return ERROR_INVAL;
+        goto out;
     }
 
+    rc = ERROR_FAIL;
     ret = xc_hvm_build_target_mem(
         ctx->xch,
         domid,
         (info->max_memkb - info->video_memkb) / 1024,
         (info->target_memkb - info->video_memkb) / 1024,
-        libxl_abs_path(ctx, (char *)info->kernel.path,
+        libxl_abs_path(&gc, (char *)info->kernel.path,
                        libxl_xenfirmwaredir_path()));
     if (ret) {
         XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "hvm building failed");
-        return ERROR_FAIL;
+        goto out;
     }
     ret = hvm_build_set_params(ctx->xch, domid, info, state->store_port,
                                &state->store_mfn, state->console_port, 
&state->console_mfn);
     if (ret) {
         XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "hvm build set params failed");
-        return ERROR_FAIL;
+        goto out;
     }
+    rc = 0;
+out:
+    libxl_free_all(&gc);
     return 0;
 }
 
@@ -263,7 +268,7 @@ int restore_common(libxl_ctx *ctx, uint3
 }
 
 struct suspendinfo {
-    libxl_ctx *ctx;
+    libxl_gc *gc;
     int xce; /* event channel handle */
     int suspend_eventchn;
     int domid;
@@ -295,39 +300,40 @@ static int core_suspend_callback(void *d
     int ret;
     char *path, *state = "suspend";
     int watchdog = 60;
+    libxl_ctx *ctx = libxl_gc_owner(si->gc);
 
     if (si->hvm)
-        xc_get_hvm_param(si->ctx->xch, si->domid, HVM_PARAM_ACPI_S_STATE, 
&s_state);
+        xc_get_hvm_param(ctx->xch, si->domid, HVM_PARAM_ACPI_S_STATE, 
&s_state);
     if ((s_state == 0) && (si->suspend_eventchn >= 0)) {
         ret = xc_evtchn_notify(si->xce, si->suspend_eventchn);
         if (ret < 0) {
-            XL_LOG(si->ctx, XL_LOG_ERROR, "xc_evtchn_notify failed ret=%d", 
ret);
+            XL_LOG(ctx, XL_LOG_ERROR, "xc_evtchn_notify failed ret=%d", ret);
             return 0;
         }
-        ret = xc_await_suspend(si->ctx->xch, si->xce, si->suspend_eventchn);
+        ret = xc_await_suspend(ctx->xch, si->xce, si->suspend_eventchn);
         if (ret < 0) {
-            XL_LOG(si->ctx, XL_LOG_ERROR, "xc_await_suspend failed ret=%d", 
ret);
+            XL_LOG(ctx, XL_LOG_ERROR, "xc_await_suspend failed ret=%d", ret);
             return 0;
         }
         return 1;
     }
-    path = libxl_sprintf(si->ctx, "%s/control/shutdown", 
libxl_xs_get_dompath(si->ctx, si->domid));
-    libxl_xs_write(si->ctx, XBT_NULL, path, "suspend");
+    path = libxl_sprintf(si->gc, "%s/control/shutdown", 
libxl_xs_get_dompath(si->gc, si->domid));
+    libxl_xs_write(si->gc, XBT_NULL, path, "suspend");
     if (si->hvm) {
         unsigned long hvm_pvdrv, hvm_s_state;
-        xc_get_hvm_param(si->ctx->xch, si->domid, HVM_PARAM_CALLBACK_IRQ, 
&hvm_pvdrv);
-        xc_get_hvm_param(si->ctx->xch, si->domid, HVM_PARAM_ACPI_S_STATE, 
&hvm_s_state);
+        xc_get_hvm_param(ctx->xch, si->domid, HVM_PARAM_CALLBACK_IRQ, 
&hvm_pvdrv);
+        xc_get_hvm_param(ctx->xch, si->domid, HVM_PARAM_ACPI_S_STATE, 
&hvm_s_state);
         if (!hvm_pvdrv || hvm_s_state) {
-            XL_LOG(si->ctx, XL_LOG_DEBUG, "Calling xc_domain_shutdown on the 
domain");
-            xc_domain_shutdown(si->ctx->xch, si->domid, SHUTDOWN_suspend);
+            XL_LOG(ctx, XL_LOG_DEBUG, "Calling xc_domain_shutdown on the 
domain");
+            xc_domain_shutdown(ctx->xch, si->domid, SHUTDOWN_suspend);
         }
     }
-    XL_LOG(si->ctx, XL_LOG_DEBUG, "wait for the guest to suspend");
+    XL_LOG(ctx, XL_LOG_DEBUG, "wait for the guest to suspend");
     while (!strcmp(state, "suspend") && watchdog > 0) {
         xc_domaininfo_t info;
 
         usleep(100000);
-        ret = xc_domain_getinfolist(si->ctx->xch, si->domid, 1, &info);
+        ret = xc_domain_getinfolist(ctx->xch, si->domid, 1, &info);
         if (ret == 1 && info.domain == si->domid && info.flags & 
XEN_DOMINF_shutdown) {
             int shutdown_reason;
 
@@ -335,12 +341,12 @@ static int core_suspend_callback(void *d
             if (shutdown_reason == SHUTDOWN_suspend)
                 return 1;
         }
-        state = libxl_xs_read(si->ctx, XBT_NULL, path);
+        state = libxl_xs_read(si->gc, XBT_NULL, path);
         watchdog--;
     }
     if (!strcmp(state, "suspend")) {
-        XL_LOG(si->ctx, XL_LOG_ERROR, "guest didn't suspend in time");
-        libxl_xs_write(si->ctx, XBT_NULL, path, "");
+        XL_LOG(ctx, XL_LOG_ERROR, "guest didn't suspend in time");
+        libxl_xs_write(si->gc, XBT_NULL, path, "");
     }
     return 1;
 }
@@ -348,10 +354,12 @@ static int core_suspend_callback(void *d
 int core_suspend(libxl_ctx *ctx, uint32_t domid, int fd,
                int hvm, int live, int debug)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     int flags;
     int port;
     struct save_callbacks callbacks;
     struct suspendinfo si;
+    int rc = ERROR_FAIL;
 
     flags = (live) ? XCFLAGS_LIVE : 0
           | (debug) ? XCFLAGS_DEBUG : 0
@@ -360,12 +368,12 @@ int core_suspend(libxl_ctx *ctx, uint32_
     si.domid = domid;
     si.flags = flags;
     si.hvm = hvm;
-    si.ctx = ctx;
+    si.gc = &gc;
     si.suspend_eventchn = -1;
 
     si.xce = xc_evtchn_open();
     if (si.xce < 0)
-        return ERROR_FAIL;
+        goto out;
 
     if (si.xce > 0) {
         port = xs_suspend_evtchn_port(si.domid);
@@ -373,7 +381,7 @@ int core_suspend(libxl_ctx *ctx, uint32_
         if (port < 0) {
             XL_LOG(ctx, XL_LOG_WARNING, "Failed to get the suspend evtchn 
port");
         } else {
-            si.suspend_eventchn = xc_suspend_evtchn_init(si.ctx->xch, si.xce, 
si.domid, port);
+            si.suspend_eventchn = xc_suspend_evtchn_init(ctx->xch, si.xce, 
si.domid, port);
 
             if (si.suspend_eventchn < 0)
                 XL_LOG(ctx, XL_LOG_WARNING, "Suspend event channel 
initialization failed");
@@ -389,21 +397,24 @@ int core_suspend(libxl_ctx *ctx, uint32_
                    &core_suspend_switch_qemu_logdirty);
 
     if (si.suspend_eventchn > 0)
-        xc_suspend_evtchn_release(si.ctx->xch, si.xce, domid, 
si.suspend_eventchn);
+        xc_suspend_evtchn_release(ctx->xch, si.xce, domid, 
si.suspend_eventchn);
     if (si.xce > 0)
         xc_evtchn_close(si.xce);
 
-    return 0;
+    rc = 0;
+out:
+    return rc;
 }
 
 int save_device_model(libxl_ctx *ctx, uint32_t domid, int fd)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     int fd2, c;
     char buf[1024];
-    char *filename = libxl_sprintf(ctx, "/var/lib/xen/qemu-save.%d", domid);
+    char *filename = libxl_sprintf(&gc, "/var/lib/xen/qemu-save.%d", domid);
 
     XL_LOG(ctx, XL_LOG_DEBUG, "Saving device model state to %s", filename);
-    libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, 
"/local/domain/0/device-model/%d/command", domid), "save");
+    libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, 
"/local/domain/0/device-model/%d/command", domid), "save");
     libxl_wait_for_device_model(ctx, domid, "paused", NULL, NULL);
 
     c = libxl_write_exactly(ctx, fd, QEMU_SIGNATURE, strlen(QEMU_SIGNATURE),
@@ -415,27 +426,42 @@ int save_device_model(libxl_ctx *ctx, ui
         if (c < 0) {
             if (errno == EINTR)
                 continue;
+            libxl_free_all(&gc);
             return errno;
         }
         c = libxl_write_exactly(
             ctx, fd, buf, c, "saved-state file", "qemu state");
-        if (c)
+        if (c) {
+            libxl_free_all(&gc);
             return c;
+        }
     }
     close(fd2);
     unlink(filename);
+    libxl_free_all(&gc);
     return 0;
 }
 
-char *libxl_uuid2string(libxl_ctx *ctx, const libxl_uuid uuid) {
-    char *s = string_of_uuid(ctx, uuid);
-    if (!s) XL_LOG(ctx, XL_LOG_ERROR, "cannot allocate for uuid");
-    return s;
+char *libxl_uuid2string(libxl_ctx *ctx, const libxl_uuid uuid)
+{
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
+    char *s = string_of_uuid(&gc, uuid);
+    char *ret;
+    if (!s) {
+        XL_LOG(ctx, XL_LOG_ERROR, "cannot allocate for uuid");
+        ret = NULL;
+    }else{
+        ret = strdup(s);
+    }
+    libxl_free_all(&gc);
+    return ret;
 }
 
-static const char *userdata_path(libxl_ctx *ctx, uint32_t domid,
+static const char *userdata_path(libxl_gc *gc, uint32_t domid,
                                       const char *userdata_userid,
-                                      const char *wh) {
+                                      const char *wh)
+{
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     char *path, *uuid_string;
     libxl_dominfo info;
     int rc;
@@ -446,9 +472,9 @@ static const char *userdata_path(libxl_c
                      " for domain %"PRIu32, domid);
         return NULL;
     }
-    uuid_string = string_of_uuid(ctx, info.uuid);
+    uuid_string = string_of_uuid(gc, info.uuid);
 
-    path = libxl_sprintf(ctx, "/var/lib/xen/"
+    path = libxl_sprintf(gc, "/var/lib/xen/"
                          "userdata-%s.%s.%s",
                          wh, uuid_string, userdata_userid);
     if (!path)
@@ -467,94 +493,132 @@ static int userdata_delete(libxl_ctx *ct
     return 0;
 }
 
-void libxl__userdata_destroyall(libxl_ctx *ctx, uint32_t domid) {
+void libxl__userdata_destroyall(libxl_ctx *ctx, uint32_t domid)
+{
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     const char *pattern;
     glob_t gl;
     int r, i;
 
-    pattern = userdata_path(ctx, domid, "*", "?");
-    if (!pattern) return;
+    pattern = userdata_path(&gc, domid, "*", "?");
+    if (!pattern)
+        goto out;
 
     gl.gl_pathc = 0;
     gl.gl_pathv = 0;
     gl.gl_offs = 0;
     r = glob(pattern, GLOB_ERR|GLOB_NOSORT|GLOB_MARK, 0, &gl);
-    if (r == GLOB_NOMATCH) return;
-    if (r) XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "glob failed for %s", pattern);
+    if (r == GLOB_NOMATCH)
+        goto out;
+    if (r)
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "glob failed for %s", pattern);
 
     for (i=0; i<gl.gl_pathc; i++) {
         userdata_delete(ctx, gl.gl_pathv[i]);
     }
     globfree(&gl);
+out:
+    libxl_free_all(&gc);
 }
 
 int libxl_userdata_store(libxl_ctx *ctx, uint32_t domid,
                               const char *userdata_userid,
-                              const uint8_t *data, int datalen) {
+                              const uint8_t *data, int datalen)
+{
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     const char *filename;
     const char *newfilename;
-    int e;
+    int e, rc;
     int fd = -1;
-    FILE *f = 0;
+    FILE *f = NULL;
     size_t rs;
 
-    filename = userdata_path(ctx, domid, userdata_userid, "d");
-    if (!filename) return ERROR_NOMEM;
+    filename = userdata_path(&gc, domid, userdata_userid, "d");
+    if (!filename) {
+        rc = ERROR_NOMEM;
+        goto out;
+    }
 
-    if (!datalen)
-        return userdata_delete(ctx, filename);
+    if (!datalen) {
+        rc = userdata_delete(ctx, filename);
+        goto out;
+    }
 
-    newfilename = userdata_path(ctx, domid, userdata_userid, "n");
-    if (!newfilename) return ERROR_NOMEM;
+    newfilename = userdata_path(&gc, domid, userdata_userid, "n");
+    if (!newfilename) {
+        rc = ERROR_NOMEM;
+        goto out;
+    }
+
+    rc = ERROR_FAIL;
 
     fd= open(newfilename, O_RDWR|O_CREAT|O_TRUNC, 0600);
-    if (fd<0) goto xe;
+    if (fd<0)
+        goto err;
 
     f= fdopen(fd, "wb");
-    if (!f) goto xe;
+    if (!f)
+        goto err;
     fd = -1;
 
     rs = fwrite(data, 1, datalen, f);
-    if (rs != datalen) { assert(ferror(f)); goto xe; }
+    if (rs != datalen) { 
+        assert(ferror(f));
+        goto err; 
+    }
 
-    if (fclose(f)) goto xe;
+    if (fclose(f))
+        goto err;
     f = 0;
 
-    if (rename(newfilename,filename)) goto xe;
+    if (rename(newfilename,filename))
+        goto err;
 
-    return 0;
+    rc = 0;
 
- xe:
+err:
     e = errno;
     if (f) fclose(f);
     if (fd>=0) close(fd);
 
     errno = e;
-    XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot write %s for %s",
+    if ( rc )
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot write %s for %s",
                  newfilename, filename);
-    return ERROR_FAIL;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 int libxl_userdata_retrieve(libxl_ctx *ctx, uint32_t domid,
                                  const char *userdata_userid,
-                                 uint8_t **data_r, int *datalen_r) {
+                                 uint8_t **data_r, int *datalen_r)
+{
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     const char *filename;
-    int e;
+    int e, rc;
     int datalen = 0;
     void *data = 0;
 
-    filename = userdata_path(ctx, domid, userdata_userid, "d");
-    if (!filename) return ERROR_NOMEM;
+    filename = userdata_path(&gc, domid, userdata_userid, "d");
+    if (!filename) {
+        rc = ERROR_NOMEM;
+        goto out;
+    }
 
     e = libxl_read_file_contents(ctx, filename, data_r ? &data : 0, &datalen);
 
     if (!e && !datalen) {
         XL_LOG(ctx, XL_LOG_ERROR, "userdata file %s is empty", filename);
         if (data_r) assert(!*data_r);
-        return ERROR_FAIL;
+        rc = ERROR_FAIL;
+        goto out;
     }
 
     if (data_r) *data_r = data;
     if (datalen_r) *datalen_r = datalen;
-    return 0;
+    rc = 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
diff -r 7b144fe8c528 tools/libxl/libxl_exec.c
--- a/tools/libxl/libxl_exec.c  Wed Aug 11 14:39:44 2010 +0100
+++ b/tools/libxl/libxl_exec.c  Thu Aug 12 15:22:56 2010 +0100
@@ -100,7 +100,7 @@ int libxl_spawn_spawn(libxl_ctx *ctx,
     libxl_spawn_starting *for_spawn = starting->for_spawn;
 
     if (for_spawn) {
-        for_spawn->what = libxl_strdup(ctx, what);
+        for_spawn->what = strdup(what);
         if (!for_spawn->what) return ERROR_NOMEM;
     }
 
@@ -140,10 +140,12 @@ static void report_spawn_intermediate_st
                                  int status)
 {
     if (!WIFEXITED(status)) {
+        char *intermediate_what;
         /* intermediate process did the logging itself if it exited */
-        char *intermediate_what = libxl_sprintf(ctx,
-                          "%s intermediate process (startup monitor)",
-                          for_spawn->what);
+        if ( asprintf(&intermediate_what,
+                 "%s intermediate process (startup monitor)",
+                 for_spawn->what) < 0 )
+            intermediate_what = "intermediate process (startup monitor)";
         libxl_report_child_exitstatus(ctx, XL_LOG_ERROR, intermediate_what,
                                       for_spawn->intermediate, status);
     }
diff -r 7b144fe8c528 tools/libxl/libxl_internal.c
--- a/tools/libxl/libxl_internal.c      Wed Aug 11 14:39:44 2010 +0100
+++ b/tools/libxl/libxl_internal.c      Thu Aug 12 15:22:56 2010 +0100
@@ -28,7 +28,7 @@ int libxl_error_set(libxl_ctx *ctx, int 
     return 0;
 }
 
-int libxl_ptr_add(libxl_ctx *ctx, void *ptr)
+int libxl_ptr_add(libxl_gc *gc, void *ptr)
 {
     int i;
     void **re;
@@ -37,29 +37,29 @@ int libxl_ptr_add(libxl_ctx *ctx, void *
         return 0;
 
     /* fast case: we have space in the array for storing the pointer */
-    for (i = 0; i < ctx->alloc_maxsize; i++) {
-        if (!ctx->alloc_ptrs[i]) {
-            ctx->alloc_ptrs[i] = ptr;
+    for (i = 0; i < gc->alloc_maxsize; i++) {
+        if (!gc->alloc_ptrs[i]) {
+            gc->alloc_ptrs[i] = ptr;
             return 0;
         }
     }
     /* realloc alloc_ptrs manually with calloc/free/replace */
-    re = calloc(ctx->alloc_maxsize + 25, sizeof(void *));
+    re = calloc(gc->alloc_maxsize + 25, sizeof(void *));
     if (!re)
         return -1;
-    for (i = 0; i < ctx->alloc_maxsize; i++)
-        re[i] = ctx->alloc_ptrs[i];
+    for (i = 0; i < gc->alloc_maxsize; i++)
+        re[i] = gc->alloc_ptrs[i];
     /* assign the next pointer */
     re[i] = ptr;
 
     /* replace the old alloc_ptr */
-    free(ctx->alloc_ptrs);
-    ctx->alloc_ptrs = re;
-    ctx->alloc_maxsize += 25;
+    free(gc->alloc_ptrs);
+    gc->alloc_ptrs = re;
+    gc->alloc_maxsize += 25;
     return 0;
 }
 
-void libxl_free(libxl_ctx *ctx, void *ptr)
+void libxl_free(libxl_gc *gc, void *ptr)
 {
     int i;
 
@@ -67,9 +67,9 @@ void libxl_free(libxl_ctx *ctx, void *pt
         return;
 
     /* remove the pointer from the tracked ptrs */
-    for (i = 0; i < ctx->alloc_maxsize; i++) {
-        if (ctx->alloc_ptrs[i] == ptr) {
-            ctx->alloc_ptrs[i] = NULL;
+    for (i = 0; i < gc->alloc_maxsize; i++) {
+        if (gc->alloc_ptrs[i] == ptr) {
+            gc->alloc_ptrs[i] = NULL;
             free(ptr);
             return;
         }
@@ -78,43 +78,44 @@ void libxl_free(libxl_ctx *ctx, void *pt
     abort();
 }
 
-void libxl_free_all(libxl_ctx *ctx)
+void libxl_free_all(libxl_gc *gc)
 {
     void *ptr;
     int i;
 
-    for (i = 0; i < ctx->alloc_maxsize; i++) {
-        ptr = ctx->alloc_ptrs[i];
-        ctx->alloc_ptrs[i] = NULL;
+    for (i = 0; i < gc->alloc_maxsize; i++) {
+        ptr = gc->alloc_ptrs[i];
+        gc->alloc_ptrs[i] = NULL;
         free(ptr);
     }
+    free(gc->alloc_ptrs);
 }
 
-void *libxl_zalloc(libxl_ctx *ctx, int bytes)
+void *libxl_zalloc(libxl_gc *gc, int bytes)
 {
     void *ptr = calloc(bytes, 1);
     if (!ptr) {
-        libxl_error_set(ctx, ENOMEM);
+        libxl_error_set(libxl_gc_owner(gc), ENOMEM);
         return NULL;
     }
 
-    libxl_ptr_add(ctx, ptr);
+    libxl_ptr_add(gc, ptr);
     return ptr;
 }
 
-void *libxl_calloc(libxl_ctx *ctx, size_t nmemb, size_t size)
+void *libxl_calloc(libxl_gc *gc, size_t nmemb, size_t size)
 {
     void *ptr = calloc(nmemb, size);
     if (!ptr) {
-        libxl_error_set(ctx, ENOMEM);
+        libxl_error_set(libxl_gc_owner(gc), ENOMEM);
         return NULL;
     }
 
-    libxl_ptr_add(ctx, ptr);
+    libxl_ptr_add(gc, ptr);
     return ptr;
 }
 
-char *libxl_sprintf(libxl_ctx *ctx, const char *fmt, ...)
+char *libxl_sprintf(libxl_gc *gc, const char *fmt, ...)
 {
     char *s;
     va_list ap;
@@ -128,7 +129,7 @@ char *libxl_sprintf(libxl_ctx *ctx, cons
         return NULL;
     }
 
-    s = libxl_zalloc(ctx, ret + 1);
+    s = libxl_zalloc(gc, ret + 1);
     if (s) {
         va_start(ap, fmt);
         ret = vsnprintf(s, ret + 1, fmt, ap);
@@ -137,20 +138,20 @@ char *libxl_sprintf(libxl_ctx *ctx, cons
     return s;
 }
 
-char *libxl_strdup(libxl_ctx *ctx, const char *c)
+char *libxl_strdup(libxl_gc *gc, const char *c)
 {
     char *s = strdup(c);
 
     if (s)
-        libxl_ptr_add(ctx, s);
+        libxl_ptr_add(gc, s);
 
     return s;
 }
 
-char *libxl_dirname(libxl_ctx *ctx, const char *s)
+char *libxl_dirname(libxl_gc *gc, const char *s)
 {
     char *c;
-    char *ptr = libxl_strdup(ctx, s);
+    char *ptr = libxl_strdup(gc, s);
 
     c = strrchr(ptr, '/');
     if (!c)
@@ -196,10 +197,10 @@ void xl_log(libxl_ctx *ctx, xentoollog_l
     va_end(ap);
 }
 
-char *libxl_abs_path(libxl_ctx *ctx, char *s, const char *path)
+char *libxl_abs_path(libxl_gc *gc, char *s, const char *path)
 {
     if (!s || s[0] == '/')
         return s;
-    return libxl_sprintf(ctx, "%s/%s", path, s);
+    return libxl_sprintf(gc, "%s/%s", path, s);
 }
 
diff -r 7b144fe8c528 tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h      Wed Aug 11 14:39:44 2010 +0100
+++ b/tools/libxl/libxl_internal.h      Thu Aug 12 15:22:56 2010 +0100
@@ -114,24 +114,37 @@ typedef struct {
 
 _hidden int xs_writev(struct xs_handle *xsh, xs_transaction_t t, char *dir, 
char *kvs[]);
 
+typedef struct {
+    /* mini-GC */
+    int alloc_maxsize;
+    void **alloc_ptrs;
+    libxl_ctx *owner;
+} libxl_gc;
+
+#define LIBXL_INIT_GC(ctx) (libxl_gc){ .alloc_maxsize = 0, .alloc_ptrs = 0, 
.owner = ctx }
+static inline libxl_ctx *libxl_gc_owner(libxl_gc *gc)
+{
+    return gc->owner;
+}
+
 /* memory allocation tracking/helpers */
-_hidden int libxl_ptr_add(libxl_ctx *ctx, void *ptr);
-_hidden void libxl_free(libxl_ctx *ctx, void *ptr);
-_hidden void libxl_free_all(libxl_ctx *ctx);
-_hidden void *libxl_zalloc(libxl_ctx *ctx, int bytes);
-_hidden void *libxl_calloc(libxl_ctx *ctx, size_t nmemb, size_t size);
-_hidden char *libxl_sprintf(libxl_ctx *ctx, const char *fmt, ...) 
PRINTF_ATTRIBUTE(2, 3);
-_hidden char *libxl_strdup(libxl_ctx *ctx, const char *c);
-_hidden char *libxl_dirname(libxl_ctx *ctx, const char *s);
+_hidden int libxl_ptr_add(libxl_gc *gc, void *ptr);
+_hidden void libxl_free(libxl_gc *gc, void *ptr);
+_hidden void libxl_free_all(libxl_gc *gc);
+_hidden void *libxl_zalloc(libxl_gc *gc, int bytes);
+_hidden void *libxl_calloc(libxl_gc *gc, size_t nmemb, size_t size);
+_hidden char *libxl_sprintf(libxl_gc *gc, const char *fmt, ...) 
PRINTF_ATTRIBUTE(2, 3);
+_hidden char *libxl_strdup(libxl_gc *gc, const char *c);
+_hidden char *libxl_dirname(libxl_gc *gc, const char *s);
 
-_hidden char **libxl_xs_kvs_of_flexarray(libxl_ctx *ctx, flexarray_t *array, 
int length);
-_hidden int libxl_xs_writev(libxl_ctx *ctx, xs_transaction_t t,
+_hidden char **libxl_xs_kvs_of_flexarray(libxl_gc *gc, flexarray_t *array, int 
length);
+_hidden int libxl_xs_writev(libxl_gc *gc, xs_transaction_t t,
                     char *dir, char **kvs);
-_hidden int libxl_xs_write(libxl_ctx *ctx, xs_transaction_t t,
+_hidden int libxl_xs_write(libxl_gc *gc, xs_transaction_t t,
                    char *path, char *fmt, ...) PRINTF_ATTRIBUTE(4, 5);
-_hidden char *libxl_xs_get_dompath(libxl_ctx *ctx, uint32_t domid); // logs 
errs
-_hidden char *libxl_xs_read(libxl_ctx *ctx, xs_transaction_t t, char *path);
-_hidden char **libxl_xs_directory(libxl_ctx *ctx, xs_transaction_t t, char 
*path, unsigned int *nb);
+_hidden char *libxl_xs_get_dompath(libxl_gc *gc, uint32_t domid); // logs errs
+_hidden char *libxl_xs_read(libxl_gc *gc, xs_transaction_t t, char *path);
+_hidden char **libxl_xs_directory(libxl_gc *gc, xs_transaction_t t, char 
*path, unsigned int *nb);
 
 /* from xl_dom */
 _hidden int is_hvm(libxl_ctx *ctx, uint32_t domid);
@@ -175,8 +188,6 @@ _hidden int libxl_wait_for_device_model(
                                                       void *userdata),
                                 void *check_callback_userdata);
 _hidden int libxl_wait_for_backend(libxl_ctx *ctx, char *be_path, char *state);
-_hidden int libxl_device_pci_reset(libxl_ctx *ctx, unsigned int domain, 
unsigned int bus,
-                           unsigned int dev, unsigned int func);
 
 /* from xenguest (helper */
 _hidden int hvm_build_set_params(xc_interface *handle, uint32_t domid,
@@ -225,18 +236,17 @@ _hidden int libxl_spawn_check(libxl_ctx 
  /* low-level stuff, for synchronous subprocesses etc. */
 
 _hidden void libxl_exec(int stdinfd, int stdoutfd, int stderrfd, char *arg0, 
char **args); // logs errors, never returns
-_hidden void libxl_log_child_exitstatus(libxl_ctx *ctx,
+_hidden void libxl_log_child_exitstatus(libxl_gc *gc,
                                 const char *what, pid_t pid, int status);
 
-_hidden char *libxl_abs_path(libxl_ctx *ctx, char *s, const char *path);
+_hidden char *libxl_abs_path(libxl_gc *gc, char *s, const char *path);
 
 #define XL_LOG_DEBUG   XTL_DEBUG
 #define XL_LOG_INFO    XTL_INFO
 #define XL_LOG_WARNING XTL_WARN
 #define XL_LOG_ERROR   XTL_ERROR
 
-_hidden char *_libxl_domid_to_name(libxl_ctx *ctx, uint32_t domid);
-_hidden char *_libxl_poolid_to_name(libxl_ctx *ctx, uint32_t poolid);
+_hidden char *_libxl_domid_to_name(libxl_gc *gc, uint32_t domid);
+_hidden char *_libxl_poolid_to_name(libxl_gc *gc, uint32_t poolid);
 
 #endif
-
diff -r 7b144fe8c528 tools/libxl/libxl_pci.c
--- a/tools/libxl/libxl_pci.c   Wed Aug 11 14:39:44 2010 +0100
+++ b/tools/libxl/libxl_pci.c   Thu Aug 12 15:22:56 2010 +0100
@@ -195,8 +195,9 @@ parse_error:
     return ERROR_INVAL;
 }
 
-static int libxl_create_pci_backend(libxl_ctx *ctx, uint32_t domid, 
libxl_device_pci *pcidev, int num)
+static int libxl_create_pci_backend(libxl_gc *gc, uint32_t domid, 
libxl_device_pci *pcidev, int num)
 {
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     flexarray_t *front;
     flexarray_t *back;
     unsigned int boffset = 0;
@@ -222,56 +223,57 @@ static int libxl_create_pci_backend(libx
     device.kind = DEVICE_PCI;
 
     flexarray_set(back, boffset++, "frontend-id");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", domid));
+    flexarray_set(back, boffset++, libxl_sprintf(gc, "%d", domid));
     flexarray_set(back, boffset++, "online");
     flexarray_set(back, boffset++, "1");
     flexarray_set(back, boffset++, "state");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, libxl_sprintf(gc, "%d", 1));
     flexarray_set(back, boffset++, "domain");
-    flexarray_set(back, boffset++, _libxl_domid_to_name(ctx, domid));
+    flexarray_set(back, boffset++, _libxl_domid_to_name(gc, domid));
     for (i = 0; i < num; i++) {
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", i));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, 
pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", i));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, 
pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
+        flexarray_set(back, boffset++, libxl_sprintf(gc, "key-%d", i));
+        flexarray_set(back, boffset++, libxl_sprintf(gc, PCI_BDF, 
pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
+        flexarray_set(back, boffset++, libxl_sprintf(gc, "dev-%d", i));
+        flexarray_set(back, boffset++, libxl_sprintf(gc, PCI_BDF, 
pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
         if (pcidev->vdevfn) {
-            flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", i));
-            flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", 
pcidev->vdevfn));
+            flexarray_set(back, boffset++, libxl_sprintf(gc, "vdevfn-%d", i));
+            flexarray_set(back, boffset++, libxl_sprintf(gc, "%x", 
pcidev->vdevfn));
         }
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", i));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, 
"msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", i));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+        flexarray_set(back, boffset++, libxl_sprintf(gc, "opts-%d", i));
+        flexarray_set(back, boffset++, libxl_sprintf(gc, 
"msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
+        flexarray_set(back, boffset++, libxl_sprintf(gc, "state-%d", i));
+        flexarray_set(back, boffset++, libxl_sprintf(gc, "%d", 1));
     }
     flexarray_set(back, boffset++, "num_devs");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num));
+    flexarray_set(back, boffset++, libxl_sprintf(gc, "%d", num));
 
     flexarray_set(front, foffset++, "backend-id");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 0));
+    flexarray_set(front, foffset++, libxl_sprintf(gc, "%d", 0));
     flexarray_set(front, foffset++, "state");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(front, foffset++, libxl_sprintf(gc, "%d", 1));
 
     libxl_device_generic_add(ctx, &device,
-                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
-                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+                             libxl_xs_kvs_of_flexarray(gc, back, boffset),
+                             libxl_xs_kvs_of_flexarray(gc, front, foffset));
 
     flexarray_free(back);
     flexarray_free(front);
     return 0;
 }
 
-static int libxl_device_pci_add_xenstore(libxl_ctx *ctx, uint32_t domid, 
libxl_device_pci *pcidev)
+static int libxl_device_pci_add_xenstore(libxl_gc *gc, uint32_t domid, 
libxl_device_pci *pcidev)
 {
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     flexarray_t *back;
     char *num_devs, *be_path;
     int num = 0;
     unsigned int boffset = 0;
     xs_transaction_t t;
 
-    be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", 
libxl_xs_get_dompath(ctx, 0), domid);
-    num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", 
be_path));
+    be_path = libxl_sprintf(gc, "%s/backend/pci/%d/0", 
libxl_xs_get_dompath(gc, 0), domid);
+    num_devs = libxl_xs_read(gc, XBT_NULL, libxl_sprintf(gc, "%s/num_devs", 
be_path));
     if (!num_devs)
-        return libxl_create_pci_backend(ctx, domid, pcidev, 1);
+        return libxl_create_pci_backend(gc, domid, pcidev, 1);
 
     if (!is_hvm(ctx, domid)) {
         if (libxl_wait_for_backend(ctx, be_path, "4") < 0)
@@ -284,27 +286,27 @@ static int libxl_device_pci_add_xenstore
 
     XL_LOG(ctx, XL_LOG_DEBUG, "Adding new pci device to xenstore");
     num = atoi(num_devs);
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", num));
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, 
pcidev->bus, pcidev->dev, pcidev->func));
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", num));
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, 
pcidev->bus, pcidev->dev, pcidev->func));
+    flexarray_set(back, boffset++, libxl_sprintf(gc, "key-%d", num));
+    flexarray_set(back, boffset++, libxl_sprintf(gc, PCI_BDF, pcidev->domain, 
pcidev->bus, pcidev->dev, pcidev->func));
+    flexarray_set(back, boffset++, libxl_sprintf(gc, "dev-%d", num));
+    flexarray_set(back, boffset++, libxl_sprintf(gc, PCI_BDF, pcidev->domain, 
pcidev->bus, pcidev->dev, pcidev->func));
     if (pcidev->vdevfn) {
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", num));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", 
pcidev->vdevfn));
+        flexarray_set(back, boffset++, libxl_sprintf(gc, "vdevfn-%d", num));
+        flexarray_set(back, boffset++, libxl_sprintf(gc, "%x", 
pcidev->vdevfn));
     }
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", num));
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, 
"msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", num));
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, libxl_sprintf(gc, "opts-%d", num));
+    flexarray_set(back, boffset++, libxl_sprintf(gc, 
"msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
+    flexarray_set(back, boffset++, libxl_sprintf(gc, "state-%d", num));
+    flexarray_set(back, boffset++, libxl_sprintf(gc, "%d", 1));
     flexarray_set(back, boffset++, "num_devs");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num + 1));
+    flexarray_set(back, boffset++, libxl_sprintf(gc, "%d", num + 1));
     flexarray_set(back, boffset++, "state");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 7));
+    flexarray_set(back, boffset++, libxl_sprintf(gc, "%d", 7));
 
 retry_transaction:
     t = xs_transaction_start(ctx->xsh);
-    libxl_xs_writev(ctx, t, be_path,
-                    libxl_xs_kvs_of_flexarray(ctx, back, boffset));
+    libxl_xs_writev(gc, t, be_path,
+                    libxl_xs_kvs_of_flexarray(gc, back, boffset));
     if (!xs_transaction_end(ctx->xsh, t, 0))
         if (errno == EAGAIN)
             goto retry_transaction;
@@ -313,16 +315,17 @@ retry_transaction:
     return 0;
 }
 
-static int libxl_device_pci_remove_xenstore(libxl_ctx *ctx, uint32_t domid, 
libxl_device_pci *pcidev)
+static int libxl_device_pci_remove_xenstore(libxl_gc *gc, uint32_t domid, 
libxl_device_pci *pcidev)
 {
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     char *be_path, *num_devs_path, *num_devs, *xsdev, *tmp, *tmppath;
     int num, i, j;
     xs_transaction_t t;
     unsigned int domain = 0, bus = 0, dev = 0, func = 0;
 
-    be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", 
libxl_xs_get_dompath(ctx, 0), domid);
-    num_devs_path = libxl_sprintf(ctx, "%s/num_devs", be_path);
-    num_devs = libxl_xs_read(ctx, XBT_NULL, num_devs_path);
+    be_path = libxl_sprintf(gc, "%s/backend/pci/%d/0", 
libxl_xs_get_dompath(gc, 0), domid);
+    num_devs_path = libxl_sprintf(gc, "%s/num_devs", be_path);
+    num_devs = libxl_xs_read(gc, XBT_NULL, num_devs_path);
     if (!num_devs)
         return ERROR_INVAL;
     num = atoi(num_devs);
@@ -335,7 +338,7 @@ static int libxl_device_pci_remove_xenst
     }
 
     for (i = 0; i < num; i++) {
-        xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", 
be_path, i));
+        xsdev = libxl_xs_read(gc, XBT_NULL, libxl_sprintf(gc, "%s/dev-%d", 
be_path, i));
         sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
         if (domain == pcidev->domain && bus == pcidev->bus &&
             pcidev->dev == dev && pcidev->func == func) {
@@ -349,8 +352,8 @@ static int libxl_device_pci_remove_xenst
 
 retry_transaction:
     t = xs_transaction_start(ctx->xsh);
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i), "5", 
strlen("5"));
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state", be_path), "7", 
strlen("7"));
+    xs_write(ctx->xsh, t, libxl_sprintf(gc, "%s/state-%d", be_path, i), "5", 
strlen("5"));
+    xs_write(ctx->xsh, t, libxl_sprintf(gc, "%s/state", be_path), "7", 
strlen("7"));
     if (!xs_transaction_end(ctx->xsh, t, 0))
         if (errno == EAGAIN)
             goto retry_transaction;
@@ -364,42 +367,42 @@ retry_transaction:
 
 retry_transaction2:
     t = xs_transaction_start(ctx->xsh);
-    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i));
-    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, i));
-    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
-    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, i));
-    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, i));
-    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, i));
-    libxl_xs_write(ctx, t, num_devs_path, "%d", num - 1);
+    xs_rm(ctx->xsh, t, libxl_sprintf(gc, "%s/state-%d", be_path, i));
+    xs_rm(ctx->xsh, t, libxl_sprintf(gc, "%s/key-%d", be_path, i));
+    xs_rm(ctx->xsh, t, libxl_sprintf(gc, "%s/dev-%d", be_path, i));
+    xs_rm(ctx->xsh, t, libxl_sprintf(gc, "%s/vdev-%d", be_path, i));
+    xs_rm(ctx->xsh, t, libxl_sprintf(gc, "%s/opts-%d", be_path, i));
+    xs_rm(ctx->xsh, t, libxl_sprintf(gc, "%s/vdevfn-%d", be_path, i));
+    libxl_xs_write(gc, t, num_devs_path, "%d", num - 1);
     for (j = i + 1; j < num; j++) {
-        tmppath = libxl_sprintf(ctx, "%s/state-%d", be_path, j);
-        tmp = libxl_xs_read(ctx, t, tmppath);
-        xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, j - 
1), tmp, strlen(tmp));
+        tmppath = libxl_sprintf(gc, "%s/state-%d", be_path, j);
+        tmp = libxl_xs_read(gc, t, tmppath);
+        xs_write(ctx->xsh, t, libxl_sprintf(gc, "%s/state-%d", be_path, j - 
1), tmp, strlen(tmp));
         xs_rm(ctx->xsh, t, tmppath);
-        tmppath = libxl_sprintf(ctx, "%s/dev-%d", be_path, j);
-        tmp = libxl_xs_read(ctx, t, tmppath);
-        xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, j - 1), 
tmp, strlen(tmp));
+        tmppath = libxl_sprintf(gc, "%s/dev-%d", be_path, j);
+        tmp = libxl_xs_read(gc, t, tmppath);
+        xs_write(ctx->xsh, t, libxl_sprintf(gc, "%s/dev-%d", be_path, j - 1), 
tmp, strlen(tmp));
         xs_rm(ctx->xsh, t, tmppath);
-        tmppath = libxl_sprintf(ctx, "%s/key-%d", be_path, j);
-        tmp = libxl_xs_read(ctx, t, tmppath);
-        xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, j - 1), 
tmp, strlen(tmp));
+        tmppath = libxl_sprintf(gc, "%s/key-%d", be_path, j);
+        tmp = libxl_xs_read(gc, t, tmppath);
+        xs_write(ctx->xsh, t, libxl_sprintf(gc, "%s/key-%d", be_path, j - 1), 
tmp, strlen(tmp));
         xs_rm(ctx->xsh, t, tmppath);
-        tmppath = libxl_sprintf(ctx, "%s/vdev-%d", be_path, j);
-        tmp = libxl_xs_read(ctx, t, tmppath);
+        tmppath = libxl_sprintf(gc, "%s/vdev-%d", be_path, j);
+        tmp = libxl_xs_read(gc, t, tmppath);
         if (tmp) {
-            xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, j 
- 1), tmp, strlen(tmp));
+            xs_write(ctx->xsh, t, libxl_sprintf(gc, "%s/vdev-%d", be_path, j - 
1), tmp, strlen(tmp));
             xs_rm(ctx->xsh, t, tmppath);
         }
-        tmppath = libxl_sprintf(ctx, "%s/opts-%d", be_path, j);
-        tmp = libxl_xs_read(ctx, t, tmppath);
+        tmppath = libxl_sprintf(gc, "%s/opts-%d", be_path, j);
+        tmp = libxl_xs_read(gc, t, tmppath);
         if (tmp) {
-            xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, j 
- 1), tmp, strlen(tmp));
+            xs_write(ctx->xsh, t, libxl_sprintf(gc, "%s/opts-%d", be_path, j - 
1), tmp, strlen(tmp));
             xs_rm(ctx->xsh, t, tmppath);
         }
-        tmppath = libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, j);
-        tmp = libxl_xs_read(ctx, t, tmppath);
+        tmppath = libxl_sprintf(gc, "%s/vdevfn-%d", be_path, j);
+        tmp = libxl_xs_read(gc, t, tmppath);
         if (tmp) {
-            xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, 
j - 1), tmp, strlen(tmp));
+            xs_write(ctx->xsh, t, libxl_sprintf(gc, "%s/vdevfn-%d", be_path, j 
- 1), tmp, strlen(tmp));
             xs_rm(ctx->xsh, t, tmppath);
         }
     }
@@ -408,7 +411,7 @@ retry_transaction2:
             goto retry_transaction2;
 
     if (num == 1) {
-        char *fe_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/frontend", be_path));
+        char *fe_path = libxl_xs_read(gc, XBT_NULL, libxl_sprintf(gc, 
"%s/frontend", be_path));
         libxl_device_destroy(ctx, be_path, 1);
         xs_rm(ctx->xsh, XBT_NULL, be_path);
         xs_rm(ctx->xsh, XBT_NULL, fe_path);
@@ -418,7 +421,7 @@ retry_transaction2:
     return 0;
 }
 
-static int get_all_assigned_devices(libxl_ctx *ctx, libxl_device_pci **list, 
int *num)
+static int get_all_assigned_devices(libxl_gc *gc, libxl_device_pci **list, int 
*num)
 {
     libxl_device_pci *pcidevs = NULL;
     char **domlist;
@@ -427,21 +430,21 @@ static int get_all_assigned_devices(libx
     *list = NULL;
     *num = 0;
 
-    domlist = libxl_xs_directory(ctx, XBT_NULL, "/local/domain", &nd);
+    domlist = libxl_xs_directory(gc, XBT_NULL, "/local/domain", &nd);
     for(i = 0; i < nd; i++) {
         char *path, *num_devs;
 
-        path = libxl_sprintf(ctx, "/local/domain/0/backend/pci/%s/0/num_devs", 
domlist[i]);
-        num_devs = libxl_xs_read(ctx, XBT_NULL, path);
+        path = libxl_sprintf(gc, "/local/domain/0/backend/pci/%s/0/num_devs", 
domlist[i]);
+        num_devs = libxl_xs_read(gc, XBT_NULL, path);
         if ( num_devs ) {
             int ndev = atoi(num_devs), j;
             char *devpath, *bdf;
 
-            pcidevs = calloc(sizeof(*pcidevs), ndev);
+            pcidevs = libxl_calloc(gc, sizeof(*pcidevs), ndev);
             for(j = (pcidevs) ? 0 : ndev; j < ndev; j++) {
-                devpath = libxl_sprintf(ctx, 
"/local/domain/0/backend/pci/%s/0/dev-%u",
+                devpath = libxl_sprintf(gc, 
"/local/domain/0/backend/pci/%s/0/dev-%u",
                                         domlist[i], j);
-                bdf = libxl_xs_read(ctx, XBT_NULL, devpath);
+                bdf = libxl_xs_read(gc, XBT_NULL, devpath);
                 if ( bdf ) {
                     unsigned dom, bus, dev, func;
                     if ( sscanf(bdf, PCI_BDF, &dom, &bus, &dev, &func) != 4 )
@@ -486,6 +489,7 @@ static int is_assigned(libxl_device_pci 
 
 int libxl_device_pci_list_assignable(libxl_ctx *ctx, libxl_device_pci **list, 
int *num)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     libxl_device_pci *pcidevs = NULL, *new, *assigned;
     struct dirent *de;
     DIR *dir;
@@ -494,7 +498,7 @@ int libxl_device_pci_list_assignable(lib
     *num = 0;
     *list = NULL;
 
-    rc = get_all_assigned_devices(ctx, &assigned, &num_assigned);
+    rc = get_all_assigned_devices(&gc, &assigned, &num_assigned);
     if ( rc )
         return rc;
 
@@ -505,7 +509,7 @@ int libxl_device_pci_list_assignable(lib
         }else{
             XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", 
SYSFS_PCIBACK_DRIVER);
         }
-        free(assigned);
+        libxl_free_all(&gc);
         return ERROR_FAIL;
     }
 
@@ -530,8 +534,8 @@ int libxl_device_pci_list_assignable(lib
     }
 
     closedir(dir);
-    free(assigned);
     *list = pcidevs;
+    libxl_free_all(&gc);
     return 0;
 }
 
@@ -540,8 +544,9 @@ int libxl_device_pci_list_assignable(lib
  * driver. It also initialises a bit-mask of which function numbers are present
  * on that device.
 */
-static int pci_multifunction_check(libxl_ctx *ctx, libxl_device_pci *pcidev, 
unsigned int *func_mask)
+static int pci_multifunction_check(libxl_gc *gc, libxl_device_pci *pcidev, 
unsigned int *func_mask)
 {
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     struct dirent *de;
     DIR *dir;
 
@@ -567,7 +572,7 @@ static int pci_multifunction_check(libxl
         if ( pcidev->dev != dev )
             continue;
 
-        path = libxl_sprintf(ctx, "%s/" PCI_BDF, SYSFS_PCIBACK_DRIVER, dom, 
bus, dev, func);
+        path = libxl_sprintf(gc, "%s/" PCI_BDF, SYSFS_PCIBACK_DRIVER, dom, 
bus, dev, func);
         if ( lstat(path, &st) ) {
             if ( errno == ENOENT )
                 XL_LOG(ctx, XL_LOG_ERROR, PCI_BDF " is not assigned to pciback 
driver",
@@ -598,8 +603,9 @@ static int pci_ins_check(libxl_ctx *ctx,
     return 1;
 }
  
-static int do_pci_add(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
+static int do_pci_add(libxl_gc *gc, uint32_t domid, libxl_device_pci *pcidev)
 {
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     char *path;
     char *state, *vdevfn;
     int rc, hvm;
@@ -609,21 +615,21 @@ static int do_pci_add(libxl_ctx *ctx, ui
         if (libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL) < 
0) {
             return ERROR_FAIL;
         }
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", 
domid);
-        state = libxl_xs_read(ctx, XBT_NULL, path);
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", 
domid);
+        path = libxl_sprintf(gc, "/local/domain/0/device-model/%d/state", 
domid);
+        state = libxl_xs_read(gc, XBT_NULL, path);
+        path = libxl_sprintf(gc, "/local/domain/0/device-model/%d/parameter", 
domid);
         if (pcidev->vdevfn)
-            libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF_VDEVFN, pcidev->domain,
+            libxl_xs_write(gc, XBT_NULL, path, PCI_BDF_VDEVFN, pcidev->domain,
                            pcidev->bus, pcidev->dev, pcidev->func, 
pcidev->vdevfn);
         else
-            libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
+            libxl_xs_write(gc, XBT_NULL, path, PCI_BDF, pcidev->domain,
                            pcidev->bus, pcidev->dev, pcidev->func);
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", 
domid);
+        path = libxl_sprintf(gc, "/local/domain/0/device-model/%d/command", 
domid);
         xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins"));
         rc = libxl_wait_for_device_model(ctx, domid, NULL, pci_ins_check, 
state);
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", 
domid);
-        vdevfn = libxl_xs_read(ctx, XBT_NULL, path);
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", 
domid);
+        path = libxl_sprintf(gc, "/local/domain/0/device-model/%d/parameter", 
domid);
+        vdevfn = libxl_xs_read(gc, XBT_NULL, path);
+        path = libxl_sprintf(gc, "/local/domain/0/device-model/%d/state", 
domid);
         if ( rc < 0 )
             XL_LOG(ctx, XL_LOG_ERROR, "qemu refused to add device: %s", 
vdevfn);
         else if ( sscanf(vdevfn, "0x%x", &pcidev->vdevfn) != 1 )
@@ -632,7 +638,7 @@ static int do_pci_add(libxl_ctx *ctx, ui
         if ( rc )
             return ERROR_FAIL;
     } else {
-        char *sysfs_path = libxl_sprintf(ctx, 
SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
+        char *sysfs_path = libxl_sprintf(gc, 
SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
                                          pcidev->bus, pcidev->dev, 
pcidev->func);
         FILE *f = fopen(sysfs_path, "r");
         unsigned long long start = 0, end = 0, flags = 0, size = 0;
@@ -667,7 +673,7 @@ static int do_pci_add(libxl_ctx *ctx, ui
             }
         }
         fclose(f);
-        sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", 
pcidev->domain,
+        sysfs_path = libxl_sprintf(gc, SYSFS_PCI_DEV"/"PCI_BDF"/irq", 
pcidev->domain,
                                    pcidev->bus, pcidev->dev, pcidev->func);
         f = fopen(sysfs_path, "r");
         if (f == NULL) {
@@ -699,38 +705,74 @@ out:
         }
     }
 
-    libxl_device_pci_add_xenstore(ctx, domid, pcidev);
+    libxl_device_pci_add_xenstore(gc, domid, pcidev);
     return 0;
 }
 
+static int libxl_device_pci_reset(libxl_gc *gc, unsigned int domain, unsigned 
int bus,
+                         unsigned int dev, unsigned int func)
+{
+    libxl_ctx *ctx = libxl_gc_owner(gc);
+    char *reset;
+    int fd, rc;
+
+    reset = libxl_sprintf(gc, "%s/pciback/do_flr", SYSFS_PCI_DEV);
+    fd = open(reset, O_WRONLY);
+    if (fd > 0) {
+        char *buf = libxl_sprintf(gc, PCI_BDF, domain, bus, dev, func);
+        rc = write(fd, buf, strlen(buf));
+        if (rc < 0)
+            XL_LOG(ctx, XL_LOG_ERROR, "write to %s returned %d", reset, rc);
+        close(fd);
+        return rc < 0 ? rc : 0;
+    }
+    if (errno != ENOENT)
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Failed to access pciback path %s", 
reset);
+    reset = libxl_sprintf(gc, "%s/"PCI_BDF"/reset", SYSFS_PCI_DEV, domain, 
bus, dev, func);
+    fd = open(reset, O_WRONLY);
+    if (fd > 0) {
+        rc = write(fd, "1", 1);
+        if (rc < 0)
+            XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "write to %s returned %d", reset, 
rc);
+        close(fd);
+        return rc < 0 ? rc : 0;
+    }
+    if (errno == ENOENT) {
+        XL_LOG(ctx, XL_LOG_ERROR, "The kernel doesn't support PCI device reset 
from sysfs");
+    } else {
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Failed to access reset path %s", 
reset);
+    }
+    return -1;
+}
+
 int libxl_device_pci_add(libxl_ctx *ctx, uint32_t domid, libxl_device_pci 
*pcidev)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     unsigned int orig_vdev, pfunc_mask;
     libxl_device_pci *assigned;
-    int num_assigned, rc, i;
+    int num_assigned, i, rc;
     int stubdomid = 0;
 
-    rc = get_all_assigned_devices(ctx, &assigned, &num_assigned);
+    rc = get_all_assigned_devices(&gc, &assigned, &num_assigned);
     if ( rc ) {
         XL_LOG(ctx, XL_LOG_ERROR, "cannot determine if device is assigned, 
refusing to continue");
-        return ERROR_FAIL;
+        goto out;
     }
     if ( is_assigned(assigned, num_assigned, pcidev->domain,
                      pcidev->bus, pcidev->dev, pcidev->func) ) {
         XL_LOG(ctx, XL_LOG_ERROR, "PCI device already attached to a domain");
-        free(assigned);
-        return ERROR_FAIL;
+        rc = ERROR_FAIL;
+        goto out;
     }
-    free(assigned);
 
-    libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, 
pcidev->func);
+    libxl_device_pci_reset(&gc, pcidev->domain, pcidev->bus, pcidev->dev, 
pcidev->func);
 
     stubdomid = libxl_get_stubdom_id(ctx, domid);
     if (stubdomid != 0) {
         libxl_device_pci pcidev_s = *pcidev;
-        rc = do_pci_add(ctx, stubdomid, &pcidev_s);
+        rc = do_pci_add(&gc, stubdomid, &pcidev_s);
         if ( rc )
-            return rc;
+            goto out;
     }
 
     orig_vdev = pcidev->vdevfn & ~7U;
@@ -738,10 +780,12 @@ int libxl_device_pci_add(libxl_ctx *ctx,
     if ( pcidev->vfunc_mask == LIBXL_PCI_FUNC_ALL ) {
         if ( !(pcidev->vdevfn >> 3) ) {
             XL_LOG(ctx, XL_LOG_ERROR, "Must specify a v-slot for 
multi-function devices");
-            return ERROR_INVAL;
+            rc = ERROR_INVAL;
+            goto out;
         }
-        if ( pci_multifunction_check(ctx, pcidev, &pfunc_mask) ) {
-            return ERROR_FAIL;
+        if ( pci_multifunction_check(&gc, pcidev, &pfunc_mask) ) {
+            rc = ERROR_FAIL;
+            goto out;
         }
         pcidev->vfunc_mask &= pfunc_mask;
         /* so now vfunc_mask == pfunc_mask */
@@ -749,7 +793,7 @@ int libxl_device_pci_add(libxl_ctx *ctx,
         pfunc_mask = (1 << pcidev->func);
     }
 
-    for(i = 7; i >= 0; --i) {
+    for(rc = 0, i = 7; i >= 0; --i) {
         if ( (1 << i) & pfunc_mask ) {
             if ( pcidev->vfunc_mask == pfunc_mask ) {
                 pcidev->func = i;
@@ -761,16 +805,19 @@ int libxl_device_pci_add(libxl_ctx *ctx,
                  */
                 pcidev->vdevfn = orig_vdev;
             }
-            if ( do_pci_add(ctx, domid, pcidev) )
+            if ( do_pci_add(&gc, domid, pcidev) )
                 rc = ERROR_FAIL;
         }
     }
 
+out:
+    libxl_free_all(&gc);
     return rc;
 }
 
-static int do_pci_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_pci 
*pcidev)
+static int do_pci_remove(libxl_gc *gc, uint32_t domid, libxl_device_pci 
*pcidev)
 {
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     libxl_device_pci *assigned;
     char *path;
     char *state;
@@ -785,19 +832,19 @@ static int do_pci_remove(libxl_ctx *ctx,
         }
     }
 
-    libxl_device_pci_remove_xenstore(ctx, domid, pcidev);
+    libxl_device_pci_remove_xenstore(gc, domid, pcidev);
 
     hvm = is_hvm(ctx, domid);
     if (hvm) {
         if (libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL) < 
0) {
             return ERROR_FAIL;
         }
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", 
domid);
-        state = libxl_xs_read(ctx, XBT_NULL, path);
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", 
domid);
-        libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
+        path = libxl_sprintf(gc, "/local/domain/0/device-model/%d/state", 
domid);
+        state = libxl_xs_read(gc, XBT_NULL, path);
+        path = libxl_sprintf(gc, "/local/domain/0/device-model/%d/parameter", 
domid);
+        libxl_xs_write(gc, XBT_NULL, path, PCI_BDF, pcidev->domain,
                        pcidev->bus, pcidev->dev, pcidev->func);
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", 
domid);
+        path = libxl_sprintf(gc, "/local/domain/0/device-model/%d/command", 
domid);
 
         /* Remove all functions at once atomically by only signalling
          * device-model for function 0 */
@@ -808,10 +855,10 @@ static int do_pci_remove(libxl_ctx *ctx,
                 return ERROR_FAIL;
             }
         }
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", 
domid);
+        path = libxl_sprintf(gc, "/local/domain/0/device-model/%d/state", 
domid);
         xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
     } else {
-        char *sysfs_path = libxl_sprintf(ctx, 
SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
+        char *sysfs_path = libxl_sprintf(gc, 
SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
                                          pcidev->bus, pcidev->dev, 
pcidev->func);
         FILE *f = fopen(sysfs_path, "r");
         unsigned int start = 0, end = 0, flags = 0, size = 0;
@@ -841,7 +888,7 @@ static int do_pci_remove(libxl_ctx *ctx,
         }
         fclose(f);
 skip1:
-        sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", 
pcidev->domain,
+        sysfs_path = libxl_sprintf(gc, SYSFS_PCI_DEV"/"PCI_BDF"/irq", 
pcidev->domain,
                                    pcidev->bus, pcidev->dev, pcidev->func);
         f = fopen(sysfs_path, "r");
         if (f == NULL) {
@@ -863,7 +910,7 @@ skip1:
 out:
     /* don't do multiple resets while some functions are still passed through 
*/
     if ( (pcidev->vdevfn & 0x7) == 0 ) {
-        libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, 
pcidev->func);
+        libxl_device_pci_reset(gc, pcidev->domain, pcidev->bus, pcidev->dev, 
pcidev->func);
     }
 
     if (!libxl_is_stubdom(ctx, domid, NULL)) {
@@ -883,21 +930,23 @@ out:
 
 int libxl_device_pci_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_pci 
*pcidev)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     unsigned int orig_vdev, pfunc_mask;
     int i, rc;
 
     orig_vdev = pcidev->vdevfn & ~7U;
 
     if ( pcidev->vfunc_mask == LIBXL_PCI_FUNC_ALL ) {
-        if ( pci_multifunction_check(ctx, pcidev, &pfunc_mask) ) {
-            return ERROR_FAIL;
+        if ( pci_multifunction_check(&gc, pcidev, &pfunc_mask) ) {
+            rc = ERROR_FAIL;
+            goto out;
         }
         pcidev->vfunc_mask &= pfunc_mask;
     }else{
         pfunc_mask = (1 << pcidev->func);
     }
 
-    for(i = 7; i >= 0; --i) {
+    for(rc = 0, i = 7; i >= 0; --i) {
         if ( (1 << i) & pfunc_mask ) {
             if ( pcidev->vfunc_mask == pfunc_mask ) {
                 pcidev->func = i;
@@ -905,26 +954,30 @@ int libxl_device_pci_remove(libxl_ctx *c
             }else{
                 pcidev->vdevfn = orig_vdev;
             }
-            if ( do_pci_remove(ctx, domid, pcidev) )
+            if ( do_pci_remove(&gc, domid, pcidev) )
                 rc = ERROR_FAIL;
         }
     }
 
+out:
+    libxl_free_all(&gc);
     return rc;
 }
 
 int libxl_device_pci_list_assigned(libxl_ctx *ctx, libxl_device_pci **list, 
uint32_t domid, int *num)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *be_path, *num_devs, *xsdev, *xsvdevfn, *xsopts;
     int n, i;
     unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
     libxl_device_pci *pcidevs;
 
-    be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", 
libxl_xs_get_dompath(ctx, 0), domid);
-    num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", 
be_path));
+    be_path = libxl_sprintf(&gc, "%s/backend/pci/%d/0", 
libxl_xs_get_dompath(&gc, 0), domid);
+    num_devs = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/num_devs", 
be_path));
     if (!num_devs) {
         *num = 0;
         *list = NULL;
+        libxl_free_all(&gc);
         return 0;
     }
     n = atoi(num_devs);
@@ -932,13 +985,13 @@ int libxl_device_pci_list_assigned(libxl
     *num = n;
 
     for (i = 0; i < n; i++) {
-        xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", 
be_path, i));
+        xsdev = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/dev-%d", 
be_path, i));
         sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
-        xsvdevfn = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/vdevfn-%d", be_path, i));
+        xsvdevfn = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/vdevfn-%d", be_path, i));
         if (xsvdevfn)
             vdevfn = strtol(xsvdevfn, (char **) NULL, 16);
         pcidev_init(pcidevs + i, domain, bus, dev, func, vdevfn);
-        xsopts = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/opts-%d", 
be_path, i));
+        xsopts = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/opts-%d", 
be_path, i));
         if (xsopts) {
             char *saveptr;
             char *p = strtok_r(xsopts, ",=", &saveptr);
@@ -957,6 +1010,7 @@ int libxl_device_pci_list_assigned(libxl
     }
     if ( *num )
         *list = pcidevs;
+    libxl_free_all(&gc);
     return 0;
 }
 
@@ -975,38 +1029,3 @@ int libxl_device_pci_shutdown(libxl_ctx 
     free(pcidevs);
     return 0;
 }
-
-int libxl_device_pci_reset(libxl_ctx *ctx, unsigned int domain, unsigned int 
bus,
-                         unsigned int dev, unsigned int func)
-{
-    char *reset;
-    int fd, rc;
-
-    reset = libxl_sprintf(ctx, "%s/pciback/do_flr", SYSFS_PCI_DEV);
-    fd = open(reset, O_WRONLY);
-    if (fd > 0) {
-        char *buf = libxl_sprintf(ctx, PCI_BDF, domain, bus, dev, func);
-        rc = write(fd, buf, strlen(buf));
-        if (rc < 0)
-            XL_LOG(ctx, XL_LOG_ERROR, "write to %s returned %d", reset, rc);
-        close(fd);
-        return rc < 0 ? rc : 0;
-    }
-    if (errno != ENOENT)
-        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Failed to access pciback path %s", 
reset);
-    reset = libxl_sprintf(ctx, "%s/"PCI_BDF"/reset", SYSFS_PCI_DEV, domain, 
bus, dev, func);
-    fd = open(reset, O_WRONLY);
-    if (fd > 0) {
-        rc = write(fd, "1", 1);
-        if (rc < 0)
-            XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "write to %s returned %d", reset, 
rc);
-        close(fd);
-        return rc < 0 ? rc : 0;
-    }
-    if (errno == ENOENT) {
-        XL_LOG(ctx, XL_LOG_ERROR, "The kernel doesn't support PCI device reset 
from sysfs");
-    } else {
-        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Failed to access reset path %s", 
reset);
-    }
-    return -1;
-}
diff -r 7b144fe8c528 tools/libxl/libxl_utils.c
--- a/tools/libxl/libxl_utils.c Wed Aug 11 14:39:44 2010 +0100
+++ b/tools/libxl/libxl_utils.c Thu Aug 12 15:22:56 2010 +0100
@@ -54,11 +54,11 @@ char *libxl_domid_to_name(libxl_ctx *ctx
     return s;
 }
 
-char *_libxl_domid_to_name(libxl_ctx *ctx, uint32_t domid)
+char *_libxl_domid_to_name(libxl_gc *gc, uint32_t domid)
 {
-    char *s = libxl_domid_to_name(ctx, domid);
+    char *s = libxl_domid_to_name(libxl_gc_owner(gc), domid);
     if ( s )
-        libxl_ptr_add(ctx, s);
+        libxl_ptr_add(gc, s);
     return s;
 }
 
@@ -75,14 +75,16 @@ int libxl_name_to_domid(libxl_ctx *ctx, 
         return ERROR_NOMEM;
 
     for (i = 0; i < nb_domains; i++) {
-        domname = _libxl_domid_to_name(ctx, dominfo[i].domid);
+        domname = libxl_domid_to_name(ctx, dominfo[i].domid);
         if (!domname)
             continue;
         if (strcmp(domname, name) == 0) {
             *domid = dominfo[i].domid;
             ret = 0;
+            free(domname);
             break;
         }
+        free(domname);
     }
     free(dominfo);
     return ret;
@@ -101,11 +103,11 @@ char *libxl_poolid_to_name(libxl_ctx *ct
     return s;
 }
 
-char *_libxl_poolid_to_name(libxl_ctx *ctx, uint32_t poolid)
+char *_libxl_poolid_to_name(libxl_gc *gc, uint32_t poolid)
 {
-    char *s = libxl_poolid_to_name(ctx, poolid);
+    char *s = libxl_poolid_to_name(libxl_gc_owner(gc), poolid);
     if ( s )
-        libxl_ptr_add(ctx, s);
+        libxl_ptr_add(gc, s);
     return s;
 }
 
@@ -122,14 +124,16 @@ int libxl_name_to_poolid(libxl_ctx *ctx,
         return ERROR_NOMEM;
 
     for (i = 0; i < nb_pools; i++) {
-        poolname = _libxl_poolid_to_name(ctx, poolinfo[i].poolid);
+        poolname = libxl_poolid_to_name(ctx, poolinfo[i].poolid);
         if (!poolname)
             continue;
         if (strcmp(poolname, name) == 0) {
             *poolid = poolinfo[i].poolid;
             ret = 0;
+            free(poolname);
             break;
         }
+        free(poolname);
     }
     free(poolinfo);
     return ret;
@@ -137,27 +141,40 @@ int libxl_name_to_poolid(libxl_ctx *ctx,
 
 int libxl_get_stubdom_id(libxl_ctx *ctx, int guest_domid)
 {
-    char * stubdom_id_s = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/image/device-model-domid", libxl_xs_get_dompath(ctx, guest_domid)));
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
+    char * stubdom_id_s;
+    int ret;
+
+    stubdom_id_s = libxl_xs_read(&gc, XBT_NULL,
+                                 libxl_sprintf(&gc, 
"%s/image/device-model-domid",
+                                               libxl_xs_get_dompath(&gc, 
guest_domid)));
     if (stubdom_id_s)
-        return atoi(stubdom_id_s);
+        ret = atoi(stubdom_id_s);
     else
-        return 0;
+        ret = 0;
+    libxl_free_all(&gc);
+    return ret;
 }
 
 int libxl_is_stubdom(libxl_ctx *ctx, uint32_t domid, uint32_t *target_domid)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *target, *endptr;
     uint32_t value;
+    int ret = 0;
 
-    target = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/target", 
libxl_xs_get_dompath(ctx, domid)));
+    target = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/target", 
libxl_xs_get_dompath(&gc, domid)));
     if (!target)
-        return 0;
+        goto out;
     value = strtol(target, &endptr, 10);
     if (*endptr != '\0')
-        return 0;
+        goto out;
     if (target_domid)
         *target_domid = value;
-    return 1;
+    ret = 1;
+out:
+    libxl_free_all(&gc);
+    return ret;
 }
 
 static int logrename(libxl_ctx *ctx, const char *old, const char *new) {
@@ -176,26 +193,29 @@ static int logrename(libxl_ctx *ctx, con
 
 int libxl_create_logfile(libxl_ctx *ctx, char *name, char **full_name)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     struct stat stat_buf;
     char *logfile, *logfile_new;
     int i, rc;
 
-    logfile = libxl_sprintf(ctx, "/var/log/xen/%s.log", name);
+    logfile = libxl_sprintf(&gc, "/var/log/xen/%s.log", name);
     if (stat(logfile, &stat_buf) == 0) {
         /* file exists, rotate */
-        logfile = libxl_sprintf(ctx, "/var/log/xen/%s.log.10", name);
+        logfile = libxl_sprintf(&gc, "/var/log/xen/%s.log.10", name);
         unlink(logfile);
         for (i = 9; i > 0; i--) {
-            logfile = libxl_sprintf(ctx, "/var/log/xen/%s.log.%d", name, i);
-            logfile_new = libxl_sprintf(ctx, "/var/log/xen/%s.log.%d", name, i 
+ 1);
+            logfile = libxl_sprintf(&gc, "/var/log/xen/%s.log.%d", name, i);
+            logfile_new = libxl_sprintf(&gc, "/var/log/xen/%s.log.%d", name, i 
+ 1);
             rc = logrename(ctx, logfile, logfile_new);
-            if (rc) return rc;
+            if (rc)
+                goto out;
         }
-        logfile = libxl_sprintf(ctx, "/var/log/xen/%s.log", name);
-        logfile_new = libxl_sprintf(ctx, "/var/log/xen/%s.log.1", name);
+        logfile = libxl_sprintf(&gc, "/var/log/xen/%s.log", name);
+        logfile_new = libxl_sprintf(&gc, "/var/log/xen/%s.log.1", name);
 
         rc = logrename(ctx, logfile, logfile_new);
-        if (rc) return rc;
+        if (rc)
+            goto out;
     } else {
         if (errno != ENOENT)
             XL_LOG_ERRNO(ctx, XL_LOG_WARNING, "problem checking existence of"
@@ -203,7 +223,10 @@ int libxl_create_logfile(libxl_ctx *ctx,
                          name);
     }
     *full_name = strdup(logfile);
-    return 0;
+    rc = 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 int libxl_string_to_phystype(libxl_ctx *ctx, char *s, libxl_disk_phystype 
*phystype)
@@ -423,122 +446,135 @@ int libxl_mac_to_device_nic(libxl_ctx *c
 int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid,
                               const char *devid, libxl_device_nic *nic)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *tok, *val;
     char *dompath, *nic_path_fe, *nic_path_be;
     unsigned int i;
+    int rc = ERROR_FAIL;
 
     memset(nic, 0, sizeof (libxl_device_nic));
-    dompath = libxl_xs_get_dompath(ctx, domid);
+    dompath = libxl_xs_get_dompath(&gc, domid);
     if (!dompath) {
-        return ERROR_FAIL;
+        goto out;
     }
-    nic_path_fe = libxl_sprintf(ctx, "%s/device/vif/%s", dompath, devid);
-    nic_path_be = libxl_xs_read(ctx, XBT_NULL,
-                                libxl_sprintf(ctx, "%s/backend", nic_path_fe));
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", 
nic_path_fe));
+    nic_path_fe = libxl_sprintf(&gc, "%s/device/vif/%s", dompath, devid);
+    nic_path_be = libxl_xs_read(&gc, XBT_NULL,
+                                libxl_sprintf(&gc, "%s/backend", nic_path_fe));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend-id", 
nic_path_fe));
     if ( NULL == val ) {
-        return ERROR_FAIL;
+        goto out;
     }
     nic->backend_domid = strtoul(val, NULL, 10);
     nic->devid = strtoul(devid, NULL, 10);
-    libxl_free(ctx, val);
 
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mac", 
nic_path_fe));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/mac", 
nic_path_fe));
     for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
          ++i, tok = strtok(NULL, ":")) {
         nic->mac[i] = strtoul(tok, NULL, 16);
     }
-    libxl_free(ctx, val);
-    nic->script = libxl_xs_read(ctx, XBT_NULL,
-                                libxl_sprintf(ctx, "%s/script", nic_path_be));
-    libxl_free(ctx, nic_path_fe);
-    libxl_free(ctx, nic_path_be);
-    return 0;
+    nic->script = libxl_xs_read(&gc, XBT_NULL,
+                                libxl_sprintf(&gc, "%s/script", nic_path_be));
+    rc = 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 int libxl_devid_to_device_disk(libxl_ctx *ctx, uint32_t domid,
                                const char *devid, libxl_device_disk *disk)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *endptr, *val;
     char *dompath, *diskpath, *be_path;
     unsigned int devid_n;
+    int rc = ERROR_INVAL;
 
     devid_n = strtoul(devid, &endptr, 10);
     if (devid == endptr) {
-        return ERROR_INVAL;
+        goto out;
     }
-    dompath = libxl_xs_get_dompath(ctx, domid);
-    diskpath = libxl_sprintf(ctx, "%s/device/vbd/%s", dompath, devid);
+    rc = ERROR_FAIL;
+    dompath = libxl_xs_get_dompath(&gc, domid);
+    diskpath = libxl_sprintf(&gc, "%s/device/vbd/%s", dompath, devid);
     if (!diskpath) {
-        return ERROR_FAIL;
+        goto out;
     }
 
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", 
diskpath));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend-id", 
diskpath));
     if (!val)
-        return ERROR_FAIL;
+        goto out;
     disk->backend_domid = strtoul(val, NULL, 10);
     disk->domid = domid;
-    be_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend", 
diskpath));
-    disk->physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/params", be_path));
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/type", be_path));
+    be_path = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend", 
diskpath));
+    disk->physpath = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, 
"%s/params", be_path));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/type", be_path));
     libxl_string_to_phystype(ctx, val, &(disk->phystype));
-    disk->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev", 
be_path));
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/removable", 
be_path));
+    disk->virtpath = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/dev", 
be_path));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/removable", 
be_path));
     disk->unpluggable = !strcmp(val, "1");
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mode", be_path));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/mode", be_path));
     disk->readwrite = !!strcmp(val, "w");
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/device-type", 
diskpath));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/device-type", 
diskpath));
     disk->is_cdrom = !strcmp(val, "cdrom");
+    rc = 0;
 
-    return 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 int libxl_devid_to_device_net2(libxl_ctx *ctx, uint32_t domid,
                                const char *devid, libxl_device_net2 *net2)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     char *tok, *endptr, *val;
     char *dompath, *net2path, *be_path;
     unsigned int devid_n, i;
+    int rc = ERROR_INVAL;
 
     devid_n = strtoul(devid, &endptr, 10);
     if (devid == endptr) {
-        return ERROR_INVAL;
+        goto out;
     }
-    dompath = libxl_xs_get_dompath(ctx, domid);
-    net2path = libxl_sprintf(ctx, "%s/device/vif2/%s", dompath, devid);
+    rc = ERROR_FAIL;
+    dompath = libxl_xs_get_dompath(&gc, domid);
+    net2path = libxl_sprintf(&gc, "%s/device/vif2/%s", dompath, devid);
     if (!net2path) {
-        return ERROR_FAIL;
+        goto out;
     }
     memset(net2, 0, sizeof (libxl_device_net2));
-    be_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend", 
net2path));
+    be_path = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend", 
net2path));
 
     net2->devid = devid_n;
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mac", net2path));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/mac", net2path));
     for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
          ++i, tok = strtok(NULL, ":")) {
         net2->front_mac[i] = strtoul(tok, NULL, 16);
     }
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/remote-mac", 
net2path));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/remote-mac", 
net2path));
     for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
          ++i, tok = strtok(NULL, ":")) {
         net2->back_mac[i] = strtoul(tok, NULL, 16);
     }
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", 
net2path));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend-id", 
net2path));
     net2->backend_domid = strtoul(val, NULL, 10);
 
     net2->domid = domid;
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/remote-trusted", 
be_path));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/remote-trusted", 
be_path));
     net2->trusted = strtoul(val, NULL, 10);
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/local-trusted", 
be_path));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/local-trusted", 
be_path));
     net2->back_trusted = strtoul(val, NULL, 10);
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/filter-mac", 
be_path));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/filter-mac", 
be_path));
     net2->filter_mac = strtoul(val, NULL, 10);
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/filter-mac", 
net2path));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/filter-mac", 
net2path));
     net2->front_filter_mac = strtoul(val, NULL, 10);
-    val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/max-bypasses", 
be_path));
+    val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/max-bypasses", 
be_path));
     net2->max_bypasses = strtoul(val, NULL, 10);
+    rc = 0;
 
-    return 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
 
 int libxl_strtomac(const char *mac_s, uint8_t *mac)
@@ -561,21 +597,23 @@ int libxl_strtomac(const char *mac_s, ui
 
 int libxl_check_device_model_version(libxl_ctx *ctx, char *path)
 {
+    libxl_gc gc = LIBXL_INIT_GC(ctx);
     pid_t pid = -1;
     int pipefd[2];
     char buf[100];
     ssize_t i, count = 0;
     int status;
     char *abs_path = NULL;
+    int rc = -1;
 
-    abs_path = libxl_abs_path(ctx, path, libxl_private_bindir_path());
+    abs_path = libxl_abs_path(&gc, path, libxl_private_bindir_path());
 
     if (pipe(pipefd))
-        return -1;
+        goto out;
 
     pid = fork();
     if (pid == -1) {
-        return -1;
+        goto out;
     }
 
     if (!pid) {
@@ -589,8 +627,6 @@ int libxl_check_device_model_version(lib
     }
 
     close(pipefd[1]);
-    if (abs_path != path)
-        libxl_free(ctx, abs_path);
 
     /* attempt to get the first line of `qemu -h` */
     while ((i = read(pipefd[0], buf + count, 99 - count)) > 0) {
@@ -606,13 +642,14 @@ int libxl_check_device_model_version(lib
     close(pipefd[0]);
     waitpid(pid, &status, 0);
     if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
-        return -1;
+        goto out;
     }
 
     /* Check if we have the forked qemu-xen. */
     /* QEMU-DM emulator version 0.10.2, ... */
     if (strncmp("QEMU-DM ", buf, 7) == 0) {
-        return 0;
+        rc = 0;
+        goto out;
     }
 
     /* Check if the version is above 12.0 */
@@ -626,10 +663,14 @@ int libxl_check_device_model_version(lib
         if (major == 0 && endptr && *endptr == '.') {
             v = endptr + 1;
             minor = strtol(v, &endptr, 10);
-            if (minor >= 12)
-                return 1;
+            if (minor >= 12) {
+                rc = 1;
+                goto out;
+            }
         }
     }
-
-    return 0;
+    rc = 0;
+out:
+    libxl_free_all(&gc);
+    return rc;
 }
diff -r 7b144fe8c528 tools/libxl/libxl_xshelp.c
--- a/tools/libxl/libxl_xshelp.c        Wed Aug 11 14:39:44 2010 +0100
+++ b/tools/libxl/libxl_xshelp.c        Thu Aug 12 15:22:56 2010 +0100
@@ -44,12 +44,12 @@ int xs_writev(struct xs_handle *xsh, xs_
     return 0;
 }
 
-char **libxl_xs_kvs_of_flexarray(libxl_ctx *ctx, flexarray_t *array, int 
length)
+char **libxl_xs_kvs_of_flexarray(libxl_gc *gc, flexarray_t *array, int length)
 {
     char **kvs;
     int i;
 
-    kvs = libxl_calloc(ctx, length + 2, sizeof(char *));
+    kvs = libxl_calloc(gc, length + 2, sizeof(char *));
     if (kvs) {
         for (i = 0; i < length; i += 2) {
             void *ptr;
@@ -65,9 +65,10 @@ char **libxl_xs_kvs_of_flexarray(libxl_c
     return kvs;
 }
 
-int libxl_xs_writev(libxl_ctx *ctx, xs_transaction_t t,
+int libxl_xs_writev(libxl_gc *gc, xs_transaction_t t,
                     char *dir, char *kvs[])
 {
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     char *path;
     int i;
 
@@ -75,19 +76,19 @@ int libxl_xs_writev(libxl_ctx *ctx, xs_t
         return 0;
 
     for (i = 0; kvs[i] != NULL; i += 2) {
-        path = libxl_sprintf(ctx, "%s/%s", dir, kvs[i]);
+        path = libxl_sprintf(gc, "%s/%s", dir, kvs[i]);
         if (path && kvs[i + 1]) {
             int length = strlen(kvs[i + 1]);
             xs_write(ctx->xsh, t, path, kvs[i + 1], length);
         }
-        libxl_free(ctx, path);
     }
     return 0;
 }
 
-int libxl_xs_write(libxl_ctx *ctx, xs_transaction_t t,
+int libxl_xs_write(libxl_gc *gc, xs_transaction_t t,
                    char *path, char *fmt, ...)
 {
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     char *s;
     va_list ap;
     int ret;
@@ -103,35 +104,38 @@ int libxl_xs_write(libxl_ctx *ctx, xs_tr
     return 0;
 }
 
-char * libxl_xs_read(libxl_ctx *ctx, xs_transaction_t t, char *path)
+char * libxl_xs_read(libxl_gc *gc, xs_transaction_t t, char *path)
 {
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     unsigned int len;
     char *ptr;
 
     ptr = xs_read(ctx->xsh, t, path, &len);
     if (ptr != NULL) {
-        libxl_ptr_add(ctx, ptr);
+        libxl_ptr_add(gc, ptr);
         return ptr;
     }
     return 0;
 }
 
-char *libxl_xs_get_dompath(libxl_ctx *ctx, uint32_t domid)
+char *libxl_xs_get_dompath(libxl_gc *gc, uint32_t domid)
 {
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     char *s = xs_get_domain_path(ctx->xsh, domid);
     if (!s) {
         XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to get dompath for %" PRIu32,
                      domid);
         return NULL;
     }
-    libxl_ptr_add(ctx, s);
+    libxl_ptr_add(gc, s);
     return s;
 }
 
-char **libxl_xs_directory(libxl_ctx *ctx, xs_transaction_t t, char *path, 
unsigned int *nb)
+char **libxl_xs_directory(libxl_gc *gc, xs_transaction_t t, char *path, 
unsigned int *nb)
 {
+    libxl_ctx *ctx = libxl_gc_owner(gc);
     char **ret = NULL;
     ret = xs_directory(ctx->xsh, XBT_NULL, path, nb);
-    libxl_ptr_add(ctx, ret);
+    libxl_ptr_add(gc, ret);
     return ret;
 }
diff -r 7b144fe8c528 tools/libxl/xl_cmdimpl.c
--- a/tools/libxl/xl_cmdimpl.c  Wed Aug 11 14:39:44 2010 +0100
+++ b/tools/libxl/xl_cmdimpl.c  Thu Aug 12 15:22:56 2010 +0100
@@ -3267,7 +3267,7 @@ static void print_vcpuinfo(uint32_t tdom
 
 void vcpulist(int argc, char **argv)
 {
-    libxl_dominfo *dominfo;
+    libxl_dominfo *dominfo, *domlist;
     libxl_vcpuinfo *vcpuinfo, *list = NULL;
     libxl_physinfo physinfo;
     int nb_vcpu, nb_domain, nrcpus;
@@ -3279,7 +3279,7 @@ void vcpulist(int argc, char **argv)
     printf("%-32s %5s %5s %5s %5s %9s %s\n",
            "Name", "ID", "VCPU", "CPU", "State", "Time(s)", "CPU Affinity");
     if (!argc) {
-        if (!(dominfo = libxl_list_domain(&ctx, &nb_domain))) {
+        if (!(domlist = dominfo = libxl_list_domain(&ctx, &nb_domain))) {
             fprintf(stderr, "libxl_list_domain failed.\n");
             goto vcpulist_out;
         }
@@ -3294,6 +3294,7 @@ void vcpulist(int argc, char **argv)
             }
             libxl_free_vcpu_list(list);
         }
+        free(domlist);
     } else {
         for (; argc > 0; ++argv, --argc) {
             if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.