Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 9539be6c880110557328e7e518cf276b94c1b07f)
+++ uspace/srv/vfs/vfs.h	(revision 32496732fb7ad82a3685431fd76c222a9738cd3f)
@@ -169,5 +169,5 @@
 
 extern int vfs_grab_phone(fs_handle_t);
-extern void vfs_release_phone(int);
+extern void vfs_release_phone(fs_handle_t, int);
 
 extern fs_handle_t fs_name_to_handle(char *, bool);
Index: uspace/srv/vfs/vfs_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision 9539be6c880110557328e7e518cf276b94c1b07f)
+++ uspace/srv/vfs/vfs_lookup.c	(revision 32496732fb7ad82a3685431fd76c222a9738cd3f)
@@ -168,5 +168,5 @@
 	ipcarg_t rc;
 	async_wait_for(req, &rc);
-	vfs_release_phone(phone);
+	vfs_release_phone(root->fs_handle, phone);
 	
 	fibril_mutex_lock(&plb_mutex);
@@ -215,5 +215,5 @@
 	ipcarg_t rc;
 	async_wait_for(req, &rc);
-	vfs_release_phone(phone);
+	vfs_release_phone(result->triplet.fs_handle, phone);
 	
 	if (rc == EOK) {
Index: uspace/srv/vfs/vfs_node.c
===================================================================
--- uspace/srv/vfs/vfs_node.c	(revision 9539be6c880110557328e7e518cf276b94c1b07f)
+++ uspace/srv/vfs/vfs_node.c	(revision 32496732fb7ad82a3685431fd76c222a9738cd3f)
@@ -133,5 +133,5 @@
 		    (ipcarg_t)node->dev_handle, (ipcarg_t)node->index);
 		assert(rc == EOK);
-		vfs_release_phone(phone);
+		vfs_release_phone(node->fs_handle, phone);
 	}
 	if (free_vfs_node)
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 9539be6c880110557328e7e518cf276b94c1b07f)
+++ uspace/srv/vfs/vfs_ops.c	(revision 32496732fb7ad82a3685431fd76c222a9738cd3f)
@@ -131,5 +131,5 @@
 			if (rc != EOK) {
 				async_wait_for(msg, NULL);
-				vfs_release_phone(phone);
+				vfs_release_phone(fs_handle, phone);
 				fibril_rwlock_write_unlock(&namespace_rwlock);
 				ipc_answer_0(rid, rc);
@@ -137,5 +137,5 @@
 			}
 			async_wait_for(msg, &rc);
-			vfs_release_phone(phone);
+			vfs_release_phone(fs_handle, phone);
 			
 			if (rc != EOK) {
@@ -196,6 +196,6 @@
 	if (rc != EOK) {
 		async_wait_for(msg, NULL);
-		vfs_release_phone(mountee_phone);
-		vfs_release_phone(phone);
+		vfs_release_phone(fs_handle, mountee_phone);
+		vfs_release_phone(mp_res.triplet.fs_handle, phone);
 		/* Mount failed, drop reference to mp_node. */
 		if (mp_node)
@@ -206,5 +206,5 @@
 	}
 
-	vfs_release_phone(mountee_phone);
+	vfs_release_phone(fs_handle, mountee_phone);
 	
 	/* send the mount options */
@@ -212,5 +212,5 @@
 	if (rc != EOK) {
 		async_wait_for(msg, NULL);
-		vfs_release_phone(phone);
+		vfs_release_phone(mp_res.triplet.fs_handle, phone);
 		/* Mount failed, drop reference to mp_node. */
 		if (mp_node)
@@ -221,5 +221,5 @@
 	}
 	async_wait_for(msg, &rc);
-	vfs_release_phone(phone);
+	vfs_release_phone(mp_res.triplet.fs_handle, phone);
 	
 	if (rc == EOK) {
@@ -423,5 +423,5 @@
 		rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED,
 		    mr_node->dev_handle);
-		vfs_release_phone(phone);
+		vfs_release_phone(mr_node->fs_handle, phone);
 		if (rc != EOK) {
 			fibril_rwlock_write_unlock(&namespace_rwlock);
@@ -460,5 +460,5 @@
 		rc = async_req_2_0(phone, VFS_OUT_UNMOUNT, mp_node->dev_handle,
 		    mp_node->index);
-		vfs_release_phone(phone);
+		vfs_release_phone(mp_node->fs_handle, phone);
 		if (rc != EOK) {
 			fibril_rwlock_write_unlock(&namespace_rwlock);
@@ -716,5 +716,5 @@
 	async_wait_for(msg, &rc);
 	
-	vfs_release_phone(fs_phone);
+	vfs_release_phone(file->node->fs_handle, fs_phone);
 	fibril_mutex_unlock(&file->lock);
 	
@@ -747,5 +747,5 @@
 		async_wait_for(msg, &rc);
 		
-		vfs_release_phone(fs_phone);
+		vfs_release_phone(file->node->fs_handle, fs_phone);
 		fibril_mutex_unlock(&file->lock);
 		
@@ -846,5 +846,5 @@
 	}
 	
-	vfs_release_phone(fs_phone);
+	vfs_release_phone(file->node->fs_handle, fs_phone);
 	
 	size_t bytes = IPC_GET_ARG1(answer);
@@ -970,5 +970,5 @@
 	rc = async_req_4_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t) dev_handle,
 	    (ipcarg_t) index, LOWER32(size), UPPER32(size));
-	vfs_release_phone(fs_phone);
+	vfs_release_phone(fs_handle, fs_phone);
 	return (int)rc;
 }
@@ -1026,5 +1026,5 @@
 	ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
 	async_wait_for(msg, &rc);
-	vfs_release_phone(fs_phone);
+	vfs_release_phone(file->node->fs_handle, fs_phone);
 
 	fibril_mutex_unlock(&file->lock);
@@ -1077,5 +1077,5 @@
 	ipcarg_t rv;
 	async_wait_for(msg, &rv);
-	vfs_release_phone(fs_phone);
+	vfs_release_phone(node->fs_handle, fs_phone);
 
 	ipc_answer_0(rid, rv);
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision 9539be6c880110557328e7e518cf276b94c1b07f)
+++ uspace/srv/vfs/vfs_register.c	(revision 32496732fb7ad82a3685431fd76c222a9738cd3f)
@@ -39,5 +39,7 @@
 #include <ipc/services.h>
 #include <async.h>
+#include <async_rel.h>
 #include <fibril.h>
+#include <fibril_synch.h>
 #include <errno.h>
 #include <stdio.h>
@@ -46,5 +48,4 @@
 #include <ctype.h>
 #include <bool.h>
-#include <fibril_synch.h>
 #include <adt/list.h>
 #include <as.h>
@@ -252,4 +253,6 @@
 int vfs_grab_phone(fs_handle_t handle)
 {
+	link_t *cur;
+	fs_info_t *fs;
 	int phone;
 
@@ -262,6 +265,4 @@
 	 */
 	fibril_mutex_lock(&fs_head_lock);
-	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);
@@ -269,5 +270,5 @@
 			fibril_mutex_unlock(&fs_head_lock);
 			fibril_mutex_lock(&fs->phone_lock);
-			phone = ipc_connect_me_to(fs->phone, 0, 0, 0);
+			phone = async_relation_create(fs->phone);
 			fibril_mutex_unlock(&fs->phone_lock);
 
@@ -284,8 +285,23 @@
  * @param phone		Phone to FS task.
  */
-void vfs_release_phone(int phone)
-{
-	/* TODO: implement connection caching */
-	ipc_hangup(phone);
+void vfs_release_phone(fs_handle_t handle, int phone)
+{
+	link_t *cur;
+	fs_info_t *fs;
+
+	fibril_mutex_lock(&fs_head_lock);
+	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) {
+			fibril_mutex_unlock(&fs_head_lock);
+			fibril_mutex_lock(&fs->phone_lock);
+			async_relation_destroy(fs->phone, phone);
+			fibril_mutex_unlock(&fs->phone_lock);
+			return;
+		}
+	}
+	/* should not really get here */
+	abort();
+	fibril_mutex_unlock(&fs_head_lock);
 }
 
