Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision 96b02eb9b2f96f3843b8275c254c43a9cb6c8c88)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision 4fe94c669d1b57c6e7167bd6698ff567b70797ca)
@@ -46,7 +46,7 @@
 #include <ipc/services.h>
 #include <async.h>
-#include <atomic.h>
-#include <futex.h>
+#include <fibril_synch.h>
 #include <errno.h>
+#include <assert.h>
 #include <str.h>
 #include <devmap.h>
@@ -54,7 +54,10 @@
 #include <ipc/devmap.h>
 
+static async_sess_t vfs_session;
+
+static FIBRIL_MUTEX_INITIALIZE(vfs_phone_mutex);
 static int vfs_phone = -1;
-static futex_t vfs_phone_futex = FUTEX_INITIALIZER;
-static futex_t cwd_futex = FUTEX_INITIALIZER;
+
+static FIBRIL_MUTEX_INITIALIZE(cwd_mutex);
 
 static int cwd_fd = -1;
@@ -67,14 +70,14 @@
 	char *ncwd_path_nc;
 
-	futex_down(&cwd_futex);
+	fibril_mutex_lock(&cwd_mutex);
 	size_t size = str_size(path);
 	if (*path != '/') {
 		if (!cwd_path) {
-			futex_up(&cwd_futex);
+			fibril_mutex_unlock(&cwd_mutex);
 			return NULL;
 		}
 		ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
 		if (!ncwd_path_nc) {
-			futex_up(&cwd_futex);
+			fibril_mutex_unlock(&cwd_mutex);
 			return NULL;
 		}
@@ -85,5 +88,5 @@
 		ncwd_path_nc = malloc(size + 1);
 		if (!ncwd_path_nc) {
-			futex_up(&cwd_futex);
+			fibril_mutex_unlock(&cwd_mutex);
 			return NULL;
 		}
@@ -93,5 +96,5 @@
 	ncwd_path = canonify(ncwd_path_nc, retlen);
 	if (!ncwd_path) {
-		futex_up(&cwd_futex);
+		fibril_mutex_unlock(&cwd_mutex);
 		free(ncwd_path_nc);
 		return NULL;
@@ -105,15 +108,43 @@
 	free(ncwd_path_nc);
 	if (!ncwd_path) {
-		futex_up(&cwd_futex);
+		fibril_mutex_unlock(&cwd_mutex);
 		return NULL;
 	}
-	futex_up(&cwd_futex);
+	fibril_mutex_unlock(&cwd_mutex);
 	return ncwd_path;
 }
 
+/** Connect to VFS service and create session. */
 static void vfs_connect(void)
 {
-	while (vfs_phone < 0)
-		vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
+	while (vfs_phone < 0) {
+		vfs_phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_VFS,
+		    0, 0);
+	}
+	
+	async_session_create(&vfs_session, vfs_phone, 0);
+}
+
+/** Start an async exchange on the VFS session.
+ *
+ * @return		New phone to be used during the exchange.
+ */
+static int vfs_exchange_begin(void)
+{
+	fibril_mutex_lock(&vfs_phone_mutex);
+	if (vfs_phone < 0)
+		vfs_connect();
+	fibril_mutex_unlock(&vfs_phone_mutex);
+
+	return async_exchange_begin(&vfs_session);
+}
+
+/** End an async exchange on the VFS session.
+ *
+ * @param phone		Phone used during the exchange.
+ */
+static void vfs_exchange_end(int phone)
+{
+	async_exchange_end(&vfs_session, phone);
 }
 
@@ -154,16 +185,13 @@
 	}
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
-	
+	int vfs_phone = vfs_exchange_begin();
+
 	sysarg_t rc_orig;
 	aid_t req = async_send_2(vfs_phone, VFS_IN_MOUNT, devmap_handle, flags, NULL);
 	sysarg_t rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(mpa);
+		async_wait_for(req, &rc_orig);
 		
 		if (null_id != -1)
@@ -178,8 +206,7 @@
 	rc = async_data_write_start(vfs_phone, (void *) opts, str_size(opts));
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(mpa);
+		async_wait_for(req, &rc_orig);
 		
 		if (null_id != -1)
@@ -194,8 +221,7 @@
 	rc = async_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(mpa);
+		async_wait_for(req, &rc_orig);
 		
 		if (null_id != -1)
@@ -211,8 +237,7 @@
 	rc = async_req_0_0(vfs_phone, IPC_M_PING);
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(mpa);
+		async_wait_for(req, &rc_orig);
 		
 		if (null_id != -1)
@@ -225,8 +250,7 @@
 	}
 	
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
 	free(mpa);
+	async_wait_for(req, &rc);
 	
 	if ((rc != EOK) && (null_id != -1))
@@ -248,26 +272,22 @@
 		return ENOMEM;
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_0(vfs_phone, VFS_IN_UNMOUNT, NULL);
 	rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(mpa);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	
-
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	
+
+	vfs_exchange_end(vfs_phone);
 	free(mpa);
+	async_wait_for(req, &rc);
 	
 	return (int) rc;
@@ -276,7 +296,5 @@
 static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag)
 {
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	ipc_call_t answer;
@@ -285,19 +303,17 @@
 	
 	if (rc != EOK) {
+		vfs_exchange_end(vfs_phone);
+
 		sysarg_t rc_orig;
 		async_wait_for(req, &rc_orig);
 		
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
-		
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	
+	vfs_exchange_end(vfs_phone);
+	async_wait_for(req, &rc);
 	
 	if (rc != EOK)
@@ -322,7 +338,5 @@
 int open_node(fdi_node_t *node, int oflag)
 {
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	ipc_call_t answer;
@@ -330,8 +344,8 @@
 	    node->devmap_handle, node->index, oflag, &answer);
 	
-	sysarg_t rc;
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
+
+	sysarg_t rc;
+	async_wait_for(req, &rc);
 	
 	if (rc != EOK)
@@ -345,12 +359,9 @@
 	sysarg_t rc;
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes);
 	
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
 	
 	return (int)rc;
@@ -363,16 +374,14 @@
 	aid_t req;
 
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
 	rc = async_data_read_start(vfs_phone, (void *)buf, nbyte);
 	if (rc != EOK) {
+		vfs_exchange_end(vfs_phone);
+
 		sysarg_t rc_orig;
-	
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+
 		if (rc_orig == EOK)
 			return (ssize_t) rc;
@@ -380,7 +389,6 @@
 			return (ssize_t) rc_orig;
 	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
+	async_wait_for(req, &rc);
 	if (rc == EOK)
 		return (ssize_t) IPC_GET_ARG1(answer);
@@ -395,16 +403,14 @@
 	aid_t req;
 
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
 	rc = async_data_write_start(vfs_phone, (void *)buf, nbyte);
 	if (rc != EOK) {
+		vfs_exchange_end(vfs_phone);
+
 		sysarg_t rc_orig;
-	
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+
 		if (rc_orig == EOK)
 			return (ssize_t) rc;
@@ -412,7 +418,6 @@
 			return (ssize_t) rc_orig;
 	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
+	async_wait_for(req, &rc);
 	if (rc == EOK)
 		return (ssize_t) IPC_GET_ARG1(answer);
@@ -423,12 +428,9 @@
 int fsync(int fildes)
 {
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	sysarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes);
 	
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
 	
 	return (int) rc;
@@ -437,7 +439,5 @@
 off64_t lseek(int fildes, off64_t offset, int whence)
 {
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	sysarg_t newoff_lo;
@@ -447,6 +447,5 @@
 	    &newoff_lo, &newoff_hi);
 	
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
 	
 	if (rc != EOK)
@@ -460,12 +459,9 @@
 	sysarg_t rc;
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	rc = async_req_3_0(vfs_phone, VFS_IN_TRUNCATE, fildes,
 	    LOWER32(length), UPPER32(length));
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
 	
 	return (int) rc;
@@ -477,16 +473,14 @@
 	aid_t req;
 
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL);
 	rc = async_data_read_start(vfs_phone, (void *) stat, sizeof(struct stat));
 	if (rc != EOK) {
+		vfs_exchange_end(vfs_phone);
+
 		sysarg_t rc_orig;
-		
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+
 		if (rc_orig == EOK)
 			return (ssize_t) rc;
@@ -494,7 +488,6 @@
 			return (ssize_t) rc_orig;
 	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
+	async_wait_for(req, &rc);
 
 	return rc;
@@ -512,15 +505,12 @@
 		return ENOMEM;
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_0(vfs_phone, VFS_IN_STAT, NULL);
 	rc = async_data_write_start(vfs_phone, pa, pa_size);
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(pa);
+		async_wait_for(req, &rc_orig);
 		if (rc_orig == EOK)
 			return (int) rc;
@@ -530,17 +520,15 @@
 	rc = async_data_read_start(vfs_phone, stat, sizeof(struct stat));
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(pa);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	vfs_exchange_end(vfs_phone);
 	free(pa);
+	async_wait_for(req, &rc);
 	return rc;
 }
@@ -601,26 +589,23 @@
 		return ENOMEM;
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL);
 	rc = async_data_write_start(vfs_phone, pa, pa_size);
 	if (rc != EOK) {
+		vfs_exchange_end(vfs_phone);
+		free(pa);
+
 		sysarg_t rc_orig;
-	
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
-		free(pa);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	vfs_exchange_end(vfs_phone);
 	free(pa);
+	async_wait_for(req, &rc);
 	return rc;
 }
@@ -636,26 +621,23 @@
 		return ENOMEM;
 
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL);
 	rc = async_data_write_start(vfs_phone, pa, pa_size);
 	if (rc != EOK) {
+		vfs_exchange_end(vfs_phone);
+		free(pa);
+
 		sysarg_t rc_orig;
-
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
-		free(pa);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	vfs_exchange_end(vfs_phone);
 	free(pa);
+	async_wait_for(req, &rc);
 	return rc;
 }
@@ -689,16 +671,13 @@
 	}
 
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL);
 	rc = async_data_write_start(vfs_phone, olda, olda_size);
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(olda);
 		free(newa);
+		async_wait_for(req, &rc_orig);
 		if (rc_orig == EOK)
 			return (int) rc;
@@ -708,19 +687,17 @@
 	rc = async_data_write_start(vfs_phone, newa, newa_size);
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(olda);
 		free(newa);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	vfs_exchange_end(vfs_phone);
 	free(olda);
 	free(newa);
+	async_wait_for(req, &rc);
 	return rc;
 }
@@ -740,5 +717,5 @@
 	}
 	
-	futex_down(&cwd_futex);
+	fibril_mutex_lock(&cwd_mutex);
 	
 	if (cwd_fd >= 0)
@@ -753,5 +730,5 @@
 	cwd_size = abs_size;
 	
-	futex_up(&cwd_futex);
+	fibril_mutex_unlock(&cwd_mutex);
 	return EOK;
 }
@@ -762,13 +739,13 @@
 		return NULL;
 	
-	futex_down(&cwd_futex);
+	fibril_mutex_lock(&cwd_mutex);
 	
 	if ((cwd_size == 0) || (size < cwd_size + 1)) {
-		futex_up(&cwd_futex);
+		fibril_mutex_unlock(&cwd_mutex);
 		return NULL;
 	}
 	
 	str_cpy(buf, size, cwd_path);
-	futex_up(&cwd_futex);
+	fibril_mutex_unlock(&cwd_mutex);
 	
 	return buf;
@@ -806,13 +783,10 @@
 int dup2(int oldfd, int newfd)
 {
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	sysarg_t ret;
 	sysarg_t rc = async_req_2_1(vfs_phone, VFS_IN_DUP, oldfd, newfd, &ret);
 	
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
 	
 	if (rc == EOK)
