Index: uspace/srv/fs/fat/fat.h
===================================================================
--- uspace/srv/fs/fat/fat.h	(revision bbf88db2c0682e7fe332dce82c3659c86fd7115c)
+++ uspace/srv/fs/fat/fat.h	(revision f5af63551dff4de3a7ab1cf6b8554664b6554751)
@@ -215,5 +215,5 @@
 extern void fat_sync(ipc_callid_t, ipc_call_t *);
 
-extern fat_idx_t *fat_idx_get_new(dev_handle_t);
+extern int fat_idx_get_new(fat_idx_t **, dev_handle_t);
 extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned);
 extern fat_idx_t *fat_idx_get_by_index(dev_handle_t, fs_index_t);
Index: uspace/srv/fs/fat/fat_idx.c
===================================================================
--- uspace/srv/fs/fat/fat_idx.c	(revision bbf88db2c0682e7fe332dce82c3659c86fd7115c)
+++ uspace/srv/fs/fat/fat_idx.c	(revision f5af63551dff4de3a7ab1cf6b8554664b6554751)
@@ -339,5 +339,5 @@
 }
 
-static fat_idx_t *fat_idx_create(dev_handle_t dev_handle)
+static int fat_idx_create(fat_idx_t **fidxp, dev_handle_t dev_handle)
 {
 	fat_idx_t *fidx;
@@ -345,8 +345,8 @@
 	fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t));
 	if (!fidx) 
-		return NULL;
+		return ENOMEM;
 	if (!fat_index_alloc(dev_handle, &fidx->index)) {
 		free(fidx);
-		return NULL;
+		return ENOSPC;
 	}
 		
@@ -359,16 +359,18 @@
 	fidx->nodep = NULL;
 
-	return fidx;
-}
-
-fat_idx_t *fat_idx_get_new(dev_handle_t dev_handle)
+	*fidxp = fidx;
+	return EOK;
+}
+
+int fat_idx_get_new(fat_idx_t **fidxp, dev_handle_t dev_handle)
 {
 	fat_idx_t *fidx;
+	int rc;
 
 	fibril_mutex_lock(&used_lock);
-	fidx = fat_idx_create(dev_handle);
-	if (!fidx) {
+	rc = fat_idx_create(&fidx, dev_handle);
+	if (rc != EOK) {
 		fibril_mutex_unlock(&used_lock);
-		return NULL;
+		return rc;
 	}
 		
@@ -382,5 +384,6 @@
 	fibril_mutex_unlock(&used_lock);
 
-	return fidx;
+	*fidxp = fidx;
+	return EOK;
 }
 
@@ -401,6 +404,8 @@
 		fidx = hash_table_get_instance(l, fat_idx_t, uph_link);
 	} else {
-		fidx = fat_idx_create(dev_handle);
-		if (!fidx) {
+		int rc;
+
+		rc = fat_idx_create(&fidx, dev_handle);
+		if (rc != EOK) {
 			fibril_mutex_unlock(&used_lock);
 			return NULL;
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision bbf88db2c0682e7fe332dce82c3659c86fd7115c)
+++ uspace/srv/fs/fat/fat_ops.c	(revision f5af63551dff4de3a7ab1cf6b8554664b6554751)
@@ -65,186 +65,4 @@
 static LIST_INITIALIZE(ffn_head);
 
-static void fat_node_initialize(fat_node_t *node)
-{
-	fibril_mutex_initialize(&node->lock);
-	node->bp = NULL;
-	node->idx = NULL;
-	node->type = 0;
-	link_initialize(&node->ffn_link);
-	node->size = 0;
-	node->lnkcnt = 0;
-	node->refcnt = 0;
-	node->dirty = false;
-}
-
-static int fat_node_sync(fat_node_t *node)
-{
-	block_t *b;
-	fat_bs_t *bs;
-	fat_dentry_t *d;
-	uint16_t bps;
-	unsigned dps;
-	int rc;
-	
-	assert(node->dirty);
-
-	bs = block_bb_get(node->idx->dev_handle);
-	bps = uint16_t_le2host(bs->bps);
-	dps = bps / sizeof(fat_dentry_t);
-	
-	/* Read the block that contains the dentry of interest. */
-	rc = _fat_block_get(&b, bs, node->idx->dev_handle, node->idx->pfc,
-	    (node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
-	if (rc != EOK)
-		return rc;
-
-	d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps);
-
-	d->firstc = host2uint16_t_le(node->firstc);
-	if (node->type == FAT_FILE) {
-		d->size = host2uint32_t_le(node->size);
-	} else if (node->type == FAT_DIRECTORY) {
-		d->attr = FAT_ATTR_SUBDIR;
-	}
-	
-	/* TODO: update other fields? (e.g time fields) */
-	
-	b->dirty = true;		/* need to sync block */
-	rc = block_put(b);
-	return rc;
-}
-
-static fat_node_t *fat_node_get_new(void)
-{
-	fs_node_t *fn;
-	fat_node_t *nodep;
-	int rc;
-
-	fibril_mutex_lock(&ffn_mutex);
-	if (!list_empty(&ffn_head)) {
-		/* Try to use a cached free node structure. */
-		fat_idx_t *idxp_tmp;
-		nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
-		if (!fibril_mutex_trylock(&nodep->lock))
-			goto skip_cache;
-		idxp_tmp = nodep->idx;
-		if (!fibril_mutex_trylock(&idxp_tmp->lock)) {
-			fibril_mutex_unlock(&nodep->lock);
-			goto skip_cache;
-		}
-		list_remove(&nodep->ffn_link);
-		fibril_mutex_unlock(&ffn_mutex);
-		if (nodep->dirty) {
-			rc = fat_node_sync(nodep);
-			assert(rc == EOK);
-		}
-		idxp_tmp->nodep = NULL;
-		fibril_mutex_unlock(&nodep->lock);
-		fibril_mutex_unlock(&idxp_tmp->lock);
-		fn = FS_NODE(nodep);
-	} else {
-skip_cache:
-		/* Try to allocate a new node structure. */
-		fibril_mutex_unlock(&ffn_mutex);
-		fn = (fs_node_t *)malloc(sizeof(fs_node_t));
-		if (!fn)
-			return NULL;
-		nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
-		if (!nodep) {
-			free(fn);
-			return NULL;
-		}
-	}
-	fat_node_initialize(nodep);
-	fs_node_initialize(fn);
-	fn->data = nodep;
-	nodep->bp = fn;
-	
-	return nodep;
-}
-
-/** Internal version of fat_node_get().
- *
- * @param idxp		Locked index structure.
- */
-static fat_node_t *fat_node_get_core(fat_idx_t *idxp)
-{
-	block_t *b;
-	fat_bs_t *bs;
-	fat_dentry_t *d;
-	fat_node_t *nodep = NULL;
-	unsigned bps;
-	unsigned spc;
-	unsigned dps;
-	int rc;
-
-	if (idxp->nodep) {
-		/*
-		 * We are lucky.
-		 * The node is already instantiated in memory.
-		 */
-		fibril_mutex_lock(&idxp->nodep->lock);
-		if (!idxp->nodep->refcnt++)
-			list_remove(&idxp->nodep->ffn_link);
-		fibril_mutex_unlock(&idxp->nodep->lock);
-		return idxp->nodep;
-	}
-
-	/*
-	 * We must instantiate the node from the file system.
-	 */
-	
-	assert(idxp->pfc);
-
-	nodep = fat_node_get_new();
-	if (!nodep)
-		return NULL;
-
-	bs = block_bb_get(idxp->dev_handle);
-	bps = uint16_t_le2host(bs->bps);
-	spc = bs->spc;
-	dps = bps / sizeof(fat_dentry_t);
-
-	/* Read the block that contains the dentry of interest. */
-	rc = _fat_block_get(&b, bs, idxp->dev_handle, idxp->pfc,
-	    (idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
-	assert(rc == EOK);
-
-	d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps);
-	if (d->attr & FAT_ATTR_SUBDIR) {
-		/* 
-		 * The only directory which does not have this bit set is the
-		 * root directory itself. The root directory node is handled
-		 * and initialized elsewhere.
-		 */
-		nodep->type = FAT_DIRECTORY;
-		/*
-		 * Unfortunately, the 'size' field of the FAT dentry is not
-		 * defined for the directory entry type. We must determine the
-		 * size of the directory by walking the FAT.
-		 */
-		uint16_t clusters;
-		rc = fat_clusters_get(&clusters, bs, idxp->dev_handle,
-		    uint16_t_le2host(d->firstc));
-		assert(rc == EOK);
-		nodep->size = bps * spc * clusters;
-	} else {
-		nodep->type = FAT_FILE;
-		nodep->size = uint32_t_le2host(d->size);
-	}
-	nodep->firstc = uint16_t_le2host(d->firstc);
-	nodep->lnkcnt = 1;
-	nodep->refcnt = 1;
-
-	rc = block_put(b);
-	assert(rc == EOK);
-
-	/* Link the idx structure with the node structure. */
-	nodep->idx = idxp;
-	idxp->nodep = nodep;
-
-	return nodep;
-}
-
 /*
  * Forward declarations of FAT libfs operations.
@@ -267,4 +85,211 @@
 
 /*
+ * Helper functions.
+ */
+static void fat_node_initialize(fat_node_t *node)
+{
+	fibril_mutex_initialize(&node->lock);
+	node->bp = NULL;
+	node->idx = NULL;
+	node->type = 0;
+	link_initialize(&node->ffn_link);
+	node->size = 0;
+	node->lnkcnt = 0;
+	node->refcnt = 0;
+	node->dirty = false;
+}
+
+static int fat_node_sync(fat_node_t *node)
+{
+	block_t *b;
+	fat_bs_t *bs;
+	fat_dentry_t *d;
+	uint16_t bps;
+	unsigned dps;
+	int rc;
+	
+	assert(node->dirty);
+
+	bs = block_bb_get(node->idx->dev_handle);
+	bps = uint16_t_le2host(bs->bps);
+	dps = bps / sizeof(fat_dentry_t);
+	
+	/* Read the block that contains the dentry of interest. */
+	rc = _fat_block_get(&b, bs, node->idx->dev_handle, node->idx->pfc,
+	    (node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
+	if (rc != EOK)
+		return rc;
+
+	d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps);
+
+	d->firstc = host2uint16_t_le(node->firstc);
+	if (node->type == FAT_FILE) {
+		d->size = host2uint32_t_le(node->size);
+	} else if (node->type == FAT_DIRECTORY) {
+		d->attr = FAT_ATTR_SUBDIR;
+	}
+	
+	/* TODO: update other fields? (e.g time fields) */
+	
+	b->dirty = true;		/* need to sync block */
+	rc = block_put(b);
+	return rc;
+}
+
+static int fat_node_get_new(fat_node_t **nodepp)
+{
+	fs_node_t *fn;
+	fat_node_t *nodep;
+	int rc;
+
+	fibril_mutex_lock(&ffn_mutex);
+	if (!list_empty(&ffn_head)) {
+		/* Try to use a cached free node structure. */
+		fat_idx_t *idxp_tmp;
+		nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
+		if (!fibril_mutex_trylock(&nodep->lock))
+			goto skip_cache;
+		idxp_tmp = nodep->idx;
+		if (!fibril_mutex_trylock(&idxp_tmp->lock)) {
+			fibril_mutex_unlock(&nodep->lock);
+			goto skip_cache;
+		}
+		list_remove(&nodep->ffn_link);
+		fibril_mutex_unlock(&ffn_mutex);
+		if (nodep->dirty) {
+			rc = fat_node_sync(nodep);
+			if (rc != EOK) {
+				idxp_tmp->nodep = NULL;
+				fibril_mutex_unlock(&nodep->lock);
+				fibril_mutex_unlock(&idxp_tmp->lock);
+				free(nodep->bp);
+				free(nodep);
+				return rc;
+			}
+		}
+		idxp_tmp->nodep = NULL;
+		fibril_mutex_unlock(&nodep->lock);
+		fibril_mutex_unlock(&idxp_tmp->lock);
+		fn = FS_NODE(nodep);
+	} else {
+skip_cache:
+		/* Try to allocate a new node structure. */
+		fibril_mutex_unlock(&ffn_mutex);
+		fn = (fs_node_t *)malloc(sizeof(fs_node_t));
+		if (!fn)
+			return ENOMEM;
+		nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
+		if (!nodep) {
+			free(fn);
+			return ENOMEM;
+		}
+	}
+	fat_node_initialize(nodep);
+	fs_node_initialize(fn);
+	fn->data = nodep;
+	nodep->bp = fn;
+	
+	*nodepp = nodep;
+	return EOK;
+}
+
+/** Internal version of fat_node_get().
+ *
+ * @param idxp		Locked index structure.
+ */
+static int fat_node_get_core(fat_node_t **nodepp, fat_idx_t *idxp)
+{
+	block_t *b;
+	fat_bs_t *bs;
+	fat_dentry_t *d;
+	fat_node_t *nodep = NULL;
+	unsigned bps;
+	unsigned spc;
+	unsigned dps;
+	int rc;
+
+	if (idxp->nodep) {
+		/*
+		 * We are lucky.
+		 * The node is already instantiated in memory.
+		 */
+		fibril_mutex_lock(&idxp->nodep->lock);
+		if (!idxp->nodep->refcnt++) {
+			fibril_mutex_lock(&ffn_mutex);
+			list_remove(&idxp->nodep->ffn_link);
+			fibril_mutex_unlock(&ffn_mutex);
+		}
+		fibril_mutex_unlock(&idxp->nodep->lock);
+		*nodepp = idxp->nodep;
+		return EOK;
+	}
+
+	/*
+	 * We must instantiate the node from the file system.
+	 */
+	
+	assert(idxp->pfc);
+
+	rc = fat_node_get_new(&nodep);
+	if (rc != EOK)
+		return rc;
+
+	bs = block_bb_get(idxp->dev_handle);
+	bps = uint16_t_le2host(bs->bps);
+	spc = bs->spc;
+	dps = bps / sizeof(fat_dentry_t);
+
+	/* Read the block that contains the dentry of interest. */
+	rc = _fat_block_get(&b, bs, idxp->dev_handle, idxp->pfc,
+	    (idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
+	if (rc != EOK) {
+		(void) fat_node_put(FS_NODE(nodep));
+		return rc;
+	}
+
+	d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps);
+	if (d->attr & FAT_ATTR_SUBDIR) {
+		/* 
+		 * The only directory which does not have this bit set is the
+		 * root directory itself. The root directory node is handled
+		 * and initialized elsewhere.
+		 */
+		nodep->type = FAT_DIRECTORY;
+		/*
+		 * Unfortunately, the 'size' field of the FAT dentry is not
+		 * defined for the directory entry type. We must determine the
+		 * size of the directory by walking the FAT.
+		 */
+		uint16_t clusters;
+		rc = fat_clusters_get(&clusters, bs, idxp->dev_handle,
+		    uint16_t_le2host(d->firstc));
+		if (rc != EOK) {
+			(void) fat_node_put(FS_NODE(nodep));
+			return rc;
+		}
+		nodep->size = bps * spc * clusters;
+	} else {
+		nodep->type = FAT_FILE;
+		nodep->size = uint32_t_le2host(d->size);
+	}
+	nodep->firstc = uint16_t_le2host(d->firstc);
+	nodep->lnkcnt = 1;
+	nodep->refcnt = 1;
+
+	rc = block_put(b);
+	if (rc != EOK) {
+		(void) fat_node_put(FS_NODE(nodep));
+		return rc;
+	}
+
+	/* Link the idx structure with the node structure. */
+	nodep->idx = idxp;
+	idxp->nodep = nodep;
+
+	*nodepp = nodep;
+	return EOK;
+}
+
+/*
  * FAT libfs operations.
  */
@@ -306,10 +331,9 @@
 				continue;
 			case FAT_DENTRY_LAST:
+				/* miss */
 				rc = block_put(b);
-				/* expect EOK as b was not dirty */
-				assert(rc == EOK);	
 				fibril_mutex_unlock(&parentp->idx->lock);
 				*rfn = NULL;
-				return EOK;
+				return rc;
 			default:
 			case FAT_DENTRY_VALID:
@@ -336,13 +360,10 @@
 					 */
 					rc = block_put(b);
-					/* expect EOK as b was not dirty */
-					assert(rc == EOK);	
-					return ENOMEM;
+					return (rc == EOK) ? ENOMEM : rc;
 				}
-				nodep = fat_node_get_core(idx);
+				rc = fat_node_get_core(&nodep, idx);
+				assert(rc == EOK);
 				fibril_mutex_unlock(&idx->lock);
-				rc = block_put(b);
-				/* expect EOK as b was not dirty */
-				assert(rc == EOK);
+				(void) block_put(b);
 				*rfn = FS_NODE(nodep);
 				return EOK;
@@ -350,5 +371,8 @@
 		}
 		rc = block_put(b);
-		assert(rc == EOK);	/* expect EOK as b was not dirty */
+		if (rc != EOK) {
+			fibril_mutex_unlock(&parentp->idx->lock);
+			return rc;
+		}
 	}
 
@@ -363,4 +387,5 @@
 	fat_node_t *nodep;
 	fat_idx_t *idxp;
+	int rc;
 
 	idxp = fat_idx_get_by_index(dev_handle, index);
@@ -370,8 +395,9 @@
 	}
 	/* idxp->lock held */
-	nodep = fat_node_get_core(idxp);
+	rc = fat_node_get_core(&nodep, idxp);
 	fibril_mutex_unlock(&idxp->lock);
-	*rfn = FS_NODE(nodep);
-	return EOK;
+	if (rc == EOK)
+		*rfn = FS_NODE(nodep);
+	return rc;
 }
 
@@ -429,14 +455,14 @@
 	}
 
-	nodep = fat_node_get_new();
-	if (!nodep) {
+	rc = fat_node_get_new(&nodep);
+	if (rc != EOK) {
 		(void) fat_free_clusters(bs, dev_handle, mcl);
-		return ENOMEM;	/* FIXME: determine the true error code */
-	}
-	idxp = fat_idx_get_new(dev_handle);
-	if (!idxp) {
+		return rc;
+	}
+	rc = fat_idx_get_new(&idxp, dev_handle);
+	if (rc != EOK) {
 		(void) fat_free_clusters(bs, dev_handle, mcl);	
 		(void) fat_node_put(FS_NODE(nodep));
-		return ENOMEM;	/* FIXME: determine the true error code */
+		return rc;
 	}
 	/* idxp->lock held */
@@ -782,21 +808,20 @@
 			case FAT_DENTRY_LAST:
 				rc = block_put(b);
-				/* expect EOK as b was not dirty */
-				assert(rc == EOK);
 				fibril_mutex_unlock(&nodep->idx->lock);
 				*has_children = false;
-				return EOK;
+				return rc;
 			default:
 			case FAT_DENTRY_VALID:
 				rc = block_put(b);
-				/* expect EOK as b was not dirty */
-				assert(rc == EOK);
 				fibril_mutex_unlock(&nodep->idx->lock);
 				*has_children = true;
-				return EOK;
+				return rc;
 			}
 		}
 		rc = block_put(b);
-		assert(rc == EOK);	/* expect EOK as b was not dirty */
+		if (rc != EOK) {
+			fibril_mutex_unlock(&nodep->idx->lock);
+			return rc;	
+		}
 	}
 
