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;
