Index: uspace/lib/fdisk/src/fdisk.c
===================================================================
--- uspace/lib/fdisk/src/fdisk.c	(revision 99c23405e687595401687deb42d610a45b2fa761)
+++ uspace/lib/fdisk/src/fdisk.c	(revision 603c1d1f2f250c70a6ee5b7b75494f1ed4c16e1a)
@@ -317,4 +317,5 @@
 int fdisk_dev_open(fdisk_t *fdisk, service_id_t sid, fdisk_dev_t **rdev)
 {
+	vol_disk_info_t vinfo;
 	fdisk_dev_t *dev = NULL;
 	service_id_t *psids = NULL;
@@ -331,5 +332,16 @@
 	list_initialize(&dev->parts_ba);
 
-	printf("get info\n");
+	rc = vol_disk_info(fdisk->vol, sid, &vinfo);
+	if (rc != EOK) {
+		rc = EIO;
+		goto error;
+	}
+
+	dev->dcnt = vinfo.dcnt;
+
+	if (dev->dcnt != dc_label)
+		goto done;
+
+	printf("get label info\n");
 	rc = vbd_disk_info(fdisk->vbd, sid, &dev->dinfo);
 	if (rc != EOK) {
@@ -361,4 +373,5 @@
 
 	free(psids);
+done:
 	*rdev = dev;
 	return EOK;
Index: uspace/lib/label/include/std/gpt.h
===================================================================
--- uspace/lib/label/include/std/gpt.h	(revision 99c23405e687595401687deb42d610a45b2fa761)
+++ uspace/lib/label/include/std/gpt.h	(revision 603c1d1f2f250c70a6ee5b7b75494f1ed4c16e1a)
@@ -38,6 +38,14 @@
 #include <sys/types.h>
 
-/** Block address of GPT header. */
-#define GPT_HDR_BA	1
+enum {
+	/** Block address of primary GPT header. */
+	gpt_hdr_ba = 1,
+
+	/** Minimum size of partition table in bytes, required by std. */
+	gpt_ptable_min_size = 16384,
+
+	/** GPT revision */
+	gpt_revision = 0x00010000
+};
 
 /** GPT header */
Index: uspace/lib/label/include/types/liblabel.h
===================================================================
--- uspace/lib/label/include/types/liblabel.h	(revision 99c23405e687595401687deb42d610a45b2fa761)
+++ uspace/lib/label/include/types/liblabel.h	(revision 603c1d1f2f250c70a6ee5b7b75494f1ed4c16e1a)
@@ -111,4 +111,5 @@
 
 typedef struct {
+	uint64_t hdr_ba[2];
 	uint64_t ptable_ba[2];
 	size_t esize;
@@ -125,5 +126,5 @@
 	label_type_t ltype;
 	/** Block device service ID */
-	service_id_t svcid;
+	service_id_t svc_id;
 	/** Partitions */
 	list_t parts; /* of label_part_t */
Index: uspace/lib/label/src/gpt.c
===================================================================
--- uspace/lib/label/src/gpt.c	(revision 99c23405e687595401687deb42d610a45b2fa761)
+++ uspace/lib/label/src/gpt.c	(revision 603c1d1f2f250c70a6ee5b7b75494f1ed4c16e1a)
@@ -120,5 +120,5 @@
 	}
 
-	rc = block_read_direct(sid, GPT_HDR_BA, 1, gpt_hdr[0]);
+	rc = block_read_direct(sid, gpt_hdr_ba, 1, gpt_hdr[0]);
 	if (rc != EOK) {
 		rc = EIO;
@@ -200,5 +200,5 @@
 	label->ops = &gpt_label_ops;
 	label->ltype = lt_gpt;
-	label->svcid = sid;
+	label->svc_id = sid;
 	label->ablock0 = ba_min;
 	label->anblocks = ba_max - ba_min + 1;
@@ -206,4 +206,6 @@
 	label->block_size = bsize;
 
+	label->lt.gpt.hdr_ba[0] = gpt_hdr_ba;
+	label->lt.gpt.hdr_ba[1] = h1ba;
 	label->lt.gpt.ptable_ba[0] = ptba[0];
 	label->lt.gpt.ptable_ba[1] = ptba[1];
@@ -222,9 +224,143 @@
 static int gpt_create(service_id_t sid, label_t **rlabel)
 {
-	return EOK;
+	label_t *label = NULL;
+	gpt_header_t *gpt_hdr = NULL;
+	uint8_t *etable = NULL;
+	size_t bsize;
+	uint32_t num_entries;
+	uint32_t esize;
+	uint64_t ptba[2];
+	uint64_t hdr_ba[2];
+	uint64_t pt_blocks;
+	uint64_t ba_min, ba_max;
+	aoff64_t nblocks;
+	uint64_t resv_blocks;
+	int i, j;
+	int rc;
+
+	rc = block_get_bsize(sid, &bsize);
+	if (rc != EOK) {
+		rc = EIO;
+		goto error;
+	}
+
+	if (bsize < 512 || (bsize % 512) != 0) {
+		rc = EINVAL;
+		goto error;
+	}
+
+	rc = block_get_nblocks(sid, &nblocks);
+	if (rc != EOK) {
+		rc = EIO;
+		goto error;
+	}
+
+	/* Number of blocks of a partition table */
+	pt_blocks = gpt_ptable_min_size / bsize;
+	/* Minimum number of reserved (not allocatable) blocks */
+	resv_blocks = 3 + 2 * pt_blocks;
+
+	if (nblocks <= resv_blocks) {
+		rc = ENOSPC;
+		goto error;
+	}
+
+	hdr_ba[0] = gpt_hdr_ba;
+	hdr_ba[1] = nblocks - 1;
+	ptba[0] = 2;
+	ptba[1] = nblocks - 1 - pt_blocks;
+	ba_min = ptba[0] + pt_blocks;
+	ba_max = ptba[1] - 1;
+	esize = sizeof(gpt_entry_t);
+
+	num_entries = pt_blocks * bsize / sizeof(gpt_entry_t);
+
+	for (i = 0; i < 2; i++) {
+		gpt_hdr = calloc(1, bsize);
+		if (gpt_hdr == NULL) {
+			rc = ENOMEM;
+			goto error;
+		}
+
+		for (j = 0; j < 8; ++j)
+			gpt_hdr->efi_signature[j] = efi_signature[j];
+		gpt_hdr->revision = host2uint32_t_le(gpt_revision);
+		gpt_hdr->header_size = host2uint32_t_le(sizeof(gpt_header_t));
+		gpt_hdr->header_crc32 = 0; /* XXX */
+		gpt_hdr->my_lba = host2uint64_t_le(hdr_ba[i]);
+		gpt_hdr->alternate_lba = host2uint64_t_le(hdr_ba[1 - i]);
+		gpt_hdr->first_usable_lba = host2uint64_t_le(ba_min);
+		gpt_hdr->last_usable_lba = host2uint64_t_le(ba_max);
+		//gpt_hdr->disk_guid
+		gpt_hdr->entry_lba = host2uint64_t_le(ptba[i]);
+		gpt_hdr->num_entries = host2uint32_t_le(num_entries);
+		gpt_hdr->entry_size = host2uint32_t_le(esize);
+		gpt_hdr->pe_array_crc32 = 0; /* XXXX */
+
+		rc = block_write_direct(sid, hdr_ba[i], 1, gpt_hdr);
+		if (rc != EOK) {
+			rc = EIO;
+			goto error;
+		}
+
+		free(gpt_hdr);
+		gpt_hdr = NULL;
+
+		etable = calloc(num_entries, esize);
+		if (etable == NULL) {
+			rc = ENOMEM;
+			goto error;
+		}
+
+		rc = block_write_direct(sid, ptba[i], pt_blocks, etable);
+		if (rc != EOK) {
+			rc = EIO;
+			goto error;
+		}
+
+		free(etable);
+		etable = 0;
+	}
+
+	label = calloc(1, sizeof(label_t));
+	if (label == NULL)
+		return ENOMEM;
+
+	list_initialize(&label->parts);
+
+	label->ops = &gpt_label_ops;
+	label->ltype = lt_gpt;
+	label->svc_id = sid;
+	label->ablock0 = ba_min;
+	label->anblocks = ba_max - ba_min + 1;
+	label->pri_entries = num_entries;
+	label->block_size = bsize;
+
+	label->lt.gpt.hdr_ba[0] = hdr_ba[0];
+	label->lt.gpt.hdr_ba[1] = hdr_ba[1];
+	label->lt.gpt.ptable_ba[0] = ptba[0];
+	label->lt.gpt.ptable_ba[1] = ptba[1];
+	label->lt.gpt.esize = esize;
+
+	*rlabel = label;
+	return EOK;
+error:
+	free(etable);
+	free(gpt_hdr);
+	free(label);
+	return rc;
 }
 
 static void gpt_close(label_t *label)
 {
+	label_part_t *part;
+
+	part = gpt_part_first(label);
+	while (part != NULL) {
+		list_remove(&part->llabel);
+		free(part);
+		part = gpt_part_first(label);
+	}
+
 	free(label);
 }
@@ -232,5 +368,58 @@
 static int gpt_destroy(label_t *label)
 {
-	return EOK;
+	gpt_header_t *gpt_hdr = NULL;
+	uint8_t *etable = NULL;
+	label_part_t *part;
+	uint64_t pt_blocks;
+	int i;
+	int rc;
+
+	part = gpt_part_first(label);
+	if (part != NULL) {
+		rc = ENOTEMPTY;
+		goto error;
+	}
+
+	pt_blocks = label->pri_entries * label->lt.gpt.esize /
+	    label->block_size;
+
+	for (i = 0; i < 2; i++) {
+		gpt_hdr = calloc(1, label->block_size);
+		if (gpt_hdr == NULL) {
+			rc = ENOMEM;
+			goto error;
+		}
+
+		rc = block_write_direct(label->svc_id, label->lt.gpt.hdr_ba[i],
+		    1, gpt_hdr);
+		if (rc != EOK) {
+			rc = EIO;
+			goto error;
+		}
+
+		free(gpt_hdr);
+		gpt_hdr = NULL;
+
+		etable = calloc(label->pri_entries, label->lt.gpt.esize);
+		if (etable == NULL) {
+			rc = ENOMEM;
+			goto error;
+		}
+
+		rc = block_write_direct(label->svc_id,
+		    label->lt.gpt.ptable_ba[i], pt_blocks, etable);
+		if (rc != EOK) {
+			rc = EIO;
+			goto error;
+		}
+
+		free(etable);
+		etable = 0;
+	}
+
+	free(label);
+	return EOK;
+error:
+	return rc;
 }
 
@@ -426,5 +615,5 @@
 		    pos / label->block_size;
 
-		rc = block_read_direct(label->svcid, ba, 1, buf);
+		rc = block_read_direct(label->svc_id, ba, 1, buf);
 		if (rc != EOK) {
 			rc = EIO;
@@ -436,5 +625,5 @@
 		*e = *pte;
 
-		rc = block_write_direct(label->svcid, ba, 1, buf);
+		rc = block_write_direct(label->svc_id, ba, 1, buf);
 		if (rc != EOK) {
 			rc = EIO;
Index: uspace/lib/label/src/label.c
===================================================================
--- uspace/lib/label/src/label.c	(revision 99c23405e687595401687deb42d610a45b2fa761)
+++ uspace/lib/label/src/label.c	(revision 603c1d1f2f250c70a6ee5b7b75494f1ed4c16e1a)
@@ -41,7 +41,9 @@
 
 #include "gpt.h"
+#include "mbr.h"
 
 static label_ops_t *probe_list[] = {
 	&gpt_label_ops,
+	&mbr_label_ops,
 	NULL
 };
@@ -72,5 +74,5 @@
 		break;
 	case lt_mbr:
-		ops = NULL;
+		ops = &mbr_label_ops;
 		break;
 	}
Index: uspace/lib/label/src/mbr.c
===================================================================
--- uspace/lib/label/src/mbr.c	(revision 99c23405e687595401687deb42d610a45b2fa761)
+++ uspace/lib/label/src/mbr.c	(revision 603c1d1f2f250c70a6ee5b7b75494f1ed4c16e1a)
@@ -142,4 +142,6 @@
 	label->ops = &mbr_label_ops;
 	label->ltype = lt_mbr;
+	label->svc_id = sid;
+	label->block_size = bsize;
 	label->ablock0 = mbr_ablock0;
 	label->anblocks = nblocks - mbr_ablock0;
@@ -155,9 +157,78 @@
 static int mbr_create(service_id_t sid, label_t **rlabel)
 {
-	return EOK;
+	label_t *label = NULL;
+	mbr_br_block_t *mbr = NULL;
+	aoff64_t nblocks;
+	size_t bsize;
+	int i;
+	int rc;
+
+	rc = block_get_bsize(sid, &bsize);
+	if (rc != EOK) {
+		rc = EIO;
+		goto error;
+	}
+
+	rc = block_get_nblocks(sid, &nblocks);
+	if (rc != EOK) {
+		rc = EIO;
+		goto error;
+	}
+
+	mbr = calloc(1, bsize);
+	if (mbr == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	label = calloc(1, sizeof(label_t));
+	if (label == NULL)
+		return ENOMEM;
+
+	list_initialize(&label->parts);
+
+	mbr->media_id = 0;
+	mbr->pad0 = 0;
+	for (i = 0; i < mbr_nprimary; i++)
+		mbr_unused_pte(&mbr->pte[i]);
+	mbr->signature = host2uint16_t_le(mbr_br_signature);
+
+	rc = block_write_direct(sid, mbr_ba, 1, mbr);
+	if (rc != EOK) {
+		rc = EIO;
+		goto error;
+	}
+
+	free(mbr);
+	mbr = NULL;
+
+	label->ops = &mbr_label_ops;
+	label->ltype = lt_mbr;
+	label->block_size = bsize;
+	label->svc_id = sid;
+	label->ablock0 = mbr_ablock0;
+	label->anblocks = nblocks - mbr_ablock0;
+	label->pri_entries = mbr_nprimary;
+
+	*rlabel = label;
+	return EOK;
+error:
+	free(mbr);
+	free(label);
+	return rc;
 }
 
 static void mbr_close(label_t *label)
 {
+	label_part_t *part;
+
+	part = mbr_part_first(label);
+	while (part != NULL) {
+		list_remove(&part->llabel);
+		free(part);
+
+		part = mbr_part_first(label);
+	}
+
 	free(label);
 }
@@ -165,5 +236,34 @@
 static int mbr_destroy(label_t *label)
 {
-	return EOK;
+	mbr_br_block_t *mbr = NULL;
+	label_part_t *part;
+	int rc;
+
+	part = mbr_part_first(label);
+	if (part != NULL) {
+		rc = ENOTEMPTY;
+		goto error;
+	}
+
+	mbr = calloc(1, label->block_size);
+	if (mbr == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = block_write_direct(label->svc_id, mbr_ba, 1, mbr);
+	if (rc != EOK) {
+		rc = EIO;
+		goto error;
+	}
+
+	free(mbr);
+	mbr = NULL;
+
+	free(label);
+	return EOK;
+error:
+	free(mbr);
+	return rc;
 }
 
@@ -340,5 +440,5 @@
 		return ENOMEM;
 
-	rc = block_read_direct(label->svcid, mbr_ba, 1, br);
+	rc = block_read_direct(label->svc_id, mbr_ba, 1, br);
 	if (rc != EOK) {
 		rc = EIO;
@@ -348,5 +448,5 @@
 	br->pte[index] = *pte;
 
-	rc = block_write_direct(label->svcid, mbr_ba, 1, br);
+	rc = block_write_direct(label->svc_id, mbr_ba, 1, br);
 	if (rc != EOK) {
 		rc = EIO;
Index: uspace/srv/bd/part/guid_part/guid_part.c
===================================================================
--- uspace/srv/bd/part/guid_part/guid_part.c	(revision 99c23405e687595401687deb42d610a45b2fa761)
+++ uspace/srv/bd/part/guid_part/guid_part.c	(revision 603c1d1f2f250c70a6ee5b7b75494f1ed4c16e1a)
@@ -250,5 +250,5 @@
 	}
 
-	rc = block_read_direct(indev_sid, GPT_HDR_BA, 1, gpt_hdr);
+	rc = block_read_direct(indev_sid, gpt_hdr_ba, 1, gpt_hdr);
 	if (rc != EOK) {
 		printf(NAME ": Failed reading GPT header block.\n");
Index: uspace/srv/bd/vbd/disk.c
===================================================================
--- uspace/srv/bd/vbd/disk.c	(revision 99c23405e687595401687deb42d610a45b2fa761)
+++ uspace/srv/bd/vbd/disk.c	(revision 603c1d1f2f250c70a6ee5b7b75494f1ed4c16e1a)
@@ -223,4 +223,5 @@
 	}
 
+	log_msg(LOG_DEFAULT, LVL_NOTE, "block_init(%zu)", sid);
 	rc = block_init(EXCHANGE_SERIALIZE, sid, 2048);
 	if (rc != EOK) {
@@ -272,6 +273,8 @@
 error:
 	label_close(label);
-	if (block_inited)
+	if (block_inited) {
+		log_msg(LOG_DEFAULT, LVL_NOTE, "block_fini(%zu)", sid);
 		block_fini(sid);
+	}
 	if (disk != NULL)
 		free(disk->svc_name);
@@ -293,4 +296,6 @@
 	list_remove(&disk->ldisks);
 	label_close(disk->label);
+	log_msg(LOG_DEFAULT, LVL_NOTE, "block_fini(%zu)", sid);
+	block_fini(sid);
 	free(disk);
 	return EOK;
@@ -353,7 +358,11 @@
 	label_t *label;
 	vbds_disk_t *disk;
+	bool block_inited = false;
+	size_t block_size;
 	int rc;
 
 	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create(%zu)", sid);
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create(%zu) - chkdup", sid);
 
 	/* Check for duplicates */
@@ -362,8 +371,38 @@
 		return EEXISTS;
 
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create(%zu) - alloc", sid);
+
 	disk = calloc(1, sizeof(vbds_disk_t));
 	if (disk == NULL)
 		return ENOMEM;
 
+	rc = loc_service_get_name(sid, &disk->svc_name);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting disk service name.");
+		rc = EIO;
+		goto error;
+	}
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "block_init(%zu)", sid);
+	rc = block_init(EXCHANGE_SERIALIZE, sid, 2048);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed opening block device %s.",
+		    disk->svc_name);
+		rc = EIO;
+		goto error;
+	}
+
+	rc = block_get_bsize(sid, &block_size);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting block size of %s.",
+		    disk->svc_name);
+		rc = EIO;
+		goto error;
+	}
+
+	block_inited = true;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create(%zu) - label_create", sid);
+
 	rc = label_create(sid, ltype, &label);
 	if (rc != EOK)
@@ -372,7 +411,19 @@
 	disk->svc_id = sid;
 	disk->label = label;
+	disk->block_size = block_size;
+	list_initialize(&disk->parts);
+
 	list_append(&disk->ldisks, &vbds_disks);
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create(%zu) - success", sid);
 	return EOK;
 error:
+	log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create(%zu) - failure", sid);
+	if (block_inited) {
+		log_msg(LOG_DEFAULT, LVL_NOTE, "block_fini(%zu)", sid);
+		block_fini(sid);
+	}
+	if (disk != NULL)
+		free(disk->svc_name);
 	free(disk);
 	return rc;
@@ -397,4 +448,6 @@
 
 	list_remove(&disk->ldisks);
+	log_msg(LOG_DEFAULT, LVL_NOTE, "block_fini(%zu)", sid);
+	block_fini(sid);
 	free(disk);
 	return EOK;
Index: uspace/srv/volsrv/disk.c
===================================================================
--- uspace/srv/volsrv/disk.c	(revision 99c23405e687595401687deb42d610a45b2fa761)
+++ uspace/srv/volsrv/disk.c	(revision 603c1d1f2f250c70a6ee5b7b75494f1ed4c16e1a)
@@ -257,4 +257,34 @@
 }
 
+int vol_disk_label_create(vol_disk_t *disk, label_type_t ltype)
+{
+	int rc;
+
+	rc = vbd_label_create(vbd, disk->svc_id, ltype);
+	if (rc != EOK)
+		return rc;
+
+	disk->dcnt = dc_label;
+	disk->ltype = ltype;
+
+	return EOK;
+}
+
+int vol_disk_empty(vol_disk_t *disk)
+{
+	int rc;
+
+	if (disk->dcnt == dc_label) {
+		rc = vbd_label_delete(vbd, disk->svc_id);
+		if (rc != EOK)
+			return rc;
+	}
+
+	disk->dcnt = dc_empty;
+
+	return EOK;
+}
+
+
 /** @}
  */
Index: uspace/srv/volsrv/disk.h
===================================================================
--- uspace/srv/volsrv/disk.h	(revision 99c23405e687595401687deb42d610a45b2fa761)
+++ uspace/srv/volsrv/disk.h	(revision 603c1d1f2f250c70a6ee5b7b75494f1ed4c16e1a)
@@ -45,4 +45,6 @@
 extern int vol_disk_get_ids(service_id_t *, size_t, size_t *);
 extern int vol_disk_find_by_id(service_id_t, vol_disk_t **);
+extern int vol_disk_label_create(vol_disk_t *, label_type_t);
+extern int vol_disk_empty(vol_disk_t *);
 
 #endif
Index: uspace/srv/volsrv/volsrv.c
===================================================================
--- uspace/srv/volsrv/volsrv.c	(revision 99c23405e687595401687deb42d610a45b2fa761)
+++ uspace/srv/volsrv/volsrv.c	(revision 603c1d1f2f250c70a6ee5b7b75494f1ed4c16e1a)
@@ -146,6 +146,9 @@
 	}
 
-	disk->dcnt = dc_label;
-	disk->ltype = ltype;
+	rc = vol_disk_label_create(disk, ltype);
+	if (rc != EOK) {
+		async_answer_0(iid, EIO);
+		return;
+	}
 
 	async_answer_0(iid, EOK);
@@ -166,5 +169,9 @@
 	}
 
-	disk->dcnt = dc_empty;
+	rc = vol_disk_empty(disk);
+	if (rc != EOK) {
+		async_answer_0(iid, EIO);
+		return;
+	}
 
 	async_answer_0(iid, EOK);
