diff --git a/block/Makefile.objs b/block/Makefile.objs
index a833ed5..27911b6 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -5,7 +5,7 @@ block-obj-y += qed-check.o
 block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o
 block-obj-$(CONFIG_QUORUM) += quorum.o
 block-obj-y += parallels.o blkdebug.o blkverify.o
-block-obj-y += snapshot.o qapi.o
+block-obj-y += block-backend.o snapshot.o qapi.o
 block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
 block-obj-$(CONFIG_POSIX) += raw-posix.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
diff --git a/block/block-backend.c b/block/block-backend.c
new file mode 100644
index 0000000..e89caa9
--- /dev/null
+++ b/block/block-backend.c
@@ -0,0 +1,120 @@
+/*
+ * QEMU Block backends
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * Authors:
+ *  Markus Armbruster <armbru@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1
+ * or later.  See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "sysemu/block-backend.h"
+#include "block/block_int.h"
+
+struct BlockBackend {
+    char *name;
+    int refcnt;
+    QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
+};
+
+/* All the BlockBackends */
+static QTAILQ_HEAD(, BlockBackend) blk_backends =
+    QTAILQ_HEAD_INITIALIZER(blk_backends);
+
+/*
+ * Create a new BlockBackend with @name, with a reference count of one.
+ * @name must not be null or empty.
+ * Fail if a BlockBackend with this name already exists.
+ * Store an error through @errp on failure, unless it's null.
+ * Return the new BlockBackend on success, null on failure.
+ */
+BlockBackend *blk_new(const char *name, Error **errp)
+{
+    BlockBackend *blk;
+
+    assert(name && name[0]);
+    if (blk_by_name(name)) {
+        error_setg(errp, "Device with id '%s' already exists", name);
+        return NULL;
+    }
+
+    blk = g_new0(BlockBackend, 1);
+    blk->name = g_strdup(name);
+    blk->refcnt = 1;
+    QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
+    return blk;
+}
+
+static void blk_delete(BlockBackend *blk)
+{
+    assert(!blk->refcnt);
+    QTAILQ_REMOVE(&blk_backends, blk, link);
+    g_free(blk->name);
+    g_free(blk);
+}
+
+/*
+ * Increment @blk's reference count.
+ * @blk must not be null.
+ */
+void blk_ref(BlockBackend *blk)
+{
+    blk->refcnt++;
+}
+
+/*
+ * Decrement @blk's reference count.
+ * If this drops it to zero, destroy @blk.
+ * For convenience, do nothing if @blk is null.
+ */
+void blk_unref(BlockBackend *blk)
+{
+    if (blk) {
+        assert(blk->refcnt > 0);
+        if (!--blk->refcnt) {
+            blk_delete(blk);
+        }
+    }
+}
+
+/*
+ * Return the BlockBackend after @blk.
+ * If @blk is null, return the first one.
+ * Else, return @blk's next sibling, which may be null.
+ *
+ * To iterate over all BlockBackends, do
+ * for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
+ *     ...
+ * }
+ */
+BlockBackend *blk_next(BlockBackend *blk)
+{
+    return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
+}
+
+/*
+ * Return @blk's name, a non-null, non-empty string.
+ */
+const char *blk_name(BlockBackend *blk)
+{
+    return blk->name;
+}
+
+/*
+ * Return the BlockBackend with name @name if it exists, else null.
+ * @name must not be null.
+ */
+BlockBackend *blk_by_name(const char *name)
+{
+    BlockBackend *blk;
+
+    assert(name);
+    QTAILQ_FOREACH(blk, &blk_backends, link) {
+        if (!strcmp(name, blk->name)) {
+            return blk;
+        }
+    }
+    return NULL;
+}
diff --git a/blockdev.c b/blockdev.c
index cf06d6d..6b9cbf2 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -30,6 +30,7 @@
  * THE SOFTWARE.
  */
 
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/block/block.h"
 #include "block/blockjob.h"
@@ -216,7 +217,10 @@ static void bdrv_format_print(void *opaque, const char *name)
 
 void drive_del(DriveInfo *dinfo)
 {
+    BlockBackend *blk = blk_by_name(dinfo->id);
+
     bdrv_unref(dinfo->bdrv);
+    blk_unref(blk);
 }
 
 void drive_info_del(DriveInfo *dinfo)
@@ -305,6 +309,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
     int ro = 0;
     int bdrv_flags = 0;
     int on_read_error, on_write_error;
+    BlockBackend *blk;
     BlockDriverState *bs;
     DriveInfo *dinfo;
     ThrottleConfig cfg;
@@ -461,9 +466,13 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
     }
 
     /* init */
+    blk = blk_new(qemu_opts_id(opts), errp);
+    if (!blk) {
+        goto early_err;
+    }
     bs = bdrv_new_root(qemu_opts_id(opts), errp);
     if (!bs) {
-        goto early_err;
+        goto bdrv_new_err;
     }
     bs->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
     bs->read_only = ro;
@@ -529,6 +538,8 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
 
 err:
     bdrv_unref(bs);
+bdrv_new_err:
+    blk_unref(blk);
 early_err:
     qemu_opts_del(opts);
 err_no_opts:
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index 7f0f66b..265cf13 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -39,6 +39,7 @@
 #include "hw/xen/xen_backend.h"
 #include "xen_blkif.h"
 #include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 
 /* ------------------------------------------------------------- */
 
@@ -854,12 +855,18 @@ static int blk_connect(struct XenDevice *xendev)
     blkdev->dinfo = drive_get(IF_XEN, 0, index);
     if (!blkdev->dinfo) {
         Error *local_err = NULL;
+        BlockBackend *blk;
         BlockDriver *drv;
 
         /* setup via xenbus -> create new block driver instance */
         xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
+        blk = blk_new(blkdev->dev, NULL);
+        if (!blk) {
+            return -1;
+        }
         blkdev->bs = bdrv_new_root(blkdev->dev, NULL);
         if (!blkdev->bs) {
+            blk_unref(blk);
             return -1;
         }
 
@@ -870,6 +877,7 @@ static int blk_connect(struct XenDevice *xendev)
                           error_get_pretty(local_err));
             error_free(local_err);
             bdrv_unref(blkdev->bs);
+            blk_unref(blk);
             blkdev->bs = NULL;
             return -1;
         }
@@ -985,6 +993,9 @@ static void blk_disconnect(struct XenDevice *xendev)
     if (blkdev->bs) {
         bdrv_detach_dev(blkdev->bs, blkdev);
         bdrv_unref(blkdev->bs);
+        if (!blkdev->dinfo) {
+            blk_unref(blk_by_name(blkdev->dev));
+        }
         blkdev->bs = NULL;
     }
     xen_be_unbind_evtchn(&blkdev->xendev);
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 5f20b0e..198da2e 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -35,6 +35,7 @@ typedef struct MachineClass MachineClass;
 typedef struct NICInfo NICInfo;
 typedef struct HCIInfo HCIInfo;
 typedef struct AudioState AudioState;
+typedef struct BlockBackend BlockBackend;
 typedef struct BlockDriverState BlockDriverState;
 typedef struct DriveInfo DriveInfo;
 typedef struct DisplayState DisplayState;
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
new file mode 100644
index 0000000..198062a
--- /dev/null
+++ b/include/sysemu/block-backend.h
@@ -0,0 +1,26 @@
+/*
+ * QEMU Block backends
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * Authors:
+ *  Markus Armbruster <armbru@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1
+ * or later.  See the COPYING.LIB file in the top-level directory.
+ */
+
+#ifndef BLOCK_BACKEND_H
+#define BLOCK_BACKEND_H
+
+#include "qemu/typedefs.h"
+#include "qapi/error.h"
+
+BlockBackend *blk_new(const char *name, Error **errp);
+void blk_ref(BlockBackend *blk);
+void blk_unref(BlockBackend *blk);
+const char *blk_name(BlockBackend *blk);
+BlockBackend *blk_by_name(const char *name);
+BlockBackend *blk_next(BlockBackend *blk);
+
+#endif
diff --git a/qemu-img.c b/qemu-img.c
index 9c77dcc..bdb95a4 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -29,6 +29,7 @@
 #include "qemu/error-report.h"
 #include "qemu/osdep.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/block-backend.h"
 #include "block/block_int.h"
 #include "block/qapi.h"
 #include <getopt.h>
@@ -575,10 +576,11 @@ static int img_check(int argc, char **argv)
     int c, ret;
     OutputFormat output_format = OFORMAT_HUMAN;
     const char *filename, *fmt, *output, *cache;
+    BlockBackend *blk;
     BlockDriverState *bs;
     int fix = 0;
     int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
-    ImageCheck *check;
+    ImageCheck *check = NULL;
     bool quiet = false;
 
     fmt = NULL;
@@ -649,9 +651,11 @@ static int img_check(int argc, char **argv)
         return 1;
     }
 
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
     if (!bs) {
-        return 1;
+        ret = 1;
+        goto fail;
     }
 
     check = g_new0(ImageCheck, 1);
@@ -710,6 +714,7 @@ static int img_check(int argc, char **argv)
 fail:
     qapi_free_ImageCheck(check);
     bdrv_unref(bs);
+    blk_unref(blk);
 
     return ret;
 }
@@ -718,6 +723,7 @@ static int img_commit(int argc, char **argv)
 {
     int c, ret, flags;
     const char *filename, *fmt, *cache;
+    BlockBackend *blk;
     BlockDriverState *bs;
     bool quiet = false;
 
@@ -756,9 +762,11 @@ static int img_commit(int argc, char **argv)
         return 1;
     }
 
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
     if (!bs) {
-        return 1;
+        ret = -1;
+        goto out;
     }
     ret = bdrv_commit(bs);
     switch(ret) {
@@ -779,7 +787,9 @@ static int img_commit(int argc, char **argv)
         break;
     }
 
+out:
     bdrv_unref(bs);
+    blk_unref(blk);
     if (ret) {
         return 1;
     }
@@ -942,6 +952,7 @@ static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
 static int img_compare(int argc, char **argv)
 {
     const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
+    BlockBackend *blk1, *blk2;
     BlockDriverState *bs1, *bs2;
     int64_t total_sectors1, total_sectors2;
     uint8_t *buf1 = NULL, *buf2 = NULL;
@@ -1011,18 +1022,20 @@ static int img_compare(int argc, char **argv)
         goto out3;
     }
 
+    blk1 = blk_new("image_1", &error_abort);
     bs1 = bdrv_new_open("image_1", filename1, fmt1, flags, true, quiet);
     if (!bs1) {
         error_report("Can't open file %s", filename1);
         ret = 2;
-        goto out3;
+        goto out2;
     }
 
+    blk2 = blk_new("image_2", &error_abort);
     bs2 = bdrv_new_open("image_2", filename2, fmt2, flags, true, quiet);
     if (!bs2) {
         error_report("Can't open file %s", filename2);
         ret = 2;
-        goto out2;
+        goto out1;
     }
 
     buf1 = qemu_blockalign(bs1, IO_BUF_SIZE);
@@ -1183,11 +1196,14 @@ static int img_compare(int argc, char **argv)
     ret = 0;
 
 out:
-    bdrv_unref(bs2);
     qemu_vfree(buf1);
     qemu_vfree(buf2);
+out1:
+    bdrv_unref(bs2);
+    blk_unref(blk2);
 out2:
     bdrv_unref(bs1);
+    blk_unref(blk1);
 out3:
     qemu_progress_end();
     return ret;
@@ -1200,6 +1216,7 @@ static int img_convert(int argc, char **argv)
     int progress = 0, flags, src_flags;
     const char *fmt, *out_fmt, *cache, *src_cache, *out_baseimg, *out_filename;
     BlockDriver *drv, *proto_drv;
+    BlockBackend **blk = NULL, *out_blk = NULL;
     BlockDriverState **bs = NULL, *out_bs = NULL;
     int64_t total_sectors, nb_sectors, sector_num, bs_offset;
     int64_t *bs_sectors = NULL;
@@ -1354,6 +1371,7 @@ static int img_convert(int argc, char **argv)
 
     qemu_progress_print(0, 100);
 
+    blk = g_new0(BlockBackend *, bs_n);
     bs = g_new0(BlockDriverState *, bs_n);
     bs_sectors = g_new(int64_t, bs_n);
 
@@ -1361,6 +1379,7 @@ static int img_convert(int argc, char **argv)
     for (bs_i = 0; bs_i < bs_n; bs_i++) {
         char *id = bs_n > 1 ? g_strdup_printf("source_%d", bs_i)
                             : g_strdup("source");
+        blk[bs_i] = blk_new(id, &error_abort);
         bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, src_flags,
                                  true, quiet);
         g_free(id);
@@ -1486,6 +1505,7 @@ static int img_convert(int argc, char **argv)
         goto out;
     }
 
+    out_blk = blk_new("target", &error_abort);
     out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
     if (!out_bs) {
         ret = -1;
@@ -1740,6 +1760,7 @@ out:
     if (out_bs) {
         bdrv_unref(out_bs);
     }
+    blk_unref(out_blk);
     if (bs) {
         for (bs_i = 0; bs_i < bs_n; bs_i++) {
             if (bs[bs_i]) {
@@ -1748,6 +1769,12 @@ out:
         }
         g_free(bs);
     }
+    if (blk) {
+        for (bs_i = 0; bs_i < bs_n; bs_i++) {
+            blk_unref(blk[bs_i]);
+        }
+        g_free(blk);
+    }
     g_free(bs_sectors);
 fail_getopt:
     g_free(options);
@@ -1856,6 +1883,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
     filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
 
     while (filename) {
+        BlockBackend *blk;
         BlockDriverState *bs;
         ImageInfo *info;
         ImageInfoList *elem;
@@ -1867,9 +1895,11 @@ static ImageInfoList *collect_image_info_list(const char *filename,
         }
         g_hash_table_insert(filenames, (gpointer)filename, NULL);
 
+        blk = blk_new("image", &error_abort);
         bs = bdrv_new_open("image", filename, fmt,
                            BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
         if (!bs) {
+            blk_unref(blk);
             goto err;
         }
 
@@ -1878,6 +1908,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
             error_report("%s", error_get_pretty(err));
             error_free(err);
             bdrv_unref(bs);
+            blk_unref(blk);
             goto err;
         }
 
@@ -1887,6 +1918,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
         last = &elem->next;
 
         bdrv_unref(bs);
+        blk_unref(blk);
 
         filename = fmt = NULL;
         if (chain) {
@@ -2080,6 +2112,7 @@ static int img_map(int argc, char **argv)
 {
     int c;
     OutputFormat output_format = OFORMAT_HUMAN;
+    BlockBackend *blk;
     BlockDriverState *bs;
     const char *filename, *fmt, *output;
     int64_t length;
@@ -2128,9 +2161,11 @@ static int img_map(int argc, char **argv)
         return 1;
     }
 
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
     if (!bs) {
-        return 1;
+        ret = -1;
+        goto out;
     }
 
     if (output_format == OFORMAT_HUMAN) {
@@ -2173,6 +2208,7 @@ static int img_map(int argc, char **argv)
 
 out:
     bdrv_unref(bs);
+    blk_unref(blk);
     return ret < 0;
 }
 
@@ -2183,6 +2219,7 @@ out:
 
 static int img_snapshot(int argc, char **argv)
 {
+    BlockBackend *blk;
     BlockDriverState *bs;
     QEMUSnapshotInfo sn;
     char *filename, *snapshot_name = NULL;
@@ -2248,9 +2285,11 @@ static int img_snapshot(int argc, char **argv)
     filename = argv[optind++];
 
     /* Open the image */
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, NULL, bdrv_oflags, true, quiet);
     if (!bs) {
-        return 1;
+        ret = -1;
+        goto out;
     }
 
     /* Perform the requested action */
@@ -2294,7 +2333,9 @@ static int img_snapshot(int argc, char **argv)
     }
 
     /* Cleanup */
+out:
     bdrv_unref(bs);
+    blk_unref(blk);
     if (ret) {
         return 1;
     }
@@ -2303,6 +2344,7 @@ static int img_snapshot(int argc, char **argv)
 
 static int img_rebase(int argc, char **argv)
 {
+    BlockBackend *blk = NULL, *blk_old_backing = NULL, *blk_new_backing = NULL;
     BlockDriverState *bs = NULL, *bs_old_backing = NULL, *bs_new_backing = NULL;
     BlockDriver *old_backing_drv, *new_backing_drv;
     char *filename;
@@ -2391,6 +2433,7 @@ static int img_rebase(int argc, char **argv)
      * Ignore the old backing file for unsafe rebase in case we want to correct
      * the reference to a renamed or moved backing file.
      */
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
     if (!bs) {
         ret = -1;
@@ -2423,6 +2466,7 @@ static int img_rebase(int argc, char **argv)
     if (!unsafe) {
         char backing_name[1024];
 
+        blk_old_backing = blk_new("old_backing", &error_abort);
         bs_old_backing = bdrv_new_root("old_backing", &error_abort);
         bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
         ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
@@ -2434,6 +2478,7 @@ static int img_rebase(int argc, char **argv)
             goto out;
         }
         if (out_baseimg[0]) {
+            blk_new_backing = blk_new("new_backing", &error_abort);
             bs_new_backing = bdrv_new_root("new_backing", &error_abort);
             ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
                             new_backing_drv, &local_err);
@@ -2612,12 +2657,15 @@ out:
         if (bs_old_backing != NULL) {
             bdrv_unref(bs_old_backing);
         }
+        blk_unref(blk_old_backing);
         if (bs_new_backing != NULL) {
             bdrv_unref(bs_new_backing);
         }
+        blk_unref(blk_new_backing);
     }
 
     bdrv_unref(bs);
+    blk_unref(blk);
     if (ret) {
         return 1;
     }
@@ -2630,6 +2678,7 @@ static int img_resize(int argc, char **argv)
     const char *filename, *fmt, *size;
     int64_t n, total_size;
     bool quiet = false;
+    BlockBackend *blk = NULL;
     BlockDriverState *bs = NULL;
     QemuOpts *param;
     static QemuOptsList resize_options = {
@@ -2706,6 +2755,7 @@ static int img_resize(int argc, char **argv)
     n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
     qemu_opts_del(param);
 
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
                        true, quiet);
     if (!bs) {
@@ -2743,6 +2793,7 @@ out:
     if (bs) {
         bdrv_unref(bs);
     }
+    blk_unref(blk);
     if (ret) {
         return 1;
     }
@@ -2758,6 +2809,7 @@ static int img_amend(int argc, char **argv)
     const char *fmt = NULL, *filename, *cache;
     int flags;
     bool quiet = false;
+    BlockBackend *blk = NULL;
     BlockDriverState *bs = NULL;
 
     cache = BDRV_DEFAULT_CACHE;
@@ -2821,6 +2873,7 @@ static int img_amend(int argc, char **argv)
         goto out;
     }
 
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
     if (!bs) {
         error_report("Could not open image '%s'", filename);
@@ -2854,6 +2907,7 @@ out:
     if (bs) {
         bdrv_unref(bs);
     }
+    blk_unref(blk);
     qemu_opts_del(opts);
     qemu_opts_free(create_opts);
     g_free(options);
diff --git a/qemu-io.c b/qemu-io.c
index d131dc5..a8dc973 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -19,6 +19,7 @@
 #include "qemu/option.h"
 #include "qemu/config-file.h"
 #include "qemu/readline.h"
+#include "sysemu/block-backend.h"
 #include "block/block_int.h"
 #include "trace/control.h"
 
@@ -26,6 +27,7 @@
 
 static char *progname;
 
+static BlockBackend *qemuio_blk;
 static BlockDriverState *qemuio_bs;
 
 /* qemu-io commands passed using -c */
@@ -37,7 +39,9 @@ static ReadLineState *readline_state;
 static int close_f(BlockDriverState *bs, int argc, char **argv)
 {
     bdrv_unref(bs);
+    blk_unref(qemuio_blk);
     qemuio_bs = NULL;
+    qemuio_blk = NULL;
     return 0;
 }
 
@@ -58,6 +62,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
         return 1;
     }
 
+    qemuio_blk = blk_new("hda", &error_abort);
     qemuio_bs = bdrv_new_root("hda", &error_abort);
 
     if (growable) {
@@ -70,7 +75,9 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
                 error_get_pretty(local_err));
         error_free(local_err);
         bdrv_unref(qemuio_bs);
+        blk_unref(qemuio_blk);
         qemuio_bs = NULL;
+        qemuio_blk = NULL;
         return 1;
     }
 
@@ -484,6 +491,7 @@ int main(int argc, char **argv)
     if (qemuio_bs) {
         bdrv_unref(qemuio_bs);
     }
+    blk_unref(qemuio_blk);
     g_free(readline_state);
     return 0;
 }
diff --git a/qemu-nbd.c b/qemu-nbd.c
index d9f1749..634ba11 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -17,7 +17,7 @@
  */
 
 #include "qemu-common.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "block/block_int.h"
 #include "block/nbd.h"
 #include "qemu/main-loop.h"
@@ -384,6 +384,7 @@ static void nbd_accept(void *opaque)
 
 int main(int argc, char **argv)
 {
+    BlockBackend *blk;
     BlockDriverState *bs;
     BlockDriver *drv;
     off_t dev_offset = 0;
@@ -691,6 +692,7 @@ int main(int argc, char **argv)
         drv = NULL;
     }
 
+    blk = blk_new("hda", &error_abort);
     bs = bdrv_new_root("hda", &error_abort);
 
     srcpath = argv[optind];
@@ -774,6 +776,7 @@ int main(int argc, char **argv)
     } while (state != TERMINATED);
 
     bdrv_unref(bs);
+    blk_unref(blk);
     if (sockpath) {
         unlink(sockpath);
     }
