Index: uspace/srv/fs/cdfs/cdfs_ops.c
===================================================================
--- uspace/srv/fs/cdfs/cdfs_ops.c	(revision d4b63faf94a09dafd6012c7e11305a83ef0151e0)
+++ uspace/srv/fs/cdfs/cdfs_ops.c	(revision 0003e0f5a06cbcc144c263d2c7642dab1b36276a)
@@ -39,4 +39,5 @@
 #include "cdfs_ops.h"
 #include <stdbool.h>
+#include <adt/list.h>
 #include <adt/hash_table.h>
 #include <adt/hash.h>
@@ -195,8 +196,14 @@
 typedef uint32_t cdfs_lba_t;
 
+/** Mounted CDFS filesystem */
+typedef struct {
+	link_t link;
+	service_id_t service_id;  /**< Service ID of block device */
+} cdfs_t;
+
 typedef struct {
 	fs_node_t *fs_node;       /**< FS node */
 	fs_index_t index;         /**< Node index */
-	service_id_t service_id;  /**< Service ID of block device */
+	cdfs_t *fs;		  /**< File system */
 	
 	ht_link_t nh_link;        /**< Nodes hash table link */
@@ -212,4 +219,7 @@
 } cdfs_node_t;
 
+/** List of all instances */
+static LIST_INITIALIZE(cdfs_instances);
+
 /** Shared index of nodes */
 static fs_index_t cdfs_index = 1;
@@ -239,5 +249,5 @@
 {
 	cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
-	return hash_combine(node->service_id, node->index);
+	return hash_combine(node->fs->service_id, node->index);
 }
 
@@ -247,5 +257,5 @@
 	ht_key_t *key = (ht_key_t*)k;
 	
-	return key->service_id == node->service_id && key->index == node->index;
+	return key->service_id == node->fs->service_id && key->index == node->index;
 }
 
@@ -305,5 +315,5 @@
 	node->fs_node = NULL;
 	node->index = 0;
-	node->service_id = 0;
+	node->fs = NULL;
 	node->type = CDFS_NONE;
 	node->lnkcnt = 0;
@@ -316,5 +326,5 @@
 }
 
-static int create_node(fs_node_t **rfn, service_id_t service_id, int lflag,
+static int create_node(fs_node_t **rfn, cdfs_t *fs, int lflag,
     fs_index_t index)
 {
@@ -337,5 +347,5 @@
 	
 	fs_node_t *rootfn;
-	int rc = cdfs_root_get(&rootfn, service_id);
+	int rc = cdfs_root_get(&rootfn, fs->service_id);
 	
 	assert(rc == EOK);
@@ -346,5 +356,5 @@
 		node->index = index;
 	
-	node->service_id = service_id;
+	node->fs = fs;
 	
 	if (lflag & L_DIRECTORY)
@@ -436,5 +446,5 @@
 }
 
-static bool cdfs_readdir(service_id_t service_id, fs_node_t *fs_node)
+static bool cdfs_readdir(cdfs_t *fs, fs_node_t *fs_node)
 {
 	cdfs_node_t *node = CDFS_NODE(fs_node);
@@ -450,5 +460,5 @@
 	for (uint32_t i = 0; i < blocks; i++) {
 		block_t *block;
-		int rc = block_get(&block, service_id, node->lba + i, BLOCK_FLAGS_NONE);
+		int rc = block_get(&block, fs->service_id, node->lba + i, BLOCK_FLAGS_NONE);
 		if (rc != EOK)
 			return false;
@@ -484,5 +494,5 @@
 			
 			fs_node_t *fn;
-			int rc = create_node(&fn, service_id, dentry_type,
+			int rc = create_node(&fn, fs, dentry_type,
 			    (node->lba + i) * BLOCK_SIZE + offset);
 			if ((rc != EOK) || (fn == NULL))
@@ -514,5 +524,5 @@
 }
 
-static fs_node_t *get_uncached_node(service_id_t service_id, fs_index_t index)
+static fs_node_t *get_uncached_node(cdfs_t *fs, fs_index_t index)
 {
 	cdfs_lba_t lba = index / BLOCK_SIZE;
@@ -520,5 +530,5 @@
 	
 	block_t *block;
-	int rc = block_get(&block, service_id, lba, BLOCK_FLAGS_NONE);
+	int rc = block_get(&block, fs->service_id, lba, BLOCK_FLAGS_NONE);
 	if (rc != EOK)
 		return NULL;
@@ -533,5 +543,5 @@
 	
 	fs_node_t *fn;
-	rc = create_node(&fn, service_id, dentry_type, index);
+	rc = create_node(&fn, fs, dentry_type, index);
 	if ((rc != EOK) || (fn == NULL))
 		return NULL;
@@ -549,9 +559,9 @@
 }
 
-static fs_node_t *get_cached_node(service_id_t service_id, fs_index_t index)
+static fs_node_t *get_cached_node(cdfs_t *fs, fs_index_t index)
 {
 	ht_key_t key = {
 		.index = index,
-		.service_id = service_id
+		.service_id = fs->service_id
 	};
 	
@@ -563,5 +573,5 @@
 	}
 	
-	return get_uncached_node(service_id, index);
+	return get_uncached_node(fs, index);
 }
 
@@ -571,5 +581,5 @@
 	
 	if (!parent->processed) {
-		int rc = cdfs_readdir(parent->service_id, pfn);
+		int rc = cdfs_readdir(parent->fs, pfn);
 		if (rc != EOK)
 			return rc;
@@ -578,5 +588,5 @@
 	list_foreach(parent->cs_list, link, cdfs_dentry_t, dentry) {
 		if (str_cmp(dentry->name, component) == 0) {
-			*fn = get_cached_node(parent->service_id, dentry->index);
+			*fn = get_cached_node(parent->fs, dentry->index);
 			return EOK;
 		}
@@ -592,5 +602,5 @@
 	
 	if (!node->processed)
-		cdfs_readdir(node->service_id, fn);
+		cdfs_readdir(node->fs, fn);
 	
 	node->opened++;
@@ -633,5 +643,5 @@
 	
 	if ((node->type == CDFS_DIRECTORY) && (!node->processed))
-		cdfs_readdir(node->service_id, fn);
+		cdfs_readdir(node->fs, fn);
 	
 	*has_children = !list_empty(&node->cs_list);
@@ -717,10 +727,10 @@
 };
 
-static bool iso_readfs(service_id_t service_id, fs_node_t *rfn,
+static bool iso_readfs(cdfs_t *fs, fs_node_t *rfn,
     cdfs_lba_t altroot)
 {
 	/* First 16 blocks of isofs are empty */
 	block_t *block;
-	int rc = block_get(&block, service_id, altroot + 16, BLOCK_FLAGS_NONE);
+	int rc = block_get(&block, fs->service_id, altroot + 16, BLOCK_FLAGS_NONE);
 	if (rc != EOK)
 		return false;
@@ -771,5 +781,5 @@
 	node->size = uint32_lb(vol_desc->data.primary.root_dir.size);
 	
-	if (!cdfs_readdir(service_id, rfn)) {
+	if (!cdfs_readdir(fs, rfn)) {
 		block_put(block);
 		return false;
@@ -783,12 +793,20 @@
  *
  */
-static bool cdfs_instance_init(service_id_t service_id, cdfs_lba_t altroot)
-{
+static cdfs_t *cdfs_fs_create(service_id_t sid, cdfs_lba_t altroot)
+{
+	cdfs_t *fs = NULL;
+	fs_node_t *rfn = NULL;
+
+	fs = calloc(1, sizeof(cdfs_t));
+	if (fs == NULL)
+		goto error;
+
+	fs->service_id = sid;
+
 	/* Create root node */
-	fs_node_t *rfn;
-	int rc = create_node(&rfn, service_id, L_DIRECTORY, cdfs_index++);
+	int rc = create_node(&rfn, fs, L_DIRECTORY, cdfs_index++);
 	
 	if ((rc != EOK) || (!rfn))
-		return false;
+		goto error;
 	
 	/* FS root is not linked */
@@ -798,10 +816,13 @@
 	
 	/* Check if there is cdfs in given session */
-	if (!iso_readfs(service_id, rfn, altroot)) {
-		// XXX destroy node
-		return false;
-	}
-	
-	return true;
+	if (!iso_readfs(fs, rfn, altroot))
+		goto error;
+	
+	list_append(&fs->link, &cdfs_instances);
+	return fs;
+error:
+	// XXX destroy node
+	free(fs);
+	return NULL;
 }
 
@@ -847,6 +868,6 @@
 	}
 	
-	/* Initialize cdfs instance */
-	if (!cdfs_instance_init(service_id, altroot)) {
+	/* Create cdfs instance */
+	if (cdfs_fs_create(service_id, altroot) == NULL) {
 		block_cache_fini(service_id);
 		block_fini(service_id);
@@ -871,5 +892,5 @@
 	cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
 	
-	if (node->service_id == service_id) {
+	if (node->fs->service_id == service_id) {
 		hash_table_remove_item(&nodes, &node->nh_link);
 	}
@@ -878,14 +899,32 @@
 }
 
-static void cdfs_instance_done(service_id_t service_id)
-{
-	hash_table_apply(&nodes, rm_service_id_nodes, &service_id);
-	block_cache_fini(service_id);
-	block_fini(service_id);
+static void cdfs_fs_destroy(cdfs_t *fs)
+{
+	list_remove(&fs->link);
+	hash_table_apply(&nodes, rm_service_id_nodes, &fs->service_id);
+	block_cache_fini(fs->service_id);
+	block_fini(fs->service_id);
+	free(fs);
+}
+
+static cdfs_t *cdfs_find_by_sid(service_id_t service_id)
+{
+	list_foreach(cdfs_instances, link, cdfs_t, fs) {
+		if (fs->service_id == service_id)
+			return fs;
+	}
+	
+	return NULL;
 }
 
 static int cdfs_unmounted(service_id_t service_id)
 {
-	cdfs_instance_done(service_id);
+	cdfs_t *fs;
+
+	fs = cdfs_find_by_sid(service_id);
+	if (fs == NULL)
+		return ENOENT;
+
+	cdfs_fs_destroy(fs);
 	return EOK;
 }
@@ -907,5 +946,5 @@
 	
 	if (!node->processed) {
-		int rc = cdfs_readdir(service_id, FS_NODE(node));
+		int rc = cdfs_readdir(node->fs, FS_NODE(node));
 		if (rc != EOK)
 			return rc;
