Index: uspace/srv/fs/mfs/Makefile
===================================================================
--- uspace/srv/fs/mfs/Makefile	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
+++ uspace/srv/fs/mfs/Makefile	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBFS_PREFIX)/libfs.a
+EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX) -I$(LIBMINIX_PREFIX)
+BINARY = mfs
+
+SOURCES = \
+	mfs.c \
+	mfs_ops.c \
+	mfs_inode.c \
+	mfs_rw.c \
+	mfs_dentry.c \
+	mfs_balloc.c \
+	mfs_utils.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/fs/mfs/mfs.c
===================================================================
--- uspace/srv/fs/mfs/mfs.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
+++ uspace/srv/fs/mfs/mfs.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2006 Martin Decky
+ * Copyright (c) 2008 Jakub Jermar
+ * Copyright (c) 2011 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+/**
+ * @file	mfs.c
+ * @brief	Minix file system driver for HelenOS.
+ */
+
+#include <ipc/services.h>
+#include <ns.h>
+#include <async.h>
+#include <errno.h>
+#include <unistd.h>
+#include <task.h>
+#include <stdio.h>
+#include <libfs.h>
+#include "mfs.h"
+
+vfs_info_t mfs_vfs_info = {
+	.name = NAME,
+	.concurrent_read_write = false,
+	.write_retains_size = false,
+};
+
+int main(int argc, char **argv)
+{
+	int rc;
+
+	printf(NAME ": HelenOS Minix file system server\n");
+
+	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+				SERVICE_VFS, 0, 0);
+
+	if (!vfs_sess) {
+		printf(NAME ": failed to connect to VFS\n");
+		return -1;
+	}
+
+	rc = mfs_global_init();
+	if (rc != EOK) {
+		printf(NAME ": Failed global initialization\n");
+		goto err;
+	}
+
+	rc = fs_register(vfs_sess, &mfs_vfs_info, &mfs_ops, &mfs_libfs_ops);
+	if (rc != EOK)
+		goto err;
+
+	printf(NAME ": Accepting connections\n");
+	task_retval(0);
+	async_manager();
+	/* not reached */
+	return 0;
+
+err:
+	printf(NAME ": Failed to register file system (%d)\n", rc);
+	return rc;
+}
+
+/**
+ * @}
+ */
+
Index: uspace/srv/fs/mfs/mfs.h
===================================================================
--- uspace/srv/fs/mfs/mfs.h	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
+++ uspace/srv/fs/mfs/mfs.h	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2011 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+#ifndef _MFS_H_
+#define _MFS_H_
+
+#include <minix.h>
+#include <macros.h>
+#include <libblock.h>
+#include <libfs.h>
+#include <adt/list.h>
+#include <malloc.h>
+#include <mem.h>
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+#include "../../vfs/vfs.h"
+
+#define NAME		"mfs"
+
+//#define DEBUG_MODE
+
+#define min(a, b)	((a) < (b) ? (a) : (b))
+
+#ifdef DEBUG_MODE
+#define mfsdebug(...)	printf(__VA_ARGS__)
+#else
+#define mfsdebug(...)
+#endif
+
+typedef uint32_t bitchunk_t;
+
+typedef enum {
+	BMAP_ZONE,
+	BMAP_INODE
+} bmap_id_t;
+
+typedef enum {
+	MFS_VERSION_V1 = 1,
+	MFS_VERSION_V2,
+	MFS_VERSION_V3
+} mfs_version_t;
+
+/*Generic MinixFS superblock*/
+struct mfs_sb_info {
+	uint32_t ninodes;
+	uint32_t nzones;
+	unsigned long ibmap_blocks;
+	unsigned long zbmap_blocks;
+	unsigned long firstdatazone;
+	int log2_zone_size;
+	int block_size;
+	uint32_t max_file_size;
+	uint16_t magic;
+	uint16_t state;
+
+	/*The following fields do not exist on disk but only in memory*/
+	unsigned long itable_size;
+	mfs_version_t fs_version;
+	int ino_per_block;
+	size_t dirsize;
+	int itable_off;
+	unsigned max_name_len;
+	bool long_names;
+	bool native;
+	unsigned isearch;
+	unsigned zsearch;
+};
+
+/*Generic MinixFS inode*/
+struct mfs_ino_info {
+	uint16_t	i_mode;
+	uint16_t	i_nlinks;
+	int16_t		i_uid;
+	uint16_t	i_gid;
+	size_t		i_size;
+	int32_t		i_atime;
+	int32_t		i_mtime;
+	int32_t		i_ctime;
+	/*Block numbers for direct zones*/
+	uint32_t	i_dzone[V2_NR_DIRECT_ZONES];
+	/*Block numbers for indirect zones*/
+	uint32_t	i_izone[V2_NR_INDIRECT_ZONES];
+
+	/*The following fields do not exist on disk but only in memory*/
+	bool dirty;
+	fs_index_t index;
+};
+
+/*Generic MFS directory entry*/
+struct mfs_dentry_info {
+	uint32_t d_inum;
+	char d_name[MFS3_MAX_NAME_LEN + 1];
+
+	/*The following fields do not exist on disk but only in memory*/
+
+	/*Index of the dentry in the list*/
+	unsigned index;
+	/*Pointer to the node at witch the dentry belongs*/
+	struct mfs_node *node;
+};
+
+struct mfs_instance {
+	link_t link;
+	service_id_t service_id;
+	struct mfs_sb_info *sbi;
+	unsigned open_nodes_cnt;
+};
+
+/*MinixFS node in core*/
+struct mfs_node {
+	struct mfs_ino_info *ino_i;
+	struct mfs_instance *instance;
+	unsigned refcnt;
+	fs_node_t *fsnode;
+	link_t link;
+};
+
+/*mfs_ops.c*/
+extern vfs_out_ops_t mfs_ops;
+extern libfs_ops_t mfs_libfs_ops;
+
+extern int
+mfs_global_init(void);
+
+/*mfs_inode.c*/
+extern int
+mfs_get_inode(struct mfs_instance *inst, struct mfs_ino_info **ino_i,
+	  fs_index_t index);
+
+extern int
+mfs_put_inode_core(struct mfs_node *mnode);
+
+extern int
+mfs_inode_shrink(struct mfs_node *mnode, size_t size_shrink);
+
+/*mfs_rw.c*/
+extern int
+mfs_read_map(uint32_t *b, const struct mfs_node *mnode, const uint32_t pos);
+
+extern int
+mfs_write_map(struct mfs_node *mnode, uint32_t pos, uint32_t new_zone,
+	  uint32_t *old_zone);
+
+extern int
+mfs_prune_ind_zones(struct mfs_node *mnode, size_t new_size);
+
+/*mfs_dentry.c*/
+extern int
+mfs_read_dentry(struct mfs_node *mnode,
+		     struct mfs_dentry_info *d_info, unsigned index);
+
+extern int
+mfs_write_dentry(struct mfs_dentry_info *d_info);
+
+extern int
+mfs_remove_dentry(struct mfs_node *mnode, const char *d_name);
+
+extern int
+mfs_insert_dentry(struct mfs_node *mnode, const char *d_name, fs_index_t d_inum);
+
+/*mfs_balloc.c*/
+extern int
+mfs_alloc_inode(struct mfs_instance *inst, uint32_t *inum);
+
+extern int
+mfs_free_inode(struct mfs_instance *inst, uint32_t inum);
+
+extern int
+mfs_alloc_zone(struct mfs_instance *inst, uint32_t *zone);
+
+extern int
+mfs_free_zone(struct mfs_instance *inst, uint32_t zone);
+
+/*mfs_utils.c*/
+extern uint16_t
+conv16(bool native, uint16_t n);
+
+extern uint32_t
+conv32(bool native, uint32_t n);
+
+extern uint64_t
+conv64(bool native, uint64_t n);
+
+#endif
+
+/**
+ * @}
+ */
+
Index: uspace/srv/fs/mfs/mfs_balloc.c
===================================================================
--- uspace/srv/fs/mfs/mfs_balloc.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
+++ uspace/srv/fs/mfs/mfs_balloc.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2011 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+#include <stdlib.h>
+#include "mfs.h"
+
+static int
+find_free_bit_and_set(bitchunk_t *b, const int bsize,
+		      const bool native, unsigned start_bit);
+
+static int
+mfs_free_bit(struct mfs_instance *inst, uint32_t idx, bmap_id_t bid);
+
+static int
+mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid);
+
+/**Allocate a new inode.
+ *
+ * @param inst		Pointer to the filesystem instance.
+ * @param inum		Pointer to a 32 bit number where the index of
+ * 			the new inode will be saved.
+ *
+ * @return		EOK on success or a negative error code.
+ */
+int
+mfs_alloc_inode(struct mfs_instance *inst, uint32_t *inum)
+{
+	int r = mfs_alloc_bit(inst, inum, BMAP_INODE);
+	return r;
+}
+
+/**Free an inode.
+ *
+ * @param inst		Pointer to the filesystem instance.
+ * @param inum		Number of the inode to free.
+ *
+ * @return		EOK on success or a negative error code.
+ */
+int
+mfs_free_inode(struct mfs_instance *inst, uint32_t inum)
+{
+	return mfs_free_bit(inst, inum, BMAP_INODE);
+}
+
+/**Allocate a new zone.
+ *
+ * @param inst		Pointer to the filesystem instance.
+ * @param zone		Pointer to a 32 bit number where the index
+ * 			of the zone will be saved.
+ *
+ * @return		EOK on success or a negative error code.
+ */
+int
+mfs_alloc_zone(struct mfs_instance *inst, uint32_t *zone)
+{
+	int r = mfs_alloc_bit(inst, zone, BMAP_ZONE);
+
+	*zone += inst->sbi->firstdatazone - 1;
+	return r;
+}
+
+/**Free a zone.
+ *
+ * @param inst		Pointer to the filesystem instance.
+ * @param zone		Index of the zone to free.
+ *
+ * @return		EOK on success or a negative error code.
+ */
+int
+mfs_free_zone(struct mfs_instance *inst, uint32_t zone)
+{
+	zone -= inst->sbi->firstdatazone - 1;
+
+	return mfs_free_bit(inst, zone, BMAP_ZONE);
+}
+
+/**Clear a bit in a bitmap.
+ *
+ * @param inst		Pointer to the filesystem instance.
+ * @param idx		Index of the bit to clear.
+ * @param bid		BMAP_ZONE if operating on the zone's bitmap,
+ * 			BMAP_INODE if operating on the inode's bitmap.
+ *
+ * @return		EOK on success or a negative error code.
+ */
+static int
+mfs_free_bit(struct mfs_instance *inst, uint32_t idx, bmap_id_t bid)
+{
+	struct mfs_sb_info *sbi;
+	int r;
+	unsigned start_block;
+	unsigned *search;
+	block_t *b;
+
+	assert(inst != NULL);
+	sbi = inst->sbi;
+	assert(sbi != NULL);
+
+	if (bid == BMAP_ZONE) {
+		search = &sbi->zsearch;
+		start_block = 2 + sbi->ibmap_blocks;
+		if (idx > sbi->nzones) {
+			printf(NAME ": Error! Trying to free beyond the" \
+			       "bitmap max size\n");
+			return -1;
+		}
+	} else {
+		/*bid == BMAP_INODE*/
+		search = &sbi->isearch;
+		start_block = 2;
+		if (idx > sbi->ninodes) {
+			printf(NAME ": Error! Trying to free beyond the" \
+			       "bitmap max size\n");
+			return -1;
+		}
+	}
+
+	/*Compute the bitmap block*/
+	uint32_t block = idx / (sbi->block_size * 8) + start_block;
+
+	r = block_get(&b, inst->service_id, block, BLOCK_FLAGS_NONE);
+	if (r != EOK)
+		goto out_err;
+
+	/*Compute the bit index in the block*/
+	idx %= (sbi->block_size * 8);
+	bitchunk_t *ptr = b->data;
+	bitchunk_t chunk;
+	const size_t chunk_bits = sizeof(bitchunk_t) * 8;
+
+	chunk = conv32(sbi->native, ptr[idx / chunk_bits]);
+	chunk &= ~(1 << (idx % chunk_bits));
+	ptr[idx / chunk_bits] = conv32(sbi->native, chunk);
+
+	b->dirty = true;
+	r = block_put(b);
+
+	if (*search > idx)
+		*search = idx;
+
+out_err:
+	return r;
+}
+
+/**Search a free bit in a bitmap and mark it as used.
+ *
+ * @param inst		Pointer to the filesystem instance.
+ * @param idx		Pointer of a 32 bit number where the index
+ * 			of the found bit will be stored.
+ * @param bid		BMAP_ZONE if operating on the zone's bitmap,
+ * 			BMAP_INODE if operating on the inode's bitmap.
+ *
+ * @return		EOK on success or a negative error code.
+ */
+static int
+mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid)
+{
+	struct mfs_sb_info *sbi;
+	uint32_t limit;
+	unsigned long nblocks;
+	unsigned *search, i, start_block;
+	unsigned bits_per_block;
+	int r, freebit;
+
+	assert(inst != NULL);
+	sbi = inst->sbi;
+	assert(sbi != NULL);
+
+	if (bid == BMAP_ZONE) {
+		search = &sbi->zsearch;
+		start_block = 2 + sbi->ibmap_blocks;
+		nblocks = sbi->zbmap_blocks;
+		limit = sbi->nzones - sbi->firstdatazone - 1;
+	} else {
+		/*bid == BMAP_INODE*/
+		search = &sbi->isearch;
+		start_block = 2;
+		nblocks = sbi->ibmap_blocks;
+		limit = sbi->ninodes;
+	}
+	bits_per_block = sbi->block_size * 8;
+
+	block_t *b;
+
+retry:
+
+	for (i = *search / bits_per_block; i < nblocks; ++i) {
+		r = block_get(&b, inst->service_id, i + start_block,
+			      BLOCK_FLAGS_NONE);
+
+		if (r != EOK)
+			goto out;
+
+		unsigned tmp = *search % bits_per_block;
+
+		freebit = find_free_bit_and_set(b->data, sbi->block_size,
+						sbi->native, tmp);
+		if (freebit == -1) {
+			/*No free bit in this block*/
+			r = block_put(b);
+			if (r != EOK)
+				goto out;
+			continue;
+		}
+
+		/*Free bit found in this block, compute the real index*/
+		*idx = freebit + bits_per_block * i;
+		if (*idx > limit) {
+			/*Index is beyond the limit, it is invalid*/
+			r = block_put(b);
+			if (r != EOK)
+				goto out;
+			break;
+		}
+
+		*search = *idx;
+		b->dirty = true;
+		r = block_put(b);
+		goto out;
+	}
+
+	if (*search > 0) {
+		/*Repeat the search from the first bitmap block*/
+		*search = 0;
+		goto retry;
+	}
+
+	/*Free bit not found, return error*/
+	return ENOSPC;
+
+out:
+	return r;
+}
+
+static int
+find_free_bit_and_set(bitchunk_t *b, const int bsize,
+		      const bool native, unsigned start_bit)
+{
+	int r = -1;
+	unsigned i, j;
+	bitchunk_t chunk;
+	const size_t chunk_bits = sizeof(bitchunk_t) * 8;
+
+	for (i = start_bit / chunk_bits;
+	     i < bsize / sizeof(bitchunk_t); ++i) {
+		if (!(~b[i])) {
+			/*No free bit in this chunk*/
+			continue;
+		}
+
+		chunk = conv32(native, b[i]);
+
+		for (j = 0; j < chunk_bits; ++j) {
+			if (!(chunk & (1 << j))) {
+				r = i * chunk_bits + j;
+				chunk |= 1 << j;
+				b[i] = conv32(native, chunk);
+				goto found;
+			}
+		}
+	}
+found:
+	return r;
+}
+
+/**
+ * @}
+ */
+
Index: uspace/srv/fs/mfs/mfs_dentry.c
===================================================================
--- uspace/srv/fs/mfs/mfs_dentry.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
+++ uspace/srv/fs/mfs/mfs_dentry.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2011 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+#include "mfs.h"
+
+/**Read a directory entry from disk.
+ *
+ * @param mnode		Pointer to the directory node.
+ * @param d_info	Pointer to a directory entry structure where the dentry info
+ *			will be stored.
+ * @param index		index of the dentry in the list.
+ *
+ * @return		EOK on success or a negative error code.
+ */
+int
+mfs_read_dentry(struct mfs_node *mnode,
+		     struct mfs_dentry_info *d_info, unsigned index)
+{
+	const struct mfs_instance *inst = mnode->instance;
+	const struct mfs_sb_info *sbi = inst->sbi;
+	const bool longnames = sbi->long_names;
+	uint32_t block;
+	block_t *b;
+
+	int r = mfs_read_map(&block, mnode, index * sbi->dirsize);
+	if (r != EOK)
+		goto out_err;
+
+	if (block == 0) {
+		/*End of the dentries list*/
+		r = EOK;
+		goto out_err;
+	}
+
+	r = block_get(&b, inst->service_id, block, BLOCK_FLAGS_NONE);
+	if (r != EOK)
+		goto out_err;
+
+	unsigned dentries_per_zone = sbi->block_size / sbi->dirsize;
+	unsigned dentry_off = index % dentries_per_zone;
+
+	if (sbi->fs_version == MFS_VERSION_V3) {
+		struct mfs3_dentry *d3;
+
+		d3 = b->data + (dentry_off * MFS3_DIRSIZE);
+
+		d_info->d_inum = conv32(sbi->native, d3->d_inum);
+		memcpy(d_info->d_name, d3->d_name, MFS3_MAX_NAME_LEN);
+	} else {
+		const int namelen = longnames ? MFS_L_MAX_NAME_LEN :
+				    MFS_MAX_NAME_LEN;
+
+		struct mfs_dentry *d;
+
+		d = b->data + dentry_off * (longnames ? MFSL_DIRSIZE :
+					    MFS_DIRSIZE);
+		d_info->d_inum = conv16(sbi->native, d->d_inum);
+		memcpy(d_info->d_name, d->d_name, namelen);
+	}
+
+	r = block_put(b);
+
+	d_info->index = index;
+	d_info->node = mnode;
+
+out_err:
+	return r;
+}
+
+/**Write a directory entry on disk.
+ *
+ * @param d_info	Pointer to the directory entry structure to write on disk.
+ *
+ * @return		EOK on success or a negative error code.
+ */
+int
+mfs_write_dentry(struct mfs_dentry_info *d_info)
+{
+	struct mfs_node *mnode = d_info->node;
+	struct mfs_sb_info *sbi = mnode->instance->sbi;
+	const unsigned d_off_bytes = d_info->index * sbi->dirsize;
+	const unsigned dirs_per_block = sbi->block_size / sbi->dirsize;
+	block_t *b;
+	uint32_t block;
+	int r;
+
+	r = mfs_read_map(&block, mnode, d_off_bytes);
+	if (r != EOK)
+		goto out;
+
+	r = block_get(&b, mnode->instance->service_id, block, BLOCK_FLAGS_NONE);
+	if (r != EOK)
+		goto out;
+
+	const size_t name_len = sbi->max_name_len;
+	uint8_t *ptr = b->data;
+	ptr += (d_info->index % dirs_per_block) * sbi->dirsize;
+
+	if (sbi->fs_version == MFS_VERSION_V3) {
+		struct mfs3_dentry *dentry;
+		dentry = (struct mfs3_dentry *) ptr;
+
+		dentry->d_inum = conv32(sbi->native, d_info->d_inum);
+		memcpy(dentry->d_name, d_info->d_name, name_len);
+	} else {
+		struct mfs_dentry *dentry;
+		dentry = (struct mfs_dentry *) ptr;
+
+		dentry->d_inum = conv16(sbi->native, d_info->d_inum);
+		memcpy(dentry->d_name, d_info->d_name, name_len);
+	}
+
+	b->dirty = true;
+	r = block_put(b);
+
+out:
+	return r;
+}
+
+/**Remove a directory entry from a directory.
+ *
+ * @param mnode		Pointer to the directory node.
+ * @param d_name	Name of the directory entry to delete.
+ *
+ * @return		EOK on success or a negative error code.
+ */
+int
+mfs_remove_dentry(struct mfs_node *mnode, const char *d_name)
+{
+	struct mfs_sb_info *sbi = mnode->instance->sbi;
+	struct mfs_dentry_info d_info;
+	int r;
+
+	const size_t name_len = str_size(d_name);
+
+	if (name_len > sbi->max_name_len)
+		return ENAMETOOLONG;
+
+	/*Search the directory entry to be removed*/
+	unsigned i;
+	for (i = 0; i < mnode->ino_i->i_size / sbi->dirsize ; ++i) {
+		r = mfs_read_dentry(mnode, &d_info, i);
+		if (r != EOK)
+			return r;
+
+		const size_t d_name_len = str_size(d_info.d_name);
+
+		if (name_len == d_name_len &&
+				!bcmp(d_info.d_name, d_name, name_len)) {
+			d_info.d_inum = 0;
+			r = mfs_write_dentry(&d_info);
+			return r;
+		}
+	}
+
+	return ENOENT;
+}
+
+/**Insert a new directory entry in a existing directory.
+ *
+ * @param mnode		Pointer to the directory node.
+ * @param d_name	Name of the new directory entry.
+ * @param d_inum	index of the inode that will be pointed by the new dentry.
+ *
+ * @return		EOK on success or a negative error code.
+ */
+int
+mfs_insert_dentry(struct mfs_node *mnode, const char *d_name, fs_index_t d_inum)
+{
+	int r;
+	struct mfs_sb_info *sbi = mnode->instance->sbi;
+	struct mfs_dentry_info d_info;
+	bool empty_dentry_found = false;
+
+	const size_t name_len = str_size(d_name);
+
+	if (name_len > sbi->max_name_len)
+		return ENAMETOOLONG;
+
+	/*Search for an empty dentry*/
+	unsigned i;
+	for (i = 0; i < mnode->ino_i->i_size / sbi->dirsize; ++i) {
+		r = mfs_read_dentry(mnode, &d_info, i);
+		if (r != EOK)
+			return r;
+
+		if (d_info.d_inum == 0) {
+			/*This entry is not used*/
+			empty_dentry_found = true;
+			break;
+		}
+	}
+
+	if (!empty_dentry_found) {
+		uint32_t b, pos;
+		pos = mnode->ino_i->i_size;
+		r = mfs_read_map(&b, mnode, pos);
+		if (r != EOK)
+			goto out;
+
+		if (b == 0) {
+			/*Increase the inode size*/
+
+			uint32_t dummy;
+			r = mfs_alloc_zone(mnode->instance, &b);
+			if (r != EOK)
+				goto out;
+			r = mfs_write_map(mnode, pos, b, &dummy);
+			if (r != EOK)
+				goto out;
+		}
+
+		mnode->ino_i->i_size += sbi->dirsize;
+		mnode->ino_i->dirty = true;
+
+		d_info.index = i;
+		d_info.node = mnode;
+	}
+
+	d_info.d_inum = d_inum;
+	memcpy(d_info.d_name, d_name, name_len);
+	d_info.d_name[name_len] = 0;
+
+	r = mfs_write_dentry(&d_info);
+out:
+	return r;
+}
+
+
+/**
+ * @}
+ */
+
Index: uspace/srv/fs/mfs/mfs_inode.c
===================================================================
--- uspace/srv/fs/mfs/mfs_inode.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
+++ uspace/srv/fs/mfs/mfs_inode.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2011 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+#include <stdlib.h>
+#include "mfs.h"
+
+static int
+mfs_write_inode_raw(struct mfs_node *mnode);
+
+static int
+mfs2_write_inode_raw(struct mfs_node *mnode);
+
+static int
+mfs_read_inode_raw(const struct mfs_instance *instance,
+		struct mfs_ino_info **ino_ptr, uint16_t inum);
+
+static int
+mfs2_read_inode_raw(const struct mfs_instance *instance,
+		struct mfs_ino_info **ino_ptr, uint32_t inum);
+
+
+int
+mfs_get_inode(struct mfs_instance *inst, struct mfs_ino_info **ino_i,
+	  fs_index_t index)
+{
+	struct mfs_sb_info *sbi = inst->sbi;
+	int r;
+
+	if (sbi->fs_version == MFS_VERSION_V1) {
+		/*Read a MFS V1 inode*/
+		r = mfs_read_inode_raw(inst, ino_i, index);
+	} else {
+		/*Read a MFS V2/V3 inode*/
+		r = mfs2_read_inode_raw(inst, ino_i, index);
+	}
+
+	return r;
+}
+
+static int
+mfs_read_inode_raw(const struct mfs_instance *instance,
+		struct mfs_ino_info **ino_ptr, uint16_t inum) {
+	struct mfs_inode *ino;
+	struct mfs_ino_info *ino_i = NULL;
+	struct mfs_sb_info *sbi;
+	block_t *b;
+	int i, r;
+
+	sbi = instance->sbi;
+	assert(sbi);
+
+	/*inode 0 does not exist*/
+	inum -= 1;
+
+	const int ino_off = inum % sbi->ino_per_block;
+
+	ino_i = malloc(sizeof(*ino_i));
+
+	if (!ino_i) {
+		r = ENOMEM;
+		goto out_err;
+	}
+
+	const int itable_off = sbi->itable_off;
+
+	r = block_get(&b, instance->service_id,
+		      itable_off + inum / sbi->ino_per_block,
+		      BLOCK_FLAGS_NONE);
+	if (r != EOK)
+		goto out_err;
+
+	ino = b->data + ino_off * sizeof(struct mfs_inode);
+
+	ino_i->i_mode = conv16(sbi->native, ino->i_mode);
+	ino_i->i_uid = conv16(sbi->native, ino->i_uid);
+	ino_i->i_size = conv32(sbi->native, ino->i_size);
+	ino_i->i_mtime = conv32(sbi->native, ino->i_mtime);
+	ino_i->i_nlinks = ino->i_nlinks;
+
+	for (i = 0; i < V1_NR_DIRECT_ZONES; ++i)
+		ino_i->i_dzone[i] = conv16(sbi->native, ino->i_dzone[i]);
+
+	for (i = 0; i < V1_NR_INDIRECT_ZONES; ++i)
+		ino_i->i_izone[i] = conv16(sbi->native, ino->i_izone[i]);
+
+	r = block_put(b);
+	ino_i->dirty = false;
+	*ino_ptr = ino_i;
+
+	return r;
+
+out_err:
+	if (ino_i)
+		free(ino_i);
+	return EOK;
+}
+
+static int
+mfs2_read_inode_raw(const struct mfs_instance *instance,
+		struct mfs_ino_info **ino_ptr, uint32_t inum) {
+	struct mfs2_inode *ino;
+	struct mfs_ino_info *ino_i = NULL;
+	struct mfs_sb_info *sbi;
+	block_t *b;
+	int i, r;
+
+	ino_i = malloc(sizeof(*ino_i));
+
+	if (!ino_i) {
+		r = ENOMEM;
+		goto out_err;
+	}
+
+	sbi = instance->sbi;
+	assert(sbi);
+
+	/*inode 0 does not exist*/
+	inum -= 1;
+
+	const int itable_off = sbi->itable_off;
+	const int ino_off = inum % sbi->ino_per_block;
+
+	r = block_get(&b, instance->service_id,
+		      itable_off + inum / sbi->ino_per_block,
+		      BLOCK_FLAGS_NONE);
+	if (r != EOK)
+		goto out_err;
+
+	ino = b->data + ino_off * sizeof(struct mfs2_inode);
+
+	ino_i->i_mode = conv16(sbi->native, ino->i_mode);
+	ino_i->i_nlinks = conv16(sbi->native, ino->i_nlinks);
+	ino_i->i_uid = conv16(sbi->native, ino->i_uid);
+	ino_i->i_gid = conv16(sbi->native, ino->i_gid);
+	ino_i->i_size = conv32(sbi->native, ino->i_size);
+	ino_i->i_atime = conv32(sbi->native, ino->i_atime);
+	ino_i->i_mtime = conv32(sbi->native, ino->i_mtime);
+	ino_i->i_ctime = conv32(sbi->native, ino->i_ctime);
+
+	for (i = 0; i < V2_NR_DIRECT_ZONES; ++i)
+		ino_i->i_dzone[i] = conv32(sbi->native, ino->i_dzone[i]);
+
+	for (i = 0; i < V2_NR_INDIRECT_ZONES; ++i)
+		ino_i->i_izone[i] = conv32(sbi->native, ino->i_izone[i]);
+
+	r = block_put(b);
+	ino_i->dirty = false;
+	*ino_ptr = ino_i;
+
+	return r;
+
+out_err:
+	if (ino_i)
+		free(ino_i);
+	return EOK;
+}
+
+int
+mfs_put_inode_core(struct mfs_node *mnode)
+{
+	int rc = EOK;
+
+	assert(mnode);
+	assert(mnode->ino_i);
+
+	if (!mnode->ino_i->dirty)
+		goto out;
+
+	struct mfs_instance *inst = mnode->instance;
+	assert(inst);
+	struct mfs_sb_info *sbi = inst->sbi;
+	assert(sbi);
+
+	if (sbi->fs_version == MFS_VERSION_V1)
+		rc = mfs_write_inode_raw(mnode);
+	else
+		rc = mfs2_write_inode_raw(mnode);
+
+out:
+	return rc;
+}
+
+static int
+mfs_write_inode_raw(struct mfs_node *mnode)
+{
+	int i, r;
+	block_t *b;
+	struct mfs_ino_info *ino_i = mnode->ino_i;
+	struct mfs_sb_info *sbi = mnode->instance->sbi;
+
+	const uint32_t inum = ino_i->index - 1;
+	const int itable_off = sbi->itable_off;
+	const int ino_off = inum % sbi->ino_per_block;
+	const bool native = sbi->native;
+
+	r = block_get(&b, mnode->instance->service_id,
+		      itable_off + inum / sbi->ino_per_block,
+		      BLOCK_FLAGS_NONE);
+
+	if (r != EOK)
+		goto out;
+
+	struct mfs_inode *ino = b->data;
+	ino += ino_off;
+
+	ino->i_mode = conv16(native, ino_i->i_mode);
+	ino->i_uid = conv16(native, ino_i->i_uid);
+	ino->i_gid = ino_i->i_gid;
+	ino->i_nlinks = ino_i->i_nlinks;
+	ino->i_size = conv32(native, ino_i->i_size);
+	ino->i_mtime = conv32(native, ino_i->i_mtime);
+
+	for (i = 0; i < V1_NR_DIRECT_ZONES; ++i)
+		ino->i_dzone[i] = conv16(native, ino_i->i_dzone[i]);
+	for (i = 0; i < V1_NR_INDIRECT_ZONES; ++i)
+		ino->i_izone[i] = conv16(native, ino_i->i_izone[i]);
+
+	b->dirty = true;
+	r = block_put(b);
+
+	ino_i->dirty = false;
+out:
+	return r;
+}
+
+static int
+mfs2_write_inode_raw(struct mfs_node *mnode)
+{
+	struct mfs_ino_info *ino_i = mnode->ino_i;
+	struct mfs_sb_info *sbi = mnode->instance->sbi;
+	block_t *b;
+	int i, r;
+
+	const uint32_t inum = ino_i->index - 1;
+	const int itable_off = sbi->itable_off;
+	const int ino_off = inum % sbi->ino_per_block;
+	const bool native = sbi->native;
+
+	r = block_get(&b, mnode->instance->service_id,
+		      itable_off + inum / sbi->ino_per_block,
+		      BLOCK_FLAGS_NONE);
+
+	if (r != EOK)
+		goto out;
+
+	struct mfs2_inode *ino2 = b->data;
+	ino2 += ino_off;
+
+	ino2->i_mode = conv16(native, ino_i->i_mode);
+	ino2->i_nlinks = conv16(native, ino_i->i_nlinks);
+	ino2->i_uid = conv16(native, ino_i->i_uid);
+	ino2->i_gid = conv16(native, ino_i->i_gid);
+	ino2->i_size = conv32(native, ino_i->i_size);
+	ino2->i_atime = conv32(native, ino_i->i_atime);
+	ino2->i_mtime = conv32(native, ino_i->i_mtime);
+	ino2->i_ctime = conv32(native, ino_i->i_ctime);
+
+	for (i = 0; i < V2_NR_DIRECT_ZONES; ++i)
+		ino2->i_dzone[i] = conv32(native, ino_i->i_dzone[i]);
+
+	for (i = 0; i < V2_NR_INDIRECT_ZONES; ++i)
+		ino2->i_izone[i] = conv32(native, ino_i->i_izone[i]);
+
+	b->dirty = true;
+	r = block_put(b);
+	ino_i->dirty = false;
+
+out:
+	return r;
+}
+
+int
+mfs_inode_shrink(struct mfs_node *mnode, size_t size_shrink)
+{
+	struct mfs_sb_info *sbi = mnode->instance->sbi;
+	struct mfs_ino_info *ino_i = mnode->ino_i;
+	const size_t bs = sbi->block_size;
+	int r;
+
+	if (size_shrink == 0) {
+		/*File is empty*/
+		return EOK;
+	}
+
+	const size_t old_size = ino_i->i_size;
+	const size_t new_size = ino_i->i_size - size_shrink;
+
+	assert(size_shrink <= old_size);
+
+	ino_i->dirty = true;
+
+	/*Compute the number of zones to free*/
+	unsigned zones_to_free;
+
+	size_t diff = old_size - new_size;
+	zones_to_free = diff / bs;
+
+	if (diff % bs != 0)
+		zones_to_free++;
+
+	uint32_t pos = old_size - 1;
+	unsigned i;
+	for (i = 0; i < zones_to_free; ++i, pos -= bs) {
+		uint32_t old_zone;
+
+		r = mfs_write_map(mnode, pos, 0, &old_zone);
+		if (r != EOK)
+			goto exit_error;
+
+		ino_i->i_size -= bs;
+
+		if (old_zone == 0)
+			continue; /*Sparse block*/
+
+		r = mfs_free_zone(mnode->instance, old_zone);
+		if (r != EOK)
+			goto exit_error;
+	}
+
+	ino_i->i_size = new_size;
+
+	return mfs_prune_ind_zones(mnode, new_size);
+
+exit_error:
+	return r;
+}
+
+/**
+ * @}
+ */
+
Index: uspace/srv/fs/mfs/mfs_ops.c
===================================================================
--- uspace/srv/fs/mfs/mfs_ops.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
+++ uspace/srv/fs/mfs/mfs_ops.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
@@ -0,0 +1,1112 @@
+/*
+ * Copyright (c) 2011 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+#include <stdlib.h>
+#include <fibril_synch.h>
+#include <align.h>
+#include <adt/hash_table.h>
+#include "mfs.h"
+
+#define OPEN_NODES_KEYS 2
+#define OPEN_NODES_SERVICE_KEY 0
+#define OPEN_NODES_INODE_KEY 1
+#define OPEN_NODES_BUCKETS 256
+
+static bool check_magic_number(uint16_t magic, bool *native,
+			       mfs_version_t *version, bool *longfilenames);
+static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
+			     fs_index_t index);
+
+static int mfs_node_put(fs_node_t *fsnode);
+static int mfs_node_open(fs_node_t *fsnode);
+static fs_index_t mfs_index_get(fs_node_t *fsnode);
+static unsigned mfs_lnkcnt_get(fs_node_t *fsnode);
+static bool mfs_is_directory(fs_node_t *fsnode);
+static bool mfs_is_file(fs_node_t *fsnode);
+static int mfs_has_children(bool *has_children, fs_node_t *fsnode);
+static int mfs_root_get(fs_node_t **rfn, service_id_t service_id);
+static service_id_t mfs_device_get(fs_node_t *fsnode);
+static aoff64_t mfs_size_get(fs_node_t *node);
+static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component);
+static int mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags);
+static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name);
+static int mfs_unlink(fs_node_t *, fs_node_t *, const char *name);
+static int mfs_destroy_node(fs_node_t *fn);
+static hash_index_t open_nodes_hash(unsigned long key[]);
+static int open_nodes_compare(unsigned long key[], hash_count_t keys,
+		link_t *item);
+static void open_nodes_remove_cb(link_t *link);
+
+static int mfs_node_get(fs_node_t **rfn, service_id_t service_id,
+			fs_index_t index);
+static int
+mfs_instance_get(service_id_t service_id, struct mfs_instance **instance);
+
+
+static LIST_INITIALIZE(inst_list);
+static FIBRIL_MUTEX_INITIALIZE(inst_list_mutex);
+static hash_table_t open_nodes;
+static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock);
+
+libfs_ops_t mfs_libfs_ops = {
+	.size_get = mfs_size_get,
+	.root_get = mfs_root_get,
+	.device_get = mfs_device_get,
+	.is_directory = mfs_is_directory,
+	.is_file = mfs_is_file,
+	.node_get = mfs_node_get,
+	.node_put = mfs_node_put,
+	.node_open = mfs_node_open,
+	.index_get = mfs_index_get,
+	.match = mfs_match,
+	.create = mfs_create_node,
+	.link = mfs_link,
+	.unlink = mfs_unlink,
+	.destroy = mfs_destroy_node,
+	.has_children = mfs_has_children,
+	.lnkcnt_get = mfs_lnkcnt_get
+};
+
+/* Hash table interface for open nodes hash table */
+static hash_index_t open_nodes_hash(unsigned long key[])
+{
+	/* TODO: This is very simple and probably can be improved */
+	return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS;
+}
+
+static int open_nodes_compare(unsigned long key[], hash_count_t keys,
+		link_t *item)
+{
+	struct mfs_node *mnode = hash_table_get_instance(item, struct mfs_node, link);
+	assert(keys > 0);
+	if (mnode->instance->service_id !=
+	    ((service_id_t) key[OPEN_NODES_SERVICE_KEY])) {
+		return false;
+	}
+	if (keys == 1) {
+		return true;
+	}
+	assert(keys == 2);
+	return (mnode->ino_i->index == key[OPEN_NODES_INODE_KEY]);
+}
+
+static void open_nodes_remove_cb(link_t *link)
+{
+	/* We don't use remove callback for this hash table */
+}
+
+static hash_table_operations_t open_nodes_ops = {
+	.hash = open_nodes_hash,
+	.compare = open_nodes_compare,
+	.remove_callback = open_nodes_remove_cb,
+};
+
+int mfs_global_init(void)
+{
+	if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
+			OPEN_NODES_KEYS, &open_nodes_ops)) {
+		return ENOMEM;
+	}
+	return EOK;
+}
+
+static int
+mfs_mounted(service_id_t service_id, const char *opts, fs_index_t *index,
+		aoff64_t *size, unsigned *linkcnt)
+{
+	enum cache_mode cmode;
+	struct mfs_superblock *sb;
+	struct mfs3_superblock *sb3;
+	struct mfs_sb_info *sbi;
+	struct mfs_instance *instance;
+	bool native, longnames;
+	mfs_version_t version;
+	uint16_t magic;
+	int rc;
+
+	/* Check for option enabling write through. */
+	if (str_cmp(opts, "wtcache") == 0)
+		cmode = CACHE_MODE_WT;
+	else
+		cmode = CACHE_MODE_WB;
+
+	/* initialize libblock */
+	rc = block_init(EXCHANGE_SERIALIZE, service_id, 4096);
+	if (rc != EOK)
+		return rc;
+
+	/*Allocate space for generic MFS superblock*/
+	sbi = malloc(sizeof(*sbi));
+	if (!sbi) {
+		block_fini(service_id);
+		return ENOMEM;
+	}
+
+	/*Allocate space for filesystem instance*/
+	instance = malloc(sizeof(*instance));
+	if (!instance) {
+		free(sbi);
+		block_fini(service_id);
+		return ENOMEM;
+	}
+
+	instance->open_nodes_cnt = 0;
+
+	sb = malloc(MFS_SUPERBLOCK_SIZE);
+	if (!sb) {
+		free(instance);
+		free(sbi);
+		block_fini(service_id);
+		return ENOMEM;
+	}
+
+	/* Read the superblock */
+	rc = block_read_direct(service_id, MFS_SUPERBLOCK << 1, 2, sb);
+	if (rc != EOK) {
+		free(instance);
+		free(sbi);
+		free(sb);
+		block_fini(service_id);
+		return rc;
+	}
+
+	sb3 = (struct mfs3_superblock *) sb;
+
+	if (check_magic_number(sb->s_magic, &native, &version, &longnames)) {
+		/*This is a V1 or V2 Minix filesystem*/
+		magic = sb->s_magic;
+	} else if (check_magic_number(sb3->s_magic, &native, &version, &longnames)) {
+		/*This is a V3 Minix filesystem*/
+		magic = sb3->s_magic;
+	} else {
+		/*Not recognized*/
+		mfsdebug("magic number not recognized\n");
+		free(instance);
+		free(sbi);
+		free(sb);
+		block_fini(service_id);
+		return ENOTSUP;
+	}
+
+	mfsdebug("magic number recognized = %04x\n", magic);
+
+	/*Fill superblock info structure*/
+
+	sbi->fs_version = version;
+	sbi->long_names = longnames;
+	sbi->native = native;
+	sbi->magic = magic;
+	sbi->isearch = 0;
+	sbi->zsearch = 0;
+
+	if (version == MFS_VERSION_V3) {
+		sbi->ninodes = conv32(native, sb3->s_ninodes);
+		sbi->ibmap_blocks = conv16(native, sb3->s_ibmap_blocks);
+		sbi->zbmap_blocks = conv16(native, sb3->s_zbmap_blocks);
+		sbi->firstdatazone = conv16(native, sb3->s_first_data_zone);
+		sbi->log2_zone_size = conv16(native, sb3->s_log2_zone_size);
+		sbi->max_file_size = conv32(native, sb3->s_max_file_size);
+		sbi->nzones = conv32(native, sb3->s_nzones);
+		sbi->block_size = conv16(native, sb3->s_block_size);
+		sbi->ino_per_block = V3_INODES_PER_BLOCK(sbi->block_size);
+		sbi->dirsize = MFS3_DIRSIZE;
+		sbi->max_name_len = MFS3_MAX_NAME_LEN;
+	} else {
+		sbi->ninodes = conv16(native, sb->s_ninodes);
+		sbi->ibmap_blocks = conv16(native, sb->s_ibmap_blocks);
+		sbi->zbmap_blocks = conv16(native, sb->s_zbmap_blocks);
+		sbi->firstdatazone = conv16(native, sb->s_first_data_zone);
+		sbi->log2_zone_size = conv16(native, sb->s_log2_zone_size);
+		sbi->max_file_size = conv32(native, sb->s_max_file_size);
+		sbi->block_size = MFS_BLOCKSIZE;
+		if (version == MFS_VERSION_V2) {
+			sbi->nzones = conv32(native, sb->s_nzones2);
+			sbi->ino_per_block = V2_INODES_PER_BLOCK;
+		} else {
+			sbi->nzones = conv16(native, sb->s_nzones);
+			sbi->ino_per_block = V1_INODES_PER_BLOCK;
+		}
+		sbi->dirsize = longnames ? MFSL_DIRSIZE : MFS_DIRSIZE;
+		sbi->max_name_len = longnames ? MFS_L_MAX_NAME_LEN :
+				    MFS_MAX_NAME_LEN;
+	}
+	sbi->itable_off = 2 + sbi->ibmap_blocks + sbi->zbmap_blocks;
+
+	free(sb);
+
+	rc = block_cache_init(service_id, sbi->block_size, 0, cmode);
+	if (rc != EOK) {
+		free(instance);
+		free(sbi);
+		free(sb);
+		block_cache_fini(service_id);
+		block_fini(service_id);
+		mfsdebug("block cache initialization failed\n");
+		return EINVAL;
+	}
+
+	/*Initialize the instance structure and add it to the list*/
+	link_initialize(&instance->link);
+	instance->service_id = service_id;
+	instance->sbi = sbi;
+
+	fibril_mutex_lock(&inst_list_mutex);
+	list_append(&instance->link, &inst_list);
+	fibril_mutex_unlock(&inst_list_mutex);
+
+	mfsdebug("mount successful\n");
+
+	fs_node_t *fn;
+	mfs_node_get(&fn, service_id, MFS_ROOT_INO);
+
+	struct mfs_node *mroot = fn->data;
+
+	*index = mroot->ino_i->index;
+	*size = mroot->ino_i->i_size;
+	*linkcnt = 1;
+
+	return mfs_node_put(fn);
+}
+
+static int
+mfs_unmounted(service_id_t service_id)
+{
+	struct mfs_instance *inst;
+
+	mfsdebug("%s()\n", __FUNCTION__);
+
+	int r = mfs_instance_get(service_id, &inst);
+	if (r != EOK)
+		return r;
+
+	if (inst->open_nodes_cnt != 0)
+		return EBUSY;
+
+	(void) block_cache_fini(service_id);
+	block_fini(service_id);
+
+	/* Remove the instance from the list */
+	fibril_mutex_lock(&inst_list_mutex);
+	list_remove(&inst->link);
+	fibril_mutex_unlock(&inst_list_mutex);
+
+	free(inst->sbi);
+	free(inst);
+	return EOK;
+}
+
+service_id_t mfs_device_get(fs_node_t *fsnode)
+{
+	struct mfs_node *node = fsnode->data;
+	return node->instance->service_id;
+}
+
+static int mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
+{
+	int r;
+	struct mfs_instance *inst;
+	struct mfs_node *mnode;
+	fs_node_t *fsnode;
+	uint32_t inum;
+
+	mfsdebug("%s()\n", __FUNCTION__);
+
+	r = mfs_instance_get(service_id, &inst);
+	if (r != EOK)
+		return r;
+
+	/*Alloc a new inode*/
+	r = mfs_alloc_inode(inst, &inum);
+	if (r != EOK)
+		return r;
+
+	struct mfs_ino_info *ino_i;
+
+	ino_i = malloc(sizeof(*ino_i));
+	if (!ino_i) {
+		r = ENOMEM;
+		goto out_err;
+	}
+
+	mnode = malloc(sizeof(*mnode));
+	if (!mnode) {
+		r = ENOMEM;
+		goto out_err_1;
+	}
+
+	fsnode = malloc(sizeof(fs_node_t));
+	if (!fsnode) {
+		r = ENOMEM;
+		goto out_err_2;
+	}
+
+	if (flags & L_DIRECTORY) {
+		ino_i->i_mode = S_IFDIR;
+		ino_i->i_nlinks = 2; /*This accounts for the '.' dentry*/
+	} else {
+		ino_i->i_mode = S_IFREG;
+		ino_i->i_nlinks = 1;
+	}
+
+	ino_i->i_uid = 0;
+	ino_i->i_gid = 0;
+	ino_i->i_size = 0;
+	ino_i->i_atime = 0;
+	ino_i->i_mtime = 0;
+	ino_i->i_ctime = 0;
+
+	memset(ino_i->i_dzone, 0, sizeof(uint32_t) * V2_NR_DIRECT_ZONES);
+	memset(ino_i->i_izone, 0, sizeof(uint32_t) * V2_NR_INDIRECT_ZONES);
+
+	mfsdebug("new node idx = %d\n", (int) inum);
+
+	ino_i->index = inum;
+	ino_i->dirty = true;
+	mnode->ino_i = ino_i;
+	mnode->instance = inst;
+	mnode->refcnt = 1;
+
+	link_initialize(&mnode->link);
+
+	unsigned long key[] = {
+		[OPEN_NODES_SERVICE_KEY] = inst->service_id,
+		[OPEN_NODES_INODE_KEY] = inum,
+	};
+
+	fibril_mutex_lock(&open_nodes_lock);
+	hash_table_insert(&open_nodes, key, &mnode->link);
+	fibril_mutex_unlock(&open_nodes_lock);
+	inst->open_nodes_cnt++;
+
+	mnode->ino_i->dirty = true;
+
+	fs_node_initialize(fsnode);
+	fsnode->data = mnode;
+	mnode->fsnode = fsnode;
+	*rfn = fsnode;
+
+	return EOK;
+
+out_err_2:
+	free(mnode);
+out_err_1:
+	free(ino_i);
+out_err:
+	return r;
+}
+
+static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
+{
+	struct mfs_node *mnode = pfn->data;
+	struct mfs_ino_info *ino_i = mnode->ino_i;
+	struct mfs_dentry_info d_info;
+	int r;
+
+	mfsdebug("%s()\n", __FUNCTION__);
+
+	if (!S_ISDIR(ino_i->i_mode))
+		return ENOTDIR;
+
+	struct mfs_sb_info *sbi = mnode->instance->sbi;
+	const size_t comp_size = str_size(component);
+
+	unsigned i;
+	for (i = 0; i < mnode->ino_i->i_size / sbi->dirsize; ++i) {
+		r = mfs_read_dentry(mnode, &d_info, i);
+		if (r != EOK)
+			return r;
+
+		if (!d_info.d_inum) {
+			/*This entry is not used*/
+			continue;
+		}
+
+		const size_t dentry_name_size = str_size(d_info.d_name);
+
+		if (comp_size == dentry_name_size &&
+			!bcmp(component, d_info.d_name, dentry_name_size)) {
+			/*Hit!*/
+			mfs_node_core_get(rfn, mnode->instance,
+					  d_info.d_inum);
+			goto found;
+		}
+	}
+	*rfn = NULL;
+found:
+	return EOK;
+}
+
+static aoff64_t mfs_size_get(fs_node_t *node)
+{
+	assert(node);
+
+	const struct mfs_node *mnode = node->data;
+	assert(mnode);
+	assert(mnode->ino_i);
+
+	return mnode->ino_i->i_size;
+}
+
+static int
+mfs_node_get(fs_node_t **rfn, service_id_t service_id,
+			fs_index_t index)
+{
+	int rc;
+	struct mfs_instance *instance;
+
+	mfsdebug("%s()\n", __FUNCTION__);
+
+	rc = mfs_instance_get(service_id, &instance);
+	if (rc != EOK)
+		return rc;
+
+	return mfs_node_core_get(rfn, instance, index);
+}
+
+static int
+mfs_node_put(fs_node_t *fsnode)
+{
+	int rc = EOK;
+	struct mfs_node *mnode = fsnode->data;
+
+	mfsdebug("%s()\n", __FUNCTION__);
+
+	fibril_mutex_lock(&open_nodes_lock);
+
+	assert(mnode->refcnt > 0);
+	mnode->refcnt--;
+	if (mnode->refcnt == 0) {
+		unsigned long key[] = {
+			[OPEN_NODES_SERVICE_KEY] = mnode->instance->service_id,
+			[OPEN_NODES_INODE_KEY] = mnode->ino_i->index
+		};
+		hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS);
+		assert(mnode->instance->open_nodes_cnt > 0);
+		mnode->instance->open_nodes_cnt--;
+		rc = mfs_put_inode_core(mnode);
+		free(mnode->ino_i);
+		free(mnode);
+		free(fsnode);
+	}
+
+	fibril_mutex_unlock(&open_nodes_lock);
+	return rc;
+}
+
+static int mfs_node_open(fs_node_t *fsnode)
+{
+	/*
+	 * Opening a file is stateless, nothing
+	 * to be done here.
+	 */
+	return EOK;
+}
+
+static fs_index_t mfs_index_get(fs_node_t *fsnode)
+{
+	struct mfs_node *mnode = fsnode->data;
+
+	assert(mnode->ino_i);
+	return mnode->ino_i->index;
+}
+
+static unsigned mfs_lnkcnt_get(fs_node_t *fsnode)
+{
+	struct mfs_node *mnode = fsnode->data;
+
+	mfsdebug("%s() %d\n", __FUNCTION__, mnode->ino_i->i_nlinks);
+
+	if (S_ISDIR(mnode->ino_i->i_mode)) {
+		if (mnode->ino_i->i_nlinks > 1)
+			return 1;
+		else
+			return 0;
+	} else
+		return mnode->ino_i->i_nlinks;
+}
+
+static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
+			     fs_index_t index)
+{
+	fs_node_t *node = NULL;
+	struct mfs_node *mnode = NULL;
+	int rc;
+
+	mfsdebug("%s()\n", __FUNCTION__);
+
+	fibril_mutex_lock(&open_nodes_lock);
+
+	/* Check if the node is not already open */
+	unsigned long key[] = {
+		[OPEN_NODES_SERVICE_KEY] = inst->service_id,
+		[OPEN_NODES_INODE_KEY] = index,
+	};
+	link_t *already_open = hash_table_find(&open_nodes, key);
+
+	if (already_open) {
+		mnode = hash_table_get_instance(already_open, struct mfs_node, link);
+		*rfn = mnode->fsnode;
+		mnode->refcnt++;
+
+		fibril_mutex_unlock(&open_nodes_lock);
+		return EOK;
+	}
+
+	node = malloc(sizeof(fs_node_t));
+	if (!node) {
+		rc = ENOMEM;
+		goto out_err;
+	}
+
+	fs_node_initialize(node);
+
+	mnode = malloc(sizeof(*mnode));
+	if (!mnode) {
+		rc = ENOMEM;
+		goto out_err;
+	}
+
+	struct mfs_ino_info *ino_i;
+
+	rc = mfs_get_inode(inst, &ino_i, index);
+	if (rc != EOK)
+		goto out_err;
+
+	ino_i->index = index;
+	mnode->ino_i = ino_i;
+	mnode->refcnt = 1;
+	link_initialize(&mnode->link);
+
+	mnode->instance = inst;
+	node->data = mnode;
+	mnode->fsnode = node;
+	*rfn = node;
+
+	hash_table_insert(&open_nodes, key, &mnode->link);
+	inst->open_nodes_cnt++;
+
+	fibril_mutex_unlock(&open_nodes_lock);
+
+	return EOK;
+
+out_err:
+	if (node)
+		free(node);
+	if (mnode)
+		free(mnode);
+	fibril_mutex_unlock(&open_nodes_lock);
+	return rc;
+}
+
+static bool mfs_is_directory(fs_node_t *fsnode)
+{
+	const struct mfs_node *node = fsnode->data;
+	return S_ISDIR(node->ino_i->i_mode);
+}
+
+static bool mfs_is_file(fs_node_t *fsnode)
+{
+	struct mfs_node *node = fsnode->data;
+	return S_ISREG(node->ino_i->i_mode);
+}
+
+static int mfs_root_get(fs_node_t **rfn, service_id_t service_id)
+{
+	int rc = mfs_node_get(rfn, service_id, MFS_ROOT_INO);
+	return rc;
+}
+
+static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
+{
+	struct mfs_node *parent = pfn->data;
+	struct mfs_node *child = cfn->data;
+	struct mfs_sb_info *sbi = parent->instance->sbi;
+
+	mfsdebug("%s()\n", __FUNCTION__);
+
+	if (str_size(name) > sbi->max_name_len)
+		return ENAMETOOLONG;
+
+	int r = mfs_insert_dentry(parent, name, child->ino_i->index);
+	if (r != EOK)
+		goto exit_error;
+
+	if (S_ISDIR(child->ino_i->i_mode)) {
+		r = mfs_insert_dentry(child, ".", child->ino_i->index);
+		if (r != EOK)
+			goto exit_error;
+
+		r = mfs_insert_dentry(child, "..", parent->ino_i->index);
+		if (r != EOK)
+			goto exit_error;
+
+		parent->ino_i->i_nlinks++;
+		parent->ino_i->dirty = true;
+	}
+
+exit_error:
+	return r;
+}
+
+static int
+mfs_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *name)
+{
+	struct mfs_node *parent = pfn->data;
+	struct mfs_node *child = cfn->data;
+	bool has_children;
+	int r;
+
+	mfsdebug("%s()\n", __FUNCTION__);
+
+	if (!parent)
+		return EBUSY;
+
+	r = mfs_has_children(&has_children, cfn);
+	if (r != EOK)
+		return r;
+
+	if (has_children)
+		return ENOTEMPTY;
+
+	r = mfs_remove_dentry(parent, name);
+	if (r != EOK)
+		return r;
+
+	struct mfs_ino_info *chino = child->ino_i;
+
+	assert(chino->i_nlinks >= 1);
+	chino->i_nlinks--;
+	mfsdebug("Links: %d\n", chino->i_nlinks);
+
+	if (chino->i_nlinks <= 1 && S_ISDIR(chino->i_mode)) {
+		/* The child directory will be destroyed, decrease the
+		 * parent hard links counter.
+		 */
+		parent->ino_i->i_nlinks--;
+		parent->ino_i->dirty = true;
+	}
+
+	chino->dirty = true;
+
+	return r;
+}
+
+static int mfs_has_children(bool *has_children, fs_node_t *fsnode)
+{
+	struct mfs_node *mnode = fsnode->data;
+	struct mfs_sb_info *sbi = mnode->instance->sbi;
+	int r;
+
+	*has_children = false;
+
+	if (!S_ISDIR(mnode->ino_i->i_mode))
+		goto out;
+
+	struct mfs_dentry_info d_info;
+
+	/* The first two dentries are always . and .. */
+	unsigned i;
+	for (i = 2; i < mnode->ino_i->i_size / sbi->dirsize; ++i) {
+		r = mfs_read_dentry(mnode, &d_info, i);
+		if (r != EOK)
+			return r;
+
+		if (d_info.d_inum) {
+			/*A valid entry has been found*/
+			*has_children = true;
+			break;
+		}
+	}
+out:
+
+	return EOK;
+}
+
+static int
+mfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
+		size_t *rbytes)
+{
+	int rc;
+	fs_node_t *fn;
+
+	rc = mfs_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
+
+	struct mfs_node *mnode;
+	struct mfs_ino_info *ino_i;
+	size_t len, bytes = 0;
+	ipc_callid_t callid;
+
+	mnode = fn->data;
+	ino_i = mnode->ino_i;
+
+	if (!async_data_read_receive(&callid, &len)) {
+		rc = EINVAL;
+		goto out_error;
+	}
+
+	if (S_ISDIR(ino_i->i_mode)) {
+		aoff64_t spos = pos;
+		struct mfs_dentry_info d_info;
+		struct mfs_sb_info *sbi = mnode->instance->sbi;
+
+		if (pos < 2) {
+			/*Skip the first two dentries ('.' and '..')*/
+			pos = 2;
+		}
+
+		for (; pos < mnode->ino_i->i_size / sbi->dirsize; ++pos) {
+			rc = mfs_read_dentry(mnode, &d_info, pos);
+			if (rc != EOK)
+				goto out_error;
+
+			if (d_info.d_inum) {
+				/*Dentry found!*/
+				goto found;
+			}
+		}
+
+		rc = mfs_node_put(fn);
+		async_answer_0(callid, rc != EOK ? rc : ENOENT);
+		return rc;
+found:
+		async_data_read_finalize(callid, d_info.d_name,
+					 str_size(d_info.d_name) + 1);
+		bytes = ((pos - spos) + 1);
+	} else {
+		struct mfs_sb_info *sbi = mnode->instance->sbi;
+
+		if (pos >= (size_t) ino_i->i_size) {
+			/*Trying to read beyond the end of file*/
+			bytes = 0;
+			(void) async_data_read_finalize(callid, NULL, 0);
+			goto out_success;
+		}
+
+		bytes = min(len, sbi->block_size - pos % sbi->block_size);
+		bytes = min(bytes, ino_i->i_size - pos);
+
+		uint32_t zone;
+		block_t *b;
+
+		rc = mfs_read_map(&zone, mnode, pos);
+		if (rc != EOK)
+			goto out_error;
+
+		if (zone == 0) {
+			/*sparse file*/
+			uint8_t *buf = malloc(sbi->block_size);
+			if (!buf) {
+				rc = ENOMEM;
+				goto out_error;
+			}
+			memset(buf, 0, sizeof(sbi->block_size));
+			async_data_read_finalize(callid,
+						 buf + pos % sbi->block_size, bytes);
+			free(buf);
+			goto out_success;
+		}
+
+		rc = block_get(&b, service_id, zone, BLOCK_FLAGS_NONE);
+		if (rc != EOK)
+			goto out_error;
+
+		async_data_read_finalize(callid, b->data +
+					 pos % sbi->block_size, bytes);
+
+		rc = block_put(b);
+		if (rc != EOK) {
+			mfs_node_put(fn);
+			return rc;
+		}
+	}
+out_success:
+	rc = mfs_node_put(fn);
+	*rbytes = bytes;
+	return rc;
+out_error:
+	;
+	int tmp = mfs_node_put(fn);
+	async_answer_0(callid, tmp != EOK ? tmp : rc);
+	return tmp != EOK ? tmp : rc;
+}
+
+static int
+mfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
+		size_t *wbytes, aoff64_t *nsize)
+{
+	fs_node_t *fn;
+	int r;
+	int flags = BLOCK_FLAGS_NONE;
+
+	r = mfs_node_get(&fn, service_id, index);
+	if (r != EOK)
+		return r;
+	if (!fn)
+		return ENOENT;
+
+	ipc_callid_t callid;
+	size_t len;
+
+	if (!async_data_write_receive(&callid, &len)) {
+		r = EINVAL;
+		goto out_err;
+	}
+
+	struct mfs_node *mnode = fn->data;
+	struct mfs_sb_info *sbi = mnode->instance->sbi;
+	struct mfs_ino_info *ino_i = mnode->ino_i;
+	const size_t bs = sbi->block_size;
+	size_t bytes = min(len, bs - pos % bs);
+	size_t boundary = ROUND_UP(ino_i->i_size, bs);
+	uint32_t block;
+
+	if (bytes == bs)
+		flags = BLOCK_FLAGS_NOREAD;
+
+	if (pos < boundary) {
+		r = mfs_read_map(&block, mnode, pos);
+		if (r != EOK)
+			goto out_err;
+
+		if (block == 0) {
+			/*Writing in a sparse block*/
+			r = mfs_alloc_zone(mnode->instance, &block);
+			if (r != EOK)
+				goto out_err;
+			flags = BLOCK_FLAGS_NOREAD;
+		}
+	} else {
+		uint32_t dummy;
+
+		r = mfs_alloc_zone(mnode->instance, &block);
+		if (r != EOK)
+			goto out_err;
+
+		r = mfs_write_map(mnode, pos, block, &dummy);
+		if (r != EOK)
+			goto out_err;
+	}
+
+	block_t *b;
+	r = block_get(&b, service_id, block, flags);
+	if (r != EOK)
+		goto out_err;
+
+	async_data_write_finalize(callid, b->data + pos % bs, bytes);
+	b->dirty = true;
+
+	r = block_put(b);
+	if (r != EOK) {
+		mfs_node_put(fn);
+		return r;
+	}
+
+	ino_i->i_size = pos + bytes;
+	ino_i->dirty = true;
+	r = mfs_node_put(fn);
+	*nsize = pos + bytes;
+	*wbytes = bytes;
+	return r;
+
+out_err:
+	mfs_node_put(fn);
+	async_answer_0(callid, r);
+	return r;
+}
+
+static int
+mfs_destroy(service_id_t service_id, fs_index_t index)
+{
+	fs_node_t *fn;
+	int r;
+
+	r = mfs_node_get(&fn, service_id, index);
+	if (r != EOK)
+		return r;
+	if (!fn)
+		return ENOENT;
+
+	/*Destroy the inode*/
+	return mfs_destroy_node(fn);
+}
+
+static int
+mfs_destroy_node(fs_node_t *fn)
+{
+	struct mfs_node *mnode = fn->data;
+	bool has_children;
+	int r;
+
+	mfsdebug("mfs_destroy_node %d\n", mnode->ino_i->index);
+
+	r = mfs_has_children(&has_children, fn);
+	if (r != EOK)
+		goto out;
+
+	assert(!has_children);
+
+	/*Free the entire inode content*/
+	r = mfs_inode_shrink(mnode, mnode->ino_i->i_size);
+	if (r != EOK)
+		goto out;
+
+	/*Mark the inode as free in the bitmap*/
+	r = mfs_free_inode(mnode->instance, mnode->ino_i->index);
+
+out:
+	mfs_node_put(fn);
+	return r;
+}
+
+static int
+mfs_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
+{
+	fs_node_t *fn;
+	int r;
+
+	r = mfs_node_get(&fn, service_id, index);
+	if (r != EOK)
+		return r;
+	if (!fn)
+		return r;
+
+	struct mfs_node *mnode = fn->data;
+	struct mfs_ino_info *ino_i = mnode->ino_i;
+
+	if (ino_i->i_size == size)
+		r = EOK;
+	else
+		r = mfs_inode_shrink(mnode, ino_i->i_size - size);
+
+	mfs_node_put(fn);
+	return r;
+}
+
+static int
+mfs_instance_get(service_id_t service_id, struct mfs_instance **instance)
+{
+	struct mfs_instance *instance_ptr;
+
+	fibril_mutex_lock(&inst_list_mutex);
+
+	if (list_empty(&inst_list)) {
+		fibril_mutex_unlock(&inst_list_mutex);
+		return EINVAL;
+	}
+
+	list_foreach(inst_list, link) {
+		instance_ptr = list_get_instance(link, struct mfs_instance,
+						 link);
+
+		if (instance_ptr->service_id == service_id) {
+			*instance = instance_ptr;
+			fibril_mutex_unlock(&inst_list_mutex);
+			return EOK;
+		}
+	}
+
+	mfsdebug("Instance not found\n");
+
+	fibril_mutex_unlock(&inst_list_mutex);
+	return EINVAL;
+}
+
+static bool check_magic_number(uint16_t magic, bool *native,
+			       mfs_version_t *version, bool *longfilenames)
+{
+	bool rc = true;
+	*longfilenames = false;
+
+	if (magic == MFS_MAGIC_V1 || magic == MFS_MAGIC_V1R) {
+		*native = magic == MFS_MAGIC_V1;
+		*version = MFS_VERSION_V1;
+	} else if (magic == MFS_MAGIC_V1L || magic == MFS_MAGIC_V1LR) {
+		*native = magic == MFS_MAGIC_V1L;
+		*version = MFS_VERSION_V1;
+		*longfilenames = true;
+	} else if (magic == MFS_MAGIC_V2 || magic == MFS_MAGIC_V2R) {
+		*native = magic == MFS_MAGIC_V2;
+		*version = MFS_VERSION_V2;
+	} else if (magic == MFS_MAGIC_V2L || magic == MFS_MAGIC_V2LR) {
+		*native = magic == MFS_MAGIC_V2L;
+		*version = MFS_VERSION_V2;
+		*longfilenames = true;
+	} else if (magic == MFS_MAGIC_V3 || magic == MFS_MAGIC_V3R) {
+		*native = magic == MFS_MAGIC_V3;
+		*version = MFS_VERSION_V3;
+	} else
+		rc = false;
+
+	return rc;
+}
+
+static int
+mfs_close(service_id_t service_id, fs_index_t index)
+{
+	return 0;
+}
+
+static int
+mfs_sync(service_id_t service_id, fs_index_t index)
+{
+	fs_node_t *fn;
+	int rc = mfs_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
+
+	struct mfs_node *mnode = fn->data;
+	mnode->ino_i->dirty = true;
+
+	return mfs_node_put(fn);
+}
+
+vfs_out_ops_t mfs_ops = {
+	.mounted = mfs_mounted,
+	.unmounted = mfs_unmounted,
+	.read = mfs_read,
+	.write = mfs_write,
+	.truncate = mfs_truncate,
+	.close = mfs_close,
+	.destroy = mfs_destroy,
+	.sync = mfs_sync,
+};
+
+/**
+ * @}
+ */
+
Index: uspace/srv/fs/mfs/mfs_rw.c
===================================================================
--- uspace/srv/fs/mfs/mfs_rw.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
+++ uspace/srv/fs/mfs/mfs_rw.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2011 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+#include "mfs.h"
+
+static int
+rw_map_ondisk(uint32_t *b, const struct mfs_node *mnode, int rblock,
+	      bool write_mode, uint32_t w_block);
+
+static int
+reset_zone_content(struct mfs_instance *inst, uint32_t zone);
+
+static int
+alloc_zone_and_clear(struct mfs_instance *inst, uint32_t *zone);
+
+static int
+read_ind_zone(struct mfs_instance *inst, uint32_t zone, uint32_t **ind_zone);
+
+static int
+write_ind_zone(struct mfs_instance *inst, uint32_t zone, uint32_t *ind_zone);
+
+
+/**Given the position in the file expressed in
+ *bytes, this function returns the on-disk block
+ *relative to that position.
+ *Returns zero if the block does not exist.
+ */
+int
+mfs_read_map(uint32_t *b, const struct mfs_node *mnode, uint32_t pos)
+{
+	int r;
+	const struct mfs_sb_info *sbi = mnode->instance->sbi;
+	const int block_size = sbi->block_size;
+
+	/*Compute relative block number in file*/
+	int rblock = pos / block_size;
+
+	if (mnode->ino_i->i_size < pos) {
+		/*Trying to read beyond the end of file*/
+		r = EOK;
+		*b = 0;
+		goto out;
+	}
+
+	r = rw_map_ondisk(b, mnode, rblock, false, 0);
+out:
+	return r;
+}
+
+int
+mfs_write_map(struct mfs_node *mnode, const uint32_t pos, uint32_t new_zone,
+	  uint32_t *old_zone)
+{
+	const struct mfs_sb_info *sbi = mnode->instance->sbi;
+
+	if (pos >= sbi->max_file_size) {
+		/*Can't write beyond the maximum file size*/
+		return EINVAL;
+	}
+
+	/*Compute the relative block number in file*/
+	int rblock = pos / sbi->block_size;
+
+	return rw_map_ondisk(old_zone, mnode, rblock, true, new_zone);
+}
+
+static int
+rw_map_ondisk(uint32_t *b, const struct mfs_node *mnode, int rblock,
+	      bool write_mode, uint32_t w_block)
+{
+	int r, nr_direct;
+	int ptrs_per_block;
+	uint32_t *ind_zone, *ind2_zone;
+
+	struct mfs_ino_info *ino_i = mnode->ino_i;
+	struct mfs_instance *inst = mnode->instance;
+	struct mfs_sb_info *sbi = inst->sbi;
+
+	const mfs_version_t fs_version = sbi->fs_version;
+	const bool deleting = write_mode && (w_block == 0);
+
+	if (fs_version == MFS_VERSION_V1) {
+		nr_direct = V1_NR_DIRECT_ZONES;
+		ptrs_per_block = MFS_BLOCKSIZE / sizeof(uint16_t);
+	} else {
+		nr_direct = V2_NR_DIRECT_ZONES;
+		ptrs_per_block = sbi->block_size / sizeof(uint32_t);
+	}
+
+	/*Check if the wanted block is in the direct zones*/
+	if (rblock < nr_direct) {
+		*b = ino_i->i_dzone[rblock];
+		if (write_mode) {
+			ino_i->i_dzone[rblock] = w_block;
+			ino_i->dirty = true;
+		}
+		return EOK;
+	}
+
+	rblock -= nr_direct;
+
+	if (rblock < ptrs_per_block) {
+		/*The wanted block is in the single indirect zone chain*/
+		if (ino_i->i_izone[0] == 0) {
+			if (write_mode && !deleting) {
+				uint32_t zone;
+				r = alloc_zone_and_clear(inst, &zone);
+				if (r != EOK)
+					return r;
+
+				ino_i->i_izone[0] = zone;
+				ino_i->dirty = true;
+			} else {
+				/*Sparse block*/
+				*b = 0;
+				return EOK;
+			}
+		}
+
+		r = read_ind_zone(inst, ino_i->i_izone[0], &ind_zone);
+		if (r != EOK)
+			return r;
+
+		*b = ind_zone[rblock];
+		if (write_mode) {
+			ind_zone[rblock] = w_block;
+			write_ind_zone(inst, ino_i->i_izone[0], ind_zone);
+		}
+
+		goto out_free_ind1;
+	}
+
+	rblock -= ptrs_per_block;
+
+	/*The wanted block is in the double indirect zone chain*/
+
+	/*read the first indirect zone of the chain*/
+	if (ino_i->i_izone[1] == 0) {
+		if (write_mode && !deleting) {
+			uint32_t zone;
+			r = alloc_zone_and_clear(inst, &zone);
+			if (r != EOK)
+				return r;
+
+			ino_i->i_izone[1] = zone;
+			ino_i->dirty = true;
+		} else {
+			/*Sparse block*/
+			*b = 0;
+			return EOK;
+		}
+	}
+
+	r = read_ind_zone(inst, ino_i->i_izone[1], &ind_zone);
+	if (r != EOK)
+		return r;
+
+	/*
+	 *Compute the position of the second indirect
+	 *zone pointer in the chain.
+	 */
+	uint32_t ind2_off = rblock / ptrs_per_block;
+
+	/*read the second indirect zone of the chain*/
+	if (ind_zone[ind2_off] == 0) {
+		if (write_mode && !deleting) {
+			uint32_t zone;
+			r = alloc_zone_and_clear(inst, &zone);
+			if (r != EOK)
+				goto out_free_ind1;
+
+			ind_zone[ind2_off] = zone;
+			write_ind_zone(inst, ino_i->i_izone[1], ind_zone);
+		} else {
+			/*Sparse block*/
+			r = EOK;
+			*b = 0;
+			goto out_free_ind1;
+		}
+	}
+
+	r = read_ind_zone(inst, ind_zone[ind2_off], &ind2_zone);
+	if (r != EOK)
+		goto out_free_ind1;
+
+	*b = ind2_zone[rblock - (ind2_off * ptrs_per_block)];
+	if (write_mode) {
+		ind2_zone[rblock - (ind2_off * ptrs_per_block)] = w_block;
+		write_ind_zone(inst, ind_zone[ind2_off], ind2_zone);
+	}
+
+	r = EOK;
+
+	free(ind2_zone);
+out_free_ind1:
+	free(ind_zone);
+	return r;
+}
+
+/*Free unused indirect zones*/
+int
+mfs_prune_ind_zones(struct mfs_node *mnode, size_t new_size)
+{
+	struct mfs_instance *inst = mnode->instance;
+	struct mfs_sb_info *sbi = inst->sbi;
+	struct mfs_ino_info *ino_i = mnode->ino_i;
+	int nr_direct, ptrs_per_block, rblock, r;
+	int i;
+
+	mfs_version_t fs_version = sbi->fs_version;
+	
+	if (fs_version == MFS_VERSION_V1) {
+		nr_direct = V1_NR_DIRECT_ZONES;
+		ptrs_per_block = MFS_BLOCKSIZE / sizeof(uint16_t);
+	} else {
+		nr_direct = V2_NR_DIRECT_ZONES;
+		ptrs_per_block = sbi->block_size / sizeof(uint32_t);
+	}
+
+	rblock = new_size / sbi->block_size;
+
+	if (rblock < nr_direct) {
+		/*free the single indirect zone*/
+		if (ino_i->i_izone[0]) {
+			r = mfs_free_zone(inst, ino_i->i_izone[0]);
+			if (r != EOK)
+				return r;
+
+			ino_i->i_izone[0] = 0;
+			ino_i->dirty = true;
+		}
+	}
+
+	rblock -= nr_direct + ptrs_per_block;
+
+	int fzone_to_free = (rblock < 0 ? 0 : rblock) / ptrs_per_block;
+
+	if ((fzone_to_free % ptrs_per_block) != 0)
+		++fzone_to_free;
+
+	/*free the entire double indirect zone*/
+	uint32_t *dbl_zone;
+
+	if (ino_i->i_izone[1] == 0) {
+		/*Nothing to be done*/
+		return EOK;
+	}
+
+	r = read_ind_zone(inst, ino_i->i_izone[1], &dbl_zone);
+	if (r != EOK)
+		return r;
+
+	for (i = fzone_to_free; i < ptrs_per_block; ++i) {
+		if (dbl_zone[i] == 0)
+			continue;
+
+		r = mfs_free_zone(inst, dbl_zone[i]);
+		if (r != EOK)
+			goto out;
+	}
+
+	if (fzone_to_free == 0) {
+		r = mfs_free_zone(inst, ino_i->i_izone[1]);
+		ino_i->i_izone[1] = 0;
+		ino_i->dirty = true;
+	}
+out:
+	free(dbl_zone);
+	return r;
+}
+
+static int
+reset_zone_content(struct mfs_instance *inst, uint32_t zone)
+{
+	block_t *b;
+	int r;
+
+	r = block_get(&b, inst->service_id, zone, BLOCK_FLAGS_NOREAD);
+	if (r != EOK)
+		return r;
+
+	memset(b->data, 0, b->size);
+	b->dirty = true;
+
+	return block_put(b);
+}
+
+static int
+alloc_zone_and_clear(struct mfs_instance *inst, uint32_t *zone)
+{
+	int r;
+
+	r = mfs_alloc_zone(inst, zone);
+	if (r != EOK)
+		return r;
+
+	r = reset_zone_content(inst, *zone);
+	return r;
+}
+
+static int
+read_ind_zone(struct mfs_instance *inst, uint32_t zone, uint32_t **ind_zone)
+{
+	struct mfs_sb_info *sbi = inst->sbi;
+	int r;
+	unsigned i;
+	block_t *b;
+	const int max_ind_zone_ptrs = (MFS_MAX_BLOCKSIZE / sizeof(uint16_t)) *
+				      sizeof(uint32_t);
+
+	*ind_zone = malloc(max_ind_zone_ptrs);
+	if (*ind_zone == NULL)
+		return ENOMEM;
+
+	r = block_get(&b, inst->service_id, zone, BLOCK_FLAGS_NONE);
+	if (r != EOK) {
+		free(*ind_zone);
+		return r;
+	}
+
+	if (sbi->fs_version == MFS_VERSION_V1) {
+		uint16_t *src_ptr = b->data;
+
+		for (i = 0; i < sbi->block_size / sizeof(uint16_t); ++i)
+			(*ind_zone)[i] = conv16(sbi->native, src_ptr[i]);
+	} else {
+		uint32_t *src_ptr = b->data;
+
+		for (i = 0; i < sbi->block_size / sizeof(uint32_t); ++i)
+			(*ind_zone)[i] = conv32(sbi->native, src_ptr[i]);
+	}
+
+	return block_put(b);
+}
+
+static int
+write_ind_zone(struct mfs_instance *inst, uint32_t zone, uint32_t *ind_zone)
+{
+	struct mfs_sb_info *sbi = inst->sbi;
+	int r;
+	unsigned i;
+	block_t *b;
+
+	r = block_get(&b, inst->service_id, zone, BLOCK_FLAGS_NOREAD);
+	if (r != EOK)
+		return r;
+
+	if (sbi->fs_version == MFS_VERSION_V1) {
+		uint16_t *dest_ptr = b->data;
+
+		for (i = 0; i < sbi->block_size / sizeof(uint16_t); ++i)
+			dest_ptr[i] = conv16(sbi->native, ind_zone[i]);
+	} else {
+		uint32_t *dest_ptr = b->data;
+
+		for (i = 0; i < sbi->block_size / sizeof(uint32_t); ++i)
+			dest_ptr[i] = conv32(sbi->native, ind_zone[i]);
+
+	}
+	b->dirty = true;
+
+	return block_put(b);
+}
+
+
+/**
+ * @}
+ */
+
Index: uspace/srv/fs/mfs/mfs_utils.c
===================================================================
--- uspace/srv/fs/mfs/mfs_utils.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
+++ uspace/srv/fs/mfs/mfs_utils.c	(revision 7a46bfe1e3cef419ea897f6581d7484b5f8d0955)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+#include <byteorder.h>
+#include "mfs.h"
+
+uint16_t conv16(bool native, uint16_t n)
+{
+	if (native)
+		return n;
+
+	return uint16_t_byteorder_swap(n);
+}
+
+uint32_t conv32(bool native, uint32_t n)
+{
+	if (native)
+		return n;
+
+	return uint32_t_byteorder_swap(n);
+}
+
+uint64_t conv64(bool native, uint64_t n)
+{
+	if (native)
+		return n;
+
+	return uint64_t_byteorder_swap(n);
+}
+
+/**
+ * @}
+ */
+
Index: uspace/srv/fs/minixfs/Makefile
===================================================================
--- uspace/srv/fs/minixfs/Makefile	(revision 9a0be341d462b5cb93242f88efe36f9ed4f4eb6d)
+++ 	(revision )
@@ -1,44 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../..
-LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBFS_PREFIX)/libfs.a
-EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX) -I$(LIBMINIX_PREFIX)
-BINARY = mfs
-
-SOURCES = \
-	mfs.c \
-	mfs_ops.c \
-	mfs_inode.c \
-	mfs_rw.c \
-	mfs_dentry.c \
-	mfs_balloc.c \
-	mfs_utils.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/fs/minixfs/mfs.c
===================================================================
--- uspace/srv/fs/minixfs/mfs.c	(revision 9a0be341d462b5cb93242f88efe36f9ed4f4eb6d)
+++ 	(revision )
@@ -1,94 +1,0 @@
-/*
- * Copyright (c) 2006 Martin Decky
- * Copyright (c) 2008 Jakub Jermar
- * Copyright (c) 2011 Maurizio Lombardi
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup fs
- * @{
- */
-
-/**
- * @file	mfs.c
- * @brief	Minix file system driver for HelenOS.
- */
-
-#include <ipc/services.h>
-#include <ns.h>
-#include <async.h>
-#include <errno.h>
-#include <unistd.h>
-#include <task.h>
-#include <stdio.h>
-#include <libfs.h>
-#include "mfs.h"
-
-vfs_info_t mfs_vfs_info = {
-	.name = NAME,
-	.concurrent_read_write = false,
-	.write_retains_size = false,
-};
-
-int main(int argc, char **argv)
-{
-	int rc;
-
-	printf(NAME ": HelenOS Minix file system server\n");
-
-	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
-				SERVICE_VFS, 0, 0);
-
-	if (!vfs_sess) {
-		printf(NAME ": failed to connect to VFS\n");
-		return -1;
-	}
-
-	rc = mfs_global_init();
-	if (rc != EOK) {
-		printf(NAME ": Failed global initialization\n");
-		goto err;
-	}
-
-	rc = fs_register(vfs_sess, &mfs_vfs_info, &mfs_ops, &mfs_libfs_ops);
-	if (rc != EOK)
-		goto err;
-
-	printf(NAME ": Accepting connections\n");
-	task_retval(0);
-	async_manager();
-	/* not reached */
-	return 0;
-
-err:
-	printf(NAME ": Failed to register file system (%d)\n", rc);
-	return rc;
-}
-
-/**
- * @}
- */
-
Index: uspace/srv/fs/minixfs/mfs.h
===================================================================
--- uspace/srv/fs/minixfs/mfs.h	(revision 9a0be341d462b5cb93242f88efe36f9ed4f4eb6d)
+++ 	(revision )
@@ -1,219 +1,0 @@
-/*
- * Copyright (c) 2011 Maurizio Lombardi
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup fs
- * @{
- */
-
-#ifndef _MFS_H_
-#define _MFS_H_
-
-#include <minix.h>
-#include <macros.h>
-#include <libblock.h>
-#include <libfs.h>
-#include <adt/list.h>
-#include <malloc.h>
-#include <mem.h>
-#include <stdio.h>
-#include <errno.h>
-#include <assert.h>
-#include "../../vfs/vfs.h"
-
-#define NAME		"mfs"
-
-//#define DEBUG_MODE
-
-#define min(a, b)	((a) < (b) ? (a) : (b))
-
-#ifdef DEBUG_MODE
-#define mfsdebug(...)	printf(__VA_ARGS__)
-#else
-#define mfsdebug(...)
-#endif
-
-typedef uint32_t bitchunk_t;
-
-typedef enum {
-	BMAP_ZONE,
-	BMAP_INODE
-} bmap_id_t;
-
-typedef enum {
-	MFS_VERSION_V1 = 1,
-	MFS_VERSION_V2,
-	MFS_VERSION_V3
-} mfs_version_t;
-
-/*Generic MinixFS superblock*/
-struct mfs_sb_info {
-	uint32_t ninodes;
-	uint32_t nzones;
-	unsigned long ibmap_blocks;
-	unsigned long zbmap_blocks;
-	unsigned long firstdatazone;
-	int log2_zone_size;
-	int block_size;
-	uint32_t max_file_size;
-	uint16_t magic;
-	uint16_t state;
-
-	/*The following fields do not exist on disk but only in memory*/
-	unsigned long itable_size;
-	mfs_version_t fs_version;
-	int ino_per_block;
-	size_t dirsize;
-	int itable_off;
-	unsigned max_name_len;
-	bool long_names;
-	bool native;
-	unsigned isearch;
-	unsigned zsearch;
-};
-
-/*Generic MinixFS inode*/
-struct mfs_ino_info {
-	uint16_t	i_mode;
-	uint16_t	i_nlinks;
-	int16_t		i_uid;
-	uint16_t	i_gid;
-	size_t		i_size;
-	int32_t		i_atime;
-	int32_t		i_mtime;
-	int32_t		i_ctime;
-	/*Block numbers for direct zones*/
-	uint32_t	i_dzone[V2_NR_DIRECT_ZONES];
-	/*Block numbers for indirect zones*/
-	uint32_t	i_izone[V2_NR_INDIRECT_ZONES];
-
-	/*The following fields do not exist on disk but only in memory*/
-	bool dirty;
-	fs_index_t index;
-};
-
-/*Generic MFS directory entry*/
-struct mfs_dentry_info {
-	uint32_t d_inum;
-	char d_name[MFS3_MAX_NAME_LEN + 1];
-
-	/*The following fields do not exist on disk but only in memory*/
-
-	/*Index of the dentry in the list*/
-	unsigned index;
-	/*Pointer to the node at witch the dentry belongs*/
-	struct mfs_node *node;
-};
-
-struct mfs_instance {
-	link_t link;
-	service_id_t service_id;
-	struct mfs_sb_info *sbi;
-	unsigned open_nodes_cnt;
-};
-
-/*MinixFS node in core*/
-struct mfs_node {
-	struct mfs_ino_info *ino_i;
-	struct mfs_instance *instance;
-	unsigned refcnt;
-	fs_node_t *fsnode;
-	link_t link;
-};
-
-/*mfs_ops.c*/
-extern vfs_out_ops_t mfs_ops;
-extern libfs_ops_t mfs_libfs_ops;
-
-extern int
-mfs_global_init(void);
-
-/*mfs_inode.c*/
-extern int
-mfs_get_inode(struct mfs_instance *inst, struct mfs_ino_info **ino_i,
-	  fs_index_t index);
-
-extern int
-mfs_put_inode_core(struct mfs_node *mnode);
-
-extern int
-mfs_inode_shrink(struct mfs_node *mnode, size_t size_shrink);
-
-/*mfs_rw.c*/
-extern int
-mfs_read_map(uint32_t *b, const struct mfs_node *mnode, const uint32_t pos);
-
-extern int
-mfs_write_map(struct mfs_node *mnode, uint32_t pos, uint32_t new_zone,
-	  uint32_t *old_zone);
-
-extern int
-mfs_prune_ind_zones(struct mfs_node *mnode, size_t new_size);
-
-/*mfs_dentry.c*/
-extern int
-mfs_read_dentry(struct mfs_node *mnode,
-		     struct mfs_dentry_info *d_info, unsigned index);
-
-extern int
-mfs_write_dentry(struct mfs_dentry_info *d_info);
-
-extern int
-mfs_remove_dentry(struct mfs_node *mnode, const char *d_name);
-
-extern int
-mfs_insert_dentry(struct mfs_node *mnode, const char *d_name, fs_index_t d_inum);
-
-/*mfs_balloc.c*/
-extern int
-mfs_alloc_inode(struct mfs_instance *inst, uint32_t *inum);
-
-extern int
-mfs_free_inode(struct mfs_instance *inst, uint32_t inum);
-
-extern int
-mfs_alloc_zone(struct mfs_instance *inst, uint32_t *zone);
-
-extern int
-mfs_free_zone(struct mfs_instance *inst, uint32_t zone);
-
-/*mfs_utils.c*/
-extern uint16_t
-conv16(bool native, uint16_t n);
-
-extern uint32_t
-conv32(bool native, uint32_t n);
-
-extern uint64_t
-conv64(bool native, uint64_t n);
-
-#endif
-
-/**
- * @}
- */
-
Index: uspace/srv/fs/minixfs/mfs_balloc.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_balloc.c	(revision 9a0be341d462b5cb93242f88efe36f9ed4f4eb6d)
+++ 	(revision )
@@ -1,298 +1,0 @@
-/*
- * Copyright (c) 2011 Maurizio Lombardi
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup fs
- * @{
- */
-
-#include <stdlib.h>
-#include "mfs.h"
-
-static int
-find_free_bit_and_set(bitchunk_t *b, const int bsize,
-		      const bool native, unsigned start_bit);
-
-static int
-mfs_free_bit(struct mfs_instance *inst, uint32_t idx, bmap_id_t bid);
-
-static int
-mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid);
-
-/**Allocate a new inode.
- *
- * @param inst		Pointer to the filesystem instance.
- * @param inum		Pointer to a 32 bit number where the index of
- * 			the new inode will be saved.
- *
- * @return		EOK on success or a negative error code.
- */
-int
-mfs_alloc_inode(struct mfs_instance *inst, uint32_t *inum)
-{
-	int r = mfs_alloc_bit(inst, inum, BMAP_INODE);
-	return r;
-}
-
-/**Free an inode.
- *
- * @param inst		Pointer to the filesystem instance.
- * @param inum		Number of the inode to free.
- *
- * @return		EOK on success or a negative error code.
- */
-int
-mfs_free_inode(struct mfs_instance *inst, uint32_t inum)
-{
-	return mfs_free_bit(inst, inum, BMAP_INODE);
-}
-
-/**Allocate a new zone.
- *
- * @param inst		Pointer to the filesystem instance.
- * @param zone		Pointer to a 32 bit number where the index
- * 			of the zone will be saved.
- *
- * @return		EOK on success or a negative error code.
- */
-int
-mfs_alloc_zone(struct mfs_instance *inst, uint32_t *zone)
-{
-	int r = mfs_alloc_bit(inst, zone, BMAP_ZONE);
-
-	*zone += inst->sbi->firstdatazone - 1;
-	return r;
-}
-
-/**Free a zone.
- *
- * @param inst		Pointer to the filesystem instance.
- * @param zone		Index of the zone to free.
- *
- * @return		EOK on success or a negative error code.
- */
-int
-mfs_free_zone(struct mfs_instance *inst, uint32_t zone)
-{
-	zone -= inst->sbi->firstdatazone - 1;
-
-	return mfs_free_bit(inst, zone, BMAP_ZONE);
-}
-
-/**Clear a bit in a bitmap.
- *
- * @param inst		Pointer to the filesystem instance.
- * @param idx		Index of the bit to clear.
- * @param bid		BMAP_ZONE if operating on the zone's bitmap,
- * 			BMAP_INODE if operating on the inode's bitmap.
- *
- * @return		EOK on success or a negative error code.
- */
-static int
-mfs_free_bit(struct mfs_instance *inst, uint32_t idx, bmap_id_t bid)
-{
-	struct mfs_sb_info *sbi;
-	int r;
-	unsigned start_block;
-	unsigned *search;
-	block_t *b;
-
-	assert(inst != NULL);
-	sbi = inst->sbi;
-	assert(sbi != NULL);
-
-	if (bid == BMAP_ZONE) {
-		search = &sbi->zsearch;
-		start_block = 2 + sbi->ibmap_blocks;
-		if (idx > sbi->nzones) {
-			printf(NAME ": Error! Trying to free beyond the" \
-			       "bitmap max size\n");
-			return -1;
-		}
-	} else {
-		/*bid == BMAP_INODE*/
-		search = &sbi->isearch;
-		start_block = 2;
-		if (idx > sbi->ninodes) {
-			printf(NAME ": Error! Trying to free beyond the" \
-			       "bitmap max size\n");
-			return -1;
-		}
-	}
-
-	/*Compute the bitmap block*/
-	uint32_t block = idx / (sbi->block_size * 8) + start_block;
-
-	r = block_get(&b, inst->service_id, block, BLOCK_FLAGS_NONE);
-	if (r != EOK)
-		goto out_err;
-
-	/*Compute the bit index in the block*/
-	idx %= (sbi->block_size * 8);
-	bitchunk_t *ptr = b->data;
-	bitchunk_t chunk;
-	const size_t chunk_bits = sizeof(bitchunk_t) * 8;
-
-	chunk = conv32(sbi->native, ptr[idx / chunk_bits]);
-	chunk &= ~(1 << (idx % chunk_bits));
-	ptr[idx / chunk_bits] = conv32(sbi->native, chunk);
-
-	b->dirty = true;
-	r = block_put(b);
-
-	if (*search > idx)
-		*search = idx;
-
-out_err:
-	return r;
-}
-
-/**Search a free bit in a bitmap and mark it as used.
- *
- * @param inst		Pointer to the filesystem instance.
- * @param idx		Pointer of a 32 bit number where the index
- * 			of the found bit will be stored.
- * @param bid		BMAP_ZONE if operating on the zone's bitmap,
- * 			BMAP_INODE if operating on the inode's bitmap.
- *
- * @return		EOK on success or a negative error code.
- */
-static int
-mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid)
-{
-	struct mfs_sb_info *sbi;
-	uint32_t limit;
-	unsigned long nblocks;
-	unsigned *search, i, start_block;
-	unsigned bits_per_block;
-	int r, freebit;
-
-	assert(inst != NULL);
-	sbi = inst->sbi;
-	assert(sbi != NULL);
-
-	if (bid == BMAP_ZONE) {
-		search = &sbi->zsearch;
-		start_block = 2 + sbi->ibmap_blocks;
-		nblocks = sbi->zbmap_blocks;
-		limit = sbi->nzones - sbi->firstdatazone - 1;
-	} else {
-		/*bid == BMAP_INODE*/
-		search = &sbi->isearch;
-		start_block = 2;
-		nblocks = sbi->ibmap_blocks;
-		limit = sbi->ninodes;
-	}
-	bits_per_block = sbi->block_size * 8;
-
-	block_t *b;
-
-retry:
-
-	for (i = *search / bits_per_block; i < nblocks; ++i) {
-		r = block_get(&b, inst->service_id, i + start_block,
-			      BLOCK_FLAGS_NONE);
-
-		if (r != EOK)
-			goto out;
-
-		unsigned tmp = *search % bits_per_block;
-
-		freebit = find_free_bit_and_set(b->data, sbi->block_size,
-						sbi->native, tmp);
-		if (freebit == -1) {
-			/*No free bit in this block*/
-			r = block_put(b);
-			if (r != EOK)
-				goto out;
-			continue;
-		}
-
-		/*Free bit found in this block, compute the real index*/
-		*idx = freebit + bits_per_block * i;
-		if (*idx > limit) {
-			/*Index is beyond the limit, it is invalid*/
-			r = block_put(b);
-			if (r != EOK)
-				goto out;
-			break;
-		}
-
-		*search = *idx;
-		b->dirty = true;
-		r = block_put(b);
-		goto out;
-	}
-
-	if (*search > 0) {
-		/*Repeat the search from the first bitmap block*/
-		*search = 0;
-		goto retry;
-	}
-
-	/*Free bit not found, return error*/
-	return ENOSPC;
-
-out:
-	return r;
-}
-
-static int
-find_free_bit_and_set(bitchunk_t *b, const int bsize,
-		      const bool native, unsigned start_bit)
-{
-	int r = -1;
-	unsigned i, j;
-	bitchunk_t chunk;
-	const size_t chunk_bits = sizeof(bitchunk_t) * 8;
-
-	for (i = start_bit / chunk_bits;
-	     i < bsize / sizeof(bitchunk_t); ++i) {
-		if (!(~b[i])) {
-			/*No free bit in this chunk*/
-			continue;
-		}
-
-		chunk = conv32(native, b[i]);
-
-		for (j = 0; j < chunk_bits; ++j) {
-			if (!(chunk & (1 << j))) {
-				r = i * chunk_bits + j;
-				chunk |= 1 << j;
-				b[i] = conv32(native, chunk);
-				goto found;
-			}
-		}
-	}
-found:
-	return r;
-}
-
-/**
- * @}
- */
-
Index: uspace/srv/fs/minixfs/mfs_dentry.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_dentry.c	(revision 9a0be341d462b5cb93242f88efe36f9ed4f4eb6d)
+++ 	(revision )
@@ -1,262 +1,0 @@
-/*
- * Copyright (c) 2011 Maurizio Lombardi
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup fs
- * @{
- */
-
-#include "mfs.h"
-
-/**Read a directory entry from disk.
- *
- * @param mnode		Pointer to the directory node.
- * @param d_info	Pointer to a directory entry structure where the dentry info
- *			will be stored.
- * @param index		index of the dentry in the list.
- *
- * @return		EOK on success or a negative error code.
- */
-int
-mfs_read_dentry(struct mfs_node *mnode,
-		     struct mfs_dentry_info *d_info, unsigned index)
-{
-	const struct mfs_instance *inst = mnode->instance;
-	const struct mfs_sb_info *sbi = inst->sbi;
-	const bool longnames = sbi->long_names;
-	uint32_t block;
-	block_t *b;
-
-	int r = mfs_read_map(&block, mnode, index * sbi->dirsize);
-	if (r != EOK)
-		goto out_err;
-
-	if (block == 0) {
-		/*End of the dentries list*/
-		r = EOK;
-		goto out_err;
-	}
-
-	r = block_get(&b, inst->service_id, block, BLOCK_FLAGS_NONE);
-	if (r != EOK)
-		goto out_err;
-
-	unsigned dentries_per_zone = sbi->block_size / sbi->dirsize;
-	unsigned dentry_off = index % dentries_per_zone;
-
-	if (sbi->fs_version == MFS_VERSION_V3) {
-		struct mfs3_dentry *d3;
-
-		d3 = b->data + (dentry_off * MFS3_DIRSIZE);
-
-		d_info->d_inum = conv32(sbi->native, d3->d_inum);
-		memcpy(d_info->d_name, d3->d_name, MFS3_MAX_NAME_LEN);
-	} else {
-		const int namelen = longnames ? MFS_L_MAX_NAME_LEN :
-				    MFS_MAX_NAME_LEN;
-
-		struct mfs_dentry *d;
-
-		d = b->data + dentry_off * (longnames ? MFSL_DIRSIZE :
-					    MFS_DIRSIZE);
-		d_info->d_inum = conv16(sbi->native, d->d_inum);
-		memcpy(d_info->d_name, d->d_name, namelen);
-	}
-
-	r = block_put(b);
-
-	d_info->index = index;
-	d_info->node = mnode;
-
-out_err:
-	return r;
-}
-
-/**Write a directory entry on disk.
- *
- * @param d_info	Pointer to the directory entry structure to write on disk.
- *
- * @return		EOK on success or a negative error code.
- */
-int
-mfs_write_dentry(struct mfs_dentry_info *d_info)
-{
-	struct mfs_node *mnode = d_info->node;
-	struct mfs_sb_info *sbi = mnode->instance->sbi;
-	const unsigned d_off_bytes = d_info->index * sbi->dirsize;
-	const unsigned dirs_per_block = sbi->block_size / sbi->dirsize;
-	block_t *b;
-	uint32_t block;
-	int r;
-
-	r = mfs_read_map(&block, mnode, d_off_bytes);
-	if (r != EOK)
-		goto out;
-
-	r = block_get(&b, mnode->instance->service_id, block, BLOCK_FLAGS_NONE);
-	if (r != EOK)
-		goto out;
-
-	const size_t name_len = sbi->max_name_len;
-	uint8_t *ptr = b->data;
-	ptr += (d_info->index % dirs_per_block) * sbi->dirsize;
-
-	if (sbi->fs_version == MFS_VERSION_V3) {
-		struct mfs3_dentry *dentry;
-		dentry = (struct mfs3_dentry *) ptr;
-
-		dentry->d_inum = conv32(sbi->native, d_info->d_inum);
-		memcpy(dentry->d_name, d_info->d_name, name_len);
-	} else {
-		struct mfs_dentry *dentry;
-		dentry = (struct mfs_dentry *) ptr;
-
-		dentry->d_inum = conv16(sbi->native, d_info->d_inum);
-		memcpy(dentry->d_name, d_info->d_name, name_len);
-	}
-
-	b->dirty = true;
-	r = block_put(b);
-
-out:
-	return r;
-}
-
-/**Remove a directory entry from a directory.
- *
- * @param mnode		Pointer to the directory node.
- * @param d_name	Name of the directory entry to delete.
- *
- * @return		EOK on success or a negative error code.
- */
-int
-mfs_remove_dentry(struct mfs_node *mnode, const char *d_name)
-{
-	struct mfs_sb_info *sbi = mnode->instance->sbi;
-	struct mfs_dentry_info d_info;
-	int r;
-
-	const size_t name_len = str_size(d_name);
-
-	if (name_len > sbi->max_name_len)
-		return ENAMETOOLONG;
-
-	/*Search the directory entry to be removed*/
-	unsigned i;
-	for (i = 0; i < mnode->ino_i->i_size / sbi->dirsize ; ++i) {
-		r = mfs_read_dentry(mnode, &d_info, i);
-		if (r != EOK)
-			return r;
-
-		const size_t d_name_len = str_size(d_info.d_name);
-
-		if (name_len == d_name_len &&
-				!bcmp(d_info.d_name, d_name, name_len)) {
-			d_info.d_inum = 0;
-			r = mfs_write_dentry(&d_info);
-			return r;
-		}
-	}
-
-	return ENOENT;
-}
-
-/**Insert a new directory entry in a existing directory.
- *
- * @param mnode		Pointer to the directory node.
- * @param d_name	Name of the new directory entry.
- * @param d_inum	index of the inode that will be pointed by the new dentry.
- *
- * @return		EOK on success or a negative error code.
- */
-int
-mfs_insert_dentry(struct mfs_node *mnode, const char *d_name, fs_index_t d_inum)
-{
-	int r;
-	struct mfs_sb_info *sbi = mnode->instance->sbi;
-	struct mfs_dentry_info d_info;
-	bool empty_dentry_found = false;
-
-	const size_t name_len = str_size(d_name);
-
-	if (name_len > sbi->max_name_len)
-		return ENAMETOOLONG;
-
-	/*Search for an empty dentry*/
-	unsigned i;
-	for (i = 0; i < mnode->ino_i->i_size / sbi->dirsize; ++i) {
-		r = mfs_read_dentry(mnode, &d_info, i);
-		if (r != EOK)
-			return r;
-
-		if (d_info.d_inum == 0) {
-			/*This entry is not used*/
-			empty_dentry_found = true;
-			break;
-		}
-	}
-
-	if (!empty_dentry_found) {
-		uint32_t b, pos;
-		pos = mnode->ino_i->i_size;
-		r = mfs_read_map(&b, mnode, pos);
-		if (r != EOK)
-			goto out;
-
-		if (b == 0) {
-			/*Increase the inode size*/
-
-			uint32_t dummy;
-			r = mfs_alloc_zone(mnode->instance, &b);
-			if (r != EOK)
-				goto out;
-			r = mfs_write_map(mnode, pos, b, &dummy);
-			if (r != EOK)
-				goto out;
-		}
-
-		mnode->ino_i->i_size += sbi->dirsize;
-		mnode->ino_i->dirty = true;
-
-		d_info.index = i;
-		d_info.node = mnode;
-	}
-
-	d_info.d_inum = d_inum;
-	memcpy(d_info.d_name, d_name, name_len);
-	d_info.d_name[name_len] = 0;
-
-	r = mfs_write_dentry(&d_info);
-out:
-	return r;
-}
-
-
-/**
- * @}
- */
-
Index: uspace/srv/fs/minixfs/mfs_inode.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_inode.c	(revision 9a0be341d462b5cb93242f88efe36f9ed4f4eb6d)
+++ 	(revision )
@@ -1,360 +1,0 @@
-/*
- * Copyright (c) 2011 Maurizio Lombardi
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup fs
- * @{
- */
-
-#include <stdlib.h>
-#include "mfs.h"
-
-static int
-mfs_write_inode_raw(struct mfs_node *mnode);
-
-static int
-mfs2_write_inode_raw(struct mfs_node *mnode);
-
-static int
-mfs_read_inode_raw(const struct mfs_instance *instance,
-		struct mfs_ino_info **ino_ptr, uint16_t inum);
-
-static int
-mfs2_read_inode_raw(const struct mfs_instance *instance,
-		struct mfs_ino_info **ino_ptr, uint32_t inum);
-
-
-int
-mfs_get_inode(struct mfs_instance *inst, struct mfs_ino_info **ino_i,
-	  fs_index_t index)
-{
-	struct mfs_sb_info *sbi = inst->sbi;
-	int r;
-
-	if (sbi->fs_version == MFS_VERSION_V1) {
-		/*Read a MFS V1 inode*/
-		r = mfs_read_inode_raw(inst, ino_i, index);
-	} else {
-		/*Read a MFS V2/V3 inode*/
-		r = mfs2_read_inode_raw(inst, ino_i, index);
-	}
-
-	return r;
-}
-
-static int
-mfs_read_inode_raw(const struct mfs_instance *instance,
-		struct mfs_ino_info **ino_ptr, uint16_t inum) {
-	struct mfs_inode *ino;
-	struct mfs_ino_info *ino_i = NULL;
-	struct mfs_sb_info *sbi;
-	block_t *b;
-	int i, r;
-
-	sbi = instance->sbi;
-	assert(sbi);
-
-	/*inode 0 does not exist*/
-	inum -= 1;
-
-	const int ino_off = inum % sbi->ino_per_block;
-
-	ino_i = malloc(sizeof(*ino_i));
-
-	if (!ino_i) {
-		r = ENOMEM;
-		goto out_err;
-	}
-
-	const int itable_off = sbi->itable_off;
-
-	r = block_get(&b, instance->service_id,
-		      itable_off + inum / sbi->ino_per_block,
-		      BLOCK_FLAGS_NONE);
-	if (r != EOK)
-		goto out_err;
-
-	ino = b->data + ino_off * sizeof(struct mfs_inode);
-
-	ino_i->i_mode = conv16(sbi->native, ino->i_mode);
-	ino_i->i_uid = conv16(sbi->native, ino->i_uid);
-	ino_i->i_size = conv32(sbi->native, ino->i_size);
-	ino_i->i_mtime = conv32(sbi->native, ino->i_mtime);
-	ino_i->i_nlinks = ino->i_nlinks;
-
-	for (i = 0; i < V1_NR_DIRECT_ZONES; ++i)
-		ino_i->i_dzone[i] = conv16(sbi->native, ino->i_dzone[i]);
-
-	for (i = 0; i < V1_NR_INDIRECT_ZONES; ++i)
-		ino_i->i_izone[i] = conv16(sbi->native, ino->i_izone[i]);
-
-	r = block_put(b);
-	ino_i->dirty = false;
-	*ino_ptr = ino_i;
-
-	return r;
-
-out_err:
-	if (ino_i)
-		free(ino_i);
-	return EOK;
-}
-
-static int
-mfs2_read_inode_raw(const struct mfs_instance *instance,
-		struct mfs_ino_info **ino_ptr, uint32_t inum) {
-	struct mfs2_inode *ino;
-	struct mfs_ino_info *ino_i = NULL;
-	struct mfs_sb_info *sbi;
-	block_t *b;
-	int i, r;
-
-	ino_i = malloc(sizeof(*ino_i));
-
-	if (!ino_i) {
-		r = ENOMEM;
-		goto out_err;
-	}
-
-	sbi = instance->sbi;
-	assert(sbi);
-
-	/*inode 0 does not exist*/
-	inum -= 1;
-
-	const int itable_off = sbi->itable_off;
-	const int ino_off = inum % sbi->ino_per_block;
-
-	r = block_get(&b, instance->service_id,
-		      itable_off + inum / sbi->ino_per_block,
-		      BLOCK_FLAGS_NONE);
-	if (r != EOK)
-		goto out_err;
-
-	ino = b->data + ino_off * sizeof(struct mfs2_inode);
-
-	ino_i->i_mode = conv16(sbi->native, ino->i_mode);
-	ino_i->i_nlinks = conv16(sbi->native, ino->i_nlinks);
-	ino_i->i_uid = conv16(sbi->native, ino->i_uid);
-	ino_i->i_gid = conv16(sbi->native, ino->i_gid);
-	ino_i->i_size = conv32(sbi->native, ino->i_size);
-	ino_i->i_atime = conv32(sbi->native, ino->i_atime);
-	ino_i->i_mtime = conv32(sbi->native, ino->i_mtime);
-	ino_i->i_ctime = conv32(sbi->native, ino->i_ctime);
-
-	for (i = 0; i < V2_NR_DIRECT_ZONES; ++i)
-		ino_i->i_dzone[i] = conv32(sbi->native, ino->i_dzone[i]);
-
-	for (i = 0; i < V2_NR_INDIRECT_ZONES; ++i)
-		ino_i->i_izone[i] = conv32(sbi->native, ino->i_izone[i]);
-
-	r = block_put(b);
-	ino_i->dirty = false;
-	*ino_ptr = ino_i;
-
-	return r;
-
-out_err:
-	if (ino_i)
-		free(ino_i);
-	return EOK;
-}
-
-int
-mfs_put_inode_core(struct mfs_node *mnode)
-{
-	int rc = EOK;
-
-	assert(mnode);
-	assert(mnode->ino_i);
-
-	if (!mnode->ino_i->dirty)
-		goto out;
-
-	struct mfs_instance *inst = mnode->instance;
-	assert(inst);
-	struct mfs_sb_info *sbi = inst->sbi;
-	assert(sbi);
-
-	if (sbi->fs_version == MFS_VERSION_V1)
-		rc = mfs_write_inode_raw(mnode);
-	else
-		rc = mfs2_write_inode_raw(mnode);
-
-out:
-	return rc;
-}
-
-static int
-mfs_write_inode_raw(struct mfs_node *mnode)
-{
-	int i, r;
-	block_t *b;
-	struct mfs_ino_info *ino_i = mnode->ino_i;
-	struct mfs_sb_info *sbi = mnode->instance->sbi;
-
-	const uint32_t inum = ino_i->index - 1;
-	const int itable_off = sbi->itable_off;
-	const int ino_off = inum % sbi->ino_per_block;
-	const bool native = sbi->native;
-
-	r = block_get(&b, mnode->instance->service_id,
-		      itable_off + inum / sbi->ino_per_block,
-		      BLOCK_FLAGS_NONE);
-
-	if (r != EOK)
-		goto out;
-
-	struct mfs_inode *ino = b->data;
-	ino += ino_off;
-
-	ino->i_mode = conv16(native, ino_i->i_mode);
-	ino->i_uid = conv16(native, ino_i->i_uid);
-	ino->i_gid = ino_i->i_gid;
-	ino->i_nlinks = ino_i->i_nlinks;
-	ino->i_size = conv32(native, ino_i->i_size);
-	ino->i_mtime = conv32(native, ino_i->i_mtime);
-
-	for (i = 0; i < V1_NR_DIRECT_ZONES; ++i)
-		ino->i_dzone[i] = conv16(native, ino_i->i_dzone[i]);
-	for (i = 0; i < V1_NR_INDIRECT_ZONES; ++i)
-		ino->i_izone[i] = conv16(native, ino_i->i_izone[i]);
-
-	b->dirty = true;
-	r = block_put(b);
-
-	ino_i->dirty = false;
-out:
-	return r;
-}
-
-static int
-mfs2_write_inode_raw(struct mfs_node *mnode)
-{
-	struct mfs_ino_info *ino_i = mnode->ino_i;
-	struct mfs_sb_info *sbi = mnode->instance->sbi;
-	block_t *b;
-	int i, r;
-
-	const uint32_t inum = ino_i->index - 1;
-	const int itable_off = sbi->itable_off;
-	const int ino_off = inum % sbi->ino_per_block;
-	const bool native = sbi->native;
-
-	r = block_get(&b, mnode->instance->service_id,
-		      itable_off + inum / sbi->ino_per_block,
-		      BLOCK_FLAGS_NONE);
-
-	if (r != EOK)
-		goto out;
-
-	struct mfs2_inode *ino2 = b->data;
-	ino2 += ino_off;
-
-	ino2->i_mode = conv16(native, ino_i->i_mode);
-	ino2->i_nlinks = conv16(native, ino_i->i_nlinks);
-	ino2->i_uid = conv16(native, ino_i->i_uid);
-	ino2->i_gid = conv16(native, ino_i->i_gid);
-	ino2->i_size = conv32(native, ino_i->i_size);
-	ino2->i_atime = conv32(native, ino_i->i_atime);
-	ino2->i_mtime = conv32(native, ino_i->i_mtime);
-	ino2->i_ctime = conv32(native, ino_i->i_ctime);
-
-	for (i = 0; i < V2_NR_DIRECT_ZONES; ++i)
-		ino2->i_dzone[i] = conv32(native, ino_i->i_dzone[i]);
-
-	for (i = 0; i < V2_NR_INDIRECT_ZONES; ++i)
-		ino2->i_izone[i] = conv32(native, ino_i->i_izone[i]);
-
-	b->dirty = true;
-	r = block_put(b);
-	ino_i->dirty = false;
-
-out:
-	return r;
-}
-
-int
-mfs_inode_shrink(struct mfs_node *mnode, size_t size_shrink)
-{
-	struct mfs_sb_info *sbi = mnode->instance->sbi;
-	struct mfs_ino_info *ino_i = mnode->ino_i;
-	const size_t bs = sbi->block_size;
-	int r;
-
-	if (size_shrink == 0) {
-		/*File is empty*/
-		return EOK;
-	}
-
-	const size_t old_size = ino_i->i_size;
-	const size_t new_size = ino_i->i_size - size_shrink;
-
-	assert(size_shrink <= old_size);
-
-	ino_i->dirty = true;
-
-	/*Compute the number of zones to free*/
-	unsigned zones_to_free;
-
-	size_t diff = old_size - new_size;
-	zones_to_free = diff / bs;
-
-	if (diff % bs != 0)
-		zones_to_free++;
-
-	uint32_t pos = old_size - 1;
-	unsigned i;
-	for (i = 0; i < zones_to_free; ++i, pos -= bs) {
-		uint32_t old_zone;
-
-		r = mfs_write_map(mnode, pos, 0, &old_zone);
-		if (r != EOK)
-			goto exit_error;
-
-		ino_i->i_size -= bs;
-
-		if (old_zone == 0)
-			continue; /*Sparse block*/
-
-		r = mfs_free_zone(mnode->instance, old_zone);
-		if (r != EOK)
-			goto exit_error;
-	}
-
-	ino_i->i_size = new_size;
-
-	return mfs_prune_ind_zones(mnode, new_size);
-
-exit_error:
-	return r;
-}
-
-/**
- * @}
- */
-
Index: uspace/srv/fs/minixfs/mfs_ops.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_ops.c	(revision 9a0be341d462b5cb93242f88efe36f9ed4f4eb6d)
+++ 	(revision )
@@ -1,1112 +1,0 @@
-/*
- * Copyright (c) 2011 Maurizio Lombardi
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup fs
- * @{
- */
-
-#include <stdlib.h>
-#include <fibril_synch.h>
-#include <align.h>
-#include <adt/hash_table.h>
-#include "mfs.h"
-
-#define OPEN_NODES_KEYS 2
-#define OPEN_NODES_SERVICE_KEY 0
-#define OPEN_NODES_INODE_KEY 1
-#define OPEN_NODES_BUCKETS 256
-
-static bool check_magic_number(uint16_t magic, bool *native,
-			       mfs_version_t *version, bool *longfilenames);
-static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
-			     fs_index_t index);
-
-static int mfs_node_put(fs_node_t *fsnode);
-static int mfs_node_open(fs_node_t *fsnode);
-static fs_index_t mfs_index_get(fs_node_t *fsnode);
-static unsigned mfs_lnkcnt_get(fs_node_t *fsnode);
-static bool mfs_is_directory(fs_node_t *fsnode);
-static bool mfs_is_file(fs_node_t *fsnode);
-static int mfs_has_children(bool *has_children, fs_node_t *fsnode);
-static int mfs_root_get(fs_node_t **rfn, service_id_t service_id);
-static service_id_t mfs_device_get(fs_node_t *fsnode);
-static aoff64_t mfs_size_get(fs_node_t *node);
-static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component);
-static int mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags);
-static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name);
-static int mfs_unlink(fs_node_t *, fs_node_t *, const char *name);
-static int mfs_destroy_node(fs_node_t *fn);
-static hash_index_t open_nodes_hash(unsigned long key[]);
-static int open_nodes_compare(unsigned long key[], hash_count_t keys,
-		link_t *item);
-static void open_nodes_remove_cb(link_t *link);
-
-static int mfs_node_get(fs_node_t **rfn, service_id_t service_id,
-			fs_index_t index);
-static int
-mfs_instance_get(service_id_t service_id, struct mfs_instance **instance);
-
-
-static LIST_INITIALIZE(inst_list);
-static FIBRIL_MUTEX_INITIALIZE(inst_list_mutex);
-static hash_table_t open_nodes;
-static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock);
-
-libfs_ops_t mfs_libfs_ops = {
-	.size_get = mfs_size_get,
-	.root_get = mfs_root_get,
-	.device_get = mfs_device_get,
-	.is_directory = mfs_is_directory,
-	.is_file = mfs_is_file,
-	.node_get = mfs_node_get,
-	.node_put = mfs_node_put,
-	.node_open = mfs_node_open,
-	.index_get = mfs_index_get,
-	.match = mfs_match,
-	.create = mfs_create_node,
-	.link = mfs_link,
-	.unlink = mfs_unlink,
-	.destroy = mfs_destroy_node,
-	.has_children = mfs_has_children,
-	.lnkcnt_get = mfs_lnkcnt_get
-};
-
-/* Hash table interface for open nodes hash table */
-static hash_index_t open_nodes_hash(unsigned long key[])
-{
-	/* TODO: This is very simple and probably can be improved */
-	return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS;
-}
-
-static int open_nodes_compare(unsigned long key[], hash_count_t keys,
-		link_t *item)
-{
-	struct mfs_node *mnode = hash_table_get_instance(item, struct mfs_node, link);
-	assert(keys > 0);
-	if (mnode->instance->service_id !=
-	    ((service_id_t) key[OPEN_NODES_SERVICE_KEY])) {
-		return false;
-	}
-	if (keys == 1) {
-		return true;
-	}
-	assert(keys == 2);
-	return (mnode->ino_i->index == key[OPEN_NODES_INODE_KEY]);
-}
-
-static void open_nodes_remove_cb(link_t *link)
-{
-	/* We don't use remove callback for this hash table */
-}
-
-static hash_table_operations_t open_nodes_ops = {
-	.hash = open_nodes_hash,
-	.compare = open_nodes_compare,
-	.remove_callback = open_nodes_remove_cb,
-};
-
-int mfs_global_init(void)
-{
-	if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
-			OPEN_NODES_KEYS, &open_nodes_ops)) {
-		return ENOMEM;
-	}
-	return EOK;
-}
-
-static int
-mfs_mounted(service_id_t service_id, const char *opts, fs_index_t *index,
-		aoff64_t *size, unsigned *linkcnt)
-{
-	enum cache_mode cmode;
-	struct mfs_superblock *sb;
-	struct mfs3_superblock *sb3;
-	struct mfs_sb_info *sbi;
-	struct mfs_instance *instance;
-	bool native, longnames;
-	mfs_version_t version;
-	uint16_t magic;
-	int rc;
-
-	/* Check for option enabling write through. */
-	if (str_cmp(opts, "wtcache") == 0)
-		cmode = CACHE_MODE_WT;
-	else
-		cmode = CACHE_MODE_WB;
-
-	/* initialize libblock */
-	rc = block_init(EXCHANGE_SERIALIZE, service_id, 4096);
-	if (rc != EOK)
-		return rc;
-
-	/*Allocate space for generic MFS superblock*/
-	sbi = malloc(sizeof(*sbi));
-	if (!sbi) {
-		block_fini(service_id);
-		return ENOMEM;
-	}
-
-	/*Allocate space for filesystem instance*/
-	instance = malloc(sizeof(*instance));
-	if (!instance) {
-		free(sbi);
-		block_fini(service_id);
-		return ENOMEM;
-	}
-
-	instance->open_nodes_cnt = 0;
-
-	sb = malloc(MFS_SUPERBLOCK_SIZE);
-	if (!sb) {
-		free(instance);
-		free(sbi);
-		block_fini(service_id);
-		return ENOMEM;
-	}
-
-	/* Read the superblock */
-	rc = block_read_direct(service_id, MFS_SUPERBLOCK << 1, 2, sb);
-	if (rc != EOK) {
-		free(instance);
-		free(sbi);
-		free(sb);
-		block_fini(service_id);
-		return rc;
-	}
-
-	sb3 = (struct mfs3_superblock *) sb;
-
-	if (check_magic_number(sb->s_magic, &native, &version, &longnames)) {
-		/*This is a V1 or V2 Minix filesystem*/
-		magic = sb->s_magic;
-	} else if (check_magic_number(sb3->s_magic, &native, &version, &longnames)) {
-		/*This is a V3 Minix filesystem*/
-		magic = sb3->s_magic;
-	} else {
-		/*Not recognized*/
-		mfsdebug("magic number not recognized\n");
-		free(instance);
-		free(sbi);
-		free(sb);
-		block_fini(service_id);
-		return ENOTSUP;
-	}
-
-	mfsdebug("magic number recognized = %04x\n", magic);
-
-	/*Fill superblock info structure*/
-
-	sbi->fs_version = version;
-	sbi->long_names = longnames;
-	sbi->native = native;
-	sbi->magic = magic;
-	sbi->isearch = 0;
-	sbi->zsearch = 0;
-
-	if (version == MFS_VERSION_V3) {
-		sbi->ninodes = conv32(native, sb3->s_ninodes);
-		sbi->ibmap_blocks = conv16(native, sb3->s_ibmap_blocks);
-		sbi->zbmap_blocks = conv16(native, sb3->s_zbmap_blocks);
-		sbi->firstdatazone = conv16(native, sb3->s_first_data_zone);
-		sbi->log2_zone_size = conv16(native, sb3->s_log2_zone_size);
-		sbi->max_file_size = conv32(native, sb3->s_max_file_size);
-		sbi->nzones = conv32(native, sb3->s_nzones);
-		sbi->block_size = conv16(native, sb3->s_block_size);
-		sbi->ino_per_block = V3_INODES_PER_BLOCK(sbi->block_size);
-		sbi->dirsize = MFS3_DIRSIZE;
-		sbi->max_name_len = MFS3_MAX_NAME_LEN;
-	} else {
-		sbi->ninodes = conv16(native, sb->s_ninodes);
-		sbi->ibmap_blocks = conv16(native, sb->s_ibmap_blocks);
-		sbi->zbmap_blocks = conv16(native, sb->s_zbmap_blocks);
-		sbi->firstdatazone = conv16(native, sb->s_first_data_zone);
-		sbi->log2_zone_size = conv16(native, sb->s_log2_zone_size);
-		sbi->max_file_size = conv32(native, sb->s_max_file_size);
-		sbi->block_size = MFS_BLOCKSIZE;
-		if (version == MFS_VERSION_V2) {
-			sbi->nzones = conv32(native, sb->s_nzones2);
-			sbi->ino_per_block = V2_INODES_PER_BLOCK;
-		} else {
-			sbi->nzones = conv16(native, sb->s_nzones);
-			sbi->ino_per_block = V1_INODES_PER_BLOCK;
-		}
-		sbi->dirsize = longnames ? MFSL_DIRSIZE : MFS_DIRSIZE;
-		sbi->max_name_len = longnames ? MFS_L_MAX_NAME_LEN :
-				    MFS_MAX_NAME_LEN;
-	}
-	sbi->itable_off = 2 + sbi->ibmap_blocks + sbi->zbmap_blocks;
-
-	free(sb);
-
-	rc = block_cache_init(service_id, sbi->block_size, 0, cmode);
-	if (rc != EOK) {
-		free(instance);
-		free(sbi);
-		free(sb);
-		block_cache_fini(service_id);
-		block_fini(service_id);
-		mfsdebug("block cache initialization failed\n");
-		return EINVAL;
-	}
-
-	/*Initialize the instance structure and add it to the list*/
-	link_initialize(&instance->link);
-	instance->service_id = service_id;
-	instance->sbi = sbi;
-
-	fibril_mutex_lock(&inst_list_mutex);
-	list_append(&instance->link, &inst_list);
-	fibril_mutex_unlock(&inst_list_mutex);
-
-	mfsdebug("mount successful\n");
-
-	fs_node_t *fn;
-	mfs_node_get(&fn, service_id, MFS_ROOT_INO);
-
-	struct mfs_node *mroot = fn->data;
-
-	*index = mroot->ino_i->index;
-	*size = mroot->ino_i->i_size;
-	*linkcnt = 1;
-
-	return mfs_node_put(fn);
-}
-
-static int
-mfs_unmounted(service_id_t service_id)
-{
-	struct mfs_instance *inst;
-
-	mfsdebug("%s()\n", __FUNCTION__);
-
-	int r = mfs_instance_get(service_id, &inst);
-	if (r != EOK)
-		return r;
-
-	if (inst->open_nodes_cnt != 0)
-		return EBUSY;
-
-	(void) block_cache_fini(service_id);
-	block_fini(service_id);
-
-	/* Remove the instance from the list */
-	fibril_mutex_lock(&inst_list_mutex);
-	list_remove(&inst->link);
-	fibril_mutex_unlock(&inst_list_mutex);
-
-	free(inst->sbi);
-	free(inst);
-	return EOK;
-}
-
-service_id_t mfs_device_get(fs_node_t *fsnode)
-{
-	struct mfs_node *node = fsnode->data;
-	return node->instance->service_id;
-}
-
-static int mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
-{
-	int r;
-	struct mfs_instance *inst;
-	struct mfs_node *mnode;
-	fs_node_t *fsnode;
-	uint32_t inum;
-
-	mfsdebug("%s()\n", __FUNCTION__);
-
-	r = mfs_instance_get(service_id, &inst);
-	if (r != EOK)
-		return r;
-
-	/*Alloc a new inode*/
-	r = mfs_alloc_inode(inst, &inum);
-	if (r != EOK)
-		return r;
-
-	struct mfs_ino_info *ino_i;
-
-	ino_i = malloc(sizeof(*ino_i));
-	if (!ino_i) {
-		r = ENOMEM;
-		goto out_err;
-	}
-
-	mnode = malloc(sizeof(*mnode));
-	if (!mnode) {
-		r = ENOMEM;
-		goto out_err_1;
-	}
-
-	fsnode = malloc(sizeof(fs_node_t));
-	if (!fsnode) {
-		r = ENOMEM;
-		goto out_err_2;
-	}
-
-	if (flags & L_DIRECTORY) {
-		ino_i->i_mode = S_IFDIR;
-		ino_i->i_nlinks = 2; /*This accounts for the '.' dentry*/
-	} else {
-		ino_i->i_mode = S_IFREG;
-		ino_i->i_nlinks = 1;
-	}
-
-	ino_i->i_uid = 0;
-	ino_i->i_gid = 0;
-	ino_i->i_size = 0;
-	ino_i->i_atime = 0;
-	ino_i->i_mtime = 0;
-	ino_i->i_ctime = 0;
-
-	memset(ino_i->i_dzone, 0, sizeof(uint32_t) * V2_NR_DIRECT_ZONES);
-	memset(ino_i->i_izone, 0, sizeof(uint32_t) * V2_NR_INDIRECT_ZONES);
-
-	mfsdebug("new node idx = %d\n", (int) inum);
-
-	ino_i->index = inum;
-	ino_i->dirty = true;
-	mnode->ino_i = ino_i;
-	mnode->instance = inst;
-	mnode->refcnt = 1;
-
-	link_initialize(&mnode->link);
-
-	unsigned long key[] = {
-		[OPEN_NODES_SERVICE_KEY] = inst->service_id,
-		[OPEN_NODES_INODE_KEY] = inum,
-	};
-
-	fibril_mutex_lock(&open_nodes_lock);
-	hash_table_insert(&open_nodes, key, &mnode->link);
-	fibril_mutex_unlock(&open_nodes_lock);
-	inst->open_nodes_cnt++;
-
-	mnode->ino_i->dirty = true;
-
-	fs_node_initialize(fsnode);
-	fsnode->data = mnode;
-	mnode->fsnode = fsnode;
-	*rfn = fsnode;
-
-	return EOK;
-
-out_err_2:
-	free(mnode);
-out_err_1:
-	free(ino_i);
-out_err:
-	return r;
-}
-
-static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
-{
-	struct mfs_node *mnode = pfn->data;
-	struct mfs_ino_info *ino_i = mnode->ino_i;
-	struct mfs_dentry_info d_info;
-	int r;
-
-	mfsdebug("%s()\n", __FUNCTION__);
-
-	if (!S_ISDIR(ino_i->i_mode))
-		return ENOTDIR;
-
-	struct mfs_sb_info *sbi = mnode->instance->sbi;
-	const size_t comp_size = str_size(component);
-
-	unsigned i;
-	for (i = 0; i < mnode->ino_i->i_size / sbi->dirsize; ++i) {
-		r = mfs_read_dentry(mnode, &d_info, i);
-		if (r != EOK)
-			return r;
-
-		if (!d_info.d_inum) {
-			/*This entry is not used*/
-			continue;
-		}
-
-		const size_t dentry_name_size = str_size(d_info.d_name);
-
-		if (comp_size == dentry_name_size &&
-			!bcmp(component, d_info.d_name, dentry_name_size)) {
-			/*Hit!*/
-			mfs_node_core_get(rfn, mnode->instance,
-					  d_info.d_inum);
-			goto found;
-		}
-	}
-	*rfn = NULL;
-found:
-	return EOK;
-}
-
-static aoff64_t mfs_size_get(fs_node_t *node)
-{
-	assert(node);
-
-	const struct mfs_node *mnode = node->data;
-	assert(mnode);
-	assert(mnode->ino_i);
-
-	return mnode->ino_i->i_size;
-}
-
-static int
-mfs_node_get(fs_node_t **rfn, service_id_t service_id,
-			fs_index_t index)
-{
-	int rc;
-	struct mfs_instance *instance;
-
-	mfsdebug("%s()\n", __FUNCTION__);
-
-	rc = mfs_instance_get(service_id, &instance);
-	if (rc != EOK)
-		return rc;
-
-	return mfs_node_core_get(rfn, instance, index);
-}
-
-static int
-mfs_node_put(fs_node_t *fsnode)
-{
-	int rc = EOK;
-	struct mfs_node *mnode = fsnode->data;
-
-	mfsdebug("%s()\n", __FUNCTION__);
-
-	fibril_mutex_lock(&open_nodes_lock);
-
-	assert(mnode->refcnt > 0);
-	mnode->refcnt--;
-	if (mnode->refcnt == 0) {
-		unsigned long key[] = {
-			[OPEN_NODES_SERVICE_KEY] = mnode->instance->service_id,
-			[OPEN_NODES_INODE_KEY] = mnode->ino_i->index
-		};
-		hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS);
-		assert(mnode->instance->open_nodes_cnt > 0);
-		mnode->instance->open_nodes_cnt--;
-		rc = mfs_put_inode_core(mnode);
-		free(mnode->ino_i);
-		free(mnode);
-		free(fsnode);
-	}
-
-	fibril_mutex_unlock(&open_nodes_lock);
-	return rc;
-}
-
-static int mfs_node_open(fs_node_t *fsnode)
-{
-	/*
-	 * Opening a file is stateless, nothing
-	 * to be done here.
-	 */
-	return EOK;
-}
-
-static fs_index_t mfs_index_get(fs_node_t *fsnode)
-{
-	struct mfs_node *mnode = fsnode->data;
-
-	assert(mnode->ino_i);
-	return mnode->ino_i->index;
-}
-
-static unsigned mfs_lnkcnt_get(fs_node_t *fsnode)
-{
-	struct mfs_node *mnode = fsnode->data;
-
-	mfsdebug("%s() %d\n", __FUNCTION__, mnode->ino_i->i_nlinks);
-
-	if (S_ISDIR(mnode->ino_i->i_mode)) {
-		if (mnode->ino_i->i_nlinks > 1)
-			return 1;
-		else
-			return 0;
-	} else
-		return mnode->ino_i->i_nlinks;
-}
-
-static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
-			     fs_index_t index)
-{
-	fs_node_t *node = NULL;
-	struct mfs_node *mnode = NULL;
-	int rc;
-
-	mfsdebug("%s()\n", __FUNCTION__);
-
-	fibril_mutex_lock(&open_nodes_lock);
-
-	/* Check if the node is not already open */
-	unsigned long key[] = {
-		[OPEN_NODES_SERVICE_KEY] = inst->service_id,
-		[OPEN_NODES_INODE_KEY] = index,
-	};
-	link_t *already_open = hash_table_find(&open_nodes, key);
-
-	if (already_open) {
-		mnode = hash_table_get_instance(already_open, struct mfs_node, link);
-		*rfn = mnode->fsnode;
-		mnode->refcnt++;
-
-		fibril_mutex_unlock(&open_nodes_lock);
-		return EOK;
-	}
-
-	node = malloc(sizeof(fs_node_t));
-	if (!node) {
-		rc = ENOMEM;
-		goto out_err;
-	}
-
-	fs_node_initialize(node);
-
-	mnode = malloc(sizeof(*mnode));
-	if (!mnode) {
-		rc = ENOMEM;
-		goto out_err;
-	}
-
-	struct mfs_ino_info *ino_i;
-
-	rc = mfs_get_inode(inst, &ino_i, index);
-	if (rc != EOK)
-		goto out_err;
-
-	ino_i->index = index;
-	mnode->ino_i = ino_i;
-	mnode->refcnt = 1;
-	link_initialize(&mnode->link);
-
-	mnode->instance = inst;
-	node->data = mnode;
-	mnode->fsnode = node;
-	*rfn = node;
-
-	hash_table_insert(&open_nodes, key, &mnode->link);
-	inst->open_nodes_cnt++;
-
-	fibril_mutex_unlock(&open_nodes_lock);
-
-	return EOK;
-
-out_err:
-	if (node)
-		free(node);
-	if (mnode)
-		free(mnode);
-	fibril_mutex_unlock(&open_nodes_lock);
-	return rc;
-}
-
-static bool mfs_is_directory(fs_node_t *fsnode)
-{
-	const struct mfs_node *node = fsnode->data;
-	return S_ISDIR(node->ino_i->i_mode);
-}
-
-static bool mfs_is_file(fs_node_t *fsnode)
-{
-	struct mfs_node *node = fsnode->data;
-	return S_ISREG(node->ino_i->i_mode);
-}
-
-static int mfs_root_get(fs_node_t **rfn, service_id_t service_id)
-{
-	int rc = mfs_node_get(rfn, service_id, MFS_ROOT_INO);
-	return rc;
-}
-
-static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
-{
-	struct mfs_node *parent = pfn->data;
-	struct mfs_node *child = cfn->data;
-	struct mfs_sb_info *sbi = parent->instance->sbi;
-
-	mfsdebug("%s()\n", __FUNCTION__);
-
-	if (str_size(name) > sbi->max_name_len)
-		return ENAMETOOLONG;
-
-	int r = mfs_insert_dentry(parent, name, child->ino_i->index);
-	if (r != EOK)
-		goto exit_error;
-
-	if (S_ISDIR(child->ino_i->i_mode)) {
-		r = mfs_insert_dentry(child, ".", child->ino_i->index);
-		if (r != EOK)
-			goto exit_error;
-
-		r = mfs_insert_dentry(child, "..", parent->ino_i->index);
-		if (r != EOK)
-			goto exit_error;
-
-		parent->ino_i->i_nlinks++;
-		parent->ino_i->dirty = true;
-	}
-
-exit_error:
-	return r;
-}
-
-static int
-mfs_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *name)
-{
-	struct mfs_node *parent = pfn->data;
-	struct mfs_node *child = cfn->data;
-	bool has_children;
-	int r;
-
-	mfsdebug("%s()\n", __FUNCTION__);
-
-	if (!parent)
-		return EBUSY;
-
-	r = mfs_has_children(&has_children, cfn);
-	if (r != EOK)
-		return r;
-
-	if (has_children)
-		return ENOTEMPTY;
-
-	r = mfs_remove_dentry(parent, name);
-	if (r != EOK)
-		return r;
-
-	struct mfs_ino_info *chino = child->ino_i;
-
-	assert(chino->i_nlinks >= 1);
-	chino->i_nlinks--;
-	mfsdebug("Links: %d\n", chino->i_nlinks);
-
-	if (chino->i_nlinks <= 1 && S_ISDIR(chino->i_mode)) {
-		/* The child directory will be destroyed, decrease the
-		 * parent hard links counter.
-		 */
-		parent->ino_i->i_nlinks--;
-		parent->ino_i->dirty = true;
-	}
-
-	chino->dirty = true;
-
-	return r;
-}
-
-static int mfs_has_children(bool *has_children, fs_node_t *fsnode)
-{
-	struct mfs_node *mnode = fsnode->data;
-	struct mfs_sb_info *sbi = mnode->instance->sbi;
-	int r;
-
-	*has_children = false;
-
-	if (!S_ISDIR(mnode->ino_i->i_mode))
-		goto out;
-
-	struct mfs_dentry_info d_info;
-
-	/* The first two dentries are always . and .. */
-	unsigned i;
-	for (i = 2; i < mnode->ino_i->i_size / sbi->dirsize; ++i) {
-		r = mfs_read_dentry(mnode, &d_info, i);
-		if (r != EOK)
-			return r;
-
-		if (d_info.d_inum) {
-			/*A valid entry has been found*/
-			*has_children = true;
-			break;
-		}
-	}
-out:
-
-	return EOK;
-}
-
-static int
-mfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
-		size_t *rbytes)
-{
-	int rc;
-	fs_node_t *fn;
-
-	rc = mfs_node_get(&fn, service_id, index);
-	if (rc != EOK)
-		return rc;
-	if (!fn)
-		return ENOENT;
-
-	struct mfs_node *mnode;
-	struct mfs_ino_info *ino_i;
-	size_t len, bytes = 0;
-	ipc_callid_t callid;
-
-	mnode = fn->data;
-	ino_i = mnode->ino_i;
-
-	if (!async_data_read_receive(&callid, &len)) {
-		rc = EINVAL;
-		goto out_error;
-	}
-
-	if (S_ISDIR(ino_i->i_mode)) {
-		aoff64_t spos = pos;
-		struct mfs_dentry_info d_info;
-		struct mfs_sb_info *sbi = mnode->instance->sbi;
-
-		if (pos < 2) {
-			/*Skip the first two dentries ('.' and '..')*/
-			pos = 2;
-		}
-
-		for (; pos < mnode->ino_i->i_size / sbi->dirsize; ++pos) {
-			rc = mfs_read_dentry(mnode, &d_info, pos);
-			if (rc != EOK)
-				goto out_error;
-
-			if (d_info.d_inum) {
-				/*Dentry found!*/
-				goto found;
-			}
-		}
-
-		rc = mfs_node_put(fn);
-		async_answer_0(callid, rc != EOK ? rc : ENOENT);
-		return rc;
-found:
-		async_data_read_finalize(callid, d_info.d_name,
-					 str_size(d_info.d_name) + 1);
-		bytes = ((pos - spos) + 1);
-	} else {
-		struct mfs_sb_info *sbi = mnode->instance->sbi;
-
-		if (pos >= (size_t) ino_i->i_size) {
-			/*Trying to read beyond the end of file*/
-			bytes = 0;
-			(void) async_data_read_finalize(callid, NULL, 0);
-			goto out_success;
-		}
-
-		bytes = min(len, sbi->block_size - pos % sbi->block_size);
-		bytes = min(bytes, ino_i->i_size - pos);
-
-		uint32_t zone;
-		block_t *b;
-
-		rc = mfs_read_map(&zone, mnode, pos);
-		if (rc != EOK)
-			goto out_error;
-
-		if (zone == 0) {
-			/*sparse file*/
-			uint8_t *buf = malloc(sbi->block_size);
-			if (!buf) {
-				rc = ENOMEM;
-				goto out_error;
-			}
-			memset(buf, 0, sizeof(sbi->block_size));
-			async_data_read_finalize(callid,
-						 buf + pos % sbi->block_size, bytes);
-			free(buf);
-			goto out_success;
-		}
-
-		rc = block_get(&b, service_id, zone, BLOCK_FLAGS_NONE);
-		if (rc != EOK)
-			goto out_error;
-
-		async_data_read_finalize(callid, b->data +
-					 pos % sbi->block_size, bytes);
-
-		rc = block_put(b);
-		if (rc != EOK) {
-			mfs_node_put(fn);
-			return rc;
-		}
-	}
-out_success:
-	rc = mfs_node_put(fn);
-	*rbytes = bytes;
-	return rc;
-out_error:
-	;
-	int tmp = mfs_node_put(fn);
-	async_answer_0(callid, tmp != EOK ? tmp : rc);
-	return tmp != EOK ? tmp : rc;
-}
-
-static int
-mfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
-		size_t *wbytes, aoff64_t *nsize)
-{
-	fs_node_t *fn;
-	int r;
-	int flags = BLOCK_FLAGS_NONE;
-
-	r = mfs_node_get(&fn, service_id, index);
-	if (r != EOK)
-		return r;
-	if (!fn)
-		return ENOENT;
-
-	ipc_callid_t callid;
-	size_t len;
-
-	if (!async_data_write_receive(&callid, &len)) {
-		r = EINVAL;
-		goto out_err;
-	}
-
-	struct mfs_node *mnode = fn->data;
-	struct mfs_sb_info *sbi = mnode->instance->sbi;
-	struct mfs_ino_info *ino_i = mnode->ino_i;
-	const size_t bs = sbi->block_size;
-	size_t bytes = min(len, bs - pos % bs);
-	size_t boundary = ROUND_UP(ino_i->i_size, bs);
-	uint32_t block;
-
-	if (bytes == bs)
-		flags = BLOCK_FLAGS_NOREAD;
-
-	if (pos < boundary) {
-		r = mfs_read_map(&block, mnode, pos);
-		if (r != EOK)
-			goto out_err;
-
-		if (block == 0) {
-			/*Writing in a sparse block*/
-			r = mfs_alloc_zone(mnode->instance, &block);
-			if (r != EOK)
-				goto out_err;
-			flags = BLOCK_FLAGS_NOREAD;
-		}
-	} else {
-		uint32_t dummy;
-
-		r = mfs_alloc_zone(mnode->instance, &block);
-		if (r != EOK)
-			goto out_err;
-
-		r = mfs_write_map(mnode, pos, block, &dummy);
-		if (r != EOK)
-			goto out_err;
-	}
-
-	block_t *b;
-	r = block_get(&b, service_id, block, flags);
-	if (r != EOK)
-		goto out_err;
-
-	async_data_write_finalize(callid, b->data + pos % bs, bytes);
-	b->dirty = true;
-
-	r = block_put(b);
-	if (r != EOK) {
-		mfs_node_put(fn);
-		return r;
-	}
-
-	ino_i->i_size = pos + bytes;
-	ino_i->dirty = true;
-	r = mfs_node_put(fn);
-	*nsize = pos + bytes;
-	*wbytes = bytes;
-	return r;
-
-out_err:
-	mfs_node_put(fn);
-	async_answer_0(callid, r);
-	return r;
-}
-
-static int
-mfs_destroy(service_id_t service_id, fs_index_t index)
-{
-	fs_node_t *fn;
-	int r;
-
-	r = mfs_node_get(&fn, service_id, index);
-	if (r != EOK)
-		return r;
-	if (!fn)
-		return ENOENT;
-
-	/*Destroy the inode*/
-	return mfs_destroy_node(fn);
-}
-
-static int
-mfs_destroy_node(fs_node_t *fn)
-{
-	struct mfs_node *mnode = fn->data;
-	bool has_children;
-	int r;
-
-	mfsdebug("mfs_destroy_node %d\n", mnode->ino_i->index);
-
-	r = mfs_has_children(&has_children, fn);
-	if (r != EOK)
-		goto out;
-
-	assert(!has_children);
-
-	/*Free the entire inode content*/
-	r = mfs_inode_shrink(mnode, mnode->ino_i->i_size);
-	if (r != EOK)
-		goto out;
-
-	/*Mark the inode as free in the bitmap*/
-	r = mfs_free_inode(mnode->instance, mnode->ino_i->index);
-
-out:
-	mfs_node_put(fn);
-	return r;
-}
-
-static int
-mfs_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
-{
-	fs_node_t *fn;
-	int r;
-
-	r = mfs_node_get(&fn, service_id, index);
-	if (r != EOK)
-		return r;
-	if (!fn)
-		return r;
-
-	struct mfs_node *mnode = fn->data;
-	struct mfs_ino_info *ino_i = mnode->ino_i;
-
-	if (ino_i->i_size == size)
-		r = EOK;
-	else
-		r = mfs_inode_shrink(mnode, ino_i->i_size - size);
-
-	mfs_node_put(fn);
-	return r;
-}
-
-static int
-mfs_instance_get(service_id_t service_id, struct mfs_instance **instance)
-{
-	struct mfs_instance *instance_ptr;
-
-	fibril_mutex_lock(&inst_list_mutex);
-
-	if (list_empty(&inst_list)) {
-		fibril_mutex_unlock(&inst_list_mutex);
-		return EINVAL;
-	}
-
-	list_foreach(inst_list, link) {
-		instance_ptr = list_get_instance(link, struct mfs_instance,
-						 link);
-
-		if (instance_ptr->service_id == service_id) {
-			*instance = instance_ptr;
-			fibril_mutex_unlock(&inst_list_mutex);
-			return EOK;
-		}
-	}
-
-	mfsdebug("Instance not found\n");
-
-	fibril_mutex_unlock(&inst_list_mutex);
-	return EINVAL;
-}
-
-static bool check_magic_number(uint16_t magic, bool *native,
-			       mfs_version_t *version, bool *longfilenames)
-{
-	bool rc = true;
-	*longfilenames = false;
-
-	if (magic == MFS_MAGIC_V1 || magic == MFS_MAGIC_V1R) {
-		*native = magic == MFS_MAGIC_V1;
-		*version = MFS_VERSION_V1;
-	} else if (magic == MFS_MAGIC_V1L || magic == MFS_MAGIC_V1LR) {
-		*native = magic == MFS_MAGIC_V1L;
-		*version = MFS_VERSION_V1;
-		*longfilenames = true;
-	} else if (magic == MFS_MAGIC_V2 || magic == MFS_MAGIC_V2R) {
-		*native = magic == MFS_MAGIC_V2;
-		*version = MFS_VERSION_V2;
-	} else if (magic == MFS_MAGIC_V2L || magic == MFS_MAGIC_V2LR) {
-		*native = magic == MFS_MAGIC_V2L;
-		*version = MFS_VERSION_V2;
-		*longfilenames = true;
-	} else if (magic == MFS_MAGIC_V3 || magic == MFS_MAGIC_V3R) {
-		*native = magic == MFS_MAGIC_V3;
-		*version = MFS_VERSION_V3;
-	} else
-		rc = false;
-
-	return rc;
-}
-
-static int
-mfs_close(service_id_t service_id, fs_index_t index)
-{
-	return 0;
-}
-
-static int
-mfs_sync(service_id_t service_id, fs_index_t index)
-{
-	fs_node_t *fn;
-	int rc = mfs_node_get(&fn, service_id, index);
-	if (rc != EOK)
-		return rc;
-	if (!fn)
-		return ENOENT;
-
-	struct mfs_node *mnode = fn->data;
-	mnode->ino_i->dirty = true;
-
-	return mfs_node_put(fn);
-}
-
-vfs_out_ops_t mfs_ops = {
-	.mounted = mfs_mounted,
-	.unmounted = mfs_unmounted,
-	.read = mfs_read,
-	.write = mfs_write,
-	.truncate = mfs_truncate,
-	.close = mfs_close,
-	.destroy = mfs_destroy,
-	.sync = mfs_sync,
-};
-
-/**
- * @}
- */
-
Index: uspace/srv/fs/minixfs/mfs_rw.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_rw.c	(revision 9a0be341d462b5cb93242f88efe36f9ed4f4eb6d)
+++ 	(revision )
@@ -1,398 +1,0 @@
-/*
- * Copyright (c) 2011 Maurizio Lombardi
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup fs
- * @{
- */
-
-#include "mfs.h"
-
-static int
-rw_map_ondisk(uint32_t *b, const struct mfs_node *mnode, int rblock,
-	      bool write_mode, uint32_t w_block);
-
-static int
-reset_zone_content(struct mfs_instance *inst, uint32_t zone);
-
-static int
-alloc_zone_and_clear(struct mfs_instance *inst, uint32_t *zone);
-
-static int
-read_ind_zone(struct mfs_instance *inst, uint32_t zone, uint32_t **ind_zone);
-
-static int
-write_ind_zone(struct mfs_instance *inst, uint32_t zone, uint32_t *ind_zone);
-
-
-/**Given the position in the file expressed in
- *bytes, this function returns the on-disk block
- *relative to that position.
- *Returns zero if the block does not exist.
- */
-int
-mfs_read_map(uint32_t *b, const struct mfs_node *mnode, uint32_t pos)
-{
-	int r;
-	const struct mfs_sb_info *sbi = mnode->instance->sbi;
-	const int block_size = sbi->block_size;
-
-	/*Compute relative block number in file*/
-	int rblock = pos / block_size;
-
-	if (mnode->ino_i->i_size < pos) {
-		/*Trying to read beyond the end of file*/
-		r = EOK;
-		*b = 0;
-		goto out;
-	}
-
-	r = rw_map_ondisk(b, mnode, rblock, false, 0);
-out:
-	return r;
-}
-
-int
-mfs_write_map(struct mfs_node *mnode, const uint32_t pos, uint32_t new_zone,
-	  uint32_t *old_zone)
-{
-	const struct mfs_sb_info *sbi = mnode->instance->sbi;
-
-	if (pos >= sbi->max_file_size) {
-		/*Can't write beyond the maximum file size*/
-		return EINVAL;
-	}
-
-	/*Compute the relative block number in file*/
-	int rblock = pos / sbi->block_size;
-
-	return rw_map_ondisk(old_zone, mnode, rblock, true, new_zone);
-}
-
-static int
-rw_map_ondisk(uint32_t *b, const struct mfs_node *mnode, int rblock,
-	      bool write_mode, uint32_t w_block)
-{
-	int r, nr_direct;
-	int ptrs_per_block;
-	uint32_t *ind_zone, *ind2_zone;
-
-	struct mfs_ino_info *ino_i = mnode->ino_i;
-	struct mfs_instance *inst = mnode->instance;
-	struct mfs_sb_info *sbi = inst->sbi;
-
-	const mfs_version_t fs_version = sbi->fs_version;
-	const bool deleting = write_mode && (w_block == 0);
-
-	if (fs_version == MFS_VERSION_V1) {
-		nr_direct = V1_NR_DIRECT_ZONES;
-		ptrs_per_block = MFS_BLOCKSIZE / sizeof(uint16_t);
-	} else {
-		nr_direct = V2_NR_DIRECT_ZONES;
-		ptrs_per_block = sbi->block_size / sizeof(uint32_t);
-	}
-
-	/*Check if the wanted block is in the direct zones*/
-	if (rblock < nr_direct) {
-		*b = ino_i->i_dzone[rblock];
-		if (write_mode) {
-			ino_i->i_dzone[rblock] = w_block;
-			ino_i->dirty = true;
-		}
-		return EOK;
-	}
-
-	rblock -= nr_direct;
-
-	if (rblock < ptrs_per_block) {
-		/*The wanted block is in the single indirect zone chain*/
-		if (ino_i->i_izone[0] == 0) {
-			if (write_mode && !deleting) {
-				uint32_t zone;
-				r = alloc_zone_and_clear(inst, &zone);
-				if (r != EOK)
-					return r;
-
-				ino_i->i_izone[0] = zone;
-				ino_i->dirty = true;
-			} else {
-				/*Sparse block*/
-				*b = 0;
-				return EOK;
-			}
-		}
-
-		r = read_ind_zone(inst, ino_i->i_izone[0], &ind_zone);
-		if (r != EOK)
-			return r;
-
-		*b = ind_zone[rblock];
-		if (write_mode) {
-			ind_zone[rblock] = w_block;
-			write_ind_zone(inst, ino_i->i_izone[0], ind_zone);
-		}
-
-		goto out_free_ind1;
-	}
-
-	rblock -= ptrs_per_block;
-
-	/*The wanted block is in the double indirect zone chain*/
-
-	/*read the first indirect zone of the chain*/
-	if (ino_i->i_izone[1] == 0) {
-		if (write_mode && !deleting) {
-			uint32_t zone;
-			r = alloc_zone_and_clear(inst, &zone);
-			if (r != EOK)
-				return r;
-
-			ino_i->i_izone[1] = zone;
-			ino_i->dirty = true;
-		} else {
-			/*Sparse block*/
-			*b = 0;
-			return EOK;
-		}
-	}
-
-	r = read_ind_zone(inst, ino_i->i_izone[1], &ind_zone);
-	if (r != EOK)
-		return r;
-
-	/*
-	 *Compute the position of the second indirect
-	 *zone pointer in the chain.
-	 */
-	uint32_t ind2_off = rblock / ptrs_per_block;
-
-	/*read the second indirect zone of the chain*/
-	if (ind_zone[ind2_off] == 0) {
-		if (write_mode && !deleting) {
-			uint32_t zone;
-			r = alloc_zone_and_clear(inst, &zone);
-			if (r != EOK)
-				goto out_free_ind1;
-
-			ind_zone[ind2_off] = zone;
-			write_ind_zone(inst, ino_i->i_izone[1], ind_zone);
-		} else {
-			/*Sparse block*/
-			r = EOK;
-			*b = 0;
-			goto out_free_ind1;
-		}
-	}
-
-	r = read_ind_zone(inst, ind_zone[ind2_off], &ind2_zone);
-	if (r != EOK)
-		goto out_free_ind1;
-
-	*b = ind2_zone[rblock - (ind2_off * ptrs_per_block)];
-	if (write_mode) {
-		ind2_zone[rblock - (ind2_off * ptrs_per_block)] = w_block;
-		write_ind_zone(inst, ind_zone[ind2_off], ind2_zone);
-	}
-
-	r = EOK;
-
-	free(ind2_zone);
-out_free_ind1:
-	free(ind_zone);
-	return r;
-}
-
-/*Free unused indirect zones*/
-int
-mfs_prune_ind_zones(struct mfs_node *mnode, size_t new_size)
-{
-	struct mfs_instance *inst = mnode->instance;
-	struct mfs_sb_info *sbi = inst->sbi;
-	struct mfs_ino_info *ino_i = mnode->ino_i;
-	int nr_direct, ptrs_per_block, rblock, r;
-	int i;
-
-	mfs_version_t fs_version = sbi->fs_version;
-	
-	if (fs_version == MFS_VERSION_V1) {
-		nr_direct = V1_NR_DIRECT_ZONES;
-		ptrs_per_block = MFS_BLOCKSIZE / sizeof(uint16_t);
-	} else {
-		nr_direct = V2_NR_DIRECT_ZONES;
-		ptrs_per_block = sbi->block_size / sizeof(uint32_t);
-	}
-
-	rblock = new_size / sbi->block_size;
-
-	if (rblock < nr_direct) {
-		/*free the single indirect zone*/
-		if (ino_i->i_izone[0]) {
-			r = mfs_free_zone(inst, ino_i->i_izone[0]);
-			if (r != EOK)
-				return r;
-
-			ino_i->i_izone[0] = 0;
-			ino_i->dirty = true;
-		}
-	}
-
-	rblock -= nr_direct + ptrs_per_block;
-
-	int fzone_to_free = (rblock < 0 ? 0 : rblock) / ptrs_per_block;
-
-	if ((fzone_to_free % ptrs_per_block) != 0)
-		++fzone_to_free;
-
-	/*free the entire double indirect zone*/
-	uint32_t *dbl_zone;
-
-	if (ino_i->i_izone[1] == 0) {
-		/*Nothing to be done*/
-		return EOK;
-	}
-
-	r = read_ind_zone(inst, ino_i->i_izone[1], &dbl_zone);
-	if (r != EOK)
-		return r;
-
-	for (i = fzone_to_free; i < ptrs_per_block; ++i) {
-		if (dbl_zone[i] == 0)
-			continue;
-
-		r = mfs_free_zone(inst, dbl_zone[i]);
-		if (r != EOK)
-			goto out;
-	}
-
-	if (fzone_to_free == 0) {
-		r = mfs_free_zone(inst, ino_i->i_izone[1]);
-		ino_i->i_izone[1] = 0;
-		ino_i->dirty = true;
-	}
-out:
-	free(dbl_zone);
-	return r;
-}
-
-static int
-reset_zone_content(struct mfs_instance *inst, uint32_t zone)
-{
-	block_t *b;
-	int r;
-
-	r = block_get(&b, inst->service_id, zone, BLOCK_FLAGS_NOREAD);
-	if (r != EOK)
-		return r;
-
-	memset(b->data, 0, b->size);
-	b->dirty = true;
-
-	return block_put(b);
-}
-
-static int
-alloc_zone_and_clear(struct mfs_instance *inst, uint32_t *zone)
-{
-	int r;
-
-	r = mfs_alloc_zone(inst, zone);
-	if (r != EOK)
-		return r;
-
-	r = reset_zone_content(inst, *zone);
-	return r;
-}
-
-static int
-read_ind_zone(struct mfs_instance *inst, uint32_t zone, uint32_t **ind_zone)
-{
-	struct mfs_sb_info *sbi = inst->sbi;
-	int r;
-	unsigned i;
-	block_t *b;
-	const int max_ind_zone_ptrs = (MFS_MAX_BLOCKSIZE / sizeof(uint16_t)) *
-				      sizeof(uint32_t);
-
-	*ind_zone = malloc(max_ind_zone_ptrs);
-	if (*ind_zone == NULL)
-		return ENOMEM;
-
-	r = block_get(&b, inst->service_id, zone, BLOCK_FLAGS_NONE);
-	if (r != EOK) {
-		free(*ind_zone);
-		return r;
-	}
-
-	if (sbi->fs_version == MFS_VERSION_V1) {
-		uint16_t *src_ptr = b->data;
-
-		for (i = 0; i < sbi->block_size / sizeof(uint16_t); ++i)
-			(*ind_zone)[i] = conv16(sbi->native, src_ptr[i]);
-	} else {
-		uint32_t *src_ptr = b->data;
-
-		for (i = 0; i < sbi->block_size / sizeof(uint32_t); ++i)
-			(*ind_zone)[i] = conv32(sbi->native, src_ptr[i]);
-	}
-
-	return block_put(b);
-}
-
-static int
-write_ind_zone(struct mfs_instance *inst, uint32_t zone, uint32_t *ind_zone)
-{
-	struct mfs_sb_info *sbi = inst->sbi;
-	int r;
-	unsigned i;
-	block_t *b;
-
-	r = block_get(&b, inst->service_id, zone, BLOCK_FLAGS_NOREAD);
-	if (r != EOK)
-		return r;
-
-	if (sbi->fs_version == MFS_VERSION_V1) {
-		uint16_t *dest_ptr = b->data;
-
-		for (i = 0; i < sbi->block_size / sizeof(uint16_t); ++i)
-			dest_ptr[i] = conv16(sbi->native, ind_zone[i]);
-	} else {
-		uint32_t *dest_ptr = b->data;
-
-		for (i = 0; i < sbi->block_size / sizeof(uint32_t); ++i)
-			dest_ptr[i] = conv32(sbi->native, ind_zone[i]);
-
-	}
-	b->dirty = true;
-
-	return block_put(b);
-}
-
-
-/**
- * @}
- */
-
Index: uspace/srv/fs/minixfs/mfs_utils.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_utils.c	(revision 9a0be341d462b5cb93242f88efe36f9ed4f4eb6d)
+++ 	(revision )
@@ -1,63 +1,0 @@
-/*
- * Copyright (c) 2011 Maurizio Lombardi
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup fs
- * @{
- */
-
-#include <byteorder.h>
-#include "mfs.h"
-
-uint16_t conv16(bool native, uint16_t n)
-{
-	if (native)
-		return n;
-
-	return uint16_t_byteorder_swap(n);
-}
-
-uint32_t conv32(bool native, uint32_t n)
-{
-	if (native)
-		return n;
-
-	return uint32_t_byteorder_swap(n);
-}
-
-uint64_t conv64(bool native, uint64_t n)
-{
-	if (native)
-		return n;
-
-	return uint64_t_byteorder_swap(n);
-}
-
-/**
- * @}
- */
-
