Index: uspace/srv/fs/fat/fat.c
===================================================================
--- uspace/srv/fs/fat/fat.c	(revision 566d798dfacec36587df252b8b9c6dc824d72fa6)
+++ uspace/srv/fs/fat/fat.c	(revision 5f4cfb1e7a458e3e1ce5197e0a3163a542b56b55)
@@ -43,5 +43,5 @@
 #include <unistd.h>
 #include <stdio.h>
-#include <as.h>>
+#include <as.h>
 #include "../../vfs/vfs.h"
 
@@ -65,4 +65,6 @@
 
 uint8_t *plb_ro = NULL;
+
+int fs_handle = 0;
 
 /**
@@ -156,6 +158,6 @@
 	 * Request sharing the Path Lookup Buffer with VFS.
 	 */
-	rc = ipc_call_sync_3(vfs_phone, IPC_M_AS_AREA_RECV, plb_ro, PLB_SIZE, 0,
-	    NULL, NULL, NULL);
+	rc = ipc_call_sync_3(vfs_phone, IPC_M_AS_AREA_RECV, (ipcarg_t) plb_ro,
+	    PLB_SIZE, 0, NULL, NULL, NULL);
 	if (rc) {
 		async_wait_for(req, NULL);
@@ -164,4 +166,11 @@
 	 
 	/*
+	 * Pick up the answer for the request to the VFS_REQUEST call.
+	 */
+	async_wait_for(req, NULL);
+	fs_handle = (int) IPC_GET_ARG1(answer);
+	dprintf("FAT filesystem registered, fs_handle=%d.\n", fs_handle);
+
+	/*
 	 * Create a connection fibril to handle the callback connection.
 	 */
@@ -173,10 +182,4 @@
 	 */
 	async_set_client_connection(fat_connection);
-
-	/*
-	 * Pick up the answer for the request to the VFS_REQUEST call.
-	 */
-	async_wait_for(req, NULL);
-	dprintf("FAT filesystem registered.\n");
 
 	async_create_manager();
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 566d798dfacec36587df252b8b9c6dc824d72fa6)
+++ uspace/srv/vfs/vfs.h	(revision 5f4cfb1e7a458e3e1ce5197e0a3163a542b56b55)
@@ -93,4 +93,6 @@
 	link_t fs_link;
 	vfs_info_t vfs_info;
+	int fs_handle;
+	atomic_t phone_futex;	/**< Phone serializing futex. */
 	ipcarg_t phone;
 } fs_info_t;
@@ -143,4 +145,7 @@
 extern link_t plb_head;		/**< List of active PLB entries. */
 
+extern int vfs_grab_phone(int);
+extern void vfs_release_phone(int);
+
 extern int vfs_lookup_internal(char *path, size_t len, vfs_node_t *result);
 
Index: uspace/srv/vfs/vfs_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision 566d798dfacec36587df252b8b9c6dc824d72fa6)
+++ uspace/srv/vfs/vfs_lookup.c	(revision 5f4cfb1e7a458e3e1ce5197e0a3163a542b56b55)
@@ -126,7 +126,8 @@
 
 	ipc_call_t answer;
-	int phone = 0;		/* TODO */
-	aid_t req = async_send_2(phone, VFS_LOOKUP, (ipcarg_t) first,
-	    (ipcarg_t) last, &answer);
+	int phone = vfs_grab_phone(rootfs->fs_handle);
+	aid_t req = async_send_3(phone, VFS_LOOKUP, (ipcarg_t) first,
+	    (ipcarg_t) last, (ipcarg_t) rootfs->dev_handle, &answer);
+	vfs_release_phone(phone);
 
 	ipcarg_t rc;
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision 566d798dfacec36587df252b8b9c6dc824d72fa6)
+++ uspace/srv/vfs/vfs_register.c	(revision 5f4cfb1e7a458e3e1ce5197e0a3163a542b56b55)
@@ -48,8 +48,13 @@
 #include <as.h>
 #include <libadt/list.h>
+#include <assert.h>
 #include "vfs.h"
 
 atomic_t fs_head_futex = FUTEX_INITIALIZER;
 link_t fs_head;
+
+atomic_t fs_handle_next = {
+	.count = 1
+};
 
 /** Verify the VFS info structure.
@@ -306,9 +311,76 @@
 	/*
 	 * That was it. The FS has been registered.
-	 */
-	ipc_answer_fast(rid, EOK, 0, 0);
-	dprintf("\"%s\" filesystem successfully registered.\n",
-	    fs_info->vfs_info.name);
-
+	 * In reply to the VFS_REGISTER request, we assign the client file
+	 * system a global file system handle.
+	 */
+	fs_info->fs_handle = (int) atomic_postinc(&fs_handle_next);
+	ipc_answer_fast(rid, EOK, (ipcarg_t) fs_info->fs_handle, 0);
+	dprintf("\"%s\" filesystem successfully registered, handle=%d.\n",
+	    fs_info->vfs_info.name, fs_info->fs_handle);
+
+}
+
+/** For a given file system handle, implement policy for allocating a phone.
+ *
+ * @param handle	File system handle.
+ *
+ * @return		Phone over which a multi-call request can be safely
+ *			sent. Return 0 if no phone was found.
+ */
+int vfs_grab_phone(int handle)
+{
+	/*
+	 * For now, we don't try to be very clever and very fast.
+	 * We simply lookup the phone in the fs_head list. We currently don't
+	 * open any additional phones (even though that itself would be pretty
+	 * straightforward; housekeeping multiple open phones to a FS task would
+	 * be more demanding). Instead, we simply take the respective
+	 * phone_futex and keep it until vfs_release_phone().
+	 */
+	futex_down(&fs_head_futex);
+	link_t *cur;
+	fs_info_t *fs;
+	for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
+		fs = list_get_instance(cur, fs_info_t, fs_link);
+		if (fs->fs_handle == handle) {
+			futex_up(&fs_head_futex);
+			/*
+			 * For now, take the futex unconditionally.
+			 * Oh yeah, serialization rocks.
+			 * It will be up'ed in vfs_release_phone().
+			 */
+			futex_down(&fs->phone_futex);
+			return fs->phone; 
+		}
+	}
+	futex_up(&fs_head_futex);
+	return 0;
+}
+
+/** Tell VFS that the phone is in use for any request.
+ *
+ * @param phone		Phone to FS task.
+ */
+void vfs_release_phone(int phone)
+{
+	bool found = false;
+
+	futex_down(&fs_head_futex);
+	link_t *cur;
+	for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
+		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
+		if (fs->phone == phone) {
+			found = true;
+			futex_up(&fs_head_futex);
+			futex_up(&fs->phone_futex);
+			return;
+		}
+	}
+	futex_up(&fs_head_futex);
+
+	/*
+	 * Not good to get here.
+	 */
+	assert(found == true);
 }
 
