Index: uspace/srv/bd/hr/metadata/foreign/geom/hr_g_mirror.c
===================================================================
--- uspace/srv/bd/hr/metadata/foreign/geom/hr_g_mirror.c	(revision 78433bbc6780846cacf166c1034df23fd5f58768)
+++ uspace/srv/bd/hr/metadata/foreign/geom/hr_g_mirror.c	(revision aa9bad8ad7f31ed589ba9008abeb38be019e40c5)
@@ -54,12 +54,15 @@
 #include "g_mirror.h"
 
+/* not exposed */
 static void *meta_gmirror_alloc_struct(void);
+/* static void meta_gmirror_encode(void *, void *); */
+static errno_t meta_gmirror_decode(const void *, void *);
+static errno_t meta_gmirror_get_block(service_id_t, void **);
+/* static errno_t meta_gmirror_write_block(service_id_t, const void *); */
+static bool meta_gmirror_has_valid_magic(const void *);
+
+static errno_t meta_gmirror_probe(service_id_t, void **);
 static errno_t meta_gmirror_init_vol2meta(hr_volume_t *);
 static errno_t meta_gmirror_init_meta2vol(const list_t *, hr_volume_t *);
-static void meta_gmirror_encode(void *, void *);
-static errno_t meta_gmirror_decode(const void *, void *);
-static errno_t meta_gmirror_get_block(service_id_t, void **);
-static errno_t meta_gmirror_write_block(service_id_t, const void *);
-static bool meta_gmirror_has_valid_magic(const void *);
 static bool meta_gmirror_compare_uuids(const void *, const void *);
 static void meta_gmirror_inc_counter(hr_volume_t *);
@@ -75,12 +78,7 @@
 
 hr_superblock_ops_t metadata_gmirror_ops = {
-	.alloc_struct = meta_gmirror_alloc_struct,
+	.probe = meta_gmirror_probe,
 	.init_vol2meta = meta_gmirror_init_vol2meta,
 	.init_meta2vol = meta_gmirror_init_meta2vol,
-	.encode = meta_gmirror_encode,
-	.decode = meta_gmirror_decode,
-	.get_block = meta_gmirror_get_block,
-	.write_block = meta_gmirror_write_block,
-	.has_valid_magic = meta_gmirror_has_valid_magic,
 	.compare_uuids = meta_gmirror_compare_uuids,
 	.inc_counter = meta_gmirror_inc_counter,
@@ -96,7 +94,35 @@
 };
 
-static void *meta_gmirror_alloc_struct(void)
-{
-	return calloc(1, sizeof(struct g_mirror_metadata));
+static errno_t meta_gmirror_probe(service_id_t svc_id, void **rmd)
+{
+	errno_t rc;
+	void *meta_block;
+
+	void *metadata_struct = meta_gmirror_alloc_struct();
+	if (metadata_struct == NULL)
+		return ENOMEM;
+
+	rc = meta_gmirror_get_block(svc_id, &meta_block);
+	if (rc != EOK)
+		goto error;
+
+	rc = meta_gmirror_decode(meta_block, metadata_struct);
+
+	free(meta_block);
+
+	if (rc != EOK)
+		goto error;
+
+	if (!meta_gmirror_has_valid_magic(metadata_struct)) {
+		rc = ENOFS;
+		goto error;
+	}
+
+	*rmd = metadata_struct;
+	return EOK;
+
+error:
+	free(metadata_struct);
+	return ENOFS;
 }
 
@@ -177,4 +203,99 @@
 }
 
+static bool meta_gmirror_compare_uuids(const void *m1_v, const void *m2_v)
+{
+	const struct g_mirror_metadata *m1 = m1_v;
+	const struct g_mirror_metadata *m2 = m2_v;
+	if (m1->md_mid == m2->md_mid)
+		return true;
+
+	return false;
+}
+
+static void meta_gmirror_inc_counter(hr_volume_t *vol)
+{
+	fibril_mutex_lock(&vol->md_lock);
+
+	struct g_mirror_metadata *md = vol->in_mem_md;
+
+	/* XXX: probably md_genid and not md_syncid is incremented */
+	md->md_genid++;
+
+	fibril_mutex_unlock(&vol->md_lock);
+}
+
+static errno_t meta_gmirror_save(hr_volume_t *vol, bool with_state_callback)
+{
+	HR_DEBUG("%s()", __func__);
+
+	(void)vol;
+	(void)with_state_callback;
+
+	/*
+	 * cannot support right now, because would need to store the
+	 * metadata for all disks, because of hardcoded provider names and
+	 * more importantly, disk unique ids
+	 */
+
+	return ENOTSUP;
+}
+
+static errno_t meta_gmirror_save_ext(hr_volume_t *vol, size_t ext_idx,
+    bool with_state_callback)
+{
+	HR_DEBUG("%s()", __func__);
+
+	return ENOTSUP;
+}
+
+static const char *meta_gmirror_get_devname(const void *md_v)
+{
+	const struct g_mirror_metadata *md = md_v;
+
+	return md->md_name;
+}
+
+static hr_level_t meta_gmirror_get_level(const void *md_v)
+{
+	(void)md_v;
+
+	return HR_LVL_1;
+}
+
+static uint64_t meta_gmirror_get_data_offset(void)
+{
+	return 0;
+}
+
+static size_t meta_gmirror_get_size(void)
+{
+	return 1;
+}
+
+static uint8_t meta_gmirror_get_flags(void)
+{
+	uint8_t flags = 0;
+
+	return flags;
+}
+
+static hr_metadata_type_t meta_gmirror_get_type(void)
+{
+	return 	HR_METADATA_GEOM_MIRROR;
+}
+
+static void meta_gmirror_dump(const void *md_v)
+{
+	HR_DEBUG("%s()", __func__);
+
+	mirror_metadata_dump(md_v);
+}
+
+static void *meta_gmirror_alloc_struct(void)
+{
+	return calloc(1, sizeof(struct g_mirror_metadata));
+}
+
+#if 0
 static void meta_gmirror_encode(void *md_v, void *block)
 {
@@ -183,4 +304,5 @@
 	mirror_metadata_encode(md_v, block);
 }
+#endif
 
 static errno_t meta_gmirror_decode(const void *block, void *md_v)
@@ -237,4 +359,5 @@
 }
 
+#if 0
 static errno_t meta_gmirror_write_block(service_id_t dev, const void *block)
 {
@@ -263,4 +386,5 @@
 	return rc;
 }
+#endif
 
 static bool meta_gmirror_has_valid_magic(const void *md_v)
@@ -276,93 +400,4 @@
 }
 
-static bool meta_gmirror_compare_uuids(const void *m1_v, const void *m2_v)
-{
-	const struct g_mirror_metadata *m1 = m1_v;
-	const struct g_mirror_metadata *m2 = m2_v;
-	if (m1->md_mid == m2->md_mid)
-		return true;
-
-	return false;
-}
-
-static void meta_gmirror_inc_counter(hr_volume_t *vol)
-{
-	fibril_mutex_lock(&vol->md_lock);
-
-	struct g_mirror_metadata *md = vol->in_mem_md;
-
-	/* XXX: probably md_genid and not md_syncid is incremented */
-	md->md_genid++;
-
-	fibril_mutex_unlock(&vol->md_lock);
-}
-
-static errno_t meta_gmirror_save(hr_volume_t *vol, bool with_state_callback)
-{
-	HR_DEBUG("%s()", __func__);
-
-	(void)vol;
-	(void)with_state_callback;
-
-	/*
-	 * cannot support right now, because would need to store the
-	 * metadata for all disks, because of hardcoded provider names and
-	 * more importantly, disk unique ids
-	 */
-
-	return ENOTSUP;
-}
-
-static errno_t meta_gmirror_save_ext(hr_volume_t *vol, size_t ext_idx,
-    bool with_state_callback)
-{
-	HR_DEBUG("%s()", __func__);
-
-	return ENOTSUP;
-}
-
-static const char *meta_gmirror_get_devname(const void *md_v)
-{
-	const struct g_mirror_metadata *md = md_v;
-
-	return md->md_name;
-}
-
-static hr_level_t meta_gmirror_get_level(const void *md_v)
-{
-	(void)md_v;
-
-	return HR_LVL_1;
-}
-
-static uint64_t meta_gmirror_get_data_offset(void)
-{
-	return 0;
-}
-
-static size_t meta_gmirror_get_size(void)
-{
-	return 1;
-}
-
-static uint8_t meta_gmirror_get_flags(void)
-{
-	uint8_t flags = 0;
-
-	return flags;
-}
-
-static hr_metadata_type_t meta_gmirror_get_type(void)
-{
-	return 	HR_METADATA_GEOM_MIRROR;
-}
-
-static void meta_gmirror_dump(const void *md_v)
-{
-	HR_DEBUG("%s()", __func__);
-
-	mirror_metadata_dump(md_v);
-}
-
 /** @}
  */
Index: uspace/srv/bd/hr/metadata/foreign/geom/hr_g_stripe.c
===================================================================
--- uspace/srv/bd/hr/metadata/foreign/geom/hr_g_stripe.c	(revision 78433bbc6780846cacf166c1034df23fd5f58768)
+++ uspace/srv/bd/hr/metadata/foreign/geom/hr_g_stripe.c	(revision aa9bad8ad7f31ed589ba9008abeb38be019e40c5)
@@ -54,12 +54,15 @@
 #include "g_stripe.h"
 
+/* not exposed */
 static void *meta_gstripe_alloc_struct(void);
+/* static void meta_gstripe_encode(void *, void *); */
+static errno_t meta_gstripe_decode(const void *, void *);
+static errno_t meta_gstripe_get_block(service_id_t, void **);
+/* static errno_t meta_gstripe_write_block(service_id_t, const void *); */
+static bool meta_gstripe_has_valid_magic(const void *);
+
+static errno_t meta_gstripe_probe(service_id_t, void **);
 static errno_t meta_gstripe_init_vol2meta(hr_volume_t *);
 static errno_t meta_gstripe_init_meta2vol(const list_t *, hr_volume_t *);
-static void meta_gstripe_encode(void *, void *);
-static errno_t meta_gstripe_decode(const void *, void *);
-static errno_t meta_gstripe_get_block(service_id_t, void **);
-static errno_t meta_gstripe_write_block(service_id_t, const void *);
-static bool meta_gstripe_has_valid_magic(const void *);
 static bool meta_gstripe_compare_uuids(const void *, const void *);
 static void meta_gstripe_inc_counter(hr_volume_t *);
@@ -75,12 +78,7 @@
 
 hr_superblock_ops_t metadata_gstripe_ops = {
-	.alloc_struct = meta_gstripe_alloc_struct,
+	.probe = meta_gstripe_probe,
 	.init_vol2meta = meta_gstripe_init_vol2meta,
 	.init_meta2vol = meta_gstripe_init_meta2vol,
-	.encode = meta_gstripe_encode,
-	.decode = meta_gstripe_decode,
-	.get_block = meta_gstripe_get_block,
-	.write_block = meta_gstripe_write_block,
-	.has_valid_magic = meta_gstripe_has_valid_magic,
 	.compare_uuids = meta_gstripe_compare_uuids,
 	.inc_counter = meta_gstripe_inc_counter,
@@ -96,7 +94,35 @@
 };
 
-static void *meta_gstripe_alloc_struct(void)
-{
-	return calloc(1, sizeof(struct g_stripe_metadata));
+static errno_t meta_gstripe_probe(service_id_t svc_id, void **rmd)
+{
+	errno_t rc;
+	void *meta_block;
+
+	void *metadata_struct = meta_gstripe_alloc_struct();
+	if (metadata_struct == NULL)
+		return ENOMEM;
+
+	rc = meta_gstripe_get_block(svc_id, &meta_block);
+	if (rc != EOK)
+		goto error;
+
+	rc = meta_gstripe_decode(meta_block, metadata_struct);
+
+	free(meta_block);
+
+	if (rc != EOK)
+		goto error;
+
+	if (!meta_gstripe_has_valid_magic(metadata_struct)) {
+		rc = ENOFS;
+		goto error;
+	}
+
+	*rmd = metadata_struct;
+	return EOK;
+
+error:
+	free(metadata_struct);
+	return ENOFS;
 }
 
@@ -178,4 +204,92 @@
 }
 
+static bool meta_gstripe_compare_uuids(const void *md1_v, const void *md2_v)
+{
+	const struct g_stripe_metadata *md1 = md1_v;
+	const struct g_stripe_metadata *md2 = md2_v;
+	if (md1->md_id == md2->md_id)
+		return true;
+
+	return false;
+}
+
+static void meta_gstripe_inc_counter(hr_volume_t *vol)
+{
+	(void)vol;
+}
+
+static errno_t meta_gstripe_save(hr_volume_t *vol, bool with_state_callback)
+{
+	HR_DEBUG("%s()", __func__);
+
+	return ENOTSUP;
+}
+
+static errno_t meta_gstripe_save_ext(hr_volume_t *vol, size_t ext_idx,
+    bool with_state_callback)
+{
+	HR_DEBUG("%s()", __func__);
+
+	return ENOTSUP;
+}
+
+static const char *meta_gstripe_get_devname(const void *md_v)
+{
+	const struct g_stripe_metadata *md = md_v;
+
+	return md->md_name;
+}
+
+static hr_level_t meta_gstripe_get_level(const void *md_v)
+{
+	(void)md_v;
+
+	return HR_LVL_0;
+}
+
+static uint64_t meta_gstripe_get_data_offset(void)
+{
+	return 0;
+}
+
+static size_t meta_gstripe_get_size(void)
+{
+	return 1;
+}
+
+static uint8_t meta_gstripe_get_flags(void)
+{
+	uint8_t flags = 0;
+
+	return flags;
+}
+
+static hr_metadata_type_t meta_gstripe_get_type(void)
+{
+	return HR_METADATA_GEOM_STRIPE;
+}
+
+static void meta_gstripe_dump(const void *md_v)
+{
+	HR_DEBUG("%s()", __func__);
+
+	const struct g_stripe_metadata *md = md_v;
+
+	printf("     magic: %s\n", md->md_magic);
+	printf("   version: %u\n", (u_int)md->md_version);
+	printf("      name: %s\n", md->md_name);
+	printf("        id: %u\n", (u_int)md->md_id);
+	printf("        no: %u\n", (u_int)md->md_no);
+	printf("       all: %u\n", (u_int)md->md_all);
+	printf("stripesize: %u\n", (u_int)md->md_stripesize);
+	printf(" mediasize: %jd\n", (intmax_t)md->md_provsize);
+}
+
+static void *meta_gstripe_alloc_struct(void)
+{
+	return calloc(1, sizeof(struct g_stripe_metadata));
+}
+
+#if 0
 static void meta_gstripe_encode(void *md_v, void *block)
 {
@@ -184,4 +298,5 @@
 	stripe_metadata_encode(md_v, block);
 }
+#endif
 
 static errno_t meta_gstripe_decode(const void *block, void *md_v)
@@ -239,4 +354,5 @@
 }
 
+#if 0
 static errno_t meta_gstripe_write_block(service_id_t dev, const void *block)
 {
@@ -265,4 +381,5 @@
 	return rc;
 }
+#endif
 
 static bool meta_gstripe_has_valid_magic(const void *md_v)
@@ -278,86 +395,4 @@
 }
 
-static bool meta_gstripe_compare_uuids(const void *md1_v, const void *md2_v)
-{
-	const struct g_stripe_metadata *md1 = md1_v;
-	const struct g_stripe_metadata *md2 = md2_v;
-	if (md1->md_id == md2->md_id)
-		return true;
-
-	return false;
-}
-
-static void meta_gstripe_inc_counter(hr_volume_t *vol)
-{
-	(void)vol;
-}
-
-static errno_t meta_gstripe_save(hr_volume_t *vol, bool with_state_callback)
-{
-	HR_DEBUG("%s()", __func__);
-
-	return ENOTSUP;
-}
-
-static errno_t meta_gstripe_save_ext(hr_volume_t *vol, size_t ext_idx,
-    bool with_state_callback)
-{
-	HR_DEBUG("%s()", __func__);
-
-	return ENOTSUP;
-}
-
-static const char *meta_gstripe_get_devname(const void *md_v)
-{
-	const struct g_stripe_metadata *md = md_v;
-
-	return md->md_name;
-}
-
-static hr_level_t meta_gstripe_get_level(const void *md_v)
-{
-	(void)md_v;
-
-	return HR_LVL_0;
-}
-
-static uint64_t meta_gstripe_get_data_offset(void)
-{
-	return 0;
-}
-
-static size_t meta_gstripe_get_size(void)
-{
-	return 1;
-}
-
-static uint8_t meta_gstripe_get_flags(void)
-{
-	uint8_t flags = 0;
-
-	return flags;
-}
-
-static hr_metadata_type_t meta_gstripe_get_type(void)
-{
-	return 	HR_METADATA_GEOM_STRIPE;
-}
-
-static void meta_gstripe_dump(const void *md_v)
-{
-	HR_DEBUG("%s()", __func__);
-
-	const struct g_stripe_metadata *md = md_v;
-
-	printf("     magic: %s\n", md->md_magic);
-	printf("   version: %u\n", (u_int)md->md_version);
-	printf("      name: %s\n", md->md_name);
-	printf("        id: %u\n", (u_int)md->md_id);
-	printf("        no: %u\n", (u_int)md->md_no);
-	printf("       all: %u\n", (u_int)md->md_all);
-	printf("stripesize: %u\n", (u_int)md->md_stripesize);
-	printf(" mediasize: %jd\n", (intmax_t)md->md_provsize);
-}
-
 /** @}
  */
Index: uspace/srv/bd/hr/metadata/foreign/softraid/hr_softraid.c
===================================================================
--- uspace/srv/bd/hr/metadata/foreign/softraid/hr_softraid.c	(revision 78433bbc6780846cacf166c1034df23fd5f58768)
+++ uspace/srv/bd/hr/metadata/foreign/softraid/hr_softraid.c	(revision aa9bad8ad7f31ed589ba9008abeb38be019e40c5)
@@ -54,12 +54,15 @@
 #include "softraidvar.h"
 
+/* not exposed */
 static void *meta_softraid_alloc_struct(void);
+/* static void meta_softraid_encode(void *, void *); */
+static errno_t meta_softraid_decode(const void *, void *);
+static errno_t meta_softraid_get_block(service_id_t, void **);
+/* static errno_t meta_softraid_write_block(service_id_t, const void *); */
+static bool meta_softraid_has_valid_magic(const void *);
+
+static errno_t meta_softraid_probe(service_id_t, void **);
 static errno_t meta_softraid_init_vol2meta(hr_volume_t *);
 static errno_t meta_softraid_init_meta2vol(const list_t *, hr_volume_t *);
-static void meta_softraid_encode(void *, void *);
-static errno_t meta_softraid_decode(const void *, void *);
-static errno_t meta_softraid_get_block(service_id_t, void **);
-static errno_t meta_softraid_write_block(service_id_t, const void *);
-static bool meta_softraid_has_valid_magic(const void *);
 static bool meta_softraid_compare_uuids(const void *, const void *);
 static void meta_softraid_inc_counter(hr_volume_t *);
@@ -75,12 +78,7 @@
 
 hr_superblock_ops_t metadata_softraid_ops = {
-	.alloc_struct = meta_softraid_alloc_struct,
+	.probe = meta_softraid_probe,
 	.init_vol2meta = meta_softraid_init_vol2meta,
 	.init_meta2vol = meta_softraid_init_meta2vol,
-	.encode = meta_softraid_encode,
-	.decode = meta_softraid_decode,
-	.get_block = meta_softraid_get_block,
-	.write_block = meta_softraid_write_block,
-	.has_valid_magic = meta_softraid_has_valid_magic,
 	.compare_uuids = meta_softraid_compare_uuids,
 	.inc_counter = meta_softraid_inc_counter,
@@ -96,7 +94,35 @@
 };
 
-static void *meta_softraid_alloc_struct(void)
-{
-	return calloc(1, SR_META_SIZE * DEV_BSIZE);
+static errno_t meta_softraid_probe(service_id_t svc_id, void **rmd)
+{
+	errno_t rc;
+	void *meta_block;
+
+	void *metadata_struct = meta_softraid_alloc_struct();
+	if (metadata_struct == NULL)
+		return ENOMEM;
+
+	rc = meta_softraid_get_block(svc_id, &meta_block);
+	if (rc != EOK)
+		goto error;
+
+	rc = meta_softraid_decode(meta_block, metadata_struct);
+
+	free(meta_block);
+
+	if (rc != EOK)
+		goto error;
+
+	if (!meta_softraid_has_valid_magic(metadata_struct)) {
+		rc = ENOFS;
+		goto error;
+	}
+
+	*rmd = metadata_struct;
+	return EOK;
+
+error:
+	free(metadata_struct);
+	return ENOFS;
 }
 
@@ -181,4 +207,101 @@
 }
 
+static bool meta_softraid_compare_uuids(const void *m1_v, const void *m2_v)
+{
+	const struct sr_metadata *m1 = m1_v;
+	const struct sr_metadata *m2 = m2_v;
+	if (memcmp(&m1->ssdi.ssd_uuid, &m2->ssdi.ssd_uuid,
+	    SR_UUID_MAX) == 0)
+		return true;
+
+	return false;
+}
+
+static void meta_softraid_inc_counter(hr_volume_t *vol)
+{
+	fibril_mutex_lock(&vol->md_lock);
+
+	struct sr_metadata *md = vol->in_mem_md;
+
+	md->ssd_ondisk++;
+
+	fibril_mutex_unlock(&vol->md_lock);
+}
+
+static errno_t meta_softraid_save(hr_volume_t *vol, bool with_state_callback)
+{
+	HR_DEBUG("%s()", __func__);
+
+	return ENOTSUP;
+}
+
+static errno_t meta_softraid_save_ext(hr_volume_t *vol, size_t ext_idx,
+    bool with_state_callback)
+{
+	HR_DEBUG("%s()", __func__);
+
+	return ENOTSUP;
+}
+
+static const char *meta_softraid_get_devname(const void *md_v)
+{
+	const struct sr_metadata *md = md_v;
+
+	return md->ssd_devname;
+}
+
+static hr_level_t meta_softraid_get_level(const void *md_v)
+{
+	const struct sr_metadata *md = md_v;
+
+	switch (md->ssdi.ssd_level) {
+	case 0:
+		return HR_LVL_0;
+	case 1:
+		return HR_LVL_1;
+	case 5:
+		return HR_LVL_5;
+	default:
+		return HR_LVL_UNKNOWN;
+	}
+}
+
+static uint64_t meta_softraid_get_data_offset(void)
+{
+	return SR_DATA_OFFSET;
+}
+
+static size_t meta_softraid_get_size(void)
+{
+	return SR_META_SIZE;
+}
+
+static uint8_t meta_softraid_get_flags(void)
+{
+	uint8_t flags = 0;
+
+	return flags;
+}
+
+static hr_metadata_type_t meta_softraid_get_type(void)
+{
+	return HR_METADATA_SOFTRAID;
+}
+
+static void meta_softraid_dump(const void *md_v)
+{
+	HR_DEBUG("%s()", __func__);
+
+	const struct sr_metadata *md = md_v;
+
+	sr_meta_print(md);
+}
+
+static void *meta_softraid_alloc_struct(void)
+{
+	return calloc(1, SR_META_SIZE * DEV_BSIZE);
+}
+
+#if 0
 static void meta_softraid_encode(void *md_v, void *block)
 {
@@ -188,4 +311,5 @@
 	(void)block;
 }
+#endif
 
 static errno_t meta_softraid_decode(const void *block, void *md_v)
@@ -372,4 +496,5 @@
 }
 
+#if 0
 static errno_t meta_softraid_write_block(service_id_t dev, const void *block)
 {
@@ -398,4 +523,5 @@
 	return rc;
 }
+#endif
 
 static bool meta_softraid_has_valid_magic(const void *md_v)
@@ -411,95 +537,4 @@
 }
 
-static bool meta_softraid_compare_uuids(const void *m1_v, const void *m2_v)
-{
-	const struct sr_metadata *m1 = m1_v;
-	const struct sr_metadata *m2 = m2_v;
-	if (memcmp(&m1->ssdi.ssd_uuid, &m2->ssdi.ssd_uuid,
-	    SR_UUID_MAX) == 0)
-		return true;
-
-	return false;
-}
-
-static void meta_softraid_inc_counter(hr_volume_t *vol)
-{
-	fibril_mutex_lock(&vol->md_lock);
-
-	struct sr_metadata *md = vol->in_mem_md;
-
-	md->ssd_ondisk++;
-
-	fibril_mutex_unlock(&vol->md_lock);
-}
-
-static errno_t meta_softraid_save(hr_volume_t *vol, bool with_state_callback)
-{
-	HR_DEBUG("%s()", __func__);
-
-	return ENOTSUP;
-}
-
-static errno_t meta_softraid_save_ext(hr_volume_t *vol, size_t ext_idx,
-    bool with_state_callback)
-{
-	HR_DEBUG("%s()", __func__);
-
-	return ENOTSUP;
-}
-
-static const char *meta_softraid_get_devname(const void *md_v)
-{
-	const struct sr_metadata *md = md_v;
-
-	return md->ssd_devname;
-}
-
-static hr_level_t meta_softraid_get_level(const void *md_v)
-{
-	const struct sr_metadata *md = md_v;
-
-	switch (md->ssdi.ssd_level) {
-	case 0:
-		return HR_LVL_0;
-	case 1:
-		return HR_LVL_1;
-	case 5:
-		return HR_LVL_5;
-	default:
-		return HR_LVL_UNKNOWN;
-	}
-}
-
-static uint64_t meta_softraid_get_data_offset(void)
-{
-	return SR_DATA_OFFSET;
-}
-
-static size_t meta_softraid_get_size(void)
-{
-	return SR_META_SIZE;
-}
-
-static uint8_t meta_softraid_get_flags(void)
-{
-	uint8_t flags = 0;
-
-	return flags;
-}
-
-static hr_metadata_type_t meta_softraid_get_type(void)
-{
-	return HR_METADATA_SOFTRAID;
-}
-
-static void meta_softraid_dump(const void *md_v)
-{
-	HR_DEBUG("%s()", __func__);
-
-	const struct sr_metadata *md = md_v;
-
-	sr_meta_print(md);
-}
-
 /** @}
  */
Index: uspace/srv/bd/hr/metadata/native.c
===================================================================
--- uspace/srv/bd/hr/metadata/native.c	(revision 78433bbc6780846cacf166c1034df23fd5f58768)
+++ uspace/srv/bd/hr/metadata/native.c	(revision aa9bad8ad7f31ed589ba9008abeb38be019e40c5)
@@ -54,13 +54,16 @@
 #include "native.h"
 
+/* not exposed */
 static void *meta_native_alloc_struct(void);
-static errno_t meta_native_init_vol2meta(hr_volume_t *);
-static errno_t meta_native_init_meta2vol(const list_t *, hr_volume_t *);
 static void meta_native_encode(void *, void *);
 static errno_t meta_native_decode(const void *, void *);
 static errno_t meta_native_get_block(service_id_t, void **);
 static errno_t meta_native_write_block(service_id_t, const void *);
+static bool meta_native_has_valid_magic(const void *);
+
+static errno_t meta_native_probe(service_id_t, void **);
+static errno_t meta_native_init_vol2meta(hr_volume_t *);
+static errno_t meta_native_init_meta2vol(const list_t *, hr_volume_t *);
 static errno_t meta_native_erase_block(service_id_t);
-static bool meta_native_has_valid_magic(const void *);
 static bool meta_native_compare_uuids(const void *, const void *);
 static void meta_native_inc_counter(hr_volume_t *);
@@ -76,13 +79,8 @@
 
 hr_superblock_ops_t metadata_native_ops = {
-	.alloc_struct = meta_native_alloc_struct,
+	.probe = meta_native_probe,
 	.init_vol2meta = meta_native_init_vol2meta,
 	.init_meta2vol = meta_native_init_meta2vol,
-	.encode = meta_native_encode,
-	.decode = meta_native_decode,
-	.get_block = meta_native_get_block,
-	.write_block = meta_native_write_block,
 	.erase_block = meta_native_erase_block,
-	.has_valid_magic = meta_native_has_valid_magic,
 	.compare_uuids = meta_native_compare_uuids,
 	.inc_counter = meta_native_inc_counter,
@@ -98,7 +96,35 @@
 };
 
-static void *meta_native_alloc_struct(void)
-{
-	return calloc(1, sizeof(hr_metadata_t));
+static errno_t meta_native_probe(service_id_t svc_id, void **rmd)
+{
+	errno_t rc;
+	void *meta_block;
+
+	void *metadata_struct = meta_native_alloc_struct();
+	if (metadata_struct == NULL)
+		return ENOMEM;
+
+	rc = meta_native_get_block(svc_id, &meta_block);
+	if (rc != EOK)
+		goto error;
+
+	rc = meta_native_decode(meta_block, metadata_struct);
+
+	free(meta_block);
+
+	if (rc != EOK)
+		goto error;
+
+	if (!meta_native_has_valid_magic(metadata_struct)) {
+		rc = ENOFS;
+		goto error;
+	}
+
+	*rmd = metadata_struct;
+	return EOK;
+
+error:
+	free(metadata_struct);
+	return ENOFS;
 }
 
@@ -200,4 +226,170 @@
 
 	return EOK;
+}
+
+static errno_t meta_native_erase_block(service_id_t dev)
+{
+	HR_DEBUG("%s()", __func__);
+
+	errno_t rc;
+	size_t bsize;
+
+	rc = block_get_bsize(dev, &bsize);
+	if (rc != EOK)
+		return rc;
+
+	void *zero_block = calloc(1, bsize);
+	if (zero_block == NULL)
+		return ENOMEM;
+
+	rc = meta_native_write_block(dev, zero_block);
+	return rc;
+}
+
+static bool meta_native_compare_uuids(const void *m1p, const void *m2p)
+{
+	const hr_metadata_t *m1 = m1p;
+	const hr_metadata_t *m2 = m2p;
+	if (memcmp(m1->uuid, m2->uuid, HR_NATIVE_UUID_LEN) == 0)
+		return true;
+
+	return false;
+}
+
+static void meta_native_inc_counter(hr_volume_t *vol)
+{
+	fibril_mutex_lock(&vol->md_lock);
+
+	hr_metadata_t *md = vol->in_mem_md;
+
+	md->counter++;
+
+	fibril_mutex_unlock(&vol->md_lock);
+}
+
+static errno_t meta_native_save(hr_volume_t *vol, bool with_state_callback)
+{
+	HR_DEBUG("%s()", __func__);
+
+	fibril_rwlock_read_lock(&vol->extents_lock);
+
+	for (size_t i = 0; i < vol->extent_no; i++)
+		meta_native_save_ext(vol, i, with_state_callback);
+
+	fibril_rwlock_read_unlock(&vol->extents_lock);
+
+	return EOK;
+}
+
+static errno_t meta_native_save_ext(hr_volume_t *vol, size_t ext_idx,
+    bool with_state_callback)
+{
+	HR_DEBUG("%s()", __func__);
+
+	assert(fibril_rwlock_is_locked(&vol->extents_lock));
+
+	void *md_block = hr_calloc_waitok(1, vol->bsize);
+
+	hr_metadata_t *md = (hr_metadata_t *)vol->in_mem_md;
+
+	hr_extent_t *ext = &vol->extents[ext_idx];
+
+	fibril_rwlock_read_lock(&vol->states_lock);
+	hr_ext_state_t s = ext->state;
+	fibril_rwlock_read_unlock(&vol->states_lock);
+
+	if (s != HR_EXT_ONLINE && s != HR_EXT_REBUILD) {
+		return EINVAL;
+	}
+
+	fibril_mutex_lock(&vol->md_lock);
+
+	md->index = ext_idx;
+	if (s == HR_EXT_REBUILD)
+		md->rebuild_pos = vol->rebuild_blk;
+	else
+		md->rebuild_pos = 0;
+	meta_native_encode(md, md_block);
+	errno_t rc = meta_native_write_block(ext->svc_id, md_block);
+	if (rc != EOK && with_state_callback)
+		vol->hr_ops.ext_state_cb(vol, ext_idx, rc);
+
+	fibril_mutex_unlock(&vol->md_lock);
+
+	if (with_state_callback)
+		vol->hr_ops.vol_state_eval(vol);
+
+	free(md_block);
+	return EOK;
+}
+
+static const char *meta_native_get_devname(const void *md_v)
+{
+	const hr_metadata_t *md = md_v;
+
+	return md->devname;
+}
+
+static hr_level_t meta_native_get_level(const void *md_v)
+{
+	const hr_metadata_t *md = md_v;
+
+	return md->level;
+}
+
+static uint64_t meta_native_get_data_offset(void)
+{
+	return HR_NATIVE_DATA_OFF;
+}
+
+static size_t meta_native_get_size(void)
+{
+	return HR_NATIVE_META_SIZE;
+}
+
+static uint8_t meta_native_get_flags(void)
+{
+	uint8_t flags = 0;
+
+	flags |= HR_METADATA_HOTSPARE_SUPPORT;
+
+	return flags;
+}
+
+static hr_metadata_type_t meta_native_get_type(void)
+{
+	return HR_METADATA_NATIVE;
+}
+
+static void meta_native_dump(const void *md_v)
+{
+	HR_DEBUG("%s()", __func__);
+
+	const hr_metadata_t *metadata = md_v;
+
+	printf("\tmagic: %s\n", metadata->magic);
+	printf("\tUUID: ");
+	for (size_t i = 0; i < HR_NATIVE_UUID_LEN; ++i) {
+		printf("%.2X", metadata->uuid[i]);
+		if (i + 1 < HR_NATIVE_UUID_LEN)
+			printf(" ");
+	}
+	printf("\n");
+	printf("\tdata_blkno: %" PRIu64 "\n", metadata->data_blkno);
+	printf("\ttruncated_blkno: %" PRIu64 "\n", metadata->truncated_blkno);
+	printf("\tcounter: %" PRIu64 "\n", metadata->counter);
+	printf("\tversion: %" PRIu32 "\n", metadata->version);
+	printf("\textent_no: %" PRIu32 "\n", metadata->extent_no);
+	printf("\tindex: %" PRIu32 "\n", metadata->index);
+	printf("\tlevel: %" PRIu32 "\n", metadata->level);
+	printf("\tlayout: %" PRIu32 "\n", metadata->layout);
+	printf("\tstrip_size: %" PRIu32 "\n", metadata->strip_size);
+	printf("\tbsize: %" PRIu32 "\n", metadata->bsize);
+	printf("\tdevname: %s\n", metadata->devname);
+}
+
+static void *meta_native_alloc_struct(void)
+{
+	return calloc(1, sizeof(hr_metadata_t));
 }
 
@@ -342,23 +534,4 @@
 }
 
-static errno_t meta_native_erase_block(service_id_t dev)
-{
-	HR_DEBUG("%s()", __func__);
-
-	errno_t rc;
-	size_t bsize;
-
-	rc = block_get_bsize(dev, &bsize);
-	if (rc != EOK)
-		return rc;
-
-	void *zero_block = calloc(1, bsize);
-	if (zero_block == NULL)
-		return ENOMEM;
-
-	rc = meta_native_write_block(dev, zero_block);
-	return rc;
-}
-
 static bool meta_native_has_valid_magic(const void *md_v)
 {
@@ -373,146 +546,4 @@
 }
 
-static bool meta_native_compare_uuids(const void *m1p, const void *m2p)
-{
-	const hr_metadata_t *m1 = m1p;
-	const hr_metadata_t *m2 = m2p;
-	if (memcmp(m1->uuid, m2->uuid, HR_NATIVE_UUID_LEN) == 0)
-		return true;
-
-	return false;
-}
-
-static void meta_native_inc_counter(hr_volume_t *vol)
-{
-	fibril_mutex_lock(&vol->md_lock);
-
-	hr_metadata_t *md = vol->in_mem_md;
-
-	md->counter++;
-
-	fibril_mutex_unlock(&vol->md_lock);
-}
-
-static errno_t meta_native_save(hr_volume_t *vol, bool with_state_callback)
-{
-	HR_DEBUG("%s()", __func__);
-
-	fibril_rwlock_read_lock(&vol->extents_lock);
-
-	for (size_t i = 0; i < vol->extent_no; i++)
-		meta_native_save_ext(vol, i, with_state_callback);
-
-	fibril_rwlock_read_unlock(&vol->extents_lock);
-
-	return EOK;
-}
-
-static errno_t meta_native_save_ext(hr_volume_t *vol, size_t ext_idx,
-    bool with_state_callback)
-{
-	HR_DEBUG("%s()", __func__);
-
-	assert(fibril_rwlock_is_locked(&vol->extents_lock));
-
-	void *md_block = hr_calloc_waitok(1, vol->bsize);
-
-	hr_metadata_t *md = (hr_metadata_t *)vol->in_mem_md;
-
-	hr_extent_t *ext = &vol->extents[ext_idx];
-
-	fibril_rwlock_read_lock(&vol->states_lock);
-	hr_ext_state_t s = ext->state;
-	fibril_rwlock_read_unlock(&vol->states_lock);
-
-	if (s != HR_EXT_ONLINE && s != HR_EXT_REBUILD) {
-		return EINVAL;
-	}
-
-	fibril_mutex_lock(&vol->md_lock);
-
-	md->index = ext_idx;
-	if (s == HR_EXT_REBUILD)
-		md->rebuild_pos = vol->rebuild_blk;
-	else
-		md->rebuild_pos = 0;
-	meta_native_encode(md, md_block);
-	errno_t rc = meta_native_write_block(ext->svc_id, md_block);
-	if (rc != EOK && with_state_callback)
-		vol->hr_ops.ext_state_cb(vol, ext_idx, rc);
-
-	fibril_mutex_unlock(&vol->md_lock);
-
-	if (with_state_callback)
-		vol->hr_ops.vol_state_eval(vol);
-
-	free(md_block);
-	return EOK;
-}
-
-static const char *meta_native_get_devname(const void *md_v)
-{
-	const hr_metadata_t *md = md_v;
-
-	return md->devname;
-}
-
-static hr_level_t meta_native_get_level(const void *md_v)
-{
-	const hr_metadata_t *md = md_v;
-
-	return md->level;
-}
-
-static uint64_t meta_native_get_data_offset(void)
-{
-	return HR_NATIVE_DATA_OFF;
-}
-
-static size_t meta_native_get_size(void)
-{
-	return HR_NATIVE_META_SIZE;
-}
-
-static uint8_t meta_native_get_flags(void)
-{
-	uint8_t flags = 0;
-
-	flags |= HR_METADATA_HOTSPARE_SUPPORT;
-
-	return flags;
-}
-
-static hr_metadata_type_t meta_native_get_type(void)
-{
-	return HR_METADATA_NATIVE;
-}
-
-static void meta_native_dump(const void *md_v)
-{
-	HR_DEBUG("%s()", __func__);
-
-	const hr_metadata_t *metadata = md_v;
-
-	printf("\tmagic: %s\n", metadata->magic);
-	printf("\tUUID: ");
-	for (size_t i = 0; i < HR_NATIVE_UUID_LEN; ++i) {
-		printf("%.2X", metadata->uuid[i]);
-		if (i + 1 < HR_NATIVE_UUID_LEN)
-			printf(" ");
-	}
-	printf("\n");
-	printf("\tdata_blkno: %" PRIu64 "\n", metadata->data_blkno);
-	printf("\ttruncated_blkno: %" PRIu64 "\n", metadata->truncated_blkno);
-	printf("\tcounter: %" PRIu64 "\n", metadata->counter);
-	printf("\tversion: %" PRIu32 "\n", metadata->version);
-	printf("\textent_no: %" PRIu32 "\n", metadata->extent_no);
-	printf("\tindex: %" PRIu32 "\n", metadata->index);
-	printf("\tlevel: %" PRIu32 "\n", metadata->level);
-	printf("\tlayout: %" PRIu32 "\n", metadata->layout);
-	printf("\tstrip_size: %" PRIu32 "\n", metadata->strip_size);
-	printf("\tbsize: %" PRIu32 "\n", metadata->bsize);
-	printf("\tdevname: %s\n", metadata->devname);
-}
-
 /** @}
  */
Index: uspace/srv/bd/hr/superblock.c
===================================================================
--- uspace/srv/bd/hr/superblock.c	(revision 78433bbc6780846cacf166c1034df23fd5f58768)
+++ uspace/srv/bd/hr/superblock.c	(revision aa9bad8ad7f31ed589ba9008abeb38be019e40c5)
@@ -68,5 +68,5 @@
 };
 
-hr_superblock_ops_t *get_type_ops(hr_metadata_type_t type)
+hr_superblock_ops_t *hr_get_meta_type_ops(hr_metadata_type_t type)
 {
 	assert(type >= HR_METADATA_NATIVE && type < HR_METADATA_LAST_DUMMY);
@@ -75,5 +75,5 @@
 }
 
-errno_t find_metadata(service_id_t svc_id, void **rmetadata,
+errno_t hr_find_metadata(service_id_t svc_id, void **rmetadata,
     hr_metadata_type_t *rtype)
 {
@@ -82,5 +82,4 @@
 	errno_t rc;
 	hr_superblock_ops_t *meta_ops;
-	void *meta_block;
 	void *metadata_struct;
 
@@ -94,28 +93,8 @@
 		meta_ops = hr_superblock_ops_all[type];
 
-		metadata_struct = meta_ops->alloc_struct();
-		if (metadata_struct == NULL)
-			return ENOMEM;
-
-		rc = meta_ops->get_block(svc_id, &meta_block);
-		if (rc == ENOMEM) {
-			free(metadata_struct);
-			return ENOMEM;
-		} else if (rc != EOK) {
-			free(metadata_struct);
-			continue;
-		}
-
-		rc = meta_ops->decode(meta_block, metadata_struct);
-
-		free(meta_block);
-
+		rc = meta_ops->probe(svc_id, &metadata_struct);
 		if (rc != EOK) {
-			free(metadata_struct);
-			continue;
-		}
-
-		if (!meta_ops->has_valid_magic(metadata_struct)) {
-			free(metadata_struct);
+			if (rc != ENOFS)
+				return rc;
 			continue;
 		}
Index: uspace/srv/bd/hr/superblock.h
===================================================================
--- uspace/srv/bd/hr/superblock.h	(revision 78433bbc6780846cacf166c1034df23fd5f58768)
+++ uspace/srv/bd/hr/superblock.h	(revision aa9bad8ad7f31ed589ba9008abeb38be019e40c5)
@@ -44,13 +44,8 @@
 
 typedef struct hr_superblock_ops {
-	void *(*alloc_struct)(void);
+	errno_t (*probe)(service_id_t, void **);
 	errno_t (*init_vol2meta)(hr_volume_t *);
 	errno_t (*init_meta2vol)(const list_t *, hr_volume_t *);
-	void (*encode)(void *, void *);
-	errno_t (*decode)(const void *, void *);
-	errno_t (*get_block)(service_id_t, void **);
-	errno_t (*write_block)(service_id_t, const void *);
 	errno_t (*erase_block)(service_id_t);
-	bool (*has_valid_magic)(const void *);
 	bool (*compare_uuids)(const void *, const void *);
 	void (*inc_counter)(hr_volume_t *);
@@ -66,6 +61,6 @@
 } hr_superblock_ops_t;
 
-extern hr_superblock_ops_t *get_type_ops(hr_metadata_type_t);
-extern errno_t find_metadata(service_id_t, void **, hr_metadata_type_t *);
+extern hr_superblock_ops_t *hr_get_meta_type_ops(hr_metadata_type_t);
+extern errno_t hr_find_metadata(service_id_t, void **, hr_metadata_type_t *);
 
 #endif
Index: uspace/srv/bd/hr/util.c
===================================================================
--- uspace/srv/bd/hr/util.c	(revision 78433bbc6780846cacf166c1034df23fd5f58768)
+++ uspace/srv/bd/hr/util.c	(revision aa9bad8ad7f31ed589ba9008abeb38be019e40c5)
@@ -115,5 +115,5 @@
 	vol->level = level;
 
-	vol->meta_ops = get_type_ops(metadata_type);
+	vol->meta_ops = hr_get_meta_type_ops(metadata_type);
 
 	uint8_t meta_flags = vol->meta_ops->get_flags();
@@ -792,5 +792,5 @@
 	errno_t rc = EOK;
 
-	hr_superblock_ops_t *meta_ops = get_type_ops(type_main);
+	hr_superblock_ops_t *meta_ops = hr_get_meta_type_ops(type_main);
 
 	list_foreach(*list, link, struct dev_list_member, iter) {
@@ -801,5 +801,5 @@
 		hr_metadata_type_t type;
 
-		rc = find_metadata(iter->svc_id, &metadata_struct, &type);
+		rc = hr_find_metadata(iter->svc_id, &metadata_struct, &type);
 		if (rc == ENOFS)
 			continue;
@@ -837,5 +837,5 @@
 	errno_t rc = EOK;
 
-	hr_superblock_ops_t *meta_ops = get_type_ops(type);
+	hr_superblock_ops_t *meta_ops = hr_get_meta_type_ops(type);
 
 	link_t *memb_l = list_first(list);
@@ -933,5 +933,5 @@
 		hr_metadata_type_t type;
 
-		rc = find_metadata(iter->svc_id, &metadata_struct_main, &type);
+		rc = hr_find_metadata(iter->svc_id, &metadata_struct_main, &type);
 		if (rc == ENOFS) {
 			block_fini(iter->svc_id);
