Index: uspace/srv/vfs/vfs_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision 62140db53b75a953d42ed31acb77916cfc0ee678)
+++ uspace/srv/vfs/vfs_lookup.c	(revision 34ca87020c63e556aea19a44031baae2f32014b4)
@@ -164,8 +164,8 @@
 	    (ipcarg_t) root->dev_handle, (ipcarg_t) lflag, (ipcarg_t) index,
 	    &answer);
-	vfs_release_phone(phone);
 	
 	ipcarg_t rc;
 	async_wait_for(req, &rc);
+	vfs_release_phone(phone);
 	
 	futex_down(&plb_futex);
@@ -209,8 +209,8 @@
 	    (ipcarg_t) result->triplet.index, &answer);
 	
-	vfs_release_phone(phone);
 	
 	ipcarg_t rc;
 	async_wait_for(req, &rc);
+	vfs_release_phone(phone);
 	
 	if (rc == EOK) {
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 62140db53b75a953d42ed31acb77916cfc0ee678)
+++ uspace/srv/vfs/vfs_ops.c	(revision 34ca87020c63e556aea19a44031baae2f32014b4)
@@ -144,12 +144,12 @@
 			    str_size(opts));
 			if (rc != EOK) {
+				async_wait_for(msg, NULL);
 				vfs_release_phone(phone);
-				async_wait_for(msg, NULL);
 				fibril_rwlock_write_unlock(&namespace_rwlock);
 				ipc_answer_0(rid, rc);
 				return;
 			}
+			async_wait_for(msg, &rc);
 			vfs_release_phone(phone);
-			async_wait_for(msg, &rc);
 			
 			if (rc != EOK) {
@@ -198,5 +198,4 @@
 	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);
@@ -210,6 +209,7 @@
 	rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone);
 	if (rc != EOK) {
+		async_wait_for(msg, NULL);
+		vfs_release_phone(mountee_phone);
 		vfs_release_phone(phone);
-		async_wait_for(msg, NULL);
 		/* Mount failed, drop reference to mp_node. */
 		if (mp_node)
@@ -219,10 +219,12 @@
 		return;
 	}
+
+	vfs_release_phone(mountee_phone);
 	
 	/* send the mount options */
 	rc = ipc_data_write_start(phone, (void *)opts, str_size(opts));
 	if (rc != EOK) {
+		async_wait_for(msg, NULL);
 		vfs_release_phone(phone);
-		async_wait_for(msg, NULL);
 		/* Mount failed, drop reference to mp_node. */
 		if (mp_node)
@@ -232,6 +234,6 @@
 		return;
 	}
+	async_wait_for(msg, &rc);
 	vfs_release_phone(phone);
-	async_wait_for(msg, &rc);
 	
 	if (rc == EOK) {
@@ -756,11 +758,10 @@
 	msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
 	    file->node->dev_handle, file->node->index, &answer);
-	
-	vfs_release_phone(fs_phone);
 
 	/* Wait for reply from the FS server. */
 	ipcarg_t rc;
 	async_wait_for(msg, &rc);
-	
+
+	vfs_release_phone(fs_phone);
 	fibril_mutex_unlock(&file->lock);
 	
@@ -792,10 +793,9 @@
 	    file->node->dev_handle, file->node->index, &answer);
 
-	vfs_release_phone(fs_phone);
-
 	/* Wait for reply from the FS server. */
 	ipcarg_t rc;
 	async_wait_for(msg, &rc);
 	
+	vfs_release_phone(fs_phone);
 	fibril_mutex_unlock(&file->lock);
 	
@@ -819,5 +819,4 @@
 	 */
 	fibril_mutex_lock(&file->lock);
-	
 	int fs_phone = vfs_grab_phone(file->node->fs_handle);
 	
@@ -828,10 +827,9 @@
 	    file->node->dev_handle, file->node->index, &answer);
 
-	vfs_release_phone(fs_phone);
-	
 	/* Wait for reply from the FS server. */
 	ipcarg_t rc;
 	async_wait_for(msg, &rc);
-	
+
+	vfs_release_phone(fs_phone);
 	fibril_mutex_unlock(&file->lock);
 	
@@ -924,9 +922,9 @@
 	ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
 
-	vfs_release_phone(fs_phone);
-	
 	/* Wait for reply from the FS server. */
 	ipcarg_t rc;
 	async_wait_for(msg, &rc);
+	
+	vfs_release_phone(fs_phone);
 	
 	size_t bytes = IPC_GET_ARG1(answer);
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision 62140db53b75a953d42ed31acb77916cfc0ee678)
+++ uspace/srv/vfs/vfs_register.c	(revision 34ca87020c63e556aea19a44031baae2f32014b4)
@@ -286,11 +286,12 @@
 int vfs_grab_phone(fs_handle_t 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().
+	int phone;
+
+	/*
+	 * For now, we don't try to be very clever and very fast.  We simply
+	 * lookup the phone in the fs_head list and duplicate it.  The duplicate
+	 * phone will be returned to the client and the client will use it for
+	 * communication.  In the future, we should cache the connections so
+	 * that they do not have to be reestablished over and over again.
 	 */
 	fibril_mutex_lock(&fs_head_lock);
@@ -302,5 +303,9 @@
 			fibril_mutex_unlock(&fs_head_lock);
 			fibril_mutex_lock(&fs->phone_lock);
-			return fs->phone;
+			phone = ipc_connect_me_to(fs->phone, 0, 0, 0);
+			fibril_mutex_unlock(&fs->phone_lock);
+
+			assert(phone > 0);
+			return phone;
 		}
 	}
@@ -309,5 +314,5 @@
 }
 
-/** Tell VFS that the phone is in use for any request.
+/** Tell VFS that the phone is not needed anymore.
  *
  * @param phone		Phone to FS task.
@@ -315,23 +320,6 @@
 void vfs_release_phone(int phone)
 {
-	bool found = false;
-
-	fibril_mutex_lock(&fs_head_lock);
-	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;
-			fibril_mutex_unlock(&fs_head_lock);
-			fibril_mutex_unlock(&fs->phone_lock);
-			return;
-		}
-	}
-	fibril_mutex_unlock(&fs_head_lock);
-
-	/*
-	 * Not good to get here.
-	 */
-	assert(found == true);
+	/* TODO: implement connection caching */
+	ipc_hangup(phone);
 }
 
