WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

To: Xen Devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH, v2]: xl: Implement per-API-call garbage-collection lifetime
From: Gianni Tedesco <gianni.tedesco@xxxxxxxxxx>
Date: Thu, 12 Aug 2010 17:30:41 +0100
Cc: Ian Campbell <Ian.Campbell@xxxxxxxxxxxxx>, Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>, Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Delivery-date: Thu, 12 Aug 2010 09:36:23 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH, v2]: xl: Implement per-API-call garbage-collection lifetime, Gianni Tedesco <=