Index: uspace/srv/fs/minixfs/Makefile
===================================================================
--- uspace/srv/fs/minixfs/Makefile	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
+++ uspace/srv/fs/minixfs/Makefile	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
@@ -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/minixfs/mfs.c
===================================================================
--- uspace/srv/fs/minixfs/mfs.c	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
+++ uspace/srv/fs/minixfs/mfs.c	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+
+#define _MAIN
+
+#include <ipc/services.h>
+#include <ipc/ns.h>
+#include <async.h>
+#include <errno.h>
+#include <unistd.h>
+#include <task.h>
+#include <stdio.h>
+#include "mfs.h"
+
+vfs_info_t mfs_vfs_info = {
+	.name = NAME,
+	.concurrent_read_write = false,
+	.write_retains_size = false,	
+};
+
+
+/**
+ * This connection fibril processes VFS requests from VFS.
+ *
+ * In order to support simultaneous VFS requests, our design is as follows.
+ * The connection fibril accepts VFS requests from VFS. If there is only one
+ * instance of the fibril, VFS will need to serialize all VFS requests it sends
+ * to MinixFS. To overcome this bottleneck, VFS can send MinixFS the IPC_M_CONNECT_ME_TO
+ * call. In that case, a new connection fibril will be created, which in turn
+ * will accept the call. Thus, a new phone will be opened for VFS.
+ *
+ * There are few issues with this arrangement. First, VFS can run out of
+ * available phones. In that case, VFS can close some other phones or use one
+ * phone for more serialized requests. Similarily, MinixFS can refuse to duplicate
+ * the connection. VFS should then just make use of already existing phones and
+ * route its requests through them. To avoid paying the fibril creation price 
+ * upon each request, MinixFS might want to keep the connections open after the
+ * request has been completed.
+ */
+
+static void mfs_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	if (iid) {
+		/*
+		 * This only happens for connections opened by
+		 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
+		 * created by IPC_M_CONNECT_TO_ME.
+		 */
+		async_answer_0(iid, EOK);
+	}
+	
+	printf(NAME ": connection opened\n");
+	while (1) {
+		ipc_callid_t callid;
+		ipc_call_t call;
+	
+		callid = async_get_call(&call);
+		int method = IPC_GET_IMETHOD(call);
+
+		mfsdebug(NAME "method = %d\n", method);
+		switch  (method) {
+		case IPC_M_PHONE_HUNGUP:
+			return;
+		case VFS_OUT_MOUNTED:
+			mfsdebug("Mount request received\n");
+			mfs_mounted(callid, &call);
+			break;
+		case VFS_OUT_MOUNT:
+			mfs_mount(callid, &call);
+			break;
+		case VFS_OUT_STAT:
+			mfs_stat(callid, &call);
+			break;
+		case VFS_OUT_LOOKUP:
+			mfsdebug("lookup called\n");
+			mfs_lookup(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+			break;
+		}
+	}
+}
+
+
+int main(int argc, char **argv)
+{
+	int vfs_phone;
+	int rc;
+
+	printf(NAME ": HelenOS Minix file system server\n");
+
+	vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
+
+	if (vfs_phone < EOK) {
+		printf(NAME ": failed to connect to VFS\n");
+		return -1;
+	}
+
+	rc = fs_register(vfs_phone, &mfs_reg, &mfs_vfs_info, mfs_connection);
+	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 969d88e9150467ef7c5e378c3ad4045fc2a63851)
+++ uspace/srv/fs/minixfs/mfs.h	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
@@ -0,0 +1,199 @@
+/*
+ * 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 <libblock.h>
+#include <libfs.h>
+#include <adt/list.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
+
+#ifdef _MAIN
+#define GLOBAL
+#else
+#define GLOBAL extern
+#endif
+
+GLOBAL fs_reg_t mfs_reg;
+
+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;
+        int32_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;
+	devmap_handle_t handle;
+	struct mfs_sb_info *sbi;
+};
+
+/*MinixFS node in core*/
+struct mfs_node {
+	struct mfs_ino_info *ino_i;
+	struct mfs_instance *instance;
+};
+
+/*mfs_ops.c*/
+extern void mfs_mounted(ipc_callid_t rid, ipc_call_t *request);
+extern void mfs_mount(ipc_callid_t rid, ipc_call_t *request);
+extern void mfs_lookup(ipc_callid_t rid, ipc_call_t *request);
+extern int mfs_instance_get(devmap_handle_t handle,
+				struct mfs_instance **instance);
+
+extern void mfs_stat(ipc_callid_t rid, ipc_call_t *request);
+
+/*mfs_inode.c*/
+int
+get_inode(struct mfs_instance *inst, struct mfs_ino_info **ino_i,
+				fs_index_t index);
+
+extern int
+put_inode(struct mfs_node *mnode);
+
+int
+inode_grow(struct mfs_node *mnode, size_t size_grow);
+
+/*mfs_rw.c*/
+extern int
+read_map(uint32_t *b, const struct mfs_node *mnode, const uint32_t pos);
+
+extern int
+write_map(struct mfs_node *mnode, uint32_t pos, uint32_t new_zone,
+				uint32_t *old_zone);
+
+extern int
+free_zone(struct mfs_node *mnode, const uint32_t zone);
+
+/*mfs_dentry.c*/
+extern struct mfs_dentry_info *
+read_directory_entry(struct mfs_node *mnode, unsigned index);
+
+extern int
+write_dentry(struct mfs_dentry_info *d_info);
+
+int
+insert_dentry(struct mfs_node *mnode, char *d_name, fs_index_t d_inum);
+
+/*mfs_balloc.c*/
+extern int
+mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid);
+
+extern int
+mfs_free_bit(struct mfs_instance *inst, uint32_t idx, bmap_id_t bid);
+
+#endif
+
+/**
+ * @}
+ */ 
+
Index: uspace/srv/fs/minixfs/mfs_balloc.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_balloc.c	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
+++ uspace/srv/fs/minixfs/mfs_balloc.c	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
@@ -0,0 +1,206 @@
+/*
+ * 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 <assert.h>
+#include <errno.h>
+#include "mfs.h"
+#include "mfs_utils.h"
+
+static int
+find_free_bit_and_set(bitchunk_t *b, const int bsize,
+				const bool native, unsigned start_bit);
+
+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;
+	block_t *b;
+
+	assert(inst != NULL);
+	sbi = inst->sbi;
+	assert(sbi != NULL);
+
+	if (bid == BMAP_ZONE) {
+		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*/
+		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->handle, 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 = EOK;
+	block_put(b);
+
+out_err:
+	return r;
+}
+
+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;
+	} 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->handle, i + start_block,
+				BLOCK_FLAGS_NONE);
+
+		if (r != EOK)
+			goto out;
+
+		freebit = find_free_bit_and_set(b->data, sbi->block_size,
+						sbi->native, *search);
+		if (freebit == -1) {
+			/*No free bit in this block*/
+			block_put(b);
+			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*/
+			block_put(b);
+			break;
+		}
+
+		*search = *idx;
+		b->dirty = true;
+		block_put(b);
+		goto found;
+	}
+
+	if (*search > 0) {
+		/*Repeat the search from the first bitmap block*/
+		*search = 0;
+		goto retry;
+	}
+
+	/*Free bit not found, return error*/
+	return ENOSPC;
+
+found:
+	r = EOK;
+
+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; i < bsize / sizeof(uint32_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 969d88e9150467ef7c5e378c3ad4045fc2a63851)
+++ uspace/srv/fs/minixfs/mfs_dentry.c	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
@@ -0,0 +1,188 @@
+/*
+ * 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 <assert.h>
+#include <errno.h>
+#include "mfs.h"
+#include "mfs_utils.h"
+
+struct mfs_dentry_info *
+read_directory_entry(struct mfs_node *mnode, 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;
+
+	struct mfs_dentry_info *d_info = malloc(sizeof(*d_info));
+
+	if (!d_info)
+		return NULL;
+
+	int r = read_map(&block, mnode, index * sbi->dirsize);
+	if (r != EOK || block == 0)
+		goto out_err;
+
+	r = block_get(&b, inst->handle, 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 - 1);
+
+	if (sbi->fs_version == MFS_VERSION_V3) {
+		struct mfs3_dentry *d3;
+
+		d3 = b->data;
+		d3 += dentry_off;
+		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;
+		d += dentry_off;
+		d_info->d_inum = conv16(sbi->native, d->d_inum);
+		memcpy(d_info->d_name, d->d_name, namelen);
+	}
+
+	block_put(b);
+
+	d_info->index = index;
+	d_info->node = mnode;
+	return d_info;
+
+out_err:
+	free(d_info);
+	return NULL;
+}
+
+int
+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 = read_map(&block, mnode, d_off_bytes);
+	if (r != EOK)
+		goto out;
+
+	r = block_get(&b, mnode->instance->handle, 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;
+	block_put(b);
+
+out:
+	return r;
+}
+
+int
+insert_dentry(struct mfs_node *mnode, char *d_name, fs_index_t d_inum)
+{
+	int i, 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);
+
+	assert(name_len <= sbi->max_name_len);
+
+	/*Search for an empty dentry*/
+
+	for (i = 2; ; ++i) {
+		d_info = read_directory_entry(mnode, i);
+
+		if (!d_info) {
+			/*Reached the end of the dentries list*/
+			break;
+		}
+
+		if (d_info->d_inum == 0) {
+			/*This entry is not used*/
+			empty_dentry_found = true;
+			break;
+		}
+		free(d_info);
+	}
+
+	if (!empty_dentry_found) {
+		r = inode_grow(mnode, sbi->dirsize);
+		if (r != EOK)
+			return r;
+
+		d_info = read_directory_entry(mnode, i);
+		if (!d_info)
+			return EIO;
+	}
+
+	d_info->d_inum = d_inum;
+	memcpy(d_info->d_name, d_name, name_len);
+	d_info->d_name[name_len] = 0;
+
+	return  write_dentry(d_info);
+}
+
+
+/**
+ * @}
+ */ 
+
Index: uspace/srv/fs/minixfs/mfs_inode.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_inode.c	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
+++ uspace/srv/fs/minixfs/mfs_inode.c	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
@@ -0,0 +1,349 @@
+/*
+ * 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 <assert.h>
+#include <errno.h>
+#include <mem.h>
+#include "mfs.h"
+#include "mfs_utils.h"
+
+static int
+mfs_write_inode_raw(struct mfs_node *mnode);
+
+static int
+mfs2_write_inode_raw(struct mfs_node *mnode);
+
+static struct mfs_ino_info *
+mfs_read_inode_raw(const struct mfs_instance *instance, uint16_t inum);
+
+static struct mfs_ino_info *
+mfs2_read_inode_raw(const struct mfs_instance *instance, uint32_t inum);
+
+
+int
+get_inode(struct mfs_instance *inst, struct mfs_ino_info **ino_i,
+				fs_index_t index)
+{
+	struct mfs_sb_info *sbi = inst->sbi;
+
+	if (sbi->fs_version == MFS_VERSION_V1) {
+		/*Read a MFS V1 inode*/
+		*ino_i = mfs_read_inode_raw(inst, index);
+	} else {
+		/*Read a MFS V2/V3 inode*/
+		*ino_i = mfs2_read_inode_raw(inst, index);
+	}
+
+	if (*ino_i == NULL)
+		return -1;
+
+	return EOK;
+}
+
+static struct mfs_ino_info *
+mfs_read_inode_raw(const struct mfs_instance *instance, uint16_t inum)
+{
+	struct mfs_inode *ino = NULL;
+	struct mfs_ino_info *ino_i = NULL;
+	struct mfs_sb_info *sbi;
+	block_t *b;
+	int i;
+
+	sbi = instance->sbi;
+	assert(sbi);
+	
+	const int ino_off = inum % sbi->ino_per_block;
+	const size_t ino_size = sizeof(struct mfs_inode);
+
+	ino_i = malloc(sizeof(*ino_i));
+	ino = malloc(ino_size);
+
+	if (!ino || !ino_i)
+		goto out_err;
+
+	const int itable_off = sbi->itable_off;
+
+	if (block_get(&b, instance->handle,
+			itable_off + inum / sbi->ino_per_block,
+			BLOCK_FLAGS_NONE) != EOK)
+		goto out_err;
+
+	memcpy(ino, ((uint8_t *) b->data) + ino_off * ino_size, ino_size);
+
+	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]);
+
+	block_put(b);
+	free(ino);
+	ino_i->dirty = false;
+
+	return ino_i;
+
+out_err:
+	if (ino)
+		free(ino);
+	if (ino_i)
+		free(ino_i);
+	return NULL;
+}
+
+static struct mfs_ino_info *
+mfs2_read_inode_raw(const struct mfs_instance *instance, uint32_t inum)
+{
+	struct mfs2_inode *ino = NULL;
+	struct mfs_ino_info *ino_i = NULL;
+	struct mfs_sb_info *sbi;
+	block_t *b;
+	int i;
+
+	const size_t ino_size = sizeof(struct mfs2_inode);
+
+	ino = malloc(ino_size);
+	ino_i = malloc(sizeof(*ino_i));
+
+	if (!ino || !ino_i)
+		goto out_err;
+
+	sbi = instance->sbi;
+	assert(sbi);
+
+	const int itable_off = sbi->itable_off;
+	const int ino_off = inum % sbi->ino_per_block;
+
+	if (block_get(&b, instance->handle, 
+		itable_off + inum / sbi->ino_per_block,
+			BLOCK_FLAGS_NONE) != EOK)
+		goto out_err;
+
+	memcpy(ino, ((uint8_t *)b->data) + ino_off * ino_size, ino_size);
+
+	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]);
+
+	block_put(b);
+	free(ino);
+	ino_i->dirty = false;
+
+	return ino_i;
+
+out_err:
+	if (ino)
+		free(ino);
+	if (ino_i)
+		free(ino_i);
+	return NULL;
+}
+
+int
+put_inode(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 int itable_off = sbi->itable_off;
+	const int ino_off = ino_i->index % sbi->ino_per_block;
+	const bool native = sbi->native;
+
+	r = block_get(&b, mnode->instance->handle,
+				itable_off + ino_i->index / 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;
+	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 int itable_off = sbi->itable_off;
+	const int ino_off = ino_i->index % sbi->ino_per_block;
+	const bool native = sbi->native;
+	
+	r = block_get(&b, mnode->instance->handle,
+				itable_off + ino_i->index / 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_mode);
+	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;
+	block_put(b);
+	ino_i->dirty = false;
+
+out:
+	return r;
+}
+
+int
+inode_grow(struct mfs_node *mnode, size_t size_grow)
+{
+	unsigned i;
+
+	if (size_grow == 0)
+		return EOK;
+
+	struct mfs_sb_info *sbi = mnode->instance->sbi;
+	struct mfs_ino_info *ino_i = mnode->ino_i;
+	const int bs = sbi->block_size;
+
+	const uint32_t old_size = ino_i->i_size;
+	const uint32_t new_size = old_size + size_grow;
+
+	/*Compute the number of zones to add to the inode*/
+	unsigned zones_to_add = 0;
+	if ((old_size % (bs - 1)) == 0)
+		zones_to_add++;
+
+	zones_to_add += (new_size - old_size) / bs;
+
+	/*Compute the start zone*/
+	unsigned start_zone = old_size / bs;
+	start_zone += (old_size % bs) != 0;
+
+	int r;
+	for (i = 0; i < zones_to_add; ++i) {
+		uint32_t new_zone;
+		uint32_t dummy;
+
+		r = mfs_alloc_bit(mnode->instance, &new_zone, BMAP_ZONE);
+		if (r != EOK)
+			return r;
+
+		r = write_map(mnode, (start_zone + i) * sbi->block_size,
+				new_zone, &dummy);
+		if (r != EOK)
+			return r;
+
+		ino_i->i_size += bs;
+		ino_i->dirty = true;
+	}
+	return EOK;
+}
+
+/**
+ * @}
+ */ 
+
Index: uspace/srv/fs/minixfs/mfs_ops.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_ops.c	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
+++ uspace/srv/fs/minixfs/mfs_ops.c	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
@@ -0,0 +1,641 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <fibril_synch.h>
+#include <errno.h>
+#include "mfs.h"
+#include "mfs_utils.h"
+
+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 char mfs_plb_get_char(unsigned pos);
+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, devmap_handle_t handle);
+static devmap_handle_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, devmap_handle_t handle, int flags);
+static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name);
+
+static
+int mfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle,
+			fs_index_t index);
+
+
+static LIST_INITIALIZE(inst_list);
+static FIBRIL_MUTEX_INITIALIZE(inst_list_mutex);
+
+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,
+	.plb_get_char = mfs_plb_get_char,
+	.has_children = mfs_has_children,
+	.lnkcnt_get = mfs_lnkcnt_get
+};
+
+void mfs_mounted(ipc_callid_t rid, ipc_call_t *request)
+{
+	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+	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;
+
+	/* Accept the mount options */
+	char *opts;
+	int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
+	
+	if (rc != EOK) {
+		mfsdebug("Can't accept async data write\n");
+		async_answer_0(rid, rc);
+		return;
+	}
+
+	/* Check for option enabling write through. */
+	if (str_cmp(opts, "wtcache") == 0)
+		cmode = CACHE_MODE_WT;
+	else
+		cmode = CACHE_MODE_WB;
+
+	free(opts);
+
+	/* initialize libblock */
+	rc = block_init(devmap_handle, 1024);
+	if (rc != EOK) {
+		mfsdebug("libblock initialization failed\n");
+		async_answer_0(rid, rc);
+		return;
+	}
+
+	/*Allocate space for generic MFS superblock*/
+	sbi = malloc(sizeof(*sbi));
+
+	if (!sbi) {
+		async_answer_0(rid, ENOMEM);
+		return;
+	}
+
+	/*Allocate space for filesystem instance*/
+	instance = malloc(sizeof(*instance));
+
+	if (!instance) {
+		async_answer_0(rid, ENOMEM);
+		return;
+	}
+
+	sb = malloc(MFS_SUPERBLOCK_SIZE);
+
+	if (!sb) {
+		async_answer_0(rid, ENOMEM);
+		return;
+	}
+
+	/* Read the superblock */
+	rc = block_read_direct(devmap_handle, MFS_SUPERBLOCK << 1, 1, sb);
+	if (rc != EOK) {
+		block_fini(devmap_handle);
+		async_answer_0(rid, rc);
+		return;
+	}
+
+	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;
+		goto recognized;
+	}
+
+	if (!check_magic_number(sb3->s_magic, &native, &version, &longnames)) {
+		mfsdebug("magic number not recognized\n");
+		block_fini(devmap_handle);
+		async_answer_0(rid, ENOTSUP);
+		return;
+	}
+
+	/*This is a V3 Minix filesystem*/
+
+	magic = sb3->s_magic;
+
+recognized:
+
+	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->nzones = conv16(native, sb->s_nzones);
+		sbi->block_size = MFS_BLOCKSIZE;
+		sbi->ino_per_block = V1_INODES_PER_BLOCK;
+		if (version == MFS_VERSION_V2)
+			sbi->nzones = conv32(native, sb->s_nzones2);
+		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(devmap_handle, sbi->block_size, 0, cmode);
+
+	if (rc != EOK) {
+		block_fini(devmap_handle);
+		async_answer_0(rid, EINVAL);
+		mfsdebug("block cache initialization failed\n");
+		return;
+	}
+
+	/*Initialize the instance structure and add it to the list*/
+	link_initialize(&instance->link);
+	instance->handle = devmap_handle;
+	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");
+
+	async_answer_0(rid, EOK);
+}
+
+void mfs_mount(ipc_callid_t rid, ipc_call_t *request)
+{
+	libfs_mount(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
+}
+
+devmap_handle_t mfs_device_get(fs_node_t *fsnode)
+{
+	struct mfs_node *node = fsnode->data;
+	return node->instance->handle;
+}
+
+static int mfs_create_node(fs_node_t **rfn, devmap_handle_t handle, int flags)
+{
+	int r;
+	struct mfs_instance *inst;
+	struct mfs_node *mnode;
+	fs_node_t *fsnode;
+	uint32_t inum;
+	
+	mfsdebug("create_node()\n");
+
+	r = mfs_instance_get(handle, &inst);
+	if (r != EOK)
+		return r;
+
+	if (flags & L_DIRECTORY) {
+		/*Not yet supported*/
+		return ENOTSUP;
+	}
+
+	/*Alloc a new inode*/
+	r = mfs_alloc_bit(inst, &inum, BMAP_INODE);
+	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;
+	}
+
+	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);
+
+	ino_i->index = inum;
+	ino_i->dirty = true;
+	mnode->ino_i = ino_i;
+	mnode->instance = inst;
+
+	put_inode(mnode);
+
+	fs_node_initialize(fsnode);
+	fsnode->data = mnode;
+	*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;
+
+	if (!S_ISDIR(ino_i->i_mode))
+		return ENOTDIR;
+
+	mfsdebug("mfs_match()\n");
+
+	struct mfs_sb_info *sbi = mnode->instance->sbi;
+	const size_t comp_size = str_size(component);
+
+	int i = 2;
+	while (1) {
+		d_info = read_directory_entry(mnode, i++);
+		if (!d_info) {
+			/*Reached the end of the directory entry list*/
+			break;
+		}
+
+		if (!d_info->d_inum) {
+			/*This entry is not used*/
+			free(d_info);
+			continue;
+		}
+
+		if (!bcmp(component, d_info->d_name, min(sbi->max_name_len,
+				comp_size))) {
+			/*Hit!*/
+			mfs_node_core_get(rfn, mnode->instance,
+				d_info->d_inum);
+			free(d_info);
+			goto found;
+		}
+		free(d_info);
+	}
+	*rfn = NULL;
+	return ENOENT;
+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);
+
+	mfsdebug("inode size is %d\n", (int) mnode->ino_i->i_size);
+
+	return mnode->ino_i->i_size;
+}
+
+void mfs_stat(ipc_callid_t rid, ipc_call_t *request)
+{
+	mfsdebug("mfs_stat()\n");
+	libfs_stat(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
+}
+
+static int mfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle,
+			fs_index_t index)
+{
+	int rc;
+	struct mfs_instance *instance;
+
+	mfsdebug("mfs_node_get()\n");
+
+	rc = mfs_instance_get(devmap_handle, &instance);
+
+	if (rc != EOK)
+		return rc;
+
+	return mfs_node_core_get(rfn, instance, index);
+}
+
+static int mfs_node_put(fs_node_t *fsnode)
+{
+	struct mfs_node *mnode = fsnode->data;
+
+	mfsdebug("mfs_node_put()\n");
+
+	put_inode(mnode);
+	free(mnode->ino_i);
+	free(mnode);
+
+	return EOK;
+}
+
+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;
+
+	mfsdebug("mfs_index_get()\n");
+
+	assert(mnode->ino_i);
+	return mnode->ino_i->index;
+}
+
+static unsigned mfs_lnkcnt_get(fs_node_t *fsnode)
+{
+	unsigned rc;
+	struct mfs_node *mnode = fsnode->data;
+
+	assert(mnode);
+	assert(mnode->ino_i);
+
+	rc = mnode->ino_i->i_nlinks;
+	mfsdebug("mfs_lnkcnt_get(): %u\n", rc);
+	return rc;
+}
+
+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;
+
+	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 = get_inode(inst, &ino_i, index);
+	if (rc != EOK)
+		goto out_err;
+
+	ino_i->index = index;
+	mnode->ino_i = ino_i;
+
+	mnode->instance = inst;
+	node->data = mnode;
+	*rfn = node;
+
+	mfsdebug("node_get_core(%d) OK\n", (int) index);
+
+	return EOK;
+
+out_err:
+	if (node)
+		free(node);
+	if (mnode)
+		free(mnode);
+	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, devmap_handle_t handle)
+{
+	int rc = mfs_node_get(rfn, handle, MFS_ROOT_INO);
+
+	mfsdebug("mfs_root_get %s\n", rc == EOK ? "OK" : "FAIL");
+	return rc;
+}
+
+void mfs_lookup(ipc_callid_t rid, ipc_call_t *request)
+{
+	libfs_lookup(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
+}
+
+static char mfs_plb_get_char(unsigned pos)
+{
+	return mfs_reg.plb_ro[pos % PLB_SIZE];
+}
+
+static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
+{
+	mfsdebug("mfs_link()\n");
+	return ENOTSUP;
+}
+
+static int mfs_has_children(bool *has_children, fs_node_t *fsnode)
+{
+	struct mfs_node *mnode = fsnode->data;
+
+	*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 .. */
+	int i = 2;
+	while (1) {
+		d_info = read_directory_entry(mnode, i++);
+
+		if (!d_info) {
+			/*Reached the end of the dentries list*/
+			break;
+		}
+
+		if (d_info->d_inum) {
+			/*A valid entry has been found*/
+			*has_children = true;
+			free(d_info);
+			break;
+		}
+
+		free(d_info);
+	}
+
+out:
+
+	if (*has_children)
+		mfsdebug("Has children\n");
+	else
+		mfsdebug("Has not children\n");
+
+	return EOK;
+}
+
+/*
+ * Find a filesystem instance given the devmap handle
+ */
+int mfs_instance_get(devmap_handle_t handle, struct mfs_instance **instance)
+{
+	link_t *link;
+	struct mfs_instance *instance_ptr;
+
+	fibril_mutex_lock(&inst_list_mutex);
+
+	for (link = inst_list.next; link != &inst_list; link = link->next) {
+		instance_ptr = list_get_instance(link, struct mfs_instance,
+				link);
+		
+		if (instance_ptr->handle == handle) {
+			*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 = false;
+	*longfilenames = false;
+
+	if (magic == MFS_MAGIC_V1 || magic == MFS_MAGIC_V1R) {
+		*native = magic == MFS_MAGIC_V1;
+		*version = MFS_VERSION_V1;
+		rc = true;
+	} else if (magic == MFS_MAGIC_V1L || magic == MFS_MAGIC_V1LR) {
+		*native = magic == MFS_MAGIC_V1L;
+		*version = MFS_VERSION_V1;
+		*longfilenames = true;
+		rc = true;
+	} else if (magic == MFS_MAGIC_V2 || magic == MFS_MAGIC_V2R) {
+		*native = magic == MFS_MAGIC_V2;
+		*version = MFS_VERSION_V2;
+		rc = true;
+	} else if (magic == MFS_MAGIC_V2L || magic == MFS_MAGIC_V2LR) {
+		*native = magic == MFS_MAGIC_V2L;
+		*version = MFS_VERSION_V2;
+		*longfilenames = true;
+		rc = true;
+	} else if (magic == MFS_MAGIC_V3 || magic == MFS_MAGIC_V3R) {
+		*native = magic == MFS_MAGIC_V3;
+		*version = MFS_VERSION_V3;
+		rc = true;
+	}
+
+	return rc;
+}
+
+/**
+ * @}
+ */ 
+
Index: uspace/srv/fs/minixfs/mfs_rw.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_rw.c	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
+++ uspace/srv/fs/minixfs/mfs_rw.c	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
@@ -0,0 +1,340 @@
+/*
+g
+ * 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 <assert.h>
+#include <errno.h>
+#include "mfs.h"
+#include "mfs_utils.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
+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 < (int32_t) 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
+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;
+	const int block_size = sbi->block_size;
+
+	/*Compute the relative block number in file*/
+	int rblock = pos / block_size;
+
+	return rw_map_ondisk(old_zone, mnode, rblock, true, new_zone);
+}
+
+int
+free_zone(struct mfs_node *mnode, const uint32_t zone)
+{
+	int r;
+	uint32_t old_zone;
+
+	r = rw_map_ondisk(&old_zone, mnode, zone, true, 0);
+	if (r != EOK)
+		return r;
+
+	if (old_zone > 0)
+		r = mfs_free_bit(mnode->instance, old_zone, BMAP_ZONE);
+
+	return r;
+}
+
+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;
+
+	assert(mnode);
+	struct mfs_ino_info *ino_i = mnode->ino_i;
+
+	assert(ino_i);
+	assert(mnode->instance);
+
+	struct mfs_instance *inst = mnode->instance;
+	struct mfs_sb_info *sbi = inst->sbi;
+	assert(sbi);
+
+	const 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);
+	}
+
+	/*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 - 1;
+
+	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) {
+				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
+				return -1;
+		}
+
+		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 - 1;
+
+	/*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) {
+			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
+			return -1;
+	}
+
+	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) {
+			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 {
+			r = -1;
+			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[ind2_off % ptrs_per_block];
+	if (write_mode) {
+		ind2_zone[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;
+}
+
+
+static int
+reset_zone_content(struct mfs_instance *inst, uint32_t zone)
+{
+	block_t *b;
+	int r;
+
+	r = block_get(&b, inst->handle, zone, BLOCK_FLAGS_NOREAD);
+	if (r != EOK)
+		return r;
+
+	memset(b->data, 0, b->size);
+	b->dirty = true;
+	block_put(b);
+
+	return EOK;
+}
+
+static int
+alloc_zone_and_clear(struct mfs_instance *inst, uint32_t *zone)
+{
+	int r;
+
+	r = mfs_alloc_bit(inst, zone, BMAP_ZONE);
+	if (r != EOK)
+		goto out;
+
+	r = reset_zone_content(inst, *zone);
+out:
+	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;
+
+	*ind_zone = malloc(sbi->block_size);
+	if (*ind_zone == NULL)
+		return ENOMEM;
+
+	r = block_get(&b, inst->handle, 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]);
+	}
+
+	block_put(b);
+	
+	return EOK;
+}
+
+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->handle, zone, BLOCK_FLAGS_NONE);
+	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;
+	block_put(b);
+	return EOK;
+}
+
+
+/**
+ * @}
+ */ 
+
Index: uspace/srv/fs/minixfs/mfs_utils.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_utils.c	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
+++ uspace/srv/fs/minixfs/mfs_utils.c	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
@@ -0,0 +1,66 @@
+/*
+ * 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 <assert.h>
+#include <errno.h>
+#include "mfs.h"
+#include "mfs_utils.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/mfs_utils.h
===================================================================
--- uspace/srv/fs/minixfs/mfs_utils.h	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
+++ uspace/srv/fs/minixfs/mfs_utils.h	(revision 969d88e9150467ef7c5e378c3ad4045fc2a63851)
@@ -0,0 +1,54 @@
+/*
+ * 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_UTILS_H_
+#define _MFS_UTILS_H_
+
+#include <sys/types.h>
+#include <bool.h>
+#include "mfs.h"
+
+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
+
+/**
+ * @}
+ */ 
+
