Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision 124c0612c8daeba21701095e42877933875fb33a)
+++ uspace/srv/vfs/vfs.c	(revision b75e92976d38e84475ccceb2fe1b4cc21aa5fe63)
@@ -59,14 +59,4 @@
 	ipc_answer_0(iid, EOK);
 	
-	/*
-	 * Here we enter the main connection fibril loop.
-	 * The logic behind this loop and the protocol is that we'd like to keep
-	 * each connection open until the client hangs up. When the client hangs
-	 * up, we will free its VFS state. The act of hanging up the connection
-	 * by the client is equivalent to client termination because we cannot
-	 * distinguish one from the other. On the other hand, the client can
-	 * hang up arbitrarily if it has no open files and reestablish the
-	 * connection later.
-	 */
 	while (keep_on_going) {
 		ipc_call_t call;
@@ -133,6 +123,9 @@
 		}
 	}
-	
-	vfs_files_done();
+
+	/*
+	 * Open files for this client will be cleaned up when its last
+	 * connection fibril terminates.
+	 */
 }
 
@@ -166,4 +159,10 @@
 	
 	/*
+	 * Set client data constructor and destructor.
+	 */
+	async_set_client_data_constructor(vfs_client_data_create);
+	async_set_client_data_destructor(vfs_client_data_destroy);
+
+	/*
 	 * Set a connection handling function/fibril.
 	 */
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 124c0612c8daeba21701095e42877933875fb33a)
+++ uspace/srv/vfs/vfs.h	(revision b75e92976d38e84475ccceb2fe1b4cc21aa5fe63)
@@ -188,13 +188,11 @@
 #define MAX_OPEN_FILES	128
 
-extern bool vfs_files_init(void);
-extern void vfs_files_done(void);
+extern void *vfs_client_data_create(void);
+extern void vfs_client_data_destroy(void *);
+
 extern vfs_file_t *vfs_file_get(int);
 extern int vfs_fd_assign(vfs_file_t *file, int fd);
 extern int vfs_fd_alloc(bool desc);
 extern int vfs_fd_free(int);
-
-extern void vfs_file_addref(vfs_file_t *);
-extern void vfs_file_delref(vfs_file_t *);
 
 extern void vfs_node_addref(vfs_node_t *);
Index: uspace/srv/vfs/vfs_file.c
===================================================================
--- uspace/srv/vfs/vfs_file.c	(revision 124c0612c8daeba21701095e42877933875fb33a)
+++ uspace/srv/vfs/vfs_file.c	(revision b75e92976d38e84475ccceb2fe1b4cc21aa5fe63)
@@ -45,50 +45,98 @@
 #include "vfs.h"
 
-/**
- * This is a per-connection table of open files.
- * Our assumption is that each client opens only one connection and therefore
- * there is one table of open files per task. However, this may not be the case
- * and the client can open more connections to VFS. In that case, there will be
- * several tables and several file handle name spaces per task. Besides of this,
- * the functionality will stay unchanged. So unless the client knows what it is
- * doing, it should open one connection to VFS only.
- *
- * Allocation of the open files table is deferred until the client makes the
- * first VFS_OPEN operation.
- *
- * This resource being per-connection and, in the first place, per-fibril, we
- * don't need to protect it by a mutex.
- */
-fibril_local vfs_file_t **files = NULL;
+#define VFS_DATA	((vfs_client_data_t *) async_client_data_get())
+#define FILES		(VFS_DATA->files)
+
+typedef struct {
+	fibril_mutex_t lock;
+	vfs_file_t **files;
+} vfs_client_data_t;
 
 /** Initialize the table of open files. */
-bool vfs_files_init(void)
-{
-	if (!files) {
-		files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
-		if (!files)
+static bool vfs_files_init(void)
+{
+	fibril_mutex_lock(&VFS_DATA->lock);
+	if (!FILES) {
+		FILES = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
+		if (!FILES) {
+			fibril_mutex_unlock(&VFS_DATA->lock);
 			return false;
-		memset(files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
-	}
+		}
+		memset(FILES, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
+	}
+	fibril_mutex_unlock(&VFS_DATA->lock);
 	return true;
 }
 
 /** Cleanup the table of open files. */
-void vfs_files_done(void)
+static void vfs_files_done(void)
 {
 	int i;
 
-	if (!files)
+	if (!FILES)
 		return;
 
 	for (i = 0; i < MAX_OPEN_FILES; i++) {
-		if (files[i]) {
-			(void) vfs_close_internal(files[i]);
+		if (FILES[i]) {
+			(void) vfs_close_internal(FILES[i]);
 			(void) vfs_fd_free(i);
 		}
 	}
 	
-	free(files);
-}
+	free(FILES);
+}
+
+void *vfs_client_data_create(void)
+{
+	vfs_client_data_t *vfs_data;
+
+	vfs_data = malloc(sizeof(vfs_client_data_t));
+	if (vfs_data) {
+		fibril_mutex_initialize(&vfs_data->lock);
+		vfs_data->files = NULL;
+	}
+	
+	return vfs_data;
+}
+
+void vfs_client_data_destroy(void *data)
+{
+	vfs_client_data_t *vfs_data = (vfs_client_data_t *) data;
+
+	vfs_files_done();
+	free(vfs_data);
+}
+
+/** Increment reference count of VFS file structure.
+ *
+ * @param file		File structure that will have reference count
+ *			incremented.
+ */
+static void vfs_file_addref(vfs_file_t *file)
+{
+	assert(fibril_mutex_is_locked(&VFS_DATA->lock));
+
+	file->refcnt++;
+}
+
+/** Decrement reference count of VFS file structure.
+ *
+ * @param file		File structure that will have reference count
+ *			decremented.
+ */
+static void vfs_file_delref(vfs_file_t *file)
+{
+	assert(fibril_mutex_is_locked(&VFS_DATA->lock));
+
+	if (file->refcnt-- == 1) {
+		/*
+		 * Lost the last reference to a file, need to drop our reference
+		 * to the underlying VFS node.
+		 */
+		vfs_node_delref(file->node);
+		free(file);
+	}
+}
+
 
 /** Allocate a file descriptor.
@@ -111,13 +159,17 @@
 		i = 0;
 	
+	fibril_mutex_lock(&VFS_DATA->lock);
 	while (true) {
-		if (!files[i]) {
-			files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
-			if (!files[i])
+		if (!FILES[i]) {
+			FILES[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
+			if (!FILES[i]) {
+				fibril_mutex_unlock(&VFS_DATA->lock);
 				return ENOMEM;
+			}
 			
-			memset(files[i], 0, sizeof(vfs_file_t));
-			fibril_mutex_initialize(&files[i]->lock);
-			vfs_file_addref(files[i]);
+			memset(FILES[i], 0, sizeof(vfs_file_t));
+			fibril_mutex_initialize(&FILES[i]->lock);
+			vfs_file_addref(FILES[i]);
+			fibril_mutex_unlock(&VFS_DATA->lock);
 			return (int) i;
 		}
@@ -135,4 +187,5 @@
 		}
 	}
+	fibril_mutex_unlock(&VFS_DATA->lock);
 	
 	return EMFILE;
@@ -150,10 +203,14 @@
 	if (!vfs_files_init())
 		return ENOMEM;
-	
-	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] == NULL))
+
+	fibril_mutex_lock(&VFS_DATA->lock);	
+	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] == NULL)) {
+		fibril_mutex_unlock(&VFS_DATA->lock);
 		return EBADF;
-	
-	vfs_file_delref(files[fd]);
-	files[fd] = NULL;
+	}
+	
+	vfs_file_delref(FILES[fd]);
+	FILES[fd] = NULL;
+	fibril_mutex_unlock(&VFS_DATA->lock);
 	
 	return EOK;
@@ -173,46 +230,18 @@
 	if (!vfs_files_init())
 		return ENOMEM;
-	
-	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] != NULL))
+
+	fibril_mutex_lock(&VFS_DATA->lock);	
+	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] != NULL)) {
+		fibril_mutex_unlock(&VFS_DATA->lock);
 		return EINVAL;
-	
-	files[fd] = file;
-	vfs_file_addref(files[fd]);
+	}
+	
+	FILES[fd] = file;
+	vfs_file_addref(FILES[fd]);
+	fibril_mutex_unlock(&VFS_DATA->lock);
 	
 	return EOK;
 }
 
-/** Increment reference count of VFS file structure.
- *
- * @param file		File structure that will have reference count
- *			incremented.
- */
-void vfs_file_addref(vfs_file_t *file)
-{
-	/*
-	 * File structures are per-connection, so no-one, except the current
-	 * fibril, should have a reference to them. This is the reason we don't
-	 * do any synchronization here.
-	 */
-	file->refcnt++;
-}
-
-/** Decrement reference count of VFS file structure.
- *
- * @param file		File structure that will have reference count
- *			decremented.
- */
-void vfs_file_delref(vfs_file_t *file)
-{
-	if (file->refcnt-- == 1) {
-		/*
-		 * Lost the last reference to a file, need to drop our reference
-		 * to the underlying VFS node.
-		 */
-		vfs_node_delref(file->node);
-		free(file);
-	}
-}
-
 /** Find VFS file structure for a given file descriptor.
  *
@@ -226,6 +255,11 @@
 		return NULL;
 	
-	if ((fd >= 0) && (fd < MAX_OPEN_FILES))
-		return files[fd];
+	fibril_mutex_lock(&VFS_DATA->lock);
+	if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
+		vfs_file_t *file = FILES[fd];
+		fibril_mutex_unlock(&VFS_DATA->lock);
+		return file;
+	}
+	fibril_mutex_unlock(&VFS_DATA->lock);
 	
 	return NULL;
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 124c0612c8daeba21701095e42877933875fb33a)
+++ uspace/srv/vfs/vfs_ops.c	(revision b75e92976d38e84475ccceb2fe1b4cc21aa5fe63)
@@ -491,9 +491,4 @@
 void vfs_open(ipc_callid_t rid, ipc_call_t *request)
 {
-	if (!vfs_files_init()) {
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	
 	/*
 	 * The POSIX interface is open(path, oflag, mode).
@@ -618,9 +613,4 @@
 	// FIXME: check for sanity of the supplied fs, dev and index
 	
-	if (!vfs_files_init()) {
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	
 	/*
 	 * The interface is open_node(fs, dev, index, oflag).
