diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index e386357..d5a3ab7 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1749,9 +1749,14 @@ int libxl_device_disk_destroy(libxl_ctx *ctx, uint32_t domid,
                               const libxl_asyncop_how *ao_how)
                               LIBXL_EXTERNAL_CALLERS_ONLY;
 
-libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int *num);
+libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx,
+                                          uint32_t domid, int *num)
+                                          LIBXL_EXTERNAL_CALLERS_ONLY;
+void libxl_device_disk_list_free(libxl_device_disk* list, int num)
+                                 LIBXL_EXTERNAL_CALLERS_ONLY;
 int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
-                              libxl_device_disk *disk, libxl_diskinfo *diskinfo);
+                              libxl_device_disk *disk, libxl_diskinfo *diskinfo)
+                              LIBXL_EXTERNAL_CALLERS_ONLY;
 
 /*
  * Insert a CD-ROM device. A device corresponding to disk must already
diff --git a/tools/libxl/libxl_checkpoint_device.c b/tools/libxl/libxl_checkpoint_device.c
index 01e74b5..f6a4437 100644
--- a/tools/libxl/libxl_checkpoint_device.c
+++ b/tools/libxl/libxl_checkpoint_device.c
@@ -66,7 +66,8 @@ void libxl__checkpoint_devices_setup(libxl__egc *egc,
         cds->nics = libxl_device_nic_list(CTX, cds->domid, &cds->num_nics);
 
     if (cds->device_kind_flags & (1 << LIBXL__DEVICE_KIND_VBD))
-        cds->disks = libxl_device_disk_list(CTX, cds->domid, &cds->num_disks);
+        cds->disks = libxl__device_list(gc, &libxl__disk_devtype, cds->domid,
+                                        "disk", &cds->num_disks);
 
     if (cds->num_nics == 0 && cds->num_disks == 0)
         goto out;
@@ -221,9 +222,7 @@ static void devices_teardown_cb(libxl__egc *egc,
     cds->num_nics = 0;
 
     /* clean disk */
-    for (i = 0; i < cds->num_disks; i++)
-        libxl_device_disk_dispose(&cds->disks[i]);
-    free(cds->disks);
+    libxl__device_list_free(&libxl__disk_devtype, cds->disks, cds->num_disks);
     cds->disks = NULL;
     cds->num_disks = 0;
 
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 70048fe..0ef54d2 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -938,8 +938,8 @@ static void initiate_domain_create(libxl__egc *egc,
     store_libxl_entry(gc, domid, &d_config->b_info);
 
     for (i = 0; i < d_config->num_disks; i++) {
-        ret = libxl__device_disk_setdefault(gc, domid, &d_config->disks[i],
-                                            false);
+        ret = libxl__disk_devtype.set_default(gc, domid, &d_config->disks[i],
+                                              false);
         if (ret) {
             LOGD(ERROR, domid, "Unable to set disk defaults for disk %d", i);
             goto error_out;
diff --git a/tools/libxl/libxl_disk.c b/tools/libxl/libxl_disk.c
index 91c77ad..c20cc49 100644
--- a/tools/libxl/libxl_disk.c
+++ b/tools/libxl/libxl_disk.c
@@ -152,8 +152,8 @@ void libxl_evdisable_disk_eject(libxl_ctx *ctx, libxl_evgen_disk_eject *evg) {
     GC_FREE;
 }
 
-int libxl__device_disk_setdefault(libxl__gc *gc, uint32_t domid,
-                                  libxl_device_disk *disk, bool hotplug)
+static int libxl__device_disk_setdefault(libxl__gc *gc, uint32_t domid,
+                                         libxl_device_disk *disk, bool hotplug)
 {
     int rc;
 
@@ -181,7 +181,7 @@ int libxl__device_disk_setdefault(libxl__gc *gc, uint32_t domid,
     return rc;
 }
 
-int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
+static int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
                                    const libxl_device_disk *disk,
                                    libxl__device *device)
 {
@@ -472,17 +472,15 @@ static void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
     device_disk_add(egc, domid, disk, aodev, NULL, NULL);
 }
 
-static int libxl__device_disk_from_xenstore(libxl__gc *gc,
-                                         const char *libxl_path,
-                                         libxl_device_disk *disk)
+static int libxl__disk_from_xenstore(libxl__gc *gc, const char *libxl_path,
+                                     libxl_devid devid,
+                                     libxl_device_disk *disk)
 {
     libxl_ctx *ctx = libxl__gc_owner(gc);
     unsigned int len;
     char *tmp;
     int rc;
 
-    libxl_device_disk_init(disk);
-
     const char *backend_path;
     rc = libxl__xs_read_checked(gc, XBT_NULL,
                                 GCSPRINTF("%s/backend", libxl_path),
@@ -617,69 +615,28 @@ int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid,
     }
     libxl_path = GCSPRINTF("%s/device/vbd/%d", dom_xl_path, devid);
 
-    rc = libxl__device_disk_from_xenstore(gc, libxl_path, disk);
+    rc = libxl__disk_from_xenstore(gc, libxl_path, devid, disk);
 out:
     GC_FREE;
     return rc;
 }
 
-static int libxl__append_disk_list(libxl__gc *gc,
-                                           uint32_t domid,
-                                           libxl_device_disk **disks,
-                                           int *ndisks)
-{
-    char *libxl_dir_path = NULL;
-    char **dir = NULL;
-    unsigned int n = 0;
-    libxl_device_disk *pdisk = NULL, *pdisk_end = NULL;
-    int rc=0;
-    int initial_disks = *ndisks;
-
-    libxl_dir_path = GCSPRINTF("%s/device/vbd",
-                        libxl__xs_libxl_path(gc, domid));
-    dir = libxl__xs_directory(gc, XBT_NULL, libxl_dir_path, &n);
-    if (dir && n) {
-        libxl_device_disk *tmp;
-        tmp = realloc(*disks, sizeof (libxl_device_disk) * (*ndisks + n));
-        if (tmp == NULL)
-            return ERROR_NOMEM;
-        *disks = tmp;
-        pdisk = *disks + initial_disks;
-        pdisk_end = *disks + initial_disks + n;
-        for (; pdisk < pdisk_end; pdisk++, dir++) {
-            const char *p;
-            p = GCSPRINTF("%s/%s", libxl_dir_path, *dir);
-            if ((rc=libxl__device_disk_from_xenstore(gc, p, pdisk)))
-                goto out;
-            *ndisks += 1;
-        }
-    }
-out:
-    return rc;
-}
-
 libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int *num)
 {
-    GC_INIT(ctx);
-    libxl_device_disk *disks = NULL;
-    int rc;
+    libxl_device_disk *r;
 
-    *num = 0;
+    GC_INIT(ctx);
 
-    rc = libxl__append_disk_list(gc, domid, &disks, num);
-    if (rc) goto out_err;
+    r = libxl__device_list(gc, &libxl__disk_devtype, domid, "disk", num);
 
     GC_FREE;
-    return disks;
 
-out_err:
-    LOG(ERROR, "Unable to list disks");
-    while (disks && *num) {
-        (*num)--;
-        libxl_device_disk_dispose(&disks[*num]);
-    }
-    free(disks);
-    return NULL;
+    return r;
+}
+
+void libxl_device_disk_list_free(libxl_device_disk *list, int num)
+{
+    libxl__device_list_free(&libxl__disk_devtype, list, num);
 }
 
 int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
@@ -783,7 +740,7 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
         goto out;
     }
 
-    disks = libxl_device_disk_list(ctx, domid, &num);
+    disks = libxl__device_list(gc, &libxl__disk_devtype, domid, "disk", &num);
     for (i = 0; i < num; i++) {
         if (disks[i].is_cdrom && !strcmp(disk->vdev, disks[i].vdev))
         {
@@ -921,9 +878,7 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
 
 out:
     libxl__xs_transaction_abort(gc, &t);
-    for (i = 0; i < num; i++)
-        libxl_device_disk_dispose(&disks[i]);
-    free(disks);
+    libxl__device_list_free(&libxl__disk_devtype, disks, num);
     libxl_device_disk_dispose(&disk_empty);
     libxl_device_disk_dispose(&disk_saved);
     libxl_domain_config_dispose(&d_config);
@@ -1250,6 +1205,8 @@ static int libxl_device_disk_dm_needed(void *e, unsigned domid)
 DEFINE_DEVICE_TYPE_STRUCT(disk,
     .merge       = libxl_device_disk_merge,
     .dm_needed   = libxl_device_disk_dm_needed,
+    .from_xenstore = (int (*)(libxl__gc *, const char *, libxl_devid, void *))
+                     libxl__disk_from_xenstore,
     .skip_attach = 1
 );
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 6b21812..de1706c 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1242,9 +1242,6 @@ _hidden int libxl__domain_create_info_setdefault(libxl__gc *gc,
                                         libxl_domain_create_info *c_info);
 _hidden int libxl__domain_build_info_setdefault(libxl__gc *gc,
                                         libxl_domain_build_info *b_info);
-_hidden int libxl__device_disk_setdefault(libxl__gc *gc, uint32_t domid,
-                                          libxl_device_disk *disk,
-                                          bool hotplug);
 _hidden int libxl__device_nic_setdefault(libxl__gc *gc, uint32_t domid,
                                          libxl_device_nic *nic, bool hotplug);
 _hidden void libxl__rdm_setdefault(libxl__gc *gc,
@@ -1754,10 +1751,6 @@ _hidden char *libxl__blktap_devpath(libxl__gc *gc,
  */
 _hidden int libxl__device_destroy_tapdisk(libxl__gc *gc, const char *params);
 
-_hidden int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
-                                   const libxl_device_disk *disk,
-                                   libxl__device *device);
-
 /* Calls poll() again - useful to check whether a signaled condition
  * is still true.  Cannot fail.  Returns currently-true revents. */
 _hidden short libxl__fd_poll_recheck(libxl__egc *egc, int fd, short events);
diff --git a/tools/ocaml/libs/xl/xenlight_stubs.c b/tools/ocaml/libs/xl/xenlight_stubs.c
index 98b52b9..55f09d7 100644
--- a/tools/ocaml/libs/xl/xenlight_stubs.c
+++ b/tools/ocaml/libs/xl/xenlight_stubs.c
@@ -763,9 +763,8 @@ value stub_xl_device_disk_list(value ctx, value domid)
 		Field(list, 1) = temp;
 		temp = list;
 		Store_field(list, 0, Val_device_disk(&c_list[i]));
-		libxl_device_disk_dispose(&c_list[i]);
 	}
-	free(c_list);
+	libxl_device_disk_list_free(c_list, nb);
 
 	CAMLreturn(list);
 }
diff --git a/tools/xl/xl_block.c b/tools/xl/xl_block.c
index da337ef..acaf9b9 100644
--- a/tools/xl/xl_block.c
+++ b/tools/xl/xl_block.c
@@ -88,9 +88,8 @@ int main_blocklist(int argc, char **argv)
                        diskinfo.state, diskinfo.evtch, diskinfo.rref, diskinfo.backend);
                 libxl_diskinfo_dispose(&diskinfo);
             }
-            libxl_device_disk_dispose(&disks[i]);
         }
-        free(disks);
+        libxl_device_disk_list_free(disks, nb);
     }
     return 0;
 }
