Index: uspace/srv/bd/hr/hr.c
===================================================================
--- uspace/srv/bd/hr/hr.c	(revision 6d0fc1180b67061b8a08ad0dadb0ce418098023c)
+++ uspace/srv/bd/hr/hr.c	(revision baa49290919a649d4090b465f31dc72c6d79b38a)
@@ -127,5 +127,5 @@
 	}
 
-	rc = hr_create_vol_struct(&new_volume, cfg->level);
+	rc = hr_create_vol_struct(&new_volume, cfg->level, cfg->devname);
 	if (rc != EOK) {
 		free(cfg);
@@ -134,18 +134,7 @@
 	}
 
-	str_cpy(new_volume->devname, HR_DEVNAME_LEN, cfg->devname);
-	for (i = 0; i < cfg->dev_no; i++)
-		new_volume->extents[i].svc_id = cfg->devs[i];
-	new_volume->level = cfg->level;
-	new_volume->extent_no = cfg->dev_no;
-
-	/* XXX: do proper initing ... */
-	rc = hr_init_devs(new_volume);
-	if (rc != EOK) {
-		free(cfg);
-		free(new_volume);
-		async_answer_0(icall, rc);
-		return;
-	}
+	rc = hr_init_extents_from_cfg(new_volume, cfg);
+	if (rc != EOK)
+		goto error;
 
 	new_volume->hr_ops.init(new_volume);
Index: uspace/srv/bd/hr/raid0.c
===================================================================
--- uspace/srv/bd/hr/raid0.c	(revision 6d0fc1180b67061b8a08ad0dadb0ce418098023c)
+++ uspace/srv/bd/hr/raid0.c	(revision baa49290919a649d4090b465f31dc72c6d79b38a)
@@ -83,4 +83,6 @@
 errno_t hr_raid0_create(hr_volume_t *new_volume)
 {
+	HR_DEBUG("%s()", __func__);
+
 	assert(new_volume->level == HR_LVL_0);
 
@@ -106,24 +108,23 @@
 errno_t hr_raid0_init(hr_volume_t *vol)
 {
-	errno_t rc;
-	size_t bsize;
-	uint64_t total_blkno;
+	HR_DEBUG("%s()", __func__);
 
 	assert(vol->level == HR_LVL_0);
 
-	rc = hr_check_devs(vol, &total_blkno, &bsize);
-	if (rc != EOK)
-		return rc;
-
+	uint64_t truncated_blkno = vol->extents[0].blkno;
+	for (size_t i = 1; i < vol->extent_no; i++) {
+		if (vol->extents[i].blkno < truncated_blkno)
+			truncated_blkno = vol->extents[i].blkno;
+	}
+
+	uint64_t total_blkno = truncated_blkno * vol->extent_no;
+
+	vol->truncated_blkno = truncated_blkno;
 	vol->nblocks = total_blkno;
-	vol->bsize = bsize;
-	/*
-	 * XXX: according to bsize set the data_offset...
-	 *
-	 * also can change this depending on level, like
-	 * RAID5 might try to put data at 64K boundary
-	 */
 	vol->data_offset = HR_DATA_OFF;
-	vol->data_blkno = vol->nblocks - (vol->data_offset * vol->extent_no);
+
+	vol->data_blkno = total_blkno;
+	vol->data_blkno -= HR_META_SIZE * vol->extent_no; /* count md blocks */
+
 	vol->strip_size = HR_STRIP_SIZE;
 
@@ -133,4 +134,6 @@
 void hr_raid0_status_event(hr_volume_t *vol)
 {
+	HR_DEBUG("%s()", __func__);
+
 	hr_raid0_update_vol_status(vol);
 }
Index: uspace/srv/bd/hr/raid1.c
===================================================================
--- uspace/srv/bd/hr/raid1.c	(revision 6d0fc1180b67061b8a08ad0dadb0ce418098023c)
+++ uspace/srv/bd/hr/raid1.c	(revision baa49290919a649d4090b465f31dc72c6d79b38a)
@@ -91,4 +91,6 @@
 errno_t hr_raid1_create(hr_volume_t *new_volume)
 {
+	HR_DEBUG("%s()", __func__);
+
 	assert(new_volume->level == HR_LVL_1);
 
@@ -120,24 +122,18 @@
 errno_t hr_raid1_init(hr_volume_t *vol)
 {
-	errno_t rc;
-	size_t bsize;
-	uint64_t total_blkno;
+	HR_DEBUG("%s()", __func__);
 
 	assert(vol->level == HR_LVL_1);
 
-	rc = hr_check_devs(vol, &total_blkno, &bsize);
-	if (rc != EOK)
-		return rc;
-
-	vol->nblocks = total_blkno / vol->extent_no;
-	vol->bsize = bsize;
-	/*
-	 * XXX: according to bsize set the data_offset...
-	 *
-	 * also can change this depending on level, like
-	 * RAID5 might try to put data at 64K boundary
-	 */
+	uint64_t truncated_blkno = vol->extents[0].blkno;
+	for (size_t i = 1; i < vol->extent_no; i++) {
+		if (vol->extents[i].blkno < truncated_blkno)
+			truncated_blkno = vol->extents[i].blkno;
+	}
+
+	vol->truncated_blkno = truncated_blkno;
+	vol->nblocks = truncated_blkno;
 	vol->data_offset = HR_DATA_OFF;
-	vol->data_blkno = vol->nblocks - vol->data_offset;
+	vol->data_blkno = truncated_blkno - HR_META_SIZE;
 	vol->strip_size = 0;
 
@@ -147,4 +143,6 @@
 void hr_raid1_status_event(hr_volume_t *vol)
 {
+	HR_DEBUG("%s()", __func__);
+
 	hr_raid1_update_vol_status(vol);
 }
Index: uspace/srv/bd/hr/raid5.c
===================================================================
--- uspace/srv/bd/hr/raid5.c	(revision 6d0fc1180b67061b8a08ad0dadb0ce418098023c)
+++ uspace/srv/bd/hr/raid5.c	(revision baa49290919a649d4090b465f31dc72c6d79b38a)
@@ -93,4 +93,6 @@
 errno_t hr_raid5_create(hr_volume_t *new_volume)
 {
+	HR_DEBUG("%s()", __func__);
+
 	assert(new_volume->level == HR_LVL_5 || new_volume->level == HR_LVL_4);
 
@@ -122,25 +124,24 @@
 errno_t hr_raid5_init(hr_volume_t *vol)
 {
-	errno_t rc;
-	size_t bsize;
-	uint64_t total_blkno;
+	HR_DEBUG("%s()", __func__);
 
 	assert(vol->level == HR_LVL_5 || vol->level == HR_LVL_4);
 
-	rc = hr_check_devs(vol, &total_blkno, &bsize);
-	if (rc != EOK)
-		return rc;
-
+	uint64_t truncated_blkno = vol->extents[0].blkno;
+	for (size_t i = 1; i < vol->extent_no; i++) {
+		if (vol->extents[i].blkno < truncated_blkno)
+			truncated_blkno = vol->extents[i].blkno;
+	}
+
+	uint64_t total_blkno = truncated_blkno * vol->extent_no;
+
+	vol->truncated_blkno = truncated_blkno;
 	vol->nblocks = total_blkno;
-	vol->bsize = bsize;
-	/*
-	 * XXX: according to bsize set the data_offset...
-	 *
-	 * also can change this depending on level, like
-	 * RAID5 might try to put data at 64K boundary
-	 */
 	vol->data_offset = HR_DATA_OFF;
-	vol->data_blkno = vol->nblocks - (vol->data_offset * vol->extent_no) -
-	    (vol->nblocks / vol->extent_no);
+
+	vol->data_blkno = total_blkno;
+	vol->data_blkno -= HR_META_SIZE * vol->extent_no; /* count md blocks */
+	vol->data_blkno -= truncated_blkno; /* count parity */
+
 	vol->strip_size = HR_STRIP_SIZE;
 
Index: uspace/srv/bd/hr/util.c
===================================================================
--- uspace/srv/bd/hr/util.c	(revision 6d0fc1180b67061b8a08ad0dadb0ce418098023c)
+++ uspace/srv/bd/hr/util.c	(revision baa49290919a649d4090b465f31dc72c6d79b38a)
@@ -45,4 +45,5 @@
 #include <stdlib.h>
 #include <stdio.h>
+#include <str.h>
 #include <str_error.h>
 #include <vbd.h>
@@ -84,5 +85,6 @@
 extern fibril_rwlock_t hr_volumes_lock;
 
-errno_t hr_create_vol_struct(hr_volume_t **rvol, hr_level_t level)
+errno_t hr_create_vol_struct(hr_volume_t **rvol, hr_level_t level,
+    const char *devname)
 {
 	errno_t rc;
@@ -92,4 +94,5 @@
 		return ENOMEM;
 
+	str_cpy(vol->devname, HR_DEVNAME_LEN, devname);
 	vol->level = level;
 
@@ -139,10 +142,4 @@
 	vol->status = HR_VOL_NONE;
 
-	for (size_t i = 0; i < HR_MAX_EXTENTS; ++i)
-		vol->extents[i].status = HR_EXT_MISSING;
-
-	for (size_t i = 0; i < HR_MAX_HOTSPARES; ++i)
-		vol->extents[i].status = HR_EXT_MISSING;
-
 	fibril_mutex_initialize(&vol->lock); /* XXX: will remove this */
 
@@ -232,33 +229,61 @@
 }
 
-errno_t hr_init_devs(hr_volume_t *vol)
+errno_t hr_init_extents_from_cfg(hr_volume_t *vol, hr_config_t *cfg)
 {
 	HR_DEBUG("%s()", __func__);
 
 	errno_t rc;
-	size_t i;
-	hr_extent_t *extent;
-
-	for (i = 0; i < vol->extent_no; i++) {
-		extent = &vol->extents[i];
-		if (extent->svc_id == 0) {
-			extent->status = HR_EXT_MISSING;
-			continue;
-		}
-
-		HR_DEBUG("hr_init_devs(): block_init() on (%lu)\n",
-		    extent->svc_id);
-		rc = block_init(extent->svc_id);
-		extent->status = HR_EXT_ONLINE;
-
+	size_t i, blkno, bsize;
+	size_t last_bsize = 0;
+
+	for (i = 0; i < cfg->dev_no; i++) {
+		service_id_t svc_id = cfg->devs[i];
+		if (svc_id == 0) {
+			rc = EINVAL;
+			goto error;
+		}
+
+		HR_DEBUG("%s(): block_init() on (%lu)\n", __func__, svc_id);
+		rc = block_init(svc_id);
 		if (rc != EOK) {
-			HR_ERROR("hr_init_devs(): initing (%lu) failed, "
-			    "aborting\n", extent->svc_id);
-			break;
-		}
-	}
+			HR_DEBUG("%s(): initing (%lu) failed, aborting\n",
+			    __func__, svc_id);
+			goto error;
+		}
+
+		rc = block_get_nblocks(svc_id, &blkno);
+		if (rc != EOK)
+			goto error;
+
+		rc = block_get_bsize(svc_id, &bsize);
+		if (rc != EOK)
+			goto error;
+
+		if (last_bsize != 0 && bsize != last_bsize) {
+			HR_DEBUG("block sizes differ\n");
+			rc = EINVAL;
+			goto error;
+		}
+
+		vol->extents[i].svc_id = svc_id;
+		vol->extents[i].blkno = blkno;
+		vol->extents[i].status = HR_EXT_ONLINE;
+
+		last_bsize = bsize;
+	}
+
+	vol->bsize = last_bsize;
+	vol->extent_no = cfg->dev_no;
 
 	for (i = 0; i < HR_MAX_HOTSPARES; i++)
 		vol->hotspares[i].status = HR_EXT_MISSING;
+
+	return EOK;
+
+error:
+	for (i = 0; i < HR_MAX_EXTENTS; i++) {
+		if (vol->extents[i].svc_id != 0)
+			block_fini(vol->extents[i].svc_id);
+	}
 
 	return rc;
@@ -330,62 +355,4 @@
 	rc = loc_service_unregister(hr_srv, new_id);
 	free(fullname);
-	return rc;
-}
-
-errno_t hr_check_devs(hr_volume_t *vol, uint64_t *rblkno, size_t *rbsize)
-{
-	HR_DEBUG("%s()", __func__);
-
-	errno_t rc;
-	size_t i, bsize;
-	uint64_t nblocks;
-	size_t last_bsize = 0;
-	uint64_t last_nblocks = 0;
-	uint64_t total_blocks = 0;
-	hr_extent_t *extent;
-
-	for (i = 0; i < vol->extent_no; i++) {
-		extent = &vol->extents[i];
-		if (extent->status == HR_EXT_MISSING)
-			continue;
-		rc = block_get_nblocks(extent->svc_id, &nblocks);
-		if (rc != EOK)
-			goto error;
-		if (last_nblocks != 0 && nblocks != last_nblocks) {
-			HR_ERROR("number of blocks differs\n");
-			rc = EINVAL;
-			goto error;
-		}
-
-		total_blocks += nblocks;
-		last_nblocks = nblocks;
-	}
-
-	for (i = 0; i < vol->extent_no; i++) {
-		extent = &vol->extents[i];
-		if (extent->status == HR_EXT_MISSING)
-			continue;
-		rc = block_get_bsize(extent->svc_id, &bsize);
-		if (rc != EOK)
-			goto error;
-		if (last_bsize != 0 && bsize != last_bsize) {
-			HR_ERROR("block sizes differ\n");
-			rc = EINVAL;
-			goto error;
-		}
-
-		last_bsize = bsize;
-	}
-
-	if ((bsize % 512) != 0) {
-		HR_ERROR("block size not multiple of 512\n");
-		return EINVAL;
-	}
-
-	if (rblkno != NULL)
-		*rblkno = total_blocks;
-	if (rbsize != NULL)
-		*rbsize = bsize;
-error:
 	return rc;
 }
@@ -816,5 +783,6 @@
 
 	hr_volume_t *vol;
-	rc = hr_create_vol_struct(&vol, (hr_level_t)main_md->level);
+	rc = hr_create_vol_struct(&vol, (hr_level_t)main_md->level,
+	    main_md->devname);
 	if (rc != EOK)
 		goto error;
@@ -827,9 +795,9 @@
 	vol->metadata_version = main_md->version;
 	vol->extent_no = main_md->extent_no;
-	vol->level = main_md->level;
+	/* vol->level = main_md->level; */
 	vol->layout = main_md->layout;
 	vol->strip_size = main_md->strip_size;
 	vol->bsize = main_md->bsize;
-	memcpy(vol->devname, main_md->devname, HR_DEVNAME_LEN);
+	/* memcpy(vol->devname, main_md->devname, HR_DEVNAME_LEN); */
 
 	memcpy(vol->in_mem_md, main_md, sizeof(hr_metadata_t));
@@ -837,4 +805,11 @@
 	list_foreach(*list, link, struct svc_id_linked, iter) {
 		vol->extents[iter->md->index].svc_id = iter->svc_id;
+
+		size_t blkno;
+		rc = block_get_nblocks(iter->svc_id, &blkno);
+		if (rc != EOK)
+			goto error;
+		vol->extents[iter->md->index].blkno = blkno;
+
 		if (iter->md->counter == max_counter_val)
 			vol->extents[iter->md->index].status = HR_EXT_ONLINE;
@@ -1045,10 +1020,27 @@
 		    "to \"%s\"\n", __func__, vol->devname);
 		rc = ELIMIT;
-		goto end;
+		goto error;
 	}
 
 	rc = block_init(hotspare);
 	if (rc != EOK)
-		goto end;
+		goto error;
+
+	size_t hs_blkno;
+	rc = block_get_nblocks(hotspare, &hs_blkno);
+	if (rc != EOK) {
+		block_fini(hotspare);
+		goto error;
+	}
+
+	/*
+	 * TODO: make more flexible, when will have foreign md, the calculation
+	 * will differ, maybe something new like vol->md_hs_blkno will be enough
+	 */
+	if (hs_blkno < vol->truncated_blkno - HR_META_SIZE) {
+		rc = EINVAL;
+		block_fini(hotspare);
+		goto error;
+	}
 
 	size_t hs_idx = vol->hotspare_no;
@@ -1060,5 +1052,5 @@
 
 	hr_mark_vol_state_dirty(vol);
-end:
+error:
 	fibril_mutex_unlock(&vol->hotspare_lock);
 	return rc;
Index: uspace/srv/bd/hr/util.h
===================================================================
--- uspace/srv/bd/hr/util.h	(revision 6d0fc1180b67061b8a08ad0dadb0ce418098023c)
+++ uspace/srv/bd/hr/util.h	(revision baa49290919a649d4090b465f31dc72c6d79b38a)
@@ -53,12 +53,12 @@
 
 
-extern errno_t		 hr_create_vol_struct(hr_volume_t **, hr_level_t);
+extern errno_t		 hr_create_vol_struct(hr_volume_t **, hr_level_t,
+    const char *);
 extern void		 hr_destroy_vol_struct(hr_volume_t *);
 extern hr_volume_t	*hr_get_volume(service_id_t);
 extern errno_t		 hr_remove_volume(service_id_t);
-extern errno_t		 hr_init_devs(hr_volume_t *);
+extern errno_t		 hr_init_extents_from_cfg(hr_volume_t *, hr_config_t *);
 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 *, uint64_t *, size_t *);
 extern errno_t		 hr_check_ba_range(hr_volume_t *, size_t, uint64_t);
 extern void		 hr_add_ba_offset(hr_volume_t *, uint64_t *);
Index: uspace/srv/bd/hr/var.h
===================================================================
--- uspace/srv/bd/hr/var.h	(revision 6d0fc1180b67061b8a08ad0dadb0ce418098023c)
+++ uspace/srv/bd/hr/var.h	(revision baa49290919a649d4090b465f31dc72c6d79b38a)
@@ -123,7 +123,4 @@
 } hr_range_lock_t;
 
-extern errno_t		hr_init_devs(hr_volume_t *);
-extern void		hr_fini_devs(hr_volume_t *);
-
 extern errno_t		hr_raid0_create(hr_volume_t *);
 extern errno_t 		hr_raid1_create(hr_volume_t *);
