Index: uspace/srv/fs/exfat/exfat_ops.c
===================================================================
--- uspace/srv/fs/exfat/exfat_ops.c	(revision 4f302225f2b25aadcba779f5a36656dd5a66959e)
+++ uspace/srv/fs/exfat/exfat_ops.c	(revision e27e36e1fb9699de71e9900d126082ea33f88bc2)
@@ -1013,4 +1013,218 @@
 };
 
+static int exfat_fs_open(service_id_t service_id, enum cache_mode cmode,
+    fs_node_t **rrfn, exfat_idx_t **rridxp, vfs_fs_probe_info_t *info)
+{
+	int rc;
+	exfat_node_t *rootp = NULL, *bitmapp = NULL, *uctablep = NULL;
+	exfat_bs_t *bs;
+
+	/* initialize libblock */
+	rc = block_init(service_id, BS_SIZE);
+	if (rc != EOK)
+		return rc;
+
+	/* prepare the boot block */
+	rc = block_bb_read(service_id, BS_BLOCK);
+	if (rc != EOK) {
+		block_fini(service_id);
+		return rc;
+	}
+
+	/* get the buffer with the boot sector */
+	bs = block_bb_get(service_id);
+
+	/* Do some simple sanity checks on the file system. */
+	rc = exfat_sanity_check(bs);
+	if (rc != EOK) {
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		return rc;
+	}
+
+	/* Initialize the block cache */
+	rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode);
+	if (rc != EOK) {
+		block_fini(service_id);
+		return rc;
+	}
+
+	rc = exfat_idx_init_by_service_id(service_id);
+	if (rc != EOK) {
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		return rc;
+	}
+
+	/* Initialize the root node. */
+	rc = exfat_node_get_new_by_pos(&rootp, service_id, EXFAT_ROOT_PAR, 
+	    EXFAT_ROOT_POS);
+	if (rc!=EOK) {
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		exfat_idx_fini_by_service_id(service_id);
+		return ENOMEM;
+	}
+	assert(rootp->idx->index == EXFAT_ROOT_IDX);
+
+	rootp->type = EXFAT_DIRECTORY;
+	rootp->firstc = ROOT_FC(bs);
+	rootp->fragmented = true;
+	rootp->refcnt = 1;
+	rootp->lnkcnt = 0;	/* FS root is not linked */
+
+	uint32_t clusters;
+	rc = exfat_clusters_get(&clusters, bs, service_id, rootp->firstc);
+	if (rc != EOK) {
+		free(rootp);
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		exfat_idx_fini_by_service_id(service_id);
+		return ENOTSUP;
+	}
+	rootp->size = BPS(bs) * SPC(bs) * clusters;
+	fibril_mutex_unlock(&rootp->idx->lock);
+
+	/* Open root directory and looking for Bitmap and UC-Table */
+	exfat_directory_t di;
+	exfat_dentry_t *de;
+	rc = exfat_directory_open(rootp, &di);
+	if (rc != EOK) {
+		free(rootp);
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		exfat_idx_fini_by_service_id(service_id);
+		return ENOTSUP;
+	}
+
+	/* Initialize the bitmap node. */
+	rc = exfat_directory_find(&di, EXFAT_DENTRY_BITMAP, &de);
+	if (rc != EOK) {
+		free(rootp);
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		exfat_idx_fini_by_service_id(service_id);
+		return ENOTSUP;
+	}
+
+	rc = exfat_node_get_new_by_pos(&bitmapp, service_id, rootp->firstc, 
+	    di.pos);
+	if (rc != EOK) {
+		free(rootp);
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		exfat_idx_fini_by_service_id(service_id);
+		return ENOMEM;
+	}
+	assert(bitmapp->idx->index == EXFAT_BITMAP_IDX);
+	fibril_mutex_unlock(&bitmapp->idx->lock);
+
+	bitmapp->type = EXFAT_BITMAP;
+	bitmapp->firstc = uint32_t_le2host(de->bitmap.firstc);
+	bitmapp->fragmented = true;
+	bitmapp->idx->parent_fragmented = true;
+	bitmapp->refcnt = 1;
+	bitmapp->lnkcnt = 0;
+	bitmapp->size = uint64_t_le2host(de->bitmap.size);
+
+	/* Initialize the uctable node. */
+	rc = exfat_directory_seek(&di, 0);
+	if (rc != EOK) {
+		free(rootp);
+		free(bitmapp);
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		exfat_idx_fini_by_service_id(service_id);
+		return ENOTSUP;
+	}
+
+	rc = exfat_directory_find(&di, EXFAT_DENTRY_UCTABLE, &de);
+	if (rc != EOK) {
+		free(rootp);
+		free(bitmapp);
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		exfat_idx_fini_by_service_id(service_id);
+		return ENOTSUP;
+	}
+
+	rc = exfat_node_get_new_by_pos(&uctablep, service_id, rootp->firstc, 
+	    di.pos);
+	if (rc != EOK) {
+		free(rootp);
+		free(bitmapp);
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		exfat_idx_fini_by_service_id(service_id);
+		return ENOMEM;
+	}
+	assert(uctablep->idx->index == EXFAT_UCTABLE_IDX);
+	fibril_mutex_unlock(&uctablep->idx->lock);
+
+	uctablep->type = EXFAT_UCTABLE;
+	uctablep->firstc = uint32_t_le2host(de->uctable.firstc);
+	uctablep->fragmented = true;
+	uctablep->idx->parent_fragmented = true;
+	uctablep->refcnt = 1;
+	uctablep->lnkcnt = 0;
+	uctablep->size = uint64_t_le2host(de->uctable.size);
+
+	if (info != NULL) {
+		/* Read volume label. */
+		rc = exfat_directory_read_vollabel(&di, info->label,
+		    FS_LABEL_MAXLEN + 1);
+		if (rc != EOK) {
+			free(rootp);
+			free(bitmapp);
+			free(uctablep);
+			(void) block_cache_fini(service_id);
+			block_fini(service_id);
+			exfat_idx_fini_by_service_id(service_id);
+    		    return ENOTSUP;
+		}
+	}
+
+	rc = exfat_directory_close(&di);
+	if (rc != EOK) {
+		free(rootp);
+		free(bitmapp);
+		free(uctablep);
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		exfat_idx_fini_by_service_id(service_id);
+		return ENOMEM;
+	}
+
+	/* exfat_fsinfo(bs, service_id); */
+
+	*rrfn = FS_NODE(rootp);
+	*rridxp = rootp->idx;
+
+	if (info != NULL) {
+//		str_cpy(info->label, FS_LABEL_MAXLEN + 1, label);
+	}
+
+	return EOK;
+}
+
+static void exfat_fs_close(service_id_t service_id, fs_node_t *rfn)
+{
+	/*
+	 * Put the root node and force it to the FAT free node list.
+	 */
+	(void) exfat_node_put(rfn);
+	(void) exfat_node_put(rfn);
+
+	/*
+	 * Perform cleanup of the node structures, index structures and
+	 * associated data. Write back this file system's dirty blocks and
+	 * stop using libblock for this instance.
+	 */
+	(void) exfat_node_fini_by_service_id(service_id);
+	exfat_idx_fini_by_service_id(service_id);
+	(void) block_cache_fini(service_id);
+	block_fini(service_id);
+}
+
 
 /*
@@ -1054,27 +1268,13 @@
 {
 	int rc;
-	exfat_bs_t *bs;
-
-	/* initialize libblock */
-	rc = block_init(service_id, BS_SIZE);
-	if (rc != EOK)
-		return rc;
-
-	/* prepare the boot block */
-	rc = block_bb_read(service_id, BS_BLOCK);
-	if (rc != EOK) {
-		block_fini(service_id);
-		return rc;
-	}
-
-	/* get the buffer with the boot sector */
-	bs = block_bb_get(service_id);
-
-	/* Do some simple sanity checks on the file system. */
-	rc = exfat_sanity_check(bs);
-
-	(void) block_cache_fini(service_id);
-	block_fini(service_id);
-	return rc;
+	exfat_idx_t *ridxp;
+	fs_node_t *rfn;
+
+	rc = exfat_fs_open(service_id, CACHE_MODE_WT, &rfn, &ridxp, info);
+	if (rc != EOK)
+		return rc;
+
+	exfat_fs_close(service_id, rfn);
+	return EOK;
 }
 
@@ -1084,7 +1284,7 @@
 {
 	int rc;
-	exfat_node_t *rootp = NULL, *bitmapp = NULL, *uctablep = NULL;
 	enum cache_mode cmode;
-	exfat_bs_t *bs;
+	exfat_idx_t *ridxp;
+	fs_node_t *rfn;
 
 	/* Check for option enabling write through. */
@@ -1094,170 +1294,11 @@
 		cmode = CACHE_MODE_WB;
 
-	/* initialize libblock */
-	rc = block_init(service_id, BS_SIZE);
-	if (rc != EOK)
-		return rc;
-
-	/* prepare the boot block */
-	rc = block_bb_read(service_id, BS_BLOCK);
-	if (rc != EOK) {
-		block_fini(service_id);
-		return rc;
-	}
-
-	/* get the buffer with the boot sector */
-	bs = block_bb_get(service_id);
-
-	/* Do some simple sanity checks on the file system. */
-	rc = exfat_sanity_check(bs);
-	if (rc != EOK) {
-		(void) block_cache_fini(service_id);
-		block_fini(service_id);
-		return rc;
-	}
-
-	/* Initialize the block cache */
-	rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode);
-	if (rc != EOK) {
-		block_fini(service_id);
-		return rc;
-	}
-
-	rc = exfat_idx_init_by_service_id(service_id);
-	if (rc != EOK) {
-		(void) block_cache_fini(service_id);
-		block_fini(service_id);
-		return rc;
-	}
-
-	/* Initialize the root node. */
-	rc = exfat_node_get_new_by_pos(&rootp, service_id, EXFAT_ROOT_PAR, 
-	    EXFAT_ROOT_POS);
-	if (rc!=EOK) {
-		(void) block_cache_fini(service_id);
-		block_fini(service_id);
-		exfat_idx_fini_by_service_id(service_id);
-		return ENOMEM;
-	}
-	assert(rootp->idx->index == EXFAT_ROOT_IDX);
-
-	rootp->type = EXFAT_DIRECTORY;
-	rootp->firstc = ROOT_FC(bs);
-	rootp->fragmented = true;
-	rootp->refcnt = 1;
-	rootp->lnkcnt = 0;	/* FS root is not linked */
-
-	uint32_t clusters;
-	rc = exfat_clusters_get(&clusters, bs, service_id, rootp->firstc);
-	if (rc != EOK) {
-		free(rootp);
-		(void) block_cache_fini(service_id);
-		block_fini(service_id);
-		exfat_idx_fini_by_service_id(service_id);
-		return ENOTSUP;
-	}
-	rootp->size = BPS(bs) * SPC(bs) * clusters;
-	fibril_mutex_unlock(&rootp->idx->lock);
-
-	/* Open root directory and looking for Bitmap and UC-Table */
-	exfat_directory_t di;
-	exfat_dentry_t *de;
-	rc = exfat_directory_open(rootp, &di);
-	if (rc != EOK) {
-		free(rootp);
-		(void) block_cache_fini(service_id);
-		block_fini(service_id);
-		exfat_idx_fini_by_service_id(service_id);
-		return ENOTSUP;
-	}
-
-	/* Initialize the bitmap node. */
-	rc = exfat_directory_find(&di, EXFAT_DENTRY_BITMAP, &de);
-	if (rc != EOK) {
-		free(rootp);
-		(void) block_cache_fini(service_id);
-		block_fini(service_id);
-		exfat_idx_fini_by_service_id(service_id);
-		return ENOTSUP;
-	}
-
-	rc = exfat_node_get_new_by_pos(&bitmapp, service_id, rootp->firstc, 
-	    di.pos);
-	if (rc != EOK) {
-		free(rootp);
-		(void) block_cache_fini(service_id);
-		block_fini(service_id);
-		exfat_idx_fini_by_service_id(service_id);
-		return ENOMEM;
-	}
-	assert(bitmapp->idx->index == EXFAT_BITMAP_IDX);
-	fibril_mutex_unlock(&bitmapp->idx->lock);
-
-	bitmapp->type = EXFAT_BITMAP;
-	bitmapp->firstc = uint32_t_le2host(de->bitmap.firstc);
-	bitmapp->fragmented = true;
-	bitmapp->idx->parent_fragmented = true;
-	bitmapp->refcnt = 1;
-	bitmapp->lnkcnt = 0;
-	bitmapp->size = uint64_t_le2host(de->bitmap.size);
-
-	/* Initialize the uctable node. */
-	rc = exfat_directory_seek(&di, 0);
-	if (rc != EOK) {
-		free(rootp);
-		free(bitmapp);
-		(void) block_cache_fini(service_id);
-		block_fini(service_id);
-		exfat_idx_fini_by_service_id(service_id);
-		return ENOTSUP;
-	}
-
-	rc = exfat_directory_find(&di, EXFAT_DENTRY_UCTABLE, &de);
-	if (rc != EOK) {
-		free(rootp);
-		free(bitmapp);
-		(void) block_cache_fini(service_id);
-		block_fini(service_id);
-		exfat_idx_fini_by_service_id(service_id);
-		return ENOTSUP;
-	}
-
-	rc = exfat_node_get_new_by_pos(&uctablep, service_id, rootp->firstc, 
-	    di.pos);
-	if (rc != EOK) {
-		free(rootp);
-		free(bitmapp);
-		(void) block_cache_fini(service_id);
-		block_fini(service_id);
-		exfat_idx_fini_by_service_id(service_id);
-		return ENOMEM;
-	}
-	assert(uctablep->idx->index == EXFAT_UCTABLE_IDX);
-	fibril_mutex_unlock(&uctablep->idx->lock);
-
-	uctablep->type = EXFAT_UCTABLE;
-	uctablep->firstc = uint32_t_le2host(de->uctable.firstc);
-	uctablep->fragmented = true;
-	uctablep->idx->parent_fragmented = true;
-	uctablep->refcnt = 1;
-	uctablep->lnkcnt = 0;
-	uctablep->size = uint64_t_le2host(de->uctable.size);
-
-	rc = exfat_directory_close(&di);
-	if (rc != EOK) {
-		free(rootp);
-		free(bitmapp);
-		free(uctablep);
-		(void) block_cache_fini(service_id);
-		block_fini(service_id);
-		exfat_idx_fini_by_service_id(service_id);
-		return ENOMEM;
-	}
-
-	/* exfat_fsinfo(bs, service_id); */
-
-	*index = rootp->idx->index;
-	*size = rootp->size;
-	
+	rc = exfat_fs_open(service_id, cmode, &rfn, &ridxp, NULL);
+	if (rc != EOK)
+		return rc;
+
+	*index = ridxp->index;
+	*size = EXFAT_NODE(rfn)->size;
+
 	return EOK;
 }
@@ -1265,38 +1306,12 @@
 static int exfat_unmounted(service_id_t service_id)
 {
-	fs_node_t *fn;
-	exfat_node_t *nodep;
-	int rc;
-
-	rc = exfat_root_get(&fn, service_id);
-	if (rc != EOK)
-		return rc;
-	nodep = EXFAT_NODE(fn);
-
-	/*
-	 * We expect exactly two references on the root node. One for the
-	 * fat_root_get() above and one created in fat_mounted().
-	 */
-	if (nodep->refcnt != 2) {
-		(void) exfat_node_put(fn);
-		return EBUSY;
-	}
-
-	/*
-	 * Put the root node and force it to the FAT free node list.
-	 */
-	(void) exfat_node_put(fn);
-	(void) exfat_node_put(fn);
-
-	/*
-	 * Perform cleanup of the node structures, index structures and
-	 * associated data. Write back this file system's dirty blocks and
-	 * stop using libblock for this instance.
-	 */
-	(void) exfat_node_fini_by_service_id(service_id);
-	exfat_idx_fini_by_service_id(service_id);
-	(void) block_cache_fini(service_id);
-	block_fini(service_id);
-
+	fs_node_t *rfn;
+	int rc;
+
+	rc = exfat_root_get(&rfn, service_id);
+	if (rc != EOK)
+		return rc;
+
+	exfat_fs_close(service_id, rfn);
 	return EOK;
 }
@@ -1363,5 +1378,5 @@
 			return ENOTSUP;
 		}
-			
+
 		aoff64_t spos = pos;
 		char name[EXFAT_FILENAME_LEN + 1];
