Index: uspace/srv/fs/devfs/devfs.c
===================================================================
--- uspace/srv/fs/devfs/devfs.c	(revision 6a44ee4a35beb95618457c456010a40522d2996a)
+++ uspace/srv/fs/devfs/devfs.c	(revision efcebe1bce63b6779458eadc2fd6f252ab7cd703)
@@ -57,65 +57,4 @@
 };
 
-fs_reg_t devfs_reg;
-
-static void devfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	if (iid)
-		async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			return;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case VFS_OUT_MOUNTED:
-			devfs_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			devfs_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			devfs_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			devfs_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			devfs_lookup(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			devfs_open_node(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			devfs_stat(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			devfs_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			devfs_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			devfs_truncate(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			devfs_close(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			devfs_sync(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			devfs_destroy(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char *argv[])
 {
@@ -134,6 +73,6 @@
 	}
 	
-	int rc = fs_register(vfs_sess, &devfs_reg, &devfs_vfs_info,
-	    devfs_connection);
+	int rc = fs_register(vfs_sess, &devfs_vfs_info, &devfs_ops,
+	    &devfs_libfs_ops);
 	if (rc != EOK) {
 		printf("%s: Failed to register file system (%d)\n", NAME, rc);
@@ -152,2 +91,3 @@
  * @}
  */
+
Index: uspace/srv/fs/devfs/devfs.h
===================================================================
--- uspace/srv/fs/devfs/devfs.h	(revision 6a44ee4a35beb95618457c456010a40522d2996a)
+++ uspace/srv/fs/devfs/devfs.h	(revision efcebe1bce63b6779458eadc2fd6f252ab7cd703)
@@ -36,5 +36,6 @@
 #include <libfs.h>
 
-extern fs_reg_t devfs_reg;
+extern vfs_out_ops_t devfs_ops;
+extern libfs_ops_t devfs_libfs_ops;
 
 #endif
Index: uspace/srv/fs/devfs/devfs_ops.c
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.c	(revision 6a44ee4a35beb95618457c456010a40522d2996a)
+++ uspace/srv/fs/devfs/devfs_ops.c	(revision efcebe1bce63b6779458eadc2fd6f252ab7cd703)
@@ -403,9 +403,4 @@
 }
 
-static char devfs_plb_get_char(unsigned pos)
-{
-	return devfs_reg.plb_ro[pos % PLB_SIZE];
-}
-
 static bool devfs_is_directory(fs_node_t *fn)
 {
@@ -447,5 +442,4 @@
 	.size_get = devfs_size_get,
 	.lnkcnt_get = devfs_lnkcnt_get,
-	.plb_get_char = devfs_plb_get_char,
 	.is_directory = devfs_is_directory,
 	.is_file = devfs_is_file,
@@ -462,56 +456,22 @@
 }
 
-void devfs_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	char *opts;
-	
-	/* Accept the mount options */
-	sysarg_t retval = async_data_write_accept((void **) &opts, true, 0, 0,
-	    0, NULL);
-	if (retval != EOK) {
-		async_answer_0(rid, retval);
-		return;
-	}
-	
-	free(opts);
-	async_answer_3(rid, EOK, 0, 0, 0);
-}
-
-void devfs_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_mount(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
-
-void devfs_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_unmount(&devfs_libfs_ops, rid, request);
-}
-
-void devfs_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_lookup(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_open_node(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_stat(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+static int devfs_mounted(devmap_handle_t devmap_handle, const char *opts,
+    fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
+{
+	*index = 0;
+	*size = 0;
+	*lnkcnt = 0;
+	return EOK;
+}
+
+static int devfs_unmounted(devmap_handle_t devmap_handle)
+{
+	return ENOTSUP;
+}
+
+static int
+devfs_read(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
 	if (index == 0) {
 		ipc_callid_t callid;
@@ -519,6 +479,5 @@
 		if (!async_data_read_receive(&callid, &size)) {
 			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
+			return EINVAL;
 		}
 		
@@ -540,6 +499,6 @@
 			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
 			free(desc);
-			async_answer_1(rid, EOK, 1);
-			return;
+			*rbytes = 1;
+			return EOK;
 		}
 		
@@ -555,6 +514,6 @@
 				async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
 				free(desc);
-				async_answer_1(rid, EOK, 1);
-				return;
+				*rbytes = 1;
+				return EOK;
 			}
 			
@@ -563,6 +522,5 @@
 		
 		async_answer_0(callid, ENOENT);
-		async_answer_1(rid, ENOENT, 0);
-		return;
+		return ENOENT;
 	}
 	
@@ -575,6 +533,5 @@
 		if (!async_data_read_receive(&callid, &size)) {
 			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
+			return EINVAL;
 		}
 		
@@ -585,12 +542,11 @@
 			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
 			free(desc);
-			async_answer_1(rid, EOK, 1);
-			return;
+			*rbytes = 1;
+			return EOK;
 		}
 		
 		free(desc);
 		async_answer_0(callid, ENOENT);
-		async_answer_1(rid, ENOENT, 0);
-		return;
+		return ENOENT;
 	}
 	
@@ -606,6 +562,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
+			return ENOENT;
 		}
 		
@@ -617,6 +572,5 @@
 			fibril_mutex_unlock(&devices_mutex);
 			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
+			return EINVAL;
 		}
 		
@@ -625,7 +579,6 @@
 		
 		ipc_call_t answer;
-		aid_t msg = async_send_3(exch, IPC_GET_IMETHOD(*request),
-		    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
-		    IPC_GET_ARG3(*request), &answer);
+		aid_t msg = async_send_4(exch, VFS_OUT_READ, devmap_handle,
+		    index, LOWER32(pos), UPPER32(pos), &answer);
 		
 		/* Forward the IPC_M_DATA_READ request to the driver */
@@ -639,21 +592,18 @@
 		sysarg_t rc;
 		async_wait_for(msg, &rc);
-		size_t bytes = IPC_GET_ARG1(answer);
-		
-		/* Driver reply is the final result of the whole operation */
-		async_answer_1(rid, rc, bytes);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void devfs_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	if (index == 0) {
-		async_answer_0(rid, ENOTSUP);
-		return;
-	}
+		
+		*rbytes = IPC_GET_ARG1(answer);
+		return rc;
+	}
+	
+	return ENOENT;
+}
+
+static int
+devfs_write(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
+	if (index == 0)
+		return ENOTSUP;
 	
 	devmap_handle_type_t type = devmap_handle_probe(index);
@@ -661,6 +611,5 @@
 	if (type == DEV_HANDLE_NAMESPACE) {
 		/* Namespace directory */
-		async_answer_0(rid, ENOTSUP);
-		return;
+		return ENOTSUP;
 	}
 	
@@ -675,6 +624,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
+			return ENOENT;
 		}
 		
@@ -686,6 +634,5 @@
 			fibril_mutex_unlock(&devices_mutex);
 			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
+			return EINVAL;
 		}
 		
@@ -694,7 +641,6 @@
 		
 		ipc_call_t answer;
-		aid_t msg = async_send_3(exch, IPC_GET_IMETHOD(*request),
-		    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
-		    IPC_GET_ARG3(*request), &answer);
+		aid_t msg = async_send_4(exch, VFS_OUT_WRITE, devmap_handle,
+		    index, LOWER32(pos), UPPER32(pos), &answer);
 		
 		/* Forward the IPC_M_DATA_WRITE request to the driver */
@@ -708,27 +654,23 @@
 		sysarg_t rc;
 		async_wait_for(msg, &rc);
-		size_t bytes = IPC_GET_ARG1(answer);
-		
-		/* Driver reply is the final result of the whole operation */
-		async_answer_1(rid, rc, bytes);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
-
-void devfs_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
-	if (index == 0) {
-		async_answer_0(rid, EOK);
-		return;
-	}
+		
+		*wbytes = IPC_GET_ARG1(answer);
+		*nsize = 0;
+		return rc;
+	}
+	
+	return ENOENT;
+}
+
+static int
+devfs_truncate(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t size)
+{
+	return ENOTSUP;
+}
+
+static int devfs_close(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	if (index == 0)
+		return EOK;
 	
 	devmap_handle_type_t type = devmap_handle_probe(index);
@@ -736,6 +678,5 @@
 	if (type == DEV_HANDLE_NAMESPACE) {
 		/* Namespace directory */
-		async_answer_0(rid, EOK);
-		return;
+		return EOK;
 	}
 	
@@ -749,6 +690,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
+			return ENOENT;
 		}
 		
@@ -764,19 +704,14 @@
 		fibril_mutex_unlock(&devices_mutex);
 		
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void devfs_sync(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
-	if (index == 0) {
-		async_answer_0(rid, EOK);
-		return;
-	}
+		return EOK;
+	}
+	
+	return ENOENT;
+}
+
+static int devfs_sync(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	if (index == 0)
+		return EOK;
 	
 	devmap_handle_type_t type = devmap_handle_probe(index);
@@ -784,6 +719,5 @@
 	if (type == DEV_HANDLE_NAMESPACE) {
 		/* Namespace directory */
-		async_answer_0(rid, EOK);
-		return;
+		return EOK;
 	}
 	
@@ -797,6 +731,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
+			return ENOENT;
 		}
 		
@@ -808,6 +741,6 @@
 		
 		ipc_call_t answer;
-		aid_t msg = async_send_2(exch, IPC_GET_IMETHOD(*request),
-		    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), &answer);
+		aid_t msg = async_send_2(exch, VFS_OUT_SYNC, devmap_handle,
+		    index, &answer);
 		
 		async_exchange_end(exch);
@@ -819,16 +752,25 @@
 		async_wait_for(msg, &rc);
 		
-		/* Driver reply is the final result of the whole operation */
-		async_answer_0(rid, rc);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void devfs_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
+		return rc;
+	}
+	
+	return  ENOENT;
+}
+
+static int devfs_destroy(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	return ENOTSUP;
+}
+
+vfs_out_ops_t devfs_ops = {
+	.mounted = devfs_mounted,
+	.unmounted = devfs_unmounted,
+	.read = devfs_read,
+	.write = devfs_write,
+	.truncate = devfs_truncate,
+	.close = devfs_close,
+	.destroy = devfs_destroy,
+	.sync = devfs_sync,
+};
 
 /**
Index: uspace/srv/fs/devfs/devfs_ops.h
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.h	(revision 6a44ee4a35beb95618457c456010a40522d2996a)
+++ uspace/srv/fs/devfs/devfs_ops.h	(revision efcebe1bce63b6779458eadc2fd6f252ab7cd703)
@@ -34,22 +34,7 @@
 #define DEVFS_DEVFS_OPS_H_
 
-#include <ipc/common.h>
 #include <bool.h>
 
 extern bool devfs_init(void);
-
-extern void devfs_mounted(ipc_callid_t, ipc_call_t *);
-extern void devfs_mount(ipc_callid_t, ipc_call_t *);
-extern void devfs_unmounted(ipc_callid_t, ipc_call_t *);
-extern void devfs_unmount(ipc_callid_t, ipc_call_t *);
-extern void devfs_lookup(ipc_callid_t, ipc_call_t *);
-extern void devfs_open_node(ipc_callid_t, ipc_call_t *);
-extern void devfs_stat(ipc_callid_t, ipc_call_t *);
-extern void devfs_sync(ipc_callid_t, ipc_call_t *);
-extern void devfs_read(ipc_callid_t, ipc_call_t *);
-extern void devfs_write(ipc_callid_t, ipc_call_t *);
-extern void devfs_truncate(ipc_callid_t, ipc_call_t *);
-extern void devfs_close(ipc_callid_t, ipc_call_t *);
-extern void devfs_destroy(ipc_callid_t, ipc_call_t *);
 
 #endif
Index: uspace/srv/fs/ext2fs/ext2fs.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs.c	(revision 6a44ee4a35beb95618457c456010a40522d2996a)
+++ uspace/srv/fs/ext2fs/ext2fs.c	(revision efcebe1bce63b6779458eadc2fd6f252ab7cd703)
@@ -1,5 +1,4 @@
 /*
  * Copyright (c) 2006 Martin Decky
- * Copyright (c) 2008 Jakub Jermar
  * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
@@ -55,90 +54,4 @@
 };
 
-fs_reg_t ext2fs_reg;
-
-/**
- * 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 EXT2FS. To overcome this bottleneck, VFS can send EXT2FS 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, EXT2FS 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, EXT2FS might want to keep the connections open after the
- * request has been completed.
- */
-static void ext2fs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	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);
-	}
-	
-	dprintf(NAME ": connection opened\n");
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			return;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case VFS_OUT_MOUNTED:
-			ext2fs_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			ext2fs_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			ext2fs_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			ext2fs_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			ext2fs_lookup(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			ext2fs_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			ext2fs_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			ext2fs_truncate(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			ext2fs_stat(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			ext2fs_close(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			ext2fs_destroy(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			ext2fs_open_node(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			ext2fs_sync(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char **argv)
 {
@@ -158,5 +71,6 @@
 	}	
 		
-	rc = fs_register(vfs_sess, &ext2fs_reg, &ext2fs_vfs_info, ext2fs_connection);
+	rc = fs_register(vfs_sess, &ext2fs_vfs_info, &ext2fs_ops,
+	    &ext2fs_libfs_ops);
 	if (rc != EOK) {
 		fprintf(stdout, NAME ": Failed to register fs (%d)\n", rc);
Index: uspace/srv/fs/ext2fs/ext2fs.h
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs.h	(revision 6a44ee4a35beb95618457c456010a40522d2996a)
+++ uspace/srv/fs/ext2fs/ext2fs.h	(revision efcebe1bce63b6779458eadc2fd6f252ab7cd703)
@@ -1,4 +1,3 @@
 /*
- * Copyright (c) 2008 Jakub Jermar
  * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
@@ -36,35 +35,14 @@
 
 #include <libext2.h>
-#include <fibril_synch.h>
 #include <libfs.h>
-#include <atomic.h>
 #include <sys/types.h>
-#include <bool.h>
-#include "../../vfs/vfs.h"
-
-#ifndef dprintf
-#define dprintf(...)	printf(__VA_ARGS__)
-#endif
 
 #define min(a, b)		((a) < (b) ? (a) : (b))
 
-extern fs_reg_t ext2fs_reg;
+extern vfs_out_ops_t ext2fs_ops;
+extern libfs_ops_t ext2fs_libfs_ops;
 
 extern int ext2fs_global_init(void);
 extern int ext2fs_global_fini(void);
-extern void ext2fs_mounted(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_mount(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_unmounted(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_unmount(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_lookup(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_read(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_write(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_truncate(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_stat(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_close(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_destroy(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_open_node(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_stat(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_sync(ipc_callid_t, ipc_call_t *);
 
 #endif
Index: uspace/srv/fs/ext2fs/ext2fs_ops.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision 6a44ee4a35beb95618457c456010a40522d2996a)
+++ uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision efcebe1bce63b6779458eadc2fd6f252ab7cd703)
@@ -1,4 +1,3 @@
 /*
- * Copyright (c) 2008 Jakub Jermar
  * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
@@ -87,8 +86,8 @@
  */
 static int ext2fs_instance_get(devmap_handle_t, ext2fs_instance_t **);
-static void ext2fs_read_directory(ipc_callid_t, ipc_callid_t, aoff64_t,
-	size_t, ext2fs_instance_t *, ext2_inode_ref_t *);
-static void ext2fs_read_file(ipc_callid_t, ipc_callid_t, aoff64_t,
-	size_t, ext2fs_instance_t *, ext2_inode_ref_t *);
+static int ext2fs_read_directory(ipc_callid_t, aoff64_t, size_t,
+    ext2fs_instance_t *, ext2_inode_ref_t *, size_t *);
+static int ext2fs_read_file(ipc_callid_t, aoff64_t, size_t, ext2fs_instance_t *,
+    ext2_inode_ref_t *, size_t *);
 static bool ext2fs_is_dots(const uint8_t *, size_t);
 static int ext2fs_node_get_core(fs_node_t **, ext2fs_instance_t *, fs_index_t);
@@ -111,5 +110,4 @@
 static aoff64_t ext2fs_size_get(fs_node_t *);
 static unsigned ext2fs_lnkcnt_get(fs_node_t *);
-static char ext2fs_plb_get_char(unsigned);
 static bool ext2fs_is_directory(fs_node_t *);
 static bool ext2fs_is_file(fs_node_t *node);
@@ -538,9 +536,4 @@
 	EXT2FS_DBG("%u", count);
 	return count;
-}
-
-char ext2fs_plb_get_char(unsigned pos)
-{
-	return ext2fs_reg.plb_ro[pos % PLB_SIZE];
 }
 
@@ -586,5 +579,4 @@
 	.size_get = ext2fs_size_get,
 	.lnkcnt_get = ext2fs_lnkcnt_get,
-	.plb_get_char = ext2fs_plb_get_char,
 	.is_directory = ext2fs_is_directory,
 	.is_file = ext2fs_is_file,
@@ -596,30 +588,17 @@
  */
 
-void ext2fs_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	int rc;
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+static int ext2fs_mounted(devmap_handle_t devmap_handle, const char *opts,
+   fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
+{
+	EXT2FS_DBG("");
+	int rc;
 	ext2_filesystem_t *fs;
 	ext2fs_instance_t *inst;
 	bool read_only;
 	
-	/* Accept the mount options */
-	char *opts;
-	rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
-	
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-
-	free(opts);
-	
 	/* Allocate libext2 filesystem structure */
 	fs = (ext2_filesystem_t *) malloc(sizeof(ext2_filesystem_t));
-	if (fs == NULL) {
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
+	if (fs == NULL)
+		return ENOMEM;
 	
 	/* Allocate instance structure */
@@ -627,6 +606,5 @@
 	if (inst == NULL) {
 		free(fs);
-		async_answer_0(rid, ENOMEM);
-		return;
+		return ENOMEM;
 	}
 	
@@ -636,6 +614,5 @@
 		free(fs);
 		free(inst);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -646,6 +623,5 @@
 		free(fs);
 		free(inst);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -656,6 +632,5 @@
 		free(fs);
 		free(inst);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -673,6 +648,5 @@
 		free(fs);
 		free(inst);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	ext2fs_node_t *enode = EXT2FS_NODE(root_node);
@@ -683,22 +657,16 @@
 	fibril_mutex_unlock(&instance_list_mutex);
 	
-	async_answer_3(rid, EOK,
-	    EXT2_INODE_ROOT_INDEX,
-	    0,
-	    ext2_inode_get_usage_count(enode->inode_ref->inode));
+	*index = EXT2_INODE_ROOT_INDEX;
+	*size = 0;
+	*lnkcnt = ext2_inode_get_usage_count(enode->inode_ref->inode);
 	
 	ext2fs_node_put(root_node);
-}
-
-void ext2fs_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_mount(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
-}
-
-void ext2fs_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+
+	return EOK;
+}
+
+static int ext2fs_unmounted(devmap_handle_t devmap_handle)
+{
+	EXT2FS_DBG("");
 	ext2fs_instance_t *inst;
 	int rc;
@@ -706,8 +674,6 @@
 	rc = ext2fs_instance_get(devmap_handle, &inst);
 	
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
 	
 	fibril_mutex_lock(&open_nodes_lock);
@@ -716,6 +682,5 @@
 	if (inst->open_nodes_count != 0) {
 		fibril_mutex_unlock(&open_nodes_lock);
-		async_answer_0(rid, EBUSY);
-		return;
+		return EBUSY;
 	}
 	
@@ -729,26 +694,12 @@
 	ext2_filesystem_fini(inst->filesystem);
 	
-	async_answer_0(rid, EOK);
-}
-
-void ext2fs_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_unmount(&ext2fs_libfs_ops, rid, request);
-}
-
-void ext2fs_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_lookup(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
-}
-
-void ext2fs_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+	return EOK;
+}
+
+static int
+ext2fs_read(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
+	EXT2FS_DBG("");
 	
 	ext2fs_instance_t *inst;
@@ -763,6 +714,5 @@
 	if (!async_data_read_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 	
@@ -770,6 +720,5 @@
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -777,24 +726,24 @@
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
 	if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
-		    EXT2_INODE_MODE_FILE)) {
-		ext2fs_read_file(rid, callid, pos, size, inst, inode_ref);
-	}
-	else if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
-		    EXT2_INODE_MODE_DIRECTORY)) {
-		ext2fs_read_directory(rid, callid, pos, size, inst, inode_ref);
-	}
-	else {
+	    EXT2_INODE_MODE_FILE)) {
+		rc = ext2fs_read_file(callid, pos, size, inst, inode_ref,
+		    rbytes);
+	} else if (ext2_inode_is_type(inst->filesystem->superblock,
+	    inode_ref->inode, EXT2_INODE_MODE_DIRECTORY)) {
+		rc = ext2fs_read_directory(callid, pos, size, inst, inode_ref,
+		    rbytes);
+	} else {
 		/* Other inode types not supported */
 		async_answer_0(callid, ENOTSUP);
-		async_answer_0(rid, ENOTSUP);
+		rc = ENOTSUP;
 	}
 	
 	ext2_filesystem_put_inode_ref(inode_ref);
 	
+	return rc;
 }
 
@@ -814,6 +763,6 @@
 }
 
-void ext2fs_read_directory(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,
-	size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)
+int ext2fs_read_directory(ipc_callid_t callid, aoff64_t pos, size_t size,
+    ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes)
 {
 	ext2_directory_iterator_t it;
@@ -827,6 +776,5 @@
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -841,5 +789,5 @@
 		
 		name_size = ext2_directory_entry_ll_get_name_length(
-			inst->filesystem->superblock, it.current);
+		    inst->filesystem->superblock, it.current);
 		
 		/* skip . and .. */
@@ -849,18 +797,17 @@
 		
 		/* The on-disk entry does not contain \0 at the end
-			* end of entry name, so we copy it to new buffer
-			* and add the \0 at the end
-			*/
+		 * end of entry name, so we copy it to new buffer
+		 * and add the \0 at the end
+		 */
 		buf = malloc(name_size+1);
 		if (buf == NULL) {
 			ext2_directory_iterator_fini(&it);
 			async_answer_0(callid, ENOMEM);
-			async_answer_0(rid, ENOMEM);
-			return;
+			return ENOMEM;
 		}
 		memcpy(buf, &it.current->name, name_size);
-		*(buf+name_size) = 0;
+		*(buf + name_size) = 0;
 		found = true;
-		(void) async_data_read_finalize(callid, buf, name_size+1);
+		(void) async_data_read_finalize(callid, buf, name_size + 1);
 		free(buf);
 		break;
@@ -871,6 +818,5 @@
 			ext2_directory_iterator_fini(&it);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 	}
@@ -878,28 +824,24 @@
 	if (found) {
 		rc = ext2_directory_iterator_next(&it);
-		if (rc != EOK) {
-			async_answer_0(rid, rc);
-			return;
-		}
+		if (rc != EOK)
+			return rc;
 		next = it.current_offset;
 	}
 	
 	rc = ext2_directory_iterator_fini(&it);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
 	
 	if (found) {
-		async_answer_1(rid, EOK, next-pos);
-	}
-	else {
+		*rbytes = next - pos;
+		return EOK;
+	} else {
 		async_answer_0(callid, ENOENT);
-		async_answer_0(rid, ENOENT);
-	}
-}
-
-void ext2fs_read_file(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,
-	size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)
+		return ENOENT;
+	}
+}
+
+int ext2fs_read_file(ipc_callid_t callid, aoff64_t pos, size_t size,
+    ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes)
 {
 	int rc;
@@ -919,6 +861,6 @@
 		/* Read 0 bytes successfully */
 		async_data_read_finalize(callid, NULL, 0);
-		async_answer_1(rid, EOK, 0);
-		return;
+		*rbytes = 0;
+		return EOK;
 	}
 	
@@ -939,6 +881,5 @@
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -952,6 +893,5 @@
 		if (buffer == NULL) {
 			async_answer_0(callid, ENOMEM);
-			async_answer_0(rid, ENOMEM);
-			return;
+			return ENOMEM;
 		}
 		
@@ -959,9 +899,9 @@
 		
 		async_data_read_finalize(callid, buffer, bytes);
-		async_answer_1(rid, EOK, bytes);
+		*rbytes = bytes;
 		
 		free(buffer);
 		
-		return;
+		return EOK;
 	}
 	
@@ -970,6 +910,5 @@
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -978,75 +917,57 @@
 	
 	rc = block_put(block);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-		
-	async_answer_1(rid, EOK, bytes);
-}
-
-void ext2fs_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-//	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-//	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-//	aoff64_t pos =
-//	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
-	// TODO
-	async_answer_0(rid, ENOTSUP);
-}
-
-void ext2fs_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-//	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-//	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-//	aoff64_t size =
-//	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
-	// TODO
-	async_answer_0(rid, ENOTSUP);
-}
-
-void ext2fs_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	async_answer_0(rid, EOK);
-}
-
-void ext2fs_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-//	devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
-//	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	
-	// TODO
-	async_answer_0(rid, ENOTSUP);
-}
-
-void ext2fs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_open_node(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
-}
-
-void ext2fs_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_stat(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
-}
-
-void ext2fs_sync(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-//	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-//	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
-	// TODO
-	async_answer_0(rid, ENOTSUP);
-}
+	if (rc != EOK)
+		return rc;
+	
+	*rbytes = bytes;
+	return EOK;
+}
+
+static int
+ext2fs_write(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+static int
+ext2fs_truncate(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t size)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+static int ext2fs_close(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	EXT2FS_DBG("");
+	return EOK;
+}
+
+static int ext2fs_destroy(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+static int ext2fs_sync(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+vfs_out_ops_t ext2fs_ops = {
+	.mounted = ext2fs_mounted,
+	.unmounted = ext2fs_unmounted,
+	.read = ext2fs_read,
+	.write = ext2fs_write,
+	.truncate = ext2fs_truncate,
+	.close = ext2fs_close,
+	.destroy = ext2fs_destroy,
+	.sync = ext2fs_sync,
+};
 
 /**
  * @}
  */
+
Index: uspace/srv/fs/fat/fat.c
===================================================================
--- uspace/srv/fs/fat/fat.c	(revision 6a44ee4a35beb95618457c456010a40522d2996a)
+++ uspace/srv/fs/fat/fat.c	(revision efcebe1bce63b6779458eadc2fd6f252ab7cd703)
@@ -56,91 +56,4 @@
 };
 
-fs_reg_t fat_reg;
-
-/**
- * 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 FAT. To overcome this bottleneck, VFS can send FAT 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, FAT 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, FAT might want to keep the connections open after the
- * request has been completed.
- */
-static void fat_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	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);
-	}
-	
-	dprintf(NAME ": connection opened\n");
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			return;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case VFS_OUT_MOUNTED:
-			fat_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			fat_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			fat_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			fat_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			fat_lookup(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			fat_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			fat_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			fat_truncate(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			fat_stat(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			fat_close(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			fat_destroy(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			fat_open_node(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			fat_sync(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char **argv)
 {
@@ -158,5 +71,5 @@
 	}
 	
-	rc = fs_register(vfs_sess, &fat_reg, &fat_vfs_info, fat_connection);
+	rc = fs_register(vfs_sess, &fat_vfs_info, &fat_ops, &fat_libfs_ops);
 	if (rc != EOK) {
 		fat_idx_fini();
Index: uspace/srv/fs/fat/fat.h
===================================================================
--- uspace/srv/fs/fat/fat.h	(revision 6a44ee4a35beb95618457c456010a40522d2996a)
+++ uspace/srv/fs/fat/fat.h	(revision efcebe1bce63b6779458eadc2fd6f252ab7cd703)
@@ -224,20 +224,6 @@
 } fat_node_t;
 
-extern fs_reg_t fat_reg;
-
-extern void fat_mounted(ipc_callid_t, ipc_call_t *);
-extern void fat_mount(ipc_callid_t, ipc_call_t *);
-extern void fat_unmounted(ipc_callid_t, ipc_call_t *);
-extern void fat_unmount(ipc_callid_t, ipc_call_t *);
-extern void fat_lookup(ipc_callid_t, ipc_call_t *);
-extern void fat_read(ipc_callid_t, ipc_call_t *);
-extern void fat_write(ipc_callid_t, ipc_call_t *);
-extern void fat_truncate(ipc_callid_t, ipc_call_t *);
-extern void fat_stat(ipc_callid_t, ipc_call_t *);
-extern void fat_close(ipc_callid_t, ipc_call_t *);
-extern void fat_destroy(ipc_callid_t, ipc_call_t *);
-extern void fat_open_node(ipc_callid_t, ipc_call_t *);
-extern void fat_stat(ipc_callid_t, ipc_call_t *);
-extern void fat_sync(ipc_callid_t, ipc_call_t *);
+extern vfs_out_ops_t fat_ops;
+extern libfs_ops_t fat_libfs_ops;
 
 extern int fat_idx_get_new(fat_idx_t **, devmap_handle_t);
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 6a44ee4a35beb95618457c456010a40522d2996a)
+++ uspace/srv/fs/fat/fat_ops.c	(revision efcebe1bce63b6779458eadc2fd6f252ab7cd703)
@@ -85,5 +85,4 @@
 static aoff64_t fat_size_get(fs_node_t *);
 static unsigned fat_lnkcnt_get(fs_node_t *);
-static char fat_plb_get_char(unsigned);
 static bool fat_is_directory(fs_node_t *);
 static bool fat_is_file(fs_node_t *node);
@@ -901,9 +900,4 @@
 }
 
-char fat_plb_get_char(unsigned pos)
-{
-	return fat_reg.plb_ro[pos % PLB_SIZE];
-}
-
 bool fat_is_directory(fs_node_t *fn)
 {
@@ -936,5 +930,4 @@
 	.size_get = fat_size_get,
 	.lnkcnt_get = fat_lnkcnt_get,
-	.plb_get_char = fat_plb_get_char,
 	.is_directory = fat_is_directory,
 	.is_file = fat_is_file,
@@ -943,22 +936,15 @@
 
 /*
- * VFS operations.
+ * FAT VFS_OUT operations.
  */
 
-void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+static int
+fat_mounted(devmap_handle_t devmap_handle, const char *opts, fs_index_t *index,
+    aoff64_t *size, unsigned *linkcnt)
+{
 	enum cache_mode cmode;
 	fat_bs_t *bs;
-	
-	/* Accept the mount options */
-	char *opts;
-	int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
-	
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-
+	int rc;
+	
 	/* Check for option enabling write through. */
 	if (str_cmp(opts, "wtcache") == 0)
@@ -967,12 +953,8 @@
 		cmode = CACHE_MODE_WB;
 
-	free(opts);
-
 	/* initialize libblock */
 	rc = block_init(EXCHANGE_SERIALIZE, devmap_handle, BS_SIZE);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
 
 	/* prepare the boot block */
@@ -980,6 +962,5 @@
 	if (rc != EOK) {
 		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 
@@ -989,6 +970,5 @@
 	if (BPS(bs) != BS_SIZE) {
 		block_fini(devmap_handle);
-		async_answer_0(rid, ENOTSUP);
-		return;
+		return ENOTSUP;
 	}
 
@@ -997,6 +977,5 @@
 	if (rc != EOK) {
 		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 
@@ -1006,6 +985,5 @@
 		(void) block_cache_fini(devmap_handle);
 		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 
@@ -1014,6 +992,5 @@
 		(void) block_cache_fini(devmap_handle);
 		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 
@@ -1024,6 +1001,5 @@
 		block_fini(devmap_handle);
 		fat_idx_fini_by_devmap_handle(devmap_handle);
-		async_answer_0(rid, ENOMEM);
-		return;
+		return ENOMEM;
 	}
 	fs_node_initialize(rfn);
@@ -1034,6 +1010,5 @@
 		block_fini(devmap_handle);
 		fat_idx_fini_by_devmap_handle(devmap_handle);
-		async_answer_0(rid, ENOMEM);
-		return;
+		return ENOMEM;
 	}
 	fat_node_initialize(rootp);
@@ -1046,6 +1021,5 @@
 		block_fini(devmap_handle);
 		fat_idx_fini_by_devmap_handle(devmap_handle);
-		async_answer_0(rid, ENOMEM);
-		return;
+		return ENOMEM;
 	}
 	assert(ridxp->index == 0);
@@ -1064,15 +1038,13 @@
 	fibril_mutex_unlock(&ridxp->lock);
 
-	async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
-}
-
-void fat_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+	*index = ridxp->index;
+	*size = rootp->size;
+	*linkcnt = rootp->lnkcnt;
+
+	return EOK;
+}
+
+static int fat_unmounted(devmap_handle_t devmap_handle)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1080,8 +1052,6 @@
 
 	rc = fat_root_get(&fn, devmap_handle);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
 	nodep = FAT_NODE(fn);
 
@@ -1092,6 +1062,5 @@
 	if (nodep->refcnt != 2) {
 		(void) fat_node_put(fn);
-		async_answer_0(rid, EBUSY);
-		return;
+		return EBUSY;
 	}
 	
@@ -1112,23 +1081,11 @@
 	block_fini(devmap_handle);
 
-	async_answer_0(rid, EOK);
-}
-
-void fat_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_unmount(&fat_libfs_ops, rid, request);
-}
-
-void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+	return EOK;
+}
+
+static int
+fat_read(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1139,12 +1096,8 @@
 
 	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 
@@ -1154,6 +1107,5 @@
 		fat_node_put(fn);
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -1178,6 +1130,5 @@
 				fat_node_put(fn);
 				async_answer_0(callid, rc);
-				async_answer_0(rid, rc);
-				return;
+				return rc;
 			}
 			(void) async_data_read_finalize(callid,
@@ -1186,6 +1137,5 @@
 			if (rc != EOK) {
 				fat_node_put(fn);
-				async_answer_0(rid, rc);
-				return;
+				return rc;
 			}
 		}
@@ -1244,12 +1194,11 @@
 		rc = fat_node_put(fn);
 		async_answer_0(callid, rc != EOK ? rc : ENOENT);
-		async_answer_1(rid, rc != EOK ? rc : ENOENT, 0);
-		return;
+		*rbytes = 0;
+		return rc != EOK ? rc : ENOENT;
 
 err:
 		(void) fat_node_put(fn);
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 
 hit:
@@ -1259,17 +1208,16 @@
 
 	rc = fat_node_put(fn);
-	async_answer_1(rid, rc, (sysarg_t)bytes);
-}
-
-void fat_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+	*rbytes = bytes;
+	return rc;
+}
+
+static int
+fat_write(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
 	fat_bs_t *bs;
-	size_t bytes, size;
+	size_t bytes;
 	block_t *b;
 	aoff64_t boundary;
@@ -1278,12 +1226,8 @@
 	
 	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 	
@@ -1293,6 +1237,5 @@
 		(void) fat_node_put(fn);
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -1322,6 +1265,5 @@
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		rc = fat_block_get(&b, bs, nodep, pos / BPS(bs), flags);
@@ -1329,6 +1271,5 @@
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		(void) async_data_write_finalize(callid,
@@ -1338,6 +1279,5 @@
 		if (rc != EOK) {
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		if (pos + bytes > nodep->size) {
@@ -1345,8 +1285,8 @@
 			nodep->dirty = true;	/* need to sync node */
 		}
-		size = nodep->size;
+		*wbytes = bytes;
+		*nsize = nodep->size;
 		rc = fat_node_put(fn);
-		async_answer_2(rid, rc, bytes, nodep->size);
-		return;
+		return rc;
 	} else {
 		/*
@@ -1364,6 +1304,5 @@
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		/* zero fill any gaps */
@@ -1373,6 +1312,5 @@
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		rc = _fat_block_get(&b, bs, devmap_handle, lcl, NULL,
@@ -1382,6 +1320,5 @@
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		(void) async_data_write_finalize(callid,
@@ -1392,6 +1329,5 @@
 			(void) fat_free_clusters(bs, devmap_handle, mcl);
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		/*
@@ -1403,21 +1339,17 @@
 			(void) fat_free_clusters(bs, devmap_handle, mcl);
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
-		}
-		nodep->size = size = pos + bytes;
+			return rc;
+		}
+		*nsize = nodep->size = pos + bytes;
+		rc = fat_node_put(fn);
 		nodep->dirty = true;		/* need to sync node */
-		rc = fat_node_put(fn);
-		async_answer_2(rid, rc, bytes, size);
-		return;
-	}
-}
-
-void fat_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t size =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+		*wbytes = bytes;
+		return rc;
+	}
+}
+
+static int
+fat_truncate(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t size)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1426,12 +1358,8 @@
 
 	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 
@@ -1477,17 +1405,14 @@
 out:
 	fat_node_put(fn);
-	async_answer_0(rid, rc);
-	return;
-}
-
-void fat_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, EOK);
-}
-
-void fat_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
+	return rc;
+}
+
+static int fat_close(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	return EOK;
+}
+
+static int fat_destroy(devmap_handle_t devmap_handle, fs_index_t index)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1495,12 +1420,8 @@
 
 	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 
 	nodep = FAT_NODE(fn);
@@ -1512,32 +1433,15 @@
 
 	rc = fat_destroy_node(fn);
-	async_answer_0(rid, rc);
-}
-
-void fat_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_sync(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
+	return rc;
+}
+
+static int fat_sync(devmap_handle_t devmap_handle, fs_index_t index)
+{
 	fs_node_t *fn;
 	int rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	
 	fat_node_t *nodep = FAT_NODE(fn);
@@ -1547,6 +1451,17 @@
 	
 	fat_node_put(fn);
-	async_answer_0(rid, rc);
-}
+	return rc;
+}
+
+vfs_out_ops_t fat_ops = {
+	.mounted = fat_mounted,
+	.unmounted = fat_unmounted,
+	.read = fat_read,
+	.write = fat_write,
+	.truncate = fat_truncate,
+	.close = fat_close,
+	.destroy = fat_destroy,
+	.sync = fat_sync,
+};
 
 /**
Index: uspace/srv/fs/tmpfs/tmpfs.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.c	(revision 6a44ee4a35beb95618457c456010a40522d2996a)
+++ uspace/srv/fs/tmpfs/tmpfs.c	(revision efcebe1bce63b6779458eadc2fd6f252ab7cd703)
@@ -61,92 +61,4 @@
 };
 
-fs_reg_t tmpfs_reg;
-
-/**
- * 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 FAT. To overcome this bottleneck, VFS can send TMPFS 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, TMPFS 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, TMPFS might want to keep the connections open after the
- * request has been completed.
- */
-static void tmpfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	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);
-	}
-	
-	dprintf(NAME ": connection opened\n");
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			return;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case VFS_OUT_MOUNTED:
-			tmpfs_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			tmpfs_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			tmpfs_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			tmpfs_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			tmpfs_lookup(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			tmpfs_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			tmpfs_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			tmpfs_truncate(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			tmpfs_close(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			tmpfs_destroy(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			tmpfs_open_node(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			tmpfs_stat(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			tmpfs_sync(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char **argv)
 {
@@ -165,6 +77,6 @@
 	}
 	
-	int rc = fs_register(vfs_sess, &tmpfs_reg, &tmpfs_vfs_info,
-	    tmpfs_connection);
+	int rc = fs_register(vfs_sess, &tmpfs_vfs_info, &tmpfs_ops,
+	    &tmpfs_libfs_ops);
 	if (rc != EOK) {
 		printf(NAME ": Failed to register file system (%d)\n", rc);
Index: uspace/srv/fs/tmpfs/tmpfs.h
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.h	(revision 6a44ee4a35beb95618457c456010a40522d2996a)
+++ uspace/srv/fs/tmpfs/tmpfs.h	(revision efcebe1bce63b6779458eadc2fd6f252ab7cd703)
@@ -70,24 +70,8 @@
 } tmpfs_node_t;
 
-extern fs_reg_t tmpfs_reg;
-
+extern vfs_out_ops_t tmpfs_ops;
 extern libfs_ops_t tmpfs_libfs_ops;
 
 extern bool tmpfs_init(void);
-
-extern void tmpfs_mounted(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_mount(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_unmounted(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_unmount(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_read(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_write(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_stat(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_close(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_open_node(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_sync(ipc_callid_t, ipc_call_t *);
-
 extern bool tmpfs_restore(devmap_handle_t);
 
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 6a44ee4a35beb95618457c456010a40522d2996a)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision efcebe1bce63b6779458eadc2fd6f252ab7cd703)
@@ -104,9 +104,4 @@
 }
 
-static char tmpfs_plb_get_char(unsigned pos)
-{
-	return tmpfs_reg.plb_ro[pos % PLB_SIZE];
-}
-
 static bool tmpfs_is_directory(fs_node_t *fn)
 {
@@ -139,5 +134,4 @@
 	.size_get = tmpfs_size_get,
 	.lnkcnt_get = tmpfs_lnkcnt_get,
-	.plb_get_char = tmpfs_plb_get_char,
 	.is_directory = tmpfs_is_directory,
 	.is_file = tmpfs_is_file,
@@ -433,33 +427,25 @@
 }
 
-void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+/*
+ * Implementation of the VFS_OUT interface.
+ */
+
+static int
+tmpfs_mounted(devmap_handle_t devmap_handle, const char *opts,
+    fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
+{
 	fs_node_t *rootfn;
 	int rc;
 	
-	/* Accept the mount options. */
-	char *opts;
-	rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-
 	/* Check if this device is not already mounted. */
 	rc = tmpfs_root_get(&rootfn, devmap_handle);
 	if ((rc == EOK) && (rootfn)) {
 		(void) tmpfs_node_put(rootfn);
-		free(opts);
-		async_answer_0(rid, EEXIST);
-		return;
+		return EEXIST;
 	}
 
 	/* Initialize TMPFS instance. */
-	if (!tmpfs_instance_init(devmap_handle)) {
-		free(opts);
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
+	if (!tmpfs_instance_init(devmap_handle))
+		return ENOMEM;
 
 	rc = tmpfs_root_get(&rootfn, devmap_handle);
@@ -467,46 +453,24 @@
 	tmpfs_node_t *rootp = TMPFS_NODE(rootfn);
 	if (str_cmp(opts, "restore") == 0) {
-		if (tmpfs_restore(devmap_handle))
-			async_answer_3(rid, EOK, rootp->index, rootp->size,
-			    rootp->lnkcnt);
-		else
-			async_answer_0(rid, ELIMIT);
-	} else {
-		async_answer_3(rid, EOK, rootp->index, rootp->size,
-		    rootp->lnkcnt);
-	}
-	free(opts);
-}
-
-void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_mount(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-
+		if (!tmpfs_restore(devmap_handle))
+			return ELIMIT;
+	}
+
+	*index = rootp->index;
+	*size = rootp->size;
+	*lnkcnt = rootp->lnkcnt;
+
+	return EOK;
+}
+
+static int tmpfs_unmounted(devmap_handle_t devmap_handle)
+{
 	tmpfs_instance_done(devmap_handle);
-	async_answer_0(rid, EOK);
-}
-
-void tmpfs_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_unmount(&tmpfs_libfs_ops, rid, request);
-}
-
-void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_lookup(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+	return EOK;
+}
+
+static int tmpfs_read(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
 	/*
 	 * Lookup the respective TMPFS node.
@@ -518,8 +482,6 @@
 	};
 	hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (!hlp)
+		return ENOENT;
 	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
 	    nh_link);
@@ -532,6 +494,5 @@
 	if (!async_data_read_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -556,6 +517,5 @@
 		if (lnk == NULL) {
 			async_answer_0(callid, ENOENT);
-			async_answer_1(rid, ENOENT, 0);
-			return;
+			return ENOENT;
 		}
 
@@ -567,17 +527,12 @@
 	}
 
-	/*
-	 * Answer the VFS_READ call.
-	 */
-	async_answer_1(rid, EOK, bytes);
-}
-
-void tmpfs_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+	*rbytes = bytes;
+	return EOK;
+}
+
+static int
+tmpfs_write(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
 	/*
 	 * Lookup the respective TMPFS node.
@@ -589,8 +544,6 @@
 	};
 	hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (!hlp)
+		return ENOENT;
 	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
 	    nh_link);
@@ -603,6 +556,5 @@
 	if (!async_data_write_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);	
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -612,7 +564,7 @@
 	if (pos + size <= nodep->size) {
 		/* The file size is not changing. */
-		(void) async_data_write_finalize(callid, nodep->data + pos, size);
-		async_answer_2(rid, EOK, size, nodep->size);
-		return;
+		(void) async_data_write_finalize(callid, nodep->data + pos,
+		    size);
+		goto out;
 	}
 	size_t delta = (pos + size) - nodep->size;
@@ -627,6 +579,6 @@
 	if (!newdata) {
 		async_answer_0(callid, ENOMEM);
-		async_answer_2(rid, EOK, 0, nodep->size);
-		return;
+		size = 0;
+		goto out;
 	}
 	/* Clear any newly allocated memory in order to emulate gaps. */
@@ -635,14 +587,14 @@
 	nodep->data = newdata;
 	(void) async_data_write_finalize(callid, nodep->data + pos, size);
-	async_answer_2(rid, EOK, size, nodep->size);
-}
-
-void tmpfs_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t size =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+
+out:
+	*wbytes = size;
+	*nsize = nodep->size;
+	return EOK;
+}
+
+static int tmpfs_truncate(devmap_handle_t devmap_handle, fs_index_t index,
+    aoff64_t size)
+{
 	/*
 	 * Lookup the respective TMPFS node.
@@ -653,26 +605,17 @@
 	};
 	link_t *hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
-	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
-	    nh_link);
-	
-	if (size == nodep->size) {
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	if (size > SIZE_MAX) {
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
+	if (!hlp)
+		return ENOENT;
+	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, nh_link);
+	
+	if (size == nodep->size)
+		return EOK;
+	
+	if (size > SIZE_MAX)
+		return ENOMEM;
 	
 	void *newdata = realloc(nodep->data, size);
-	if (!newdata) {
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
+	if (!newdata)
+		return ENOMEM;
 	
 	if (size > nodep->size) {
@@ -683,18 +626,14 @@
 	nodep->size = size;
 	nodep->data = newdata;
-	async_answer_0(rid, EOK);
-}
-
-void tmpfs_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, EOK);
-}
-
-void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	int rc;
-
+	return EOK;
+}
+
+static int tmpfs_close(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	return EOK;
+}
+
+static int tmpfs_destroy(devmap_handle_t devmap_handle, fs_index_t index)
+{
 	link_t *hlp;
 	unsigned long key[] = {
@@ -703,25 +642,12 @@
 	};
 	hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (!hlp)
+		return ENOENT;
 	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
 	    nh_link);
-	rc = tmpfs_destroy_node(FS_NODE(nodep));
-	async_answer_0(rid, rc);
-}
-
-void tmpfs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_open_node(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_stat(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_sync(ipc_callid_t rid, ipc_call_t *request)
+	return tmpfs_destroy_node(FS_NODE(nodep));
+}
+
+static int tmpfs_sync(devmap_handle_t devmap_handle, fs_index_t index)
 {
 	/*
@@ -729,8 +655,20 @@
 	 * thus the sync operation is a no-op.
 	 */
-	async_answer_0(rid, EOK);
-}
+	return EOK;
+}
+
+vfs_out_ops_t tmpfs_ops = {
+	.mounted = tmpfs_mounted,
+	.unmounted = tmpfs_unmounted,
+	.read = tmpfs_read,
+	.write = tmpfs_write,
+	.truncate = tmpfs_truncate,
+	.close = tmpfs_close,
+	.destroy = tmpfs_destroy,
+	.sync = tmpfs_sync,
+};
 
 /**
  * @}
  */
+
