Index: uspace/srv/bd/hr/hr.c
===================================================================
--- uspace/srv/bd/hr/hr.c	(revision dbd91da773a98e6f1f92d0c5c5edcaf3a15e0b6b)
+++ uspace/srv/bd/hr/hr.c	(revision 6b8e89b02035d2148fde496fb715b80f3df10686)
@@ -154,20 +154,16 @@
 	}
 
-	rc = hr_check_devs(new_volume);
-	if (rc != EOK)
-		goto error;
-
 	switch (new_volume->level) {
 	case hr_l_1:
 		new_volume->hr_ops.create = hr_raid1_create;
-		new_volume->strip_size = 0;
+		new_volume->hr_ops.init = hr_raid1_init;
 		break;
 	case hr_l_0:
 		new_volume->hr_ops.create = hr_raid0_create;
-		new_volume->strip_size = HR_STRIP_SIZE;
+		new_volume->hr_ops.init = hr_raid0_init;
 		break;
 	case hr_l_4:
 		new_volume->hr_ops.create = hr_raid4_create;
-		new_volume->strip_size = HR_STRIP_SIZE;
+		new_volume->hr_ops.init = hr_raid4_init;
 		break;
 	default:
@@ -177,4 +173,8 @@
 		goto error;
 	}
+
+	new_volume->hr_ops.init(new_volume);
+	if (rc != EOK)
+		goto error;
 
 	rc = hr_write_meta_to_vol(new_volume);
@@ -263,5 +263,6 @@
 	}
 
-	rc = hr_check_devs(new_volume);
+	/* just bsize needed for reading metadata later */
+	rc = hr_check_devs(new_volume, NULL, &new_volume->bsize);
 	if (rc != EOK)
 		goto error;
Index: uspace/srv/bd/hr/raid0.c
===================================================================
--- uspace/srv/bd/hr/raid0.c	(revision dbd91da773a98e6f1f92d0c5c5edcaf3a15e0b6b)
+++ uspace/srv/bd/hr/raid0.c	(revision 6b8e89b02035d2148fde496fb715b80f3df10686)
@@ -48,4 +48,5 @@
 #include <str_error.h>
 
+#include "superblock.h"
 #include "util.h"
 #include "var.h"
@@ -233,4 +234,25 @@
 }
 
+errno_t hr_raid0_init(hr_volume_t *vol)
+{
+	errno_t rc;
+	size_t bsize;
+	uint64_t total_blkno;
+
+	assert(vol->level == hr_l_0);
+
+	rc = hr_check_devs(vol, &total_blkno, &bsize);
+	if (rc != EOK)
+		return rc;
+
+	vol->nblocks = total_blkno;
+	vol->bsize = bsize;
+	vol->data_offset = HR_DATA_OFF;
+	vol->data_blkno = vol->nblocks - (vol->data_offset * vol->dev_no);
+	vol->strip_size = HR_STRIP_SIZE;
+
+	return EOK;
+}
+
 /** @}
  */
Index: uspace/srv/bd/hr/raid1.c
===================================================================
--- uspace/srv/bd/hr/raid1.c	(revision dbd91da773a98e6f1f92d0c5c5edcaf3a15e0b6b)
+++ uspace/srv/bd/hr/raid1.c	(revision 6b8e89b02035d2148fde496fb715b80f3df10686)
@@ -47,4 +47,5 @@
 #include <str_error.h>
 
+#include "superblock.h"
 #include "util.h"
 #include "var.h"
@@ -201,4 +202,25 @@
 }
 
+errno_t hr_raid1_init(hr_volume_t *vol)
+{
+	errno_t rc;
+	size_t bsize;
+	uint64_t total_blkno;
+
+	assert(vol->level == hr_l_1);
+
+	rc = hr_check_devs(vol, &total_blkno, &bsize);
+	if (rc != EOK)
+		return rc;
+
+	vol->nblocks = total_blkno / vol->dev_no;
+	vol->bsize = bsize;
+	vol->data_offset = HR_DATA_OFF;
+	vol->data_blkno = vol->nblocks - vol->data_offset;
+	vol->strip_size = 0;
+
+	return EOK;
+}
+
 /** @}
  */
Index: uspace/srv/bd/hr/raid4.c
===================================================================
--- uspace/srv/bd/hr/raid4.c	(revision dbd91da773a98e6f1f92d0c5c5edcaf3a15e0b6b)
+++ uspace/srv/bd/hr/raid4.c	(revision 6b8e89b02035d2148fde496fb715b80f3df10686)
@@ -48,4 +48,5 @@
 #include <str_error.h>
 
+#include "superblock.h"
 #include "util.h"
 #include "var.h"
@@ -281,4 +282,26 @@
 }
 
+errno_t hr_raid4_init(hr_volume_t *vol)
+{
+	errno_t rc;
+	size_t bsize;
+	uint64_t total_blkno;
+
+	assert(vol->level == hr_l_4);
+
+	rc = hr_check_devs(vol, &total_blkno, &bsize);
+	if (rc != EOK)
+		return rc;
+
+	vol->nblocks = total_blkno;
+	vol->bsize = bsize;
+	vol->data_offset = HR_DATA_OFF;
+	vol->data_blkno = vol->nblocks - (vol->data_offset * vol->dev_no) -
+	    (vol->nblocks / vol->dev_no);
+	vol->strip_size = HR_STRIP_SIZE;
+
+	return EOK;
+}
+
 /** @}
  */
Index: uspace/srv/bd/hr/superblock.c
===================================================================
--- uspace/srv/bd/hr/superblock.c	(revision dbd91da773a98e6f1f92d0c5c5edcaf3a15e0b6b)
+++ uspace/srv/bd/hr/superblock.c	(revision 6b8e89b02035d2148fde496fb715b80f3df10686)
@@ -57,6 +57,6 @@
 
 	errno_t rc;
-	size_t i, data_offset;
-	uint64_t data_blkno;
+	size_t i;
+	size_t meta_blkno; /* blocks needed to write metadata */
 	hr_metadata_t *metadata;
 	uuid_t uuid;
@@ -66,22 +66,18 @@
 		return ENOMEM;
 
-	if (vol->nblocks <= HR_META_OFF + HR_META_SIZE) {
+	meta_blkno = (HR_META_OFF + HR_META_SIZE);
+	if (vol->level != hr_l_1)
+		meta_blkno *= vol->dev_no;
+
+	if (vol->nblocks < meta_blkno) {
 		log_msg(LOG_DEFAULT, LVL_ERROR,
-		    "not enough blocks");
+		    "not enough blocks to write metadata");
 		rc = EINVAL;
 		goto error;
-	}
-
-	data_offset = HR_META_OFF + HR_META_SIZE;
-	if (vol->level == hr_l_1) {
-		data_blkno = vol->nblocks - data_offset;
-	} else if (vol->level == hr_l_0) {
-		data_blkno = vol->nblocks - (data_offset * vol->dev_no);
-	} else if (vol->level == hr_l_4) {
-		data_blkno = vol->nblocks - (data_offset * vol->dev_no) - (vol->nblocks / vol->dev_no);
-	} else {
+	} else if (vol->nblocks == meta_blkno) {
 		log_msg(LOG_DEFAULT, LVL_ERROR,
-		    "level %d not implemented yet", vol->level);
-		return EINVAL;
+		    "there would be zero data blocks after writing metadata, aborting");
+		rc = EINVAL;
+		goto error;
 	}
 
@@ -90,6 +86,6 @@
 	metadata->level = host2uint32_t_le(vol->level);
 	metadata->nblocks = host2uint64_t_le(vol->nblocks);
-	metadata->data_blkno = host2uint64_t_le(data_blkno);
-	metadata->data_offset = host2uint32_t_le(data_offset);
+	metadata->data_blkno = host2uint64_t_le(vol->data_blkno);
+	metadata->data_offset = host2uint32_t_le(vol->data_offset);
 	metadata->strip_size = host2uint32_t_le(vol->strip_size);
 	for (i = 0; i < vol->dev_no; i++) {
@@ -103,14 +99,9 @@
 		str_cpy(metadata->devname, 32, vol->devname);
 
-		rc = block_write_direct(vol->extents[i].svc_id, HR_META_OFF, HR_META_SIZE,
-		    metadata);
+		rc = block_write_direct(vol->extents[i].svc_id, HR_META_OFF,
+		    HR_META_SIZE, metadata);
 		if (rc != EOK)
 			goto error;
 	}
-
-	/* fill in new members */
-	vol->data_offset = data_offset;
-	vol->data_blkno = data_blkno;
-
 error:
 	free(metadata);
Index: uspace/srv/bd/hr/superblock.h
===================================================================
--- uspace/srv/bd/hr/superblock.h	(revision dbd91da773a98e6f1f92d0c5c5edcaf3a15e0b6b)
+++ uspace/srv/bd/hr/superblock.h	(revision 6b8e89b02035d2148fde496fb715b80f3df10686)
@@ -41,4 +41,5 @@
 #define HR_META_SIZE 1	/* in blocks */
 #define HR_META_OFF 7	/* in blocks */
+#define HR_DATA_OFF (HR_META_SIZE + HR_META_OFF)
 
 #define HR_MAGIC 0x4420492041205248LLU
Index: uspace/srv/bd/hr/util.c
===================================================================
--- uspace/srv/bd/hr/util.c	(revision dbd91da773a98e6f1f92d0c5c5edcaf3a15e0b6b)
+++ uspace/srv/bd/hr/util.c	(revision 6b8e89b02035d2148fde496fb715b80f3df10686)
@@ -122,5 +122,5 @@
 }
 
-errno_t hr_check_devs(hr_volume_t *vol)
+errno_t hr_check_devs(hr_volume_t *vol, uint64_t *rblkno, size_t *rbsize)
 {
 	log_msg(LOG_DEFAULT, LVL_NOTE, "hr_check_devs()");
@@ -157,15 +157,8 @@
 	}
 
-	if (vol->level == hr_l_1) {
-		vol->nblocks = total_blocks / vol->dev_no;
-	} else if (vol->level == hr_l_0 || vol->level == hr_l_4) {
-		vol->nblocks = total_blocks;
-	} else {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "unkown level, ok when assembling");
-		vol->nblocks = 0;
-	}
-
-	vol->bsize = bsize;
-
+	if (rblkno != NULL)
+		*rblkno = total_blocks;
+	if (rbsize != NULL)
+		*rbsize = bsize;
 error:
 	return rc;
Index: uspace/srv/bd/hr/util.h
===================================================================
--- uspace/srv/bd/hr/util.h	(revision dbd91da773a98e6f1f92d0c5c5edcaf3a15e0b6b)
+++ uspace/srv/bd/hr/util.h	(revision 6b8e89b02035d2148fde496fb715b80f3df10686)
@@ -44,7 +44,7 @@
 extern void hr_fini_devs(hr_volume_t *);
 extern errno_t hr_register_volume(hr_volume_t *);
-extern errno_t hr_check_devs(hr_volume_t *vol);
-errno_t hr_check_ba_range(hr_volume_t *vol, size_t cnt, uint64_t ba);
-void hr_add_ba_offset(hr_volume_t *vol, uint64_t *ba);
+errno_t hr_check_devs(hr_volume_t *, uint64_t *, size_t *);
+errno_t hr_check_ba_range(hr_volume_t *, size_t, uint64_t);
+void hr_add_ba_offset(hr_volume_t *, uint64_t *);
 
 #endif
Index: uspace/srv/bd/hr/var.h
===================================================================
--- uspace/srv/bd/hr/var.h	(revision dbd91da773a98e6f1f92d0c5c5edcaf3a15e0b6b)
+++ uspace/srv/bd/hr/var.h	(revision 6b8e89b02035d2148fde496fb715b80f3df10686)
@@ -49,4 +49,5 @@
 typedef struct hr_ops {
 	errno_t (*create)(hr_volume_t *);
+	errno_t (*init)(hr_volume_t *);
 } hr_ops_t;
 
@@ -59,5 +60,5 @@
 	uint64_t nblocks;
 	uint64_t data_blkno;
-	uint32_t data_offset;
+	uint32_t data_offset; /* in blocks */
 	uint32_t strip_size;
 	service_id_t svc_id;
@@ -74,4 +75,8 @@
 extern errno_t hr_raid4_create(hr_volume_t *);
 
+extern errno_t hr_raid0_init(hr_volume_t *);
+extern errno_t hr_raid1_init(hr_volume_t *);
+extern errno_t hr_raid4_init(hr_volume_t *);
+
 #endif
 
