diff --git a/.gitignore b/.gitignore
index 6d2acab..7221431 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
-config-devices.*
-config-all-devices.*
+config-devices.* config-all-devices.*
 config-host.*
 config-target.*
 trace.h
diff --git a/Makefile.objs b/Makefile.objs
index 01587c8..a355061 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -171,6 +171,15 @@ common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
 common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o xenfb.o xen_disk.o xen_nic.o
 
 ######################################################################
+# libvdisk
+
+vdisk-obj-y = $(block-obj-y)
+
+vdisk-obj-y += qemu-tool.o qemu-error.o vdisk.o
+vdisk-obj-y += $(oslib-obj-y) $(trace-obj-y) $(block-obj-y)
+vdisk-obj-y += $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
+
+######################################################################
 # libuser
 
 user-obj-y =
diff --git a/libvdisk/Makefile b/libvdisk/Makefile
new file mode 100644
index 0000000..6b0a28f
--- /dev/null
+++ b/libvdisk/Makefile
@@ -0,0 +1,53 @@
+# Makefile for libvdisk.
+
+include ../config-host.mak
+include $(SRC_PATH)/rules.mak
+BUILD_DIR=$(CURDIR)
+
+.PHONY: all libvdisk block trace install uninstall
+
+$(call set-vpath, $(SRC_PATH))
+
+QEMU_CFLAGS+=-I.. -fPIC -I$(BUILD_DIR)
+
+include $(SRC_PATH)/Makefile.objs
+
+libvdisk: block block.o libvdisk.so.1.0
+
+$(BUILD_DIR)/config-host.mak: ../config-host.mak
+	ln -sf $< $@
+
+# Copy because I build the obj with -fPIC which is not needed
+# for regular qemu build
+block: trace
+	mkdir -p block
+	ln -sf $(SRC_PATH)/block/*.[ch] block
+trace: trace.h
+	mkdir -p trace
+	ln -sf $(SRC_PATH)/trace/*.[chd] trace
+
+libvdisk.so.1.0: $(vdisk-obj-y)
+	$(LD) -shared -soname $@ -o $@ -lc $^
+
+install: libvdisk
+	$(INSTALL) vdisk.h $(PREFIX)$(includedir)
+	$(INSTALL) libvdisk.so.1.0 $(PREFIX)$(libdir)
+	ln -sf $(PREFIX)$(libdir)/libvdisk.so.1.0 $(PREFIX)$(libdir)/libvdisk.so.1
+	ln -sf $(PREFIX)$(libdir)/libvdisk.so.1.0 $(PREFIX)$(libdir)/libvdisk.so
+
+uninstall:
+	rm -rf $(PREFIX)$(includedir)/vdisk
+	rm -f $(PREFIX)$(libdir)/libvdisk.so.*
+
+all: libvdisk
+
+clean:
+	rm -rf block/
+	rm -rf trace/
+	rm -f *.[od]
+	rm -f *.mak
+	rm -f trace*
+	rm -f libvdisk.so.*
+
+# Include automatically generated dependency files
+-include $(wildcard *.d */*.d)
diff --git a/libvdisk/vdisk.c b/libvdisk/vdisk.c
new file mode 100644
index 0000000..d28862d
--- /dev/null
+++ b/libvdisk/vdisk.c
@@ -0,0 +1,134 @@
+#include "vdisk.h"
+
+#include <pthread.h>
+#include "block.h"
+
+typedef struct t_virtual_disk {
+    BlockDriverState *bs;
+    pthread_mutex_t mtx;
+
+} VirtualDisk;
+
+void vdisk_init(void) {
+    bdrv_init();
+}
+
+static int open_bdrv_from_path(const char* path, BlockDriverState** bs,
+        int flags, const char* format) {
+    int rc;
+    BlockDriver* driver;
+
+    *bs = bdrv_new(path);
+    if (format == NULL) {
+        driver = NULL;
+    } else {
+        driver = bdrv_find_format(format);
+        if (driver == NULL) {
+            return -EINVAL;
+        }
+    }
+
+    rc = bdrv_open(*bs, path, flags, driver);
+    if (rc < 0) {
+        bdrv_delete(*bs);
+    }
+    return rc;
+}
+
+int vdisk_create(const char *filename, const char *fmt,
+                 const char *base_filename, const char *base_fmt,
+                 char *options, uint64_t img_size, int flags) {
+
+    return bdrv_img_create(filename, fmt, base_filename, base_fmt,
+            options, img_size, flags);
+}
+
+int vdisk_open(VDD* vdd, const char* pathname, int flags, const char* format) {
+    int rc;
+    VirtualDisk* vd = malloc(sizeof(VirtualDisk));
+    if (!vd) { return -ENOMEM; }
+
+    rc = open_bdrv_from_path(pathname, &vd->bs, flags, format);
+    if (rc < 0) {
+        goto free_vd;
+    }
+
+    rc = pthread_mutex_init(&vd->mtx, NULL);
+    if (rc != 0) {
+        rc = -rc;
+        goto free_bs;
+    }
+
+    vdd->virtual_disk = vd;
+
+    return 0;
+
+free_bs:
+    bdrv_delete(vd->bs);
+free_vd:
+    free(vd);
+    return rc;
+}
+
+ssize_t vdisk_pread(VDD* vdd, void *buf, size_t count, off_t offset) {
+    int rc;
+    uint64_t totalSectors;
+    VirtualDisk* vd = vdd->virtual_disk;
+    if (!vd) {
+        return -EBADF;
+    }
+
+    pthread_mutex_lock(&vd->mtx);
+    bdrv_get_geometry(vd->bs, &totalSectors);
+    if ((totalSectors * 512) <= offset) {
+        rc = 0;
+        goto end;
+    }
+
+    rc = bdrv_pread(vd->bs, offset, buf, count);
+end:
+    pthread_mutex_unlock(&vd->mtx);
+    return rc;
+}
+
+ssize_t vdisk_pwrite(VDD* vdd, const void *buf, size_t count, off_t offset) {
+    int rc;
+    uint64_t totalSectors;
+    VirtualDisk* vd = vdd->virtual_disk;
+    if (!vd) {
+        return -EBADF;
+    }
+
+    pthread_mutex_lock(&vd->mtx);
+    bdrv_get_geometry(vd->bs, &totalSectors);
+    if ((totalSectors * 512) <= offset) {
+        rc = 0;
+        goto end;
+    }
+
+    rc = bdrv_pwrite(vd->bs, offset, buf, count);
+end:
+    pthread_mutex_unlock(&vd->mtx);
+    return rc;
+}
+
+int vdisk_flush(VDD* vdd) {
+    VirtualDisk* vd = vdd->virtual_disk;
+    if (!vd) {
+        return -EBADF;
+    }
+
+    return bdrv_flush(vd->bs);
+}
+
+int vdisk_close(VDD* vdd) {
+    VirtualDisk* vd = vdd->virtual_disk;
+    if (!vd) {
+        return -EBADF;
+    }
+
+    bdrv_flush(vd->bs);
+    bdrv_delete(vd->bs);
+    memset(vdd, 0, sizeof(VDD));
+    return 0;
+}
diff --git a/libvdisk/vdisk.h b/libvdisk/vdisk.h
new file mode 100644
index 0000000..6dba7a3
--- /dev/null
+++ b/libvdisk/vdisk.h
@@ -0,0 +1,27 @@
+#include <unistd.h>
+#include <inttypes.h>
+
+#define VDISK_O_RDWR        0x0002
+#define VDISK_O_SNAPSHOT    0x0008 /* open the file read only and save writes in a snapshot */
+#define VDISK_O_NOCACHE     0x0020 /* do not use the host page cache */
+#define VDISK_O_CACHE_WB    0x0040 /* use write-back caching */
+#define VDISK_O_NATIVE_AIO  0x0080 /* use native AIO instead of the thread pool */
+#define VDISK_O_NO_BACKING  0x0100 /* don't open the backing file */
+#define VDISK_O_NO_FLUSH    0x0200 /* disable flushing on this disk */
+
+#define DEFAULT_MAX_DESCIPTORS 1000
+
+typedef struct t_virtual_disk_descriptor {
+    void* virtual_disk;
+} VDD;
+
+void vdisk_init(void);
+
+int vdisk_create(const char *filename, const char *fmt,
+                 const char *base_filename, const char *base_fmt,
+                 char *options, uint64_t img_size, int flags);
+int vdisk_open(VDD* vdd, const char* pathname, int flags, const char* format);
+ssize_t vdisk_pread(VDD* vdd, void *buf, size_t count, off_t offset);
+ssize_t vdisk_pwrite(VDD* vdd, const void *buf, size_t count, off_t offset);
+int vdisk_flush(VDD* vdd);
+int vdisk_close(VDD* vdd);
