Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision 22fb7ab62c90645d53594ec9d4efb3974dd3167f)
+++ uspace/Makefile.common	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -123,4 +123,5 @@
 LIBBLOCK_PREFIX = $(LIB_PREFIX)/block
 LIBFDISK_PREFIX = $(LIB_PREFIX)/fdisk
+LIBLABEL_PREFIX = $(LIB_PREFIX)/label
 LIBFS_PREFIX = $(LIB_PREFIX)/fs
 LIBCLUI_PREFIX = $(LIB_PREFIX)/clui
Index: uspace/lib/c/generic/vbd.c
===================================================================
--- uspace/lib/c/generic/vbd.c	(revision 22fb7ab62c90645d53594ec9d4efb3974dd3167f)
+++ uspace/lib/c/generic/vbd.c	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -37,4 +37,5 @@
 #include <ipc/vbd.h>
 #include <loc.h>
+#include <mem.h>
 #include <stdlib.h>
 #include <types/label.h>
@@ -153,4 +154,157 @@
 }
 
+/** Get list of IDs into a buffer of fixed size.
+ *
+ * @param vbd      Virtual Block Device
+ * @param method   IPC method
+ * @param arg1     First argument
+ * @param id_buf   Buffer to store IDs
+ * @param buf_size Buffer size
+ * @param act_size Place to store actual size of complete data.
+ *
+ * @return EOK on success or negative error code.
+ */
+static int vbd_get_ids_once(vbd_t *vbd, sysarg_t method, sysarg_t arg1,
+    sysarg_t *id_buf, size_t buf_size, size_t *act_size)
+{
+	async_exch_t *exch = async_exchange_begin(vbd->sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, method, arg1, &answer);
+	int rc = async_data_read_start(exch, id_buf, buf_size);
+
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+
+	if (retval != EOK) {
+		return retval;
+	}
+
+	*act_size = IPC_GET_ARG1(answer);
+	return EOK;
+}
+
+/** Get list of IDs.
+ *
+ * Returns an allocated array of service IDs.
+ *
+ * @param vbd    Virtual Block Device
+ * @param method IPC method
+ * @param arg1   IPC argument 1
+ * @param data   Place to store pointer to array of IDs
+ * @param count  Place to store number of IDs
+ * @return       EOK on success or negative error code
+ */
+static int vbd_get_ids_internal(vbd_t *vbd, sysarg_t method, sysarg_t arg1,
+    sysarg_t **data, size_t *count)
+{
+	*data = NULL;
+	*count = 0;
+
+	size_t act_size = 0;
+	int rc = vbd_get_ids_once(vbd, method, arg1, NULL, 0, &act_size);
+	if (rc != EOK)
+		return rc;
+
+	size_t alloc_size = act_size;
+	service_id_t *ids = malloc(alloc_size);
+	if (ids == NULL)
+		return ENOMEM;
+
+	while (true) {
+		rc = vbd_get_ids_once(vbd, method, arg1, ids, alloc_size,
+		    &act_size);
+		if (rc != EOK)
+			return rc;
+
+		if (act_size <= alloc_size)
+			break;
+
+		alloc_size = act_size;
+		ids = realloc(ids, alloc_size);
+		if (ids == NULL)
+			return ENOMEM;
+	}
+
+	*count = act_size / sizeof(service_id_t);
+	*data = ids;
+	return EOK;
+}
+
+/** Get list of disks as array of service IDs.
+ *
+ * @param vbd   Virtual Block Device
+ * @param data  Place to store pointer to array
+ * @param count Place to store length of array (number of entries)
+ *
+ * @return EOK on success or negative error code
+ */
+int vbd_label_get_parts(vbd_t *vbd, service_id_t disk,
+    service_id_t **data, size_t *count)
+{
+	return vbd_get_ids_internal(vbd, VBD_LABEL_GET_PARTS, disk,
+	    data, count);
+}
+
+int vbd_part_get_info(vbd_t *vbd, vbd_part_id_t part, vbd_part_info_t *pinfo)
+{
+	async_exch_t *exch;
+	int retval;
+
+	exch = async_exchange_begin(vbd->sess);
+	retval = async_req_1_0(exch, VBD_PART_GET_INFO, part);
+	async_exchange_end(exch);
+
+	if (retval != EOK)
+		return EIO;
+
+	return EOK;
+}
+
+int vbd_part_create(vbd_t *vbd, service_id_t disk, vbd_part_spec_t *pspec,
+    vbd_part_id_t *rpart)
+{
+	async_exch_t *exch;
+	sysarg_t part;
+	int retval;
+
+	exch = async_exchange_begin(vbd->sess);
+	retval = async_req_1_1(exch, VBD_PART_CREATE, disk, &part);
+	async_exchange_end(exch);
+
+	if (retval != EOK)
+		return EIO;
+
+	*rpart = (vbd_part_id_t)part;
+	return EOK;
+}
+
+int vbd_part_delete(vbd_t *vbd, vbd_part_id_t part)
+{
+	async_exch_t *exch;
+	int retval;
+
+	exch = async_exchange_begin(vbd->sess);
+	retval = async_req_1_0(exch, VBD_PART_DELETE, part);
+	async_exchange_end(exch);
+
+	if (retval != EOK)
+		return EIO;
+
+	return EOK;
+}
+
+void vbd_pspec_init(vbd_part_spec_t *pspec)
+{
+	memset(pspec, 0, sizeof(vbd_part_spec_t));
+}
+
 /** @}
  */
Index: uspace/lib/c/include/ipc/vbd.h
===================================================================
--- uspace/lib/c/include/ipc/vbd.h	(revision 22fb7ab62c90645d53594ec9d4efb3974dd3167f)
+++ uspace/lib/c/include/ipc/vbd.h	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -41,5 +41,9 @@
 	VBD_DISK_INFO,
 	VBD_LABEL_CREATE,
-	VBD_LABEL_DELETE
+	VBD_LABEL_DELETE,
+	VBD_LABEL_GET_PARTS,
+	VBD_PART_GET_INFO,
+	VBD_PART_CREATE,
+	VBD_PART_DELETE,
 } vbd_request_t;
 
Index: uspace/lib/c/include/vbd.h
===================================================================
--- uspace/lib/c/include/vbd.h	(revision 22fb7ab62c90645d53594ec9d4efb3974dd3167f)
+++ uspace/lib/c/include/vbd.h	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -52,4 +52,12 @@
 } vbd_disk_info_t;
 
+typedef struct {
+} vbd_part_spec_t;
+
+typedef struct {
+} vbd_part_info_t;
+
+typedef sysarg_t vbd_part_id_t;
+
 extern int vbd_create(vbd_t **);
 extern void vbd_destroy(vbd_t *);
@@ -59,4 +67,11 @@
 extern int vbd_label_create(vbd_t *, service_id_t, label_type_t);
 extern int vbd_label_delete(vbd_t *, service_id_t);
+extern int vbd_label_get_parts(vbd_t *, service_id_t, service_id_t **,
+    size_t *);
+extern int vbd_part_get_info(vbd_t *, vbd_part_id_t, vbd_part_info_t *);
+extern int vbd_part_create(vbd_t *, service_id_t, vbd_part_spec_t *,
+    vbd_part_id_t *);
+extern int vbd_part_delete(vbd_t *, vbd_part_id_t);
+extern void vbd_pspec_init(vbd_part_spec_t *);
 
 #endif
Index: uspace/lib/fdisk/include/types/fdisk.h
===================================================================
--- uspace/lib/fdisk/include/types/fdisk.h	(revision 22fb7ab62c90645d53594ec9d4efb3974dd3167f)
+++ uspace/lib/fdisk/include/types/fdisk.h	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -41,4 +41,5 @@
 #include <stdint.h>
 #include <types/label.h>
+#include <vbd.h>
 #include <vol.h>
 
@@ -126,4 +127,6 @@
 	/** File system type */
 	fdisk_fstype_t fstype;
+	/** Partition ID */
+	vbd_part_id_t part_id;
 } fdisk_part_t;
 
@@ -147,4 +150,6 @@
 	/** Volume service */
 	vol_t *vol;
+	/** Virtual Block Device */
+	vbd_t *vbd;
 } fdisk_t;
 
Index: uspace/lib/fdisk/src/fdisk.c
===================================================================
--- uspace/lib/fdisk/src/fdisk.c	(revision 22fb7ab62c90645d53594ec9d4efb3974dd3167f)
+++ uspace/lib/fdisk/src/fdisk.c	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -43,4 +43,5 @@
 #include <stdlib.h>
 #include <str.h>
+#include <vbd.h>
 #include <vol.h>
 
@@ -71,24 +72,40 @@
 int fdisk_create(fdisk_t **rfdisk)
 {
-	fdisk_t *fdisk;
+	fdisk_t *fdisk = NULL;
 	int rc;
 
 	fdisk = calloc(1, sizeof(fdisk_t));
-	if (fdisk == NULL)
-		return ENOMEM;
+	if (fdisk == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
 
 	rc = vol_create(&fdisk->vol);
 	if (rc != EOK) {
-		free(fdisk);
-		return EIO;
+		rc = EIO;
+		goto error;
+	}
+
+	rc = vbd_create(&fdisk->vbd);
+	if (rc != EOK) {
+		rc = EIO;
+		goto error;
 	}
 
 	*rfdisk = fdisk;
 	return EOK;
+error:
+	fdisk_destroy(fdisk);
+
+	return rc;
 }
 
 void fdisk_destroy(fdisk_t *fdisk)
 {
+	if (fdisk == NULL)
+		return;
+
 	vol_destroy(fdisk->vol);
+	vbd_destroy(fdisk->vbd);
 	free(fdisk);
 }
@@ -368,8 +385,17 @@
 {
 	fdisk_part_t *part;
+	vbd_part_spec_t vpspec;
+	vbd_part_id_t partid;
+	int rc;
 
 	part = calloc(1, sizeof(fdisk_part_t));
 	if (part == NULL)
 		return ENOMEM;
+
+	rc = vbd_part_create(dev->fdisk->vbd, dev->sid, &vpspec, &partid);
+	if (rc != EOK) {
+		free(part);
+		return EIO;
+	}
 
 	part->dev = dev;
@@ -377,4 +403,5 @@
 	part->capacity = pspec->capacity;
 	part->fstype = pspec->fstype;
+	part->part_id = partid;
 
 	if (rpart != NULL)
@@ -385,4 +412,10 @@
 int fdisk_part_destroy(fdisk_part_t *part)
 {
+	int rc;
+
+	rc = vbd_part_delete(part->dev->fdisk->vbd, part->part_id);
+	if (rc != EOK)
+		return EIO;
+
 	list_remove(&part->ldev);
 	free(part);
Index: uspace/lib/label/include/label.h
===================================================================
--- uspace/lib/label/include/label.h	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
+++ uspace/lib/label/include/label.h	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup liblabel
+ * @{
+ */
+/**
+ * @file Disk label library.
+ */
+
+#ifndef LIBLABEL_LABEL_H_
+#define LIBLABEL_LABEL_H_
+
+#include <loc.h>
+#include <types/label.h>
+#include <types/liblabel.h>
+
+extern int label_open(service_id_t, label_t **);
+extern int label_create(service_id_t, label_type_t, label_t **);
+extern void label_close(label_t *);
+extern int label_destroy(label_t *);
+extern int label_get_info(label_t *, label_info_t *);
+
+extern label_part_t *label_part_first(label_t *);
+extern label_part_t *label_part_next(label_part_t *);
+
+extern int label_part_create(label_t *, label_part_spec_t *,
+    label_part_t **);
+extern int label_part_destroy(label_part_t *);
+extern void label_pspec_init(label_part_spec_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/label/include/types/liblabel.h
===================================================================
--- uspace/lib/label/include/types/liblabel.h	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
+++ uspace/lib/label/include/types/liblabel.h	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup liblabel
+ * @{
+ */
+/**
+ * @file Disk label library types.
+ */
+
+#ifndef LIBLABEL_TYPES_H_
+#define LIBLABEL_TYPES_H_
+
+#include <adt/list.h>
+#include <types/label.h>
+#include <vol.h>
+
+typedef struct {
+	/** Disk contents */
+	label_disk_cnt_t dcnt;
+	/** Label type */
+	label_type_t ltype;
+} label_info_t;
+
+/** Partition */
+typedef struct {
+	/** Containing label */
+	struct label *label;
+	/** Link to fdisk_dev_t.parts */
+	link_t ldev;
+	/** Capacity */
+//	fdisk_cap_t capacity;
+	/** File system type */
+//	fdisk_fstype_t fstype;
+} label_part_t;
+
+/** Specification of new partition */
+typedef struct {
+	/** Desired capacity */
+//	fdisk_cap_t capacity;
+	/** File system type */
+//	fdisk_fstype_t fstype;
+} label_part_spec_t;
+
+/** Label instance */
+typedef struct label {
+} label_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/label/src/label.c
===================================================================
--- uspace/lib/label/src/label.c	(revision 22fb7ab62c90645d53594ec9d4efb3974dd3167f)
+++ uspace/lib/label/src/label.c	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -34,4 +34,78 @@
  */
 
+#include <errno.h>
+#include <label.h>
+#include <mem.h>
+#include <stdlib.h>
+
+int label_open(service_id_t sid, label_t **rlabel)
+{
+	label_t *label;
+
+	label = calloc(1, sizeof(label_t));
+	if (label == NULL)
+		return ENOMEM;
+
+	*rlabel = label;
+	return EOK;
+}
+
+int label_create(service_id_t sid, label_type_t ltype, label_t **rlabel)
+{
+	label_t *label;
+
+	label = calloc(1, sizeof(label_t));
+	if (label == NULL)
+		return ENOMEM;
+
+	*rlabel = label;
+	return EOK;
+}
+
+void label_close(label_t *label)
+{
+	free(label);
+}
+
+int label_destroy(label_t *label)
+{
+	free(label);
+	return EOK;
+}
+
+int label_get_info(label_t *label, label_info_t *linfo)
+{
+	memset(linfo, 0, sizeof(label_info_t));
+	linfo->dcnt = dc_empty;
+	return EOK;
+}
+
+label_part_t *label_part_first(label_t *label)
+{
+	return NULL;
+}
+
+label_part_t *label_part_next(label_part_t *oart)
+{
+	return NULL;
+}
+
+
+int label_part_create(label_t *label, label_part_spec_t *pspec,
+    label_part_t **rpart)
+{
+	return ENOTSUP;
+}
+
+int label_part_destroy(label_part_t *part)
+{
+	return EOK;
+}
+
+void label_pspec_init(label_part_spec_t *pspec)
+{
+	memset(pspec, 0, sizeof(label_part_spec_t));
+}
+
 /** @}
  */
Index: uspace/srv/bd/vbd/Makefile
===================================================================
--- uspace/srv/bd/vbd/Makefile	(revision 22fb7ab62c90645d53594ec9d4efb3974dd3167f)
+++ uspace/srv/bd/vbd/Makefile	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -28,7 +28,16 @@
 
 USPACE_PREFIX = ../../..
+
+LIBS = \
+	$(LIBLABEL_PREFIX)/liblabel.a \
+	$(LIBBLOCK_PREFIX)/libblock.a
+
+EXTRA_CFLAGS = \
+	-I$(LIBLABEL_PREFIX)/include
+
 BINARY = vbd
 
 SOURCES = \
+	disk.c \
 	vbd.c
 
Index: uspace/srv/bd/vbd/disk.c
===================================================================
--- uspace/srv/bd/vbd/disk.c	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
+++ uspace/srv/bd/vbd/disk.c	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2015 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup vbd
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <adt/list.h>
+#include <errno.h>
+#include <io/log.h>
+#include <stdlib.h>
+#include <task.h>
+
+#include "disk.h"
+#include "types/vbd.h"
+
+static list_t vbds_disks; /* of vbds_disk_t */
+
+void vbds_disks_init(void)
+{
+	list_initialize(&vbds_disks);
+}
+
+static int vbds_disk_by_svcid(service_id_t sid, vbds_disk_t **rdisk)
+{
+	list_foreach(vbds_disks, ldisks, vbds_disk_t, disk) {
+		if (disk->svc_id == sid) {
+			*rdisk = disk;
+			return EOK;
+		}
+	}
+
+	return ENOENT;
+}
+
+static int vbds_part_add(vbds_disk_t *disk, label_part_t *lpart)
+{
+	vbds_part_t *part;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_part_add(%p, %p)",
+	    disk, lpart);
+
+	part = calloc(1, sizeof(vbds_part_t));
+	if (part == NULL) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
+		return ENOMEM;
+	}
+
+	part->lpart = lpart;
+	part->disk = disk;
+	list_append(&part->ldisk, &disk->parts);
+
+	return EOK;
+}
+
+int vbds_disk_add(service_id_t sid)
+{
+	label_t *label;
+	label_part_t *part;
+	vbds_disk_t *disk;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_disk_add(%zu)", sid);
+
+	/* Check for duplicates */
+	rc = vbds_disk_by_svcid(sid, &disk);
+	if (rc == EOK)
+		return EEXISTS;
+
+	disk = calloc(1, sizeof(vbds_disk_t));
+	if (disk == NULL)
+		return ENOMEM;
+
+	rc = label_open(sid, &label);
+	if (rc != EOK)
+		goto error;
+
+	disk->svc_id = sid;
+	disk->label = label;
+	list_initialize(&disk->parts);
+	list_append(&disk->ldisks, &vbds_disks);
+
+	part = label_part_first(label);
+	while (part != NULL) {
+		rc = vbds_part_add(disk, part);
+		if (rc != EOK) {
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding partition.");
+		}
+
+		part = label_part_next(part);
+	}
+
+	return EOK;
+error:
+	free(disk);
+	return rc;
+}
+
+int vbds_disk_remove(service_id_t sid)
+{
+	vbds_disk_t *disk;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_disk_remove(%zu)", sid);
+
+	rc = vbds_disk_by_svcid(sid, &disk);
+	if (rc != EOK)
+		return rc;
+
+	list_remove(&disk->ldisks);
+	label_close(disk->label);
+	free(disk);
+	return EOK;
+}
+
+int vbds_disk_info(service_id_t sid, vbds_disk_info_t *info)
+{
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_disk_info(%zu)", sid);
+	info->ltype = lt_mbr;
+	return EOK;
+}
+
+int vbds_label_create(service_id_t sid, label_type_t ltype)
+{
+	label_t *label;
+	vbds_disk_t *disk;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create(%zu)", sid);
+
+	/* Check for duplicates */
+	rc = vbds_disk_by_svcid(sid, &disk);
+	if (rc == EOK)
+		return EEXISTS;
+
+	disk = calloc(1, sizeof(vbds_disk_t));
+	if (disk == NULL)
+		return ENOMEM;
+
+	rc = label_create(sid, ltype, &label);
+	if (rc != EOK)
+		goto error;
+
+	disk->svc_id = sid;
+	disk->label = label;
+	list_append(&disk->ldisks, &vbds_disks);
+	return EOK;
+error:
+	free(disk);
+	return rc;
+}
+
+int vbds_label_delete(service_id_t sid)
+{
+	return EOK;
+	vbds_disk_t *disk;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_delete(%zu)", sid);
+
+	rc = vbds_disk_by_svcid(sid, &disk);
+	if (rc != EOK)
+		return rc;
+
+	rc = label_destroy(disk->label);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed deleting label.");
+		return rc;
+	}
+
+	list_remove(&disk->ldisks);
+	free(disk);
+	return EOK;
+}
+
+int vbds_part_get_info(vbds_part_id_t part, vbds_part_info_t *pinfo)
+{
+	return EOK;
+}
+
+int vbds_part_create(service_id_t disk, vbds_part_id_t *rpart)
+{
+	return EOK;
+}
+
+int vbds_part_delete(vbds_part_id_t part)
+{
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/bd/vbd/disk.h
===================================================================
--- uspace/srv/bd/vbd/disk.h	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
+++ uspace/srv/bd/vbd/disk.h	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup vbd
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef DISK_H_
+#define DISK_H_
+
+#include <loc.h>
+#include "types/vbd.h"
+
+extern void vbds_disks_init(void);
+extern int vbds_disk_add(service_id_t);
+extern int vbds_disk_remove(service_id_t);
+extern int vbds_disk_info(service_id_t, vbds_disk_info_t *);
+extern int vbds_label_create(service_id_t, label_type_t);
+extern int vbds_label_delete(service_id_t);
+extern int vbds_part_get_info(vbds_part_id_t, vbds_part_info_t *);
+extern int vbds_part_create(service_id_t, vbds_part_id_t *);
+extern int vbds_part_delete(vbds_part_id_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/bd/vbd/types/vbd.h
===================================================================
--- uspace/srv/bd/vbd/types/vbd.h	(revision 22fb7ab62c90645d53594ec9d4efb3974dd3167f)
+++ uspace/srv/bd/vbd/types/vbd.h	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -35,14 +35,46 @@
  */
 
-#ifndef TYPES_VBD_H_
-#define TYPES_VBD_H_
+#ifndef TYPES_VBDS_H_
+#define TYPES_VBDS_H_
 
+#include <adt/list.h>
+#include <label.h>
+#include <loc.h>
 #include <types/label.h>
 
 /** Disk info */
 typedef struct {
+	/** Label */
+	label_t *label;
 	/** Label type */
 	label_type_t ltype;
-} vbd_disk_info_t;
+} vbds_disk_info_t;
+
+/** Partition */
+typedef struct {
+	/** Disk this partition belongs to */
+	struct vbds_disk *disk;
+	/** Link to vbds_disk_t.parts */
+	link_t ldisk;
+	/** Label partition */
+	label_part_t *lpart;
+} vbds_part_t;
+
+/** Disk */
+typedef struct vbds_disk {
+	/** Link to vbds_disks */
+	link_t ldisks;
+	/** Service ID */
+	service_id_t svc_id;
+	/** Label */
+	label_t *label;
+	/** Partitions */
+	list_t parts; /* of vbds_part_t */
+} vbds_disk_t;
+
+typedef struct {
+} vbds_part_info_t;
+
+typedef sysarg_t vbds_part_id_t;
 
 #endif
Index: uspace/srv/bd/vbd/vbd.c
===================================================================
--- uspace/srv/bd/vbd/vbd.c	(revision 22fb7ab62c90645d53594ec9d4efb3974dd3167f)
+++ uspace/srv/bd/vbd/vbd.c	(revision 28ed0d952e53138af66cace5b8439cbfaeda61ca)
@@ -44,16 +44,19 @@
 #include <task.h>
 
+#include "disk.h"
 #include "types/vbd.h"
 
 #define NAME  "vbd"
 
-static void vbd_client_conn(ipc_callid_t, ipc_call_t *, void *);
-
-static int vbd_init(void)
-{
-	int rc;
-	log_msg(LOG_DEFAULT, LVL_NOTE, "vbd_init()");
-
-	async_set_client_connection(vbd_client_conn);
+static void vbds_client_conn(ipc_callid_t, ipc_call_t *, void *);
+
+static int vbds_init(void)
+{
+	int rc;
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_init()");
+
+	vbds_disks_init();
+
+	async_set_client_connection(vbds_client_conn);
 
 	rc = loc_server_register(NAME);
@@ -73,75 +76,43 @@
 }
 
-static int vbd_disk_add(service_id_t sid)
-{
-	log_msg(LOG_DEFAULT, LVL_NOTE, "vbd_disk_add(%zu)", sid);
-	return EOK;
-}
-
-static int vbd_disk_remove(service_id_t sid)
-{
-	log_msg(LOG_DEFAULT, LVL_NOTE, "vbd_disk_remove(%zu)", sid);
-	return EOK;
-}
-
-static int vbd_disk_info(service_id_t sid, vbd_disk_info_t *info)
-{
-	log_msg(LOG_DEFAULT, LVL_NOTE, "vbd_disk_info(%zu)", sid);
-	info->ltype = lt_mbr;
-	return EOK;
-}
-
-static int vbd_label_create(service_id_t sid, label_type_t ltype)
-{
-	log_msg(LOG_DEFAULT, LVL_NOTE, "vbd_label_create(%zu, %d)", sid,
-	    ltype);
-	return EOK;
-}
-
-static int vbd_label_delete(service_id_t sid, label_type_t ltype)
-{
-	log_msg(LOG_DEFAULT, LVL_NOTE, "vbd_label_delete(%zu, %d)", sid,
-	    ltype);
-	return EOK;
-}
-
-static void vbd_disk_add_srv(ipc_callid_t iid, ipc_call_t *icall)
-{
-	service_id_t disk_sid;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_NOTE, "vbd_disk_add_srv()");
-
-	disk_sid = IPC_GET_ARG1(*icall);
-	rc = vbd_disk_add(disk_sid);
-	async_answer_0(iid, (sysarg_t) rc);
-}
-
-static void vbd_disk_remove_srv(ipc_callid_t iid, ipc_call_t *icall)
-{
-	service_id_t disk_sid;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_NOTE, "vbd_disk_remove_srv()");
-
-	disk_sid = IPC_GET_ARG1(*icall);
-	rc = vbd_disk_remove(disk_sid);
-	async_answer_0(iid, (sysarg_t) rc);
-}
-
-static void vbd_disk_info_srv(ipc_callid_t iid, ipc_call_t *icall)
-{
-	service_id_t disk_sid;
-	vbd_disk_info_t dinfo;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_NOTE, "vbd_disk_info_srv()");
-
-	disk_sid = IPC_GET_ARG1(*icall);
-	rc = vbd_disk_info(disk_sid, &dinfo);
+
+static void vbds_disk_add_srv(ipc_callid_t iid, ipc_call_t *icall)
+{
+	service_id_t disk_sid;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_disk_add_srv()");
+
+	disk_sid = IPC_GET_ARG1(*icall);
+	rc = vbds_disk_add(disk_sid);
+	async_answer_0(iid, (sysarg_t) rc);
+}
+
+static void vbds_disk_remove_srv(ipc_callid_t iid, ipc_call_t *icall)
+{
+	service_id_t disk_sid;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_disk_remove_srv()");
+
+	disk_sid = IPC_GET_ARG1(*icall);
+	rc = vbds_disk_remove(disk_sid);
+	async_answer_0(iid, (sysarg_t) rc);
+}
+
+static void vbds_disk_info_srv(ipc_callid_t iid, ipc_call_t *icall)
+{
+	service_id_t disk_sid;
+	vbds_disk_info_t dinfo;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_disk_info_srv()");
+
+	disk_sid = IPC_GET_ARG1(*icall);
+	rc = vbds_disk_info(disk_sid, &dinfo);
 	async_answer_1(iid, (sysarg_t)rc, (sysarg_t)dinfo.ltype);
 }
 
-static void vbd_label_create_srv(ipc_callid_t iid, ipc_call_t *icall)
+static void vbds_label_create_srv(ipc_callid_t iid, ipc_call_t *icall)
 {
 	service_id_t disk_sid;
@@ -149,29 +120,78 @@
 	int rc;
 
-	log_msg(LOG_DEFAULT, LVL_NOTE, "vbd_label_create_srv()");
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create_srv()");
 
 	disk_sid = IPC_GET_ARG1(*icall);
 	ltype = IPC_GET_ARG2(*icall);
-	rc = vbd_label_create(disk_sid, ltype);
-	async_answer_0(iid, (sysarg_t) rc);
-}
-
-static void vbd_label_delete_srv(ipc_callid_t iid, ipc_call_t *icall)
-{
-	service_id_t disk_sid;
-	label_type_t ltype;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_NOTE, "vbd_label_delete_srv()");
-
-	disk_sid = IPC_GET_ARG1(*icall);
-	ltype = IPC_GET_ARG2(*icall);
-	rc = vbd_label_delete(disk_sid, ltype);
-	async_answer_0(iid, (sysarg_t) rc);
-}
-
-static void vbd_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	log_msg(LOG_DEFAULT, LVL_NOTE, "vbd_client_conn()");
+	rc = vbds_label_create(disk_sid, ltype);
+	async_answer_0(iid, (sysarg_t) rc);
+}
+
+static void vbds_label_delete_srv(ipc_callid_t iid, ipc_call_t *icall)
+{
+	service_id_t disk_sid;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_delete_srv()");
+
+	disk_sid = IPC_GET_ARG1(*icall);
+	rc = vbds_label_delete(disk_sid);
+	async_answer_0(iid, (sysarg_t) rc);
+}
+
+static void vbds_label_get_parts_srv(ipc_callid_t iid, ipc_call_t *icall)
+{
+//	service_id_t disk_sid;
+//	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_get_parts_srv()");
+
+//	disk_sid = IPC_GET_ARG1(*icall);
+//	rc = vbds_label_delete(disk_sid);
+//	async_answer_0(iid, (sysarg_t) rc);
+	async_answer_0(iid, ENOTSUP);
+}
+
+static void vbds_part_get_info_srv(ipc_callid_t iid, ipc_call_t *icall)
+{
+	vbds_part_id_t part;
+	vbds_part_info_t pinfo;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_part_get_info_srv()");
+
+	part = IPC_GET_ARG1(*icall);
+	rc = vbds_part_get_info(part, &pinfo);
+	async_answer_0(iid, (sysarg_t)rc);
+}
+
+static void vbds_part_create_srv(ipc_callid_t iid, ipc_call_t *icall)
+{
+	service_id_t disk_sid;
+	vbds_part_id_t part;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_part_create_srv()");
+
+	disk_sid = IPC_GET_ARG1(*icall);
+	rc = vbds_part_create(disk_sid, &part);
+	async_answer_1(iid, (sysarg_t)rc, (sysarg_t)part);
+}
+
+static void vbds_part_delete_srv(ipc_callid_t iid, ipc_call_t *icall)
+{
+	vbds_part_id_t part;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_part_delete_srv()");
+
+	part = IPC_GET_ARG1(*icall);
+	rc = vbds_part_delete(part);
+	async_answer_0(iid, (sysarg_t) rc);
+}
+
+static void vbds_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_client_conn()");
 
 	/* Accept the connection */
@@ -191,17 +211,29 @@
 		switch (method) {
 		case VBD_DISK_ADD:
-			vbd_disk_add_srv(callid, &call);
+			vbds_disk_add_srv(callid, &call);
 			break;
 		case VBD_DISK_REMOVE:
-			vbd_disk_remove_srv(callid, &call);
+			vbds_disk_remove_srv(callid, &call);
 			break;
 		case VBD_DISK_INFO:
-			vbd_disk_info_srv(callid, &call);
+			vbds_disk_info_srv(callid, &call);
 			break;
 		case VBD_LABEL_CREATE:
-			vbd_label_create_srv(callid, &call);
+			vbds_label_create_srv(callid, &call);
 			break;
 		case VBD_LABEL_DELETE:
-			vbd_label_delete_srv(callid, &call);
+			vbds_label_delete_srv(callid, &call);
+			break;
+		case VBD_LABEL_GET_PARTS:
+			vbds_label_get_parts_srv(callid, &call);
+			break;
+		case VBD_PART_GET_INFO:
+			vbds_part_get_info_srv(callid, &call);
+			break;
+		case VBD_PART_CREATE:
+			vbds_part_create_srv(callid, &call);
+			break;
+		case VBD_PART_DELETE:
+			vbds_part_delete_srv(callid, &call);
 			break;
 		default:
@@ -222,5 +254,5 @@
 	}
 
-	rc = vbd_init();
+	rc = vbds_init();
 	if (rc != EOK)
 		return 1;
