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 aaf741ff297c52b299e30bf30b37ec6ea32c8ec9)
@@ -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);
-}
-
 /** @}
  */
