Index: uspace/lib/libfs/libfs.c
===================================================================
--- uspace/lib/libfs/libfs.c	(revision 27fd65116fa3cd8417356ac80ae88c098a4e2b42)
+++ uspace/lib/libfs/libfs.c	(revision 83937ccdc2b837d5c6a3681b11f3c1e76e3a6ade)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2008 Jakub Jermar 
+ * Copyright (c) 2009 Jakub Jermar 
  * All rights reserved.
  *
@@ -123,4 +123,83 @@
 }
 
+void fs_node_initialize(fs_node_t *fn)
+{
+	memset(fn, 0, sizeof(fs_node_t));
+}
+
+void libfs_mount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *request)
+{
+	dev_handle_t mp_dev_handle = (dev_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);
+	dev_handle_t mr_dev_handle = (dev_handle_t)IPC_GET_ARG4(*request);
+	int res;
+	ipcarg_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_METHOD(call) != IPC_M_CONNECTION_CLONE) ||
+	    mountee_phone < 0) {
+		ipc_answer_0(callid, EINVAL);
+		ipc_answer_0(rid, EINVAL);
+		return;
+	}
+	ipc_answer_0(callid, EOK);	/* acknowledge the mountee_phone */
+	
+	res = ipc_data_write_receive(&callid, NULL);
+	if (!res) {
+		ipc_hangup(mountee_phone);
+		ipc_answer_0(callid, EINVAL);
+		ipc_answer_0(rid, EINVAL);
+		return;
+	}
+
+	fs_node_t *fn = ops->node_get(mp_dev_handle, mp_fs_index);
+	if (!fn) {
+		ipc_hangup(mountee_phone);
+		ipc_answer_0(callid, ENOENT);
+		ipc_answer_0(rid, ENOENT);
+		return;
+	}
+
+	if (fn->mp_data.mp_active) {
+		ipc_hangup(mountee_phone);
+		ops->node_put(fn);
+		ipc_answer_0(callid, EBUSY);
+		ipc_answer_0(rid, EBUSY);
+		return;
+	}
+
+	rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME);
+	if (rc != 0) {
+		ipc_hangup(mountee_phone);
+		ops->node_put(fn);
+		ipc_answer_0(callid, rc);
+		ipc_answer_0(rid, rc);
+		return;
+	}
+	
+	ipc_call_t answer;
+	aid_t msg = async_send_1(mountee_phone, VFS_MOUNTED, mr_dev_handle,
+	    &answer);
+	ipc_forward_fast(callid, mountee_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+	async_wait_for(msg, &rc);
+	
+	if (rc == EOK) {
+		fn->mp_data.mp_active = true;
+		fn->mp_data.fs_handle = mr_fs_handle;
+		fn->mp_data.dev_handle = mr_dev_handle;
+		fn->mp_data.phone = mountee_phone;
+	}
+	/*
+	 * Do not release the FS node so that it stays in memory.
+	 */
+	ipc_answer_0(rid, rc);
+}
+
 /** Lookup VFS triplet by name in the file system name space.
  *
@@ -138,6 +217,7 @@
     ipc_call_t *request)
 {
-	unsigned next = IPC_GET_ARG1(*request);
+	unsigned first = IPC_GET_ARG1(*request);
 	unsigned last = IPC_GET_ARG2(*request);
+	unsigned next = first;
 	dev_handle_t dev_handle = IPC_GET_ARG3(*request);
 	int lflag = IPC_GET_ARG4(*request);
@@ -152,4 +232,12 @@
 	fs_node_t *cur = ops->root_get(dev_handle);
 	fs_node_t *tmp = NULL;
+
+	if (cur->mp_data.mp_active) {
+		ipc_forward_slow(rid, cur->mp_data.phone, VFS_LOOKUP,
+		    next, last, cur->mp_data.dev_handle, lflag, index,
+		    IPC_FF_ROUTE_FROM_ME);
+		ops->node_put(cur);
+		return;
+	}
 
 	if (ops->plb_get_char(next) == '/')
@@ -175,4 +263,19 @@
 		/* match the component */
 		tmp = ops->match(cur, component);
+		if (tmp && tmp->mp_data.mp_active) {
+			if (next > last)
+				next = last = first;
+			else
+				next--;
+				
+			ipc_forward_slow(rid, tmp->mp_data.phone, VFS_LOOKUP,
+			    next, last, tmp->mp_data.dev_handle, lflag, index,
+			    IPC_FF_ROUTE_FROM_ME);
+			ops->node_put(cur);
+			ops->node_put(tmp);
+			if (par)
+				ops->node_put(par);
+			return;
+		}
 
 		/* handle miss: match amongst siblings */
Index: uspace/lib/libfs/libfs.h
===================================================================
--- uspace/lib/libfs/libfs.h	(revision 27fd65116fa3cd8417356ac80ae88c098a4e2b42)
+++ uspace/lib/libfs/libfs.h	(revision 83937ccdc2b837d5c6a3681b11f3c1e76e3a6ade)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2007 Jakub Jermar
+ * Copyright (c) 2009 Jakub Jermar
  * All rights reserved.
  *
@@ -43,5 +43,13 @@
 
 typedef struct {
-	void *data;	/**< Data of the file system implementation. */
+	bool mp_active;
+	int phone;
+	fs_handle_t fs_handle;
+	dev_handle_t dev_handle;
+} mp_data_t;
+
+typedef struct {
+	mp_data_t mp_data;	/**< Mount point info. */
+	void *data;		/**< Data of the file system implementation. */
 } fs_node_t;
 
@@ -72,4 +80,7 @@
 extern int fs_register(int, fs_reg_t *, vfs_info_t *, async_client_conn_t);
 
+extern void fs_node_initialize(fs_node_t *);
+
+extern void libfs_mount(libfs_ops_t *, ipc_callid_t, ipc_call_t *);
 extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
 
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 27fd65116fa3cd8417356ac80ae88c098a4e2b42)
+++ uspace/srv/fs/fat/fat_ops.c	(revision 83937ccdc2b837d5c6a3681b11f3c1e76e3a6ade)
@@ -150,4 +150,5 @@
 	}
 	fat_node_initialize(nodep);
+	fs_node_initialize(fn);
 	fn->data = nodep;
 	nodep->bp = fn;
@@ -848,4 +849,5 @@
 		return;
 	}
+	fs_node_initialize(rfn);
 	fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
 	if (!rootp) {
@@ -887,5 +889,5 @@
 void fat_mount(ipc_callid_t rid, ipc_call_t *request)
 {
-	ipc_answer_0(rid, ENOTSUP);
+	libfs_mount(&fat_libfs_ops, rid, request);
 }
 
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 27fd65116fa3cd8417356ac80ae88c098a4e2b42)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 83937ccdc2b837d5c6a3681b11f3c1e76e3a6ade)
@@ -251,4 +251,5 @@
 		return NULL;
 	}
+	fs_node_initialize(nodep->bp);
 	nodep->bp->data = nodep;	/* link the FS and TMPFS nodes */
 	if (!tmpfs_root_get(dev_handle))
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 27fd65116fa3cd8417356ac80ae88c098a4e2b42)
+++ uspace/srv/vfs/vfs_ops.c	(revision 83937ccdc2b837d5c6a3681b11f3c1e76e3a6ade)
@@ -85,9 +85,15 @@
 {
 	vfs_lookup_res_t mp_res;
+	vfs_lookup_res_t mr_res;
 	vfs_node_t *mp_node = NULL;
+	vfs_node_t *mr_node;
+	fs_index_t rindex;
+	size_t rsize;
+	unsigned rlnkcnt;
 	ipcarg_t rc;
 	int phone;
 	aid_t msg;
 	ipc_call_t answer;
+			
 
 	/* Resolve the path to the mountpoint. */
@@ -130,10 +136,4 @@
 		/* We still don't have the root file system mounted. */
 		if (str_cmp(mp, "/") == 0) {
-			vfs_lookup_res_t mr_res;
-			vfs_node_t *mr_node;
-			fs_index_t rindex;
-			size_t rsize;
-			unsigned rlnkcnt;
-			
 			/*
 			 * For this simple, but important case,
@@ -202,4 +202,8 @@
 	 */
 	
+	int mountee_phone = vfs_grab_phone(fs_handle);
+	assert(mountee_phone >= 0);
+	vfs_release_phone(mountee_phone);
+
 	phone = vfs_grab_phone(mp_res.triplet.fs_handle);
 	msg = async_send_4(phone, VFS_MOUNT,
@@ -208,4 +212,17 @@
 	    (ipcarg_t) fs_handle,
 	    (ipcarg_t) dev_handle, &answer);
+	
+	/* send connection */
+	rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone);
+	if (rc != EOK) {
+		async_wait_for(msg, NULL);
+		vfs_release_phone(phone);
+		/* Mount failed, drop reference to mp_node. */
+		if (mp_node)
+			vfs_node_put(mp_node);
+		ipc_answer_0(rid, rc);
+		return;
+	}
+	
 	/* send the mount options */
 	rc = ipc_data_write_start(phone, (void *)opts, str_size(opts));
@@ -228,4 +245,19 @@
 	}
 	
+	rindex = (fs_index_t) IPC_GET_ARG1(answer);
+	rsize = (size_t) IPC_GET_ARG2(answer);
+	rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
+	
+	mr_res.triplet.fs_handle = fs_handle;
+	mr_res.triplet.dev_handle = dev_handle;
+	mr_res.triplet.index = rindex;
+	mr_res.size = rsize;
+	mr_res.lnkcnt = rlnkcnt;
+	mr_res.type = VFS_NODE_DIRECTORY;
+	
+	/* Add reference to the mounted root. */
+	mr_node = vfs_node_get(&mr_res); 
+	assert(mr_node);
+
 	ipc_answer_0(rid, rc);
 }
