Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision 44451ee572dc1c629706741a55d795a8c556cec0)
+++ uspace/lib/fs/libfs.c	(revision ffa2c8ef45390c01f3f4be4827bcd41c32f7951c)
@@ -45,5 +45,4 @@
 #include <mem.h>
 #include <sys/stat.h>
-#include <stdlib.h>
 
 #define on_error(rc, action) \
@@ -62,226 +61,4 @@
 	} while (0)
 
-static fs_reg_t reg;
-
-static vfs_out_ops_t *vfs_out_ops = NULL;
-static libfs_ops_t *libfs_ops = NULL;
-
-static void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
-static void libfs_unmount(libfs_ops_t *, ipc_callid_t, ipc_call_t *);
-static void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t,
-    ipc_call_t *);
-static void libfs_stat(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
-static void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t,
-    ipc_call_t *);
-
-static void vfs_out_mounted(ipc_callid_t rid, ipc_call_t *req)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
-	char *opts;
-	int rc;
-	
-	/* Accept the mount options. */
-	rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-
-	fs_index_t index;
-	aoff64_t size;
-	unsigned lnkcnt;
-	rc = vfs_out_ops->mounted(devmap_handle, opts, &index, &size, &lnkcnt);
-
-	if (rc == EOK)
-		async_answer_4(rid, EOK, index, LOWER32(size), UPPER32(size),
-		    lnkcnt);
-	else
-		async_answer_0(rid, rc);
-
-	free(opts);
-}
-
-static void vfs_out_mount(ipc_callid_t rid, ipc_call_t *req)
-{
-	libfs_mount(libfs_ops, reg.fs_handle, rid, req);
-}
-
-static void vfs_out_unmounted(ipc_callid_t rid, ipc_call_t *req)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
-	int rc; 
-
-	rc = vfs_out_ops->unmounted(devmap_handle);
-
-	async_answer_0(rid, rc);
-}
-
-static void vfs_out_unmount(ipc_callid_t rid, ipc_call_t *req)
-{
-		
-	libfs_unmount(libfs_ops, rid, req);
-}
-
-static void vfs_out_lookup(ipc_callid_t rid, ipc_call_t *req)
-{
-	libfs_lookup(libfs_ops, reg.fs_handle, rid, req);
-}
-
-static void vfs_out_read(ipc_callid_t rid, ipc_call_t *req)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
-	aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
-	    IPC_GET_ARG4(*req));
-	size_t rbytes;
-	int rc;
-
-	rc = vfs_out_ops->read(devmap_handle, index, pos, &rbytes);
-
-	if (rc == EOK)
-		async_answer_1(rid, EOK, rbytes);
-	else
-		async_answer_0(rid, rc);
-}
-
-static void vfs_out_write(ipc_callid_t rid, ipc_call_t *req)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
-	aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
-	    IPC_GET_ARG4(*req));
-	size_t wbytes;
-	aoff64_t nsize;
-	int rc;
-
-	rc = vfs_out_ops->write(devmap_handle, index, pos, &wbytes, &nsize);
-
-	if (rc == EOK)
-		async_answer_3(rid, EOK, wbytes, LOWER32(nsize), UPPER32(nsize));
-	else
-		async_answer_0(rid, rc);
-}
-
-static void vfs_out_truncate(ipc_callid_t rid, ipc_call_t *req)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
-	aoff64_t size = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
-	    IPC_GET_ARG4(*req));
-	int rc;
-
-	rc = vfs_out_ops->truncate(devmap_handle, index, size);
-
-	async_answer_0(rid, rc);
-}
-
-static void vfs_out_close(ipc_callid_t rid, ipc_call_t *req)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
-	int rc;
-
-	rc = vfs_out_ops->close(devmap_handle, index);
-
-	async_answer_0(rid, rc);
-}
-
-static void vfs_out_destroy(ipc_callid_t rid, ipc_call_t *req)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
-	int rc;
-
-	rc = vfs_out_ops->destroy(devmap_handle, index);
-
-	async_answer_0(rid, rc);
-}
-
-static void vfs_out_open_node(ipc_callid_t rid, ipc_call_t *req)
-{
-	libfs_open_node(libfs_ops, reg.fs_handle, rid, req);
-}
-
-static void vfs_out_stat(ipc_callid_t rid, ipc_call_t *req)
-{
-	libfs_stat(libfs_ops, reg.fs_handle, rid, req);
-}
-
-static void vfs_out_sync(ipc_callid_t rid, ipc_call_t *req)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
-	int rc;
-
-	rc = vfs_out_ops->sync(devmap_handle, index);
-
-	async_answer_0(rid, rc);
-}
-
-static void vfs_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);
-	}
-	
-	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:
-			vfs_out_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			vfs_out_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			vfs_out_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			vfs_out_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			vfs_out_lookup(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			vfs_out_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			vfs_out_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			vfs_out_truncate(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			vfs_out_close(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			vfs_out_destroy(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			vfs_out_open_node(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			vfs_out_stat(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			vfs_out_sync(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 /** Register file system server.
  *
@@ -290,15 +67,17 @@
  * code.
  *
- * @param sess Session for communication with VFS.
- * @param info VFS info structure supplied by the file system
- *             implementation.
- * @param vops Address of the vfs_out_ops_t structure.
- * @param lops Address of the libfs_ops_t structure.
+ * @param vfs_phone Open phone for communication with VFS.
+ * @param reg       File system registration structure. It will be
+ *                  initialized by this function.
+ * @param info      VFS info structure supplied by the file system
+ *                  implementation.
+ * @param conn      Connection fibril for handling all calls originating in
+ *                  VFS.
  *
  * @return EOK on success or a non-zero error code on errror.
  *
  */
-int fs_register(async_sess_t *sess, vfs_info_t *info, vfs_out_ops_t *vops,
-    libfs_ops_t *lops)
+int fs_register(int vfs_phone, fs_reg_t *reg, vfs_info_t *info,
+    async_client_conn_t conn)
 {
 	/*
@@ -307,17 +86,12 @@
 	 * out-of-order, when it knows that the operation succeeded or failed.
 	 */
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	
 	ipc_call_t answer;
-	aid_t req = async_send_0(exch, VFS_IN_REGISTER, &answer);
+	aid_t req = async_send_0(vfs_phone, VFS_IN_REGISTER, &answer);
 	
 	/*
 	 * Send our VFS info structure to VFS.
 	 */
-	int rc = async_data_write_start(exch, info, sizeof(*info));
-	
+	int rc = async_data_write_start(vfs_phone, info, sizeof(*info)); 
 	if (rc != EOK) {
-		async_exchange_end(exch);
 		async_wait_for(req, NULL);
 		return rc;
@@ -325,20 +99,13 @@
 	
 	/*
-	 * Set VFS_OUT and libfs operations.
-	 */
-	vfs_out_ops = vops;
-	libfs_ops = lops;
-
-	/*
 	 * Ask VFS for callback connection.
 	 */
-	async_connect_to_me(exch, 0, 0, 0, vfs_connection, NULL);
+	async_connect_to_me(vfs_phone, 0, 0, 0, conn);
 	
 	/*
 	 * Allocate piece of address space for PLB.
 	 */
-	reg.plb_ro = as_get_mappable_page(PLB_SIZE);
-	if (!reg.plb_ro) {
-		async_exchange_end(exch);
+	reg->plb_ro = as_get_mappable_page(PLB_SIZE);
+	if (!reg->plb_ro) {
 		async_wait_for(req, NULL);
 		return ENOMEM;
@@ -348,8 +115,5 @@
 	 * Request sharing the Path Lookup Buffer with VFS.
 	 */
-	rc = async_share_in_start_0_0(exch, reg.plb_ro, PLB_SIZE);
-	
-	async_exchange_end(exch);
-	
+	rc = async_share_in_start_0_0(vfs_phone, reg->plb_ro, PLB_SIZE);
 	if (rc) {
 		async_wait_for(req, NULL);
@@ -361,5 +125,5 @@
 	 */
 	async_wait_for(req, NULL);
-	reg.fs_handle = (int) IPC_GET_ARG1(answer);
+	reg->fs_handle = (int) IPC_GET_ARG1(answer);
 	
 	/*
@@ -367,5 +131,5 @@
 	 * the same connection fibril as well.
 	 */
-	async_set_client_connection(vfs_connection);
+	async_set_client_connection(conn);
 	
 	return IPC_GET_RETVAL(answer);
@@ -378,21 +142,33 @@
 
 void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
-    ipc_call_t *req)
+    ipc_call_t *request)
 {
-	devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
-	fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req);
-	fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*req);
-	devmap_handle_t mr_devmap_handle = (devmap_handle_t) IPC_GET_ARG4(*req);
-	
-	async_sess_t *mountee_sess = async_clone_receive(EXCHANGE_PARALLEL);
-	if (mountee_sess == NULL) {
+	devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+	fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request);
+	fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request);
+	devmap_handle_t mr_devmap_handle = (devmap_handle_t) IPC_GET_ARG4(*request);
+	int res;
+	sysarg_t rc;
+	
+	ipc_call_t call;
+	ipc_callid_t callid;
+	
+	/* Accept the phone */
+	callid = async_get_call(&call);
+	int mountee_phone = (int) IPC_GET_ARG1(call);
+	if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECTION_CLONE) ||
+	    (mountee_phone < 0)) {
+		async_answer_0(callid, EINVAL);
 		async_answer_0(rid, EINVAL);
 		return;
 	}
 	
+	/* Acknowledge the mountee_phone */
+	async_answer_0(callid, EOK);
+	
 	fs_node_t *fn;
-	int res = ops->node_get(&fn, mp_devmap_handle, mp_fs_index);
+	res = ops->node_get(&fn, mp_devmap_handle, mp_fs_index);
 	if ((res != EOK) || (!fn)) {
-		async_hangup(mountee_sess);
+		async_hangup(mountee_phone);
 		async_data_write_void(combine_rc(res, ENOENT));
 		async_answer_0(rid, combine_rc(res, ENOENT));
@@ -401,5 +177,5 @@
 	
 	if (fn->mp_data.mp_active) {
-		async_hangup(mountee_sess);
+		async_hangup(mountee_phone);
 		(void) ops->node_put(fn);
 		async_data_write_void(EBUSY);
@@ -408,20 +184,16 @@
 	}
 	
-	async_exch_t *exch = async_exchange_begin(mountee_sess);
-	async_sess_t *sess = async_connect_me(EXCHANGE_PARALLEL, exch);
-	
-	if (!sess) {
-		async_exchange_end(exch);
-		async_hangup(mountee_sess);
+	rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME);
+	if (rc != EOK) {
+		async_hangup(mountee_phone);
 		(void) ops->node_put(fn);
-		async_data_write_void(errno);
-		async_answer_0(rid, errno);
+		async_data_write_void(rc);
+		async_answer_0(rid, rc);
 		return;
 	}
 	
 	ipc_call_t answer;
-	int rc = async_data_write_forward_1_1(exch, VFS_OUT_MOUNTED,
+	rc = async_data_write_forward_1_1(mountee_phone, VFS_OUT_MOUNTED,
 	    mr_devmap_handle, &answer);
-	async_exchange_end(exch);
 	
 	if (rc == EOK) {
@@ -429,5 +201,5 @@
 		fn->mp_data.fs_handle = mr_fs_handle;
 		fn->mp_data.devmap_handle = mr_devmap_handle;
-		fn->mp_data.sess = mountee_sess;
+		fn->mp_data.phone = mountee_phone;
 	}
 	
@@ -435,12 +207,12 @@
 	 * Do not release the FS node so that it stays in memory.
 	 */
-	async_answer_4(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
-	    IPC_GET_ARG3(answer), IPC_GET_ARG4(answer));
+	async_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
+	    IPC_GET_ARG3(answer));
 }
 
-void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *req)
+void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *request)
 {
-	devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
-	fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req);
+	devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+	fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request);
 	fs_node_t *fn;
 	int res;
@@ -464,7 +236,6 @@
 	 * Tell the mounted file system to unmount.
 	 */
-	async_exch_t *exch = async_exchange_begin(fn->mp_data.sess);
-	res = async_req_1_0(exch, VFS_OUT_UNMOUNTED, fn->mp_data.devmap_handle);
-	async_exchange_end(exch);
+	res = async_req_1_0(fn->mp_data.phone, VFS_OUT_UNMOUNTED,
+	    fn->mp_data.devmap_handle);
 
 	/*
@@ -472,10 +243,9 @@
 	 */
 	if (res == EOK) {
-		async_hangup(fn->mp_data.sess);
+		async_hangup(fn->mp_data.phone);
 		fn->mp_data.mp_active = false;
 		fn->mp_data.fs_handle = 0;
 		fn->mp_data.devmap_handle = 0;
-		fn->mp_data.sess = NULL;
-		
+		fn->mp_data.phone = 0;
 		/* Drop the reference created in libfs_mount(). */
 		(void) ops->node_put(fn);
@@ -484,9 +254,4 @@
 	(void) ops->node_put(fn);
 	async_answer_0(rid, res);
-}
-
-static char plb_get_char(unsigned pos)
-{
-	return reg.plb_ro[pos % PLB_SIZE];
 }
 
@@ -505,12 +270,12 @@
  */
 void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
-    ipc_call_t *req)
+    ipc_call_t *request)
 {
-	unsigned int first = IPC_GET_ARG1(*req);
-	unsigned int last = IPC_GET_ARG2(*req);
+	unsigned int first = IPC_GET_ARG1(*request);
+	unsigned int last = IPC_GET_ARG2(*request);
 	unsigned int next = first;
-	devmap_handle_t devmap_handle = IPC_GET_ARG3(*req);
-	int lflag = IPC_GET_ARG4(*req);
-	fs_index_t index = IPC_GET_ARG5(*req);
+	devmap_handle_t devmap_handle = IPC_GET_ARG3(*request);
+	int lflag = IPC_GET_ARG4(*request);
+	fs_index_t index = IPC_GET_ARG5(*request);
 	char component[NAME_MAX + 1];
 	int len;
@@ -528,10 +293,7 @@
 	
 	if (cur->mp_data.mp_active) {
-		async_exch_t *exch = async_exchange_begin(cur->mp_data.sess);
-		async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, last,
-		    cur->mp_data.devmap_handle, lflag, index,
+		async_forward_slow(rid, cur->mp_data.phone, VFS_OUT_LOOKUP,
+		    next, last, cur->mp_data.devmap_handle, lflag, index,
 		    IPC_FF_ROUTE_FROM_ME);
-		async_exchange_end(exch);
-		
 		(void) ops->node_put(cur);
 		return;
@@ -539,5 +301,5 @@
 	
 	/* Eat slash */
-	if (plb_get_char(next) == '/')
+	if (ops->plb_get_char(next) == '/')
 		next++;
 	
@@ -552,5 +314,5 @@
 		/* Collect the component */
 		len = 0;
-		while ((next <= last) && (plb_get_char(next) != '/')) {
+		while ((next <= last) && (ops->plb_get_char(next) != '/')) {
 			if (len + 1 == NAME_MAX) {
 				/* Component length overflow */
@@ -558,5 +320,5 @@
 				goto out;
 			}
-			component[len++] = plb_get_char(next);
+			component[len++] = ops->plb_get_char(next);
 			/* Process next character */
 			next++;
@@ -589,10 +351,7 @@
 				next--;
 			
-			async_exch_t *exch = async_exchange_begin(tmp->mp_data.sess);
-			async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next,
-			    last, tmp->mp_data.devmap_handle, lflag, index,
-			    IPC_FF_ROUTE_FROM_ME);
-			async_exchange_end(exch);
-			
+			async_forward_slow(rid, tmp->mp_data.phone,
+			    VFS_OUT_LOOKUP, next, last, tmp->mp_data.devmap_handle,
+			    lflag, index, IPC_FF_ROUTE_FROM_ME);
 			(void) ops->node_put(cur);
 			(void) ops->node_put(tmp);
@@ -632,6 +391,4 @@
 						if (lflag & L_CREATE)
 							(void) ops->destroy(fn);
-						else
-							(void) ops->node_put(fn);
 						async_answer_0(rid, rc);
 					} else {
@@ -684,5 +441,5 @@
 			len = 0;
 			while (next <= last) {
-				if (plb_get_char(next) == '/') {
+				if (ops->plb_get_char(next) == '/') {
 					/* More than one component */
 					async_answer_0(rid, ENOENT);
@@ -696,5 +453,5 @@
 				}
 				
-				component[len++] = plb_get_char(next);
+				component[len++] = ops->plb_get_char(next);
 				/* Process next character */
 				next++;
@@ -716,6 +473,4 @@
 					if (lflag & L_CREATE)
 						(void) ops->destroy(fn);
-					else
-						(void) ops->node_put(fn);
 					async_answer_0(rid, rc);
 				} else {
@@ -870,6 +625,5 @@
 	rc = ops->node_open(fn);
 	aoff64_t size = ops->size_get(fn);
-	async_answer_4(rid, rc, LOWER32(size), UPPER32(size),
-	    ops->lnkcnt_get(fn),
+	async_answer_4(rid, rc, LOWER32(size), UPPER32(size), ops->lnkcnt_get(fn),
 	    (ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0));
 	
