Index: uspace/lib/label/Makefile
===================================================================
--- uspace/lib/label/Makefile	(revision 94c05b89b35e97bd16e44d00f32fdf77dcd0470c)
+++ uspace/lib/label/Makefile	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
@@ -34,4 +34,5 @@
 SOURCES = \
 	src/dummy.c \
+	src/empty.c \
 	src/mbr.c \
 	src/gpt.c \
Index: pace/lib/label/include/label.h
===================================================================
--- uspace/lib/label/include/label.h	(revision 94c05b89b35e97bd16e44d00f32fdf77dcd0470c)
+++ 	(revision )
@@ -1,61 +1,0 @@
-/*
- * 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 <types/label.h>
-#include <types/liblabel.h>
-
-extern int label_open(label_bd_t *, label_t **);
-extern int label_create(label_bd_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 void label_part_get_info(label_part_t *, label_part_info_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 *);
-extern int label_suggest_ptype(label_t *, label_pcnt_t, label_ptype_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/label/include/label/empty.h
===================================================================
--- uspace/lib/label/include/label/empty.h	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
+++ uspace/lib/label/include/label/empty.h	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
@@ -0,0 +1,50 @@
+/*
+ * 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
+ * @brief
+ */
+
+#ifndef LABEL_EMPTY_H_
+#define LABEL_EMPTY_H_
+
+#include <loc.h>
+#include <types/liblabel.h>
+
+extern int label_bd_is_empty(label_bd_t *, bool *);
+extern int label_bd_empty(label_bd_t *);
+extern int label_part_empty(label_part_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/label/include/label/label.h
===================================================================
--- uspace/lib/label/include/label/label.h	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
+++ uspace/lib/label/include/label/label.h	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
@@ -0,0 +1,61 @@
+/*
+ * 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 <types/label.h>
+#include <types/liblabel.h>
+
+extern int label_open(label_bd_t *, label_t **);
+extern int label_create(label_bd_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 void label_part_get_info(label_part_t *, label_part_info_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 *);
+extern int label_suggest_ptype(label_t *, label_pcnt_t, label_ptype_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/label/src/empty.c
===================================================================
--- uspace/lib/label/src/empty.c	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
+++ uspace/lib/label/src/empty.c	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
@@ -0,0 +1,293 @@
+/*
+ * 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 Empty partition handling
+ * @brief
+ */
+
+#include <errno.h>
+#include <io/log.h>
+#include <label/empty.h>
+#include <loc.h>
+#include <stdlib.h>
+
+/*
+ * The partition will be considered empty if at least a minimum number of
+ * bytes *and* blocks (whichever is larger) at the beginning and end of
+ * the partition is zero.
+ */
+enum {
+	min_empty_bytes = 16384,
+	/*
+	 * First block in ISO 9660 that cannot be empty is the first
+	 * volume descriptor at LBA 16
+	 */
+	min_empty_blocks = 17
+};
+
+static bool mem_is_zero(void *buf, size_t size)
+{
+	uint8_t *bp;
+	size_t i;
+
+	bp = (uint8_t *)buf;
+	for (i = 0; i < size; i++) {
+		if (bp[i] != 0)
+			return false;
+	}
+
+	return true;
+}
+
+/** Calculate number of blocks to check.
+ *
+ * Will store to @a *ncb the number of blocks that should be checked
+ * at the beginning and end of device each.
+ *
+ * @param nblocks Total number of blocks on block device
+ * @param block_size Block size
+ * @param ncb Place to store number of blocks to check.
+ */
+static void calc_num_check_blocks(aoff64_t nblocks, size_t block_size,
+    aoff64_t *ncb)
+{
+	aoff64_t n;
+
+	/* Check first 16 kiB / 16 blocks, whichever is more */
+	n = (min_empty_bytes + block_size - 1) / block_size;
+	if (n < min_empty_blocks)
+		n = min_empty_blocks;
+	/*
+	 * Limit to half of the device so we do not process the same blocks
+	 * twice
+	 */
+	if (n > (nblocks + 1) / 2)
+		n = (nblocks + 1) / 2;
+
+	*ncb = n;
+}
+
+int label_bd_is_empty(label_bd_t *bd, bool *rempty)
+{
+	int rc;
+	void *buf = NULL;
+	aoff64_t nblocks;
+	aoff64_t n;
+	aoff64_t i;
+	size_t block_size;
+	bool empty;
+
+	rc = bd->ops->get_bsize(bd->arg, &block_size);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
+		    "block size.");
+		rc = EIO;
+		goto error;
+	}
+
+	rc = bd->ops->get_nblocks(bd->arg, &nblocks);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
+		    "number of blocks.");
+		rc = EIO;
+		goto error;
+	}
+
+	calc_num_check_blocks(nblocks, block_size, &n);
+
+	buf = calloc(block_size, 1);
+	if (buf == NULL) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error allocating buffer.");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	empty = true;
+
+	for (i = 0; i < n; i++) {
+		rc = bd->ops->read(bd->arg, i, 1, buf);
+		if (rc != EOK) {
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
+			    "reading blocks.");
+			rc = EIO;
+			goto error;
+		}
+
+		if (!mem_is_zero(buf, block_size)) {
+			empty = false;
+			goto done;
+		}
+	}
+
+	for (i = 0; i < n; i++) {
+		rc = bd->ops->read(bd->arg, nblocks - n + i, 1, buf);
+		if (rc != EOK) {
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
+			    "reading blocks.");
+			rc = EIO;
+			goto error;
+		}
+
+		if (!mem_is_zero(buf, block_size)) {
+			empty = false;
+			goto done;
+		}
+	}
+
+done:
+	free(buf);
+	*rempty = empty;
+	return EOK;
+error:
+	if (buf != NULL)
+		free(buf);
+	return rc;
+}
+
+int label_bd_empty(label_bd_t *bd)
+{
+	int rc;
+	void *buf = NULL;
+	aoff64_t nblocks;
+	aoff64_t n;
+	aoff64_t i;
+	size_t block_size;
+
+	rc = bd->ops->get_bsize(bd->arg, &block_size);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
+		    "block size.");
+		rc = EIO;
+		goto error;
+	}
+
+	rc = bd->ops->get_nblocks(bd->arg, &nblocks);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
+		    "number of blocks.");
+		rc = EIO;
+		goto error;
+	}
+
+	calc_num_check_blocks(nblocks, block_size, &n);
+
+	buf = calloc(block_size, 1);
+	if (buf == NULL) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error allocating buffer.");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	for (i = 0; i < n; i++) {
+		rc = bd->ops->write(bd->arg, i, 1, buf);
+		if (rc != EOK) {
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
+			    "reading blocks.");
+			rc = EIO;
+			goto error;
+		}
+	}
+
+	for (i = 0; i < n; i++) {
+		rc = bd->ops->write(bd->arg, nblocks - n + i, 1, buf);
+		if (rc != EOK) {
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
+			    "reading blocks.");
+			rc = EIO;
+			goto error;
+		}
+	}
+
+	free(buf);
+	return EOK;
+error:
+	if (buf != NULL)
+		free(buf);
+	return rc;
+}
+
+int label_part_empty(label_part_t *part)
+{
+	int rc;
+	void *buf = NULL;
+	aoff64_t block0;
+	aoff64_t nblocks;
+	aoff64_t n;
+	aoff64_t i;
+	size_t block_size;
+	label_bd_t *bd;
+
+	bd = &part->label->bd;
+
+	block_size = part->label->block_size;
+	block0 = part->block0;
+	nblocks = part->nblocks;
+
+	calc_num_check_blocks(nblocks, block_size, &n);
+
+	buf = calloc(block_size, 1);
+	if (buf == NULL) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error allocating buffer.");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	for (i = 0; i < n; i++) {
+		rc = bd->ops->write(bd->arg, block0 + i, 1, buf);
+		if (rc != EOK) {
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
+			    "reading blocks.");
+			rc = EIO;
+			goto error;
+		}
+	}
+
+	for (i = 0; i < n; i++) {
+		rc = bd->ops->write(bd->arg, block0 + nblocks - n + i, 1, buf);
+		if (rc != EOK) {
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
+			    "reading blocks.");
+			rc = EIO;
+			goto error;
+		}
+	}
+
+	free(buf);
+	return EOK;
+error:
+	if (buf != NULL)
+		free(buf);
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/label/src/label.c
===================================================================
--- uspace/lib/label/src/label.c	(revision 94c05b89b35e97bd16e44d00f32fdf77dcd0470c)
+++ uspace/lib/label/src/label.c	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
@@ -36,5 +36,5 @@
 #include <adt/list.h>
 #include <errno.h>
-#include <label.h>
+#include <label/label.h>
 #include <mem.h>
 #include <stdlib.h>
Index: uspace/lib/label/test/label.c
===================================================================
--- uspace/lib/label/test/label.c	(revision 94c05b89b35e97bd16e44d00f32fdf77dcd0470c)
+++ uspace/lib/label/test/label.c	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
@@ -27,5 +27,5 @@
  */
 
-#include <label.h>
+#include <label/label.h>
 #include <mem.h>
 #include <pcut/pcut.h>
Index: uspace/srv/bd/vbd/disk.c
===================================================================
--- uspace/srv/bd/vbd/disk.c	(revision 94c05b89b35e97bd16e44d00f32fdf77dcd0470c)
+++ uspace/srv/bd/vbd/disk.c	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
@@ -39,4 +39,6 @@
 #include <errno.h>
 #include <io/log.h>
+#include <label/empty.h>
+#include <label/label.h>
 #include <loc.h>
 #include <stdio.h>
@@ -842,4 +844,10 @@
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Error creating partition.");
+		goto error;
+	}
+
+	rc = label_part_empty(lpart);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error emptying partition.");
 		goto error;
 	}
Index: uspace/srv/bd/vbd/types/vbd.h
===================================================================
--- uspace/srv/bd/vbd/types/vbd.h	(revision 94c05b89b35e97bd16e44d00f32fdf77dcd0470c)
+++ uspace/srv/bd/vbd/types/vbd.h	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
@@ -41,5 +41,5 @@
 #include <atomic.h>
 #include <bd_srv.h>
-#include <label.h>
+#include <label/label.h>
 #include <loc.h>
 #include <stdbool.h>
Index: uspace/srv/bd/vbd/vbd.c
===================================================================
--- uspace/srv/bd/vbd/vbd.c	(revision 94c05b89b35e97bd16e44d00f32fdf77dcd0470c)
+++ uspace/srv/bd/vbd/vbd.c	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
@@ -39,4 +39,5 @@
 #include <ipc/services.h>
 #include <ipc/vbd.h>
+#include <label/label.h>
 #include <loc.h>
 #include <macros.h>
Index: uspace/srv/volsrv/Makefile
===================================================================
--- uspace/srv/volsrv/Makefile	(revision 94c05b89b35e97bd16e44d00f32fdf77dcd0470c)
+++ uspace/srv/volsrv/Makefile	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
@@ -29,6 +29,11 @@
 USPACE_PREFIX = ../..
 
-LIBS = $(LIBBLOCK_PREFIX)/libblock.a
-EXTRA_CFLAGS = -I $(LIBBLOCK_PREFIX)
+LIBS = \
+	$(LIBLABEL_PREFIX)/liblabel.a \
+	$(LIBBLOCK_PREFIX)/libblock.a
+
+EXTRA_CFLAGS = \
+	-I$(LIBLABEL_PREFIX)/include \
+	-I$(LIBBLOCK_PREFIX)
 
 BINARY = volsrv
Index: uspace/srv/volsrv/empty.c
===================================================================
--- uspace/srv/volsrv/empty.c	(revision 94c05b89b35e97bd16e44d00f32fdf77dcd0470c)
+++ uspace/srv/volsrv/empty.c	(revision 5772aa1259315387724d7fca7781519f8e8c5653)
@@ -38,4 +38,5 @@
 #include <errno.h>
 #include <io/log.h>
+#include <label/empty.h>
 #include <loc.h>
 #include <stdlib.h>
@@ -43,70 +44,21 @@
 #include "empty.h"
 
-/*
- * The partition will be considered empty if at least a minimum number of
- * bytes *and* blocks (whichever is larger) at the beginning and end of
- * the partition is zero.
- */
-enum {
-	min_empty_bytes = 16384,
-	/*
-	 * First block in ISO 9660 that cannot be empty is the first
-	 * volume descriptor at LBA 16
-	 */
-	min_empty_blocks = 17
+static int empty_get_bsize(void *, size_t *);
+static int empty_get_nblocks(void *, aoff64_t *);
+static int empty_read(void *, aoff64_t, size_t, void *);
+static int empty_write(void *, aoff64_t, size_t, const void *);
+
+/** Provide disk access to liblabel */
+static label_bd_ops_t empty_bd_ops = {
+	.get_bsize = empty_get_bsize,
+	.get_nblocks = empty_get_nblocks,
+	.read = empty_read,
+	.write = empty_write
 };
-
-static bool mem_is_zero(void *buf, size_t size)
-{
-	uint8_t *bp;
-	size_t i;
-
-	bp = (uint8_t *)buf;
-	for (i = 0; i < size; i++) {
-		if (bp[i] != 0)
-			return false;
-	}
-
-	return true;
-}
-
-/** Calculate number of blocks to check.
- *
- * Will store to @a *ncb the number of blocks that should be checked
- * at the beginning and end of device each.
- *
- * @param nblocks Total number of blocks on block device
- * @param block_size Block size
- * @param ncb Place to store number of blocks to check.
- */
-static void calc_num_check_blocks(aoff64_t nblocks, size_t block_size,
-    aoff64_t *ncb)
-{
-	aoff64_t n;
-
-	/* Check first 16 kiB / 16 blocks, whichever is more */
-	n = (min_empty_bytes + block_size - 1) / block_size;
-	if (n < min_empty_blocks)
-		n = min_empty_blocks;
-	/*
-	 * Limit to half of the device so we do not process the same blocks
-	 * twice
-	 */
-	if (n > (nblocks + 1) / 2)
-		n = (nblocks + 1) / 2;
-
-	*ncb = n;
-}
 
 int volsrv_part_is_empty(service_id_t sid, bool *rempty)
 {
 	int rc;
-	bool block_inited = false;
-	void *buf = NULL;
-	aoff64_t nblocks;
-	aoff64_t n;
-	aoff64_t i;
-	size_t block_size;
-	bool empty;
+	label_bd_t lbd;
 
 	rc = block_init(sid, 2048);
@@ -114,77 +66,13 @@
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Error opening "
 		    "block device service %zu", sid);
-		rc = EIO;
-		goto error;
+		return EIO;
 	}
 
-	block_inited = true;
+	lbd.ops = &empty_bd_ops;
+	lbd.arg = (void *)&sid;
 
-	rc = block_get_bsize(sid, &block_size);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
-		    "block size.");
-		rc = EIO;
-		goto error;
-	}
+	rc = label_bd_is_empty(&lbd, rempty);
 
-	rc = block_get_nblocks(sid, &nblocks);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
-		    "number of blocks.");
-		rc = EIO;
-		goto error;
-	}
-
-	calc_num_check_blocks(nblocks, block_size, &n);
-
-	buf = calloc(block_size, 1);
-	if (buf == NULL) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Error allocating buffer.");
-		rc = ENOMEM;
-		goto error;
-	}
-
-	empty = true;
-
-	for (i = 0; i < n; i++) {
-		rc = block_read_direct(sid, i, 1, buf);
-		if (rc != EOK) {
-			log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
-			    "reading blocks.");
-			rc = EIO;
-			goto error;
-		}
-
-		if (!mem_is_zero(buf, block_size)) {
-			empty = false;
-			goto done;
-		}
-	}
-
-	for (i = 0; i < n; i++) {
-		rc = block_read_direct(sid, nblocks - n + i, 1, buf);
-		if (rc != EOK) {
-			log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
-			    "reading blocks.");
-			rc = EIO;
-			goto error;
-		}
-
-		if (!mem_is_zero(buf, block_size)) {
-			empty = false;
-			goto done;
-		}
-	}
-
-done:
 	block_fini(sid);
-	free(buf);
-	*rempty = empty;
-	return EOK;
-error:
-	if (block_inited)
-		block_fini(sid);
-	if (buf != NULL)
-		free(buf);
 	return rc;
 }
@@ -193,10 +81,5 @@
 {
 	int rc;
-	bool block_inited = false;
-	void *buf = NULL;
-	aoff64_t nblocks;
-	aoff64_t n;
-	aoff64_t i;
-	size_t block_size;
+	label_bd_t lbd;
 
 	rc = block_init(sid, 2048);
@@ -204,64 +87,42 @@
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Error opening "
 		    "block device service %zu", sid);
-		rc = EIO;
-		goto error;
+		return EIO;
 	}
 
-	block_inited = true;
+	lbd.ops = &empty_bd_ops;
+	lbd.arg = (void *)&sid;
 
-	rc = block_get_bsize(sid, &block_size);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
-		    "block size.");
-		rc = EIO;
-		goto error;
-	}
-
-	rc = block_get_nblocks(sid, &nblocks);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting "
-		    "number of blocks.");
-		rc = EIO;
-		goto error;
-	}
-
-	calc_num_check_blocks(nblocks, block_size, &n);
-
-	buf = calloc(block_size, 1);
-	if (buf == NULL) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Error allocating buffer.");
-		rc = ENOMEM;
-		goto error;
-	}
-
-	for (i = 0; i < n; i++) {
-		rc = block_write_direct(sid, i, 1, buf);
-		if (rc != EOK) {
-			log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
-			    "reading blocks.");
-			rc = EIO;
-			goto error;
-		}
-	}
-
-	for (i = 0; i < n; i++) {
-		rc = block_write_direct(sid, nblocks - n + i, 1, buf);
-		if (rc != EOK) {
-			log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
-			    "reading blocks.");
-			rc = EIO;
-			goto error;
-		}
-	}
+	rc = label_bd_empty(&lbd);
 
 	block_fini(sid);
-	free(buf);
-	return EOK;
-error:
-	if (block_inited)
-		block_fini(sid);
-	if (buf != NULL)
-		free(buf);
 	return rc;
+}
+
+/** Get block size wrapper for liblabel */
+static int empty_get_bsize(void *arg, size_t *bsize)
+{
+	service_id_t svc_id = *(service_id_t *)arg;
+	return block_get_bsize(svc_id, bsize);
+}
+
+/** Get number of blocks wrapper for liblabel */
+static int empty_get_nblocks(void *arg, aoff64_t *nblocks)
+{
+	service_id_t svc_id = *(service_id_t *)arg;
+	return block_get_nblocks(svc_id, nblocks);
+}
+
+/** Read blocks wrapper for liblabel */
+static int empty_read(void *arg, aoff64_t ba, size_t cnt, void *buf)
+{
+	service_id_t svc_id = *(service_id_t *)arg;
+	return block_read_direct(svc_id, ba, cnt, buf);
+}
+
+/** Write blocks wrapper for liblabel */
+static int empty_write(void *arg, aoff64_t ba, size_t cnt, const void *data)
+{
+	service_id_t svc_id = *(service_id_t *)arg;
+	return block_write_direct(svc_id, ba, cnt, data);
 }
 
