Index: uspace/srv/vfs/Makefile
===================================================================
--- uspace/srv/vfs/Makefile	(revision ec01adf792cc98673b1eb8d4405d8a1e678e1279)
+++ uspace/srv/vfs/Makefile	(revision 320c884ce7849114860dfbac7d5040eb876a08f2)
@@ -44,8 +44,10 @@
 	vfs.c \
 	vfs_node.c \
+	vfs_file.c \
 	vfs_register.c \
 	vfs_lookup.c \
 	vfs_mount.c \
-	vfs_open.c
+	vfs_open.c \
+	vfs_unlink.c
 
 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision ec01adf792cc98673b1eb8d4405d8a1e678e1279)
+++ uspace/srv/vfs/vfs.c	(revision 320c884ce7849114860dfbac7d5040eb876a08f2)
@@ -101,4 +101,6 @@
 		case VFS_WRITE:
 		case VFS_SEEK:
+		case VFS_UNLINK:
+		case VFS_RENAME:
 		default:
 			ipc_answer_fast_0(callid, ENOTSUP);
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision ec01adf792cc98673b1eb8d4405d8a1e678e1279)
+++ uspace/srv/vfs/vfs.h	(revision 320c884ce7849114860dfbac7d5040eb876a08f2)
@@ -57,4 +57,6 @@
 	VFS_WRITE,
 	VFS_SEEK,
+	VFS_RENAME,
+	VFS_UNLINK,
 	VFS_LAST,		/* keep this the last member of the enum */
 } vfs_request_t;
@@ -131,5 +133,6 @@
 typedef struct {
 	VFS_TRIPLET;		/**< Identity of the node. */
-	atomic_t refcnt;	/**< Usage counter. */
+	unsigned refcnt;	/**< Usage counter. */
+	link_t nh_link;		/**< Node hash-table link. */
 } vfs_node_t;
 
@@ -142,5 +145,5 @@
 	
 	/** Number of file handles referencing this file. */
-	atomic_t refcnt;
+	unsigned refcnt;
 
 	/** Current position in the file. */
@@ -167,4 +170,6 @@
 extern link_t plb_head;		/**< List of active PLB entries. */
 
+extern atomic_t unlink_futex;	/**< VFS_{CREATE|OPEN|UNLINK} serialization. */
+
 extern int vfs_grab_phone(int);
 extern void vfs_release_phone(int);
@@ -173,5 +178,19 @@
 
 extern int vfs_lookup_internal(char *, size_t, vfs_triplet_t *, vfs_pair_t *);
+
+
 extern vfs_node_t *vfs_node_get(vfs_triplet_t *);
+extern void vfs_node_put(vfs_node_t *);
+
+extern bool vfs_files_init(void);
+extern vfs_file_t *vfs_file_get(int);
+extern int vfs_fd_alloc(void);
+extern void 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 *);
+extern void vfs_node_delref(vfs_node_t *);
 
 #define MAX_OPEN_FILES	128	
Index: uspace/srv/vfs/vfs_file.c
===================================================================
--- uspace/srv/vfs/vfs_file.c	(revision 320c884ce7849114860dfbac7d5040eb876a08f2)
+++ uspace/srv/vfs/vfs_file.c	(revision 320c884ce7849114860dfbac7d5040eb876a08f2)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2007 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */ 
+
+/**
+ * @file	vfs_file.c
+ * @brief	Various operations on files have their home in this file.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <bool.h>
+#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 futex.
+ */
+__thread vfs_file_t **files = NULL;
+
+/** Initialize the table of open files. */
+bool vfs_files_init(void)
+{
+	if (!files) {
+		files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
+		if (!files)
+			return false;
+		memset(files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
+	}
+	return true;
+}
+
+/** Allocate a file descriptor.
+ *
+ * @return		First available file descriptor or a negative error
+ *			code.
+ */
+int vfs_fd_alloc(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_OPEN_FILES; i++) {
+		if (!files[i]) {
+			files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
+			if (!files[i])
+				return ENOMEM;
+			memset(files[i], 0, sizeof(vfs_file_t));
+			vfs_file_addref(files[i]);
+			return i;
+		}
+	}
+	return EMFILE;
+}
+
+/** Release file descriptor.
+ *
+ * @param fd		File descriptor being released.
+ */
+void vfs_fd_free(int fd)
+{
+	assert(files[fd] != NULL);
+	vfs_file_delref(files[fd]);
+	files[fd] = NULL;
+}
+
+/** 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 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.
+ *
+ * @param fd		File descriptor.
+ *
+ * @return		VFS file structure corresponding to fd.
+ */
+vfs_file_t *vfs_file_get(int fd)
+{
+	return files[fd];
+}
+
+/**
+ * @}
+ */ 
Index: uspace/srv/vfs/vfs_node.c
===================================================================
--- uspace/srv/vfs/vfs_node.c	(revision ec01adf792cc98673b1eb8d4405d8a1e678e1279)
+++ uspace/srv/vfs/vfs_node.c	(revision 320c884ce7849114860dfbac7d5040eb876a08f2)
@@ -38,7 +38,53 @@
 #include "vfs.h"
 
+/** Increment reference count of a VFS node.
+ *
+ * @param node		VFS node that will have its refcnt incremented.
+ */
+void vfs_node_addref(vfs_node_t *node)
+{
+	/* TODO */
+}
+
+/** Decrement reference count of a VFS node.
+ *
+ * This function handles the case when the reference count drops to zero.
+ *
+ * @param node		VFS node that will have its refcnt decremented.
+ */
+void vfs_node_delref(vfs_node_t *node)
+{
+	/* TODO */
+}
+
+/** Find VFS node.
+ *
+ * This function will try to lookup the given triplet in the VFS node hash
+ * table. In case the triplet is not found there, a new VFS node is created.
+ * In any case, the VFS node will have its reference count incremented. Every
+ * node returned by this call should be eventually put back by calling
+ * vfs_node_put() on it.
+ *
+ * @param triplet	Triplet encoding the identity of the VFS node.
+ *
+ * @return		VFS node corresponding to the given triplet.
+ */
 vfs_node_t *vfs_node_get(vfs_triplet_t *triplet)
 {
-	return NULL;	// TODO: not implemented
+	/* TODO */
+	return NULL;
+}
+
+/** Return VFS node when no longer needed by the caller.
+ *
+ * This function will remove the reference on the VFS node created by
+ * vfs_node_get(). This function can only be called as a closing bracket to the
+ * preceding vfs_node_get() call.
+ *
+ * @param node		VFS node being released.
+ */
+void vfs_node_put(vfs_node_t *node)
+{
+	vfs_node_delref(node);
 }
 
Index: uspace/srv/vfs/vfs_open.c
===================================================================
--- uspace/srv/vfs/vfs_open.c	(revision ec01adf792cc98673b1eb8d4405d8a1e678e1279)
+++ uspace/srv/vfs/vfs_open.c	(revision 320c884ce7849114860dfbac7d5040eb876a08f2)
@@ -39,56 +39,12 @@
 #include <async.h>
 #include <errno.h>
+#include <futex.h>
+#include <sys/types.h>
 #include <stdlib.h>
-#include <string.h>
-#include <bool.h>
-#include <futex.h>
-#include <libadt/list.h>
-#include <sys/types.h>
 #include "vfs.h"
-
-/** Per-connection futex protecting the files array. */
-__thread atomic_t files_futex = FUTEX_INITIALIZER;
-
-/**
- * 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.
- */
-__thread vfs_file_t *files = NULL;
-
-/** Initialize the table of open files. */
-static bool vfs_conn_open_files_init(void)
-{
-	/*
-	 * Optimized fast path that will never go to sleep unnecessarily.
-	 * The assumption is that once files is non-zero, it will never be zero
-	 * again.
-	 */
-	if (files)
-		return true;
-		
-	futex_down(&files_futex);
-	if (!files) {
-		files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t));
-		if (!files) {
-			futex_up(&files_futex);
-			return false;
-		}
-		memset(files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t));
-	}
-	futex_up(&files_futex);
-	return true;
-}
 
 void vfs_open(ipc_callid_t rid, ipc_call_t *request)
 {
-	if (!vfs_conn_open_files_init()) {
+	if (!vfs_files_init()) {
 		ipc_answer_fast_0(rid, ENOMEM);
 		return;
@@ -128,5 +84,5 @@
 
 	int rc;
-	if (rc = ipc_data_deliver(callid, &call, path, size)) {
+	if ((rc = ipc_data_deliver(callid, &call, path, size))) {
 		ipc_answer_fast_0(rid, rc);
 		free(path);
@@ -135,4 +91,11 @@
 	
 	/*
+	 * Avoid the race condition in which the file can be deleted before we
+	 * find/create-and-lock the VFS node corresponding to the looked-up
+	 * triplet.
+	 */
+	futex_down(&unlink_futex);
+
+	/*
 	 * The path is now populated and we can call vfs_lookup_internal().
 	 */
@@ -140,4 +103,5 @@
 	rc = vfs_lookup_internal(path, size, &triplet, NULL);
 	if (rc) {
+		futex_up(&unlink_futex);
 		ipc_answer_fast_0(rid, rc);
 		free(path);
@@ -151,5 +115,33 @@
 
 	vfs_node_t *node = vfs_node_get(&triplet);
-	// TODO: not finished	
+	futex_up(&unlink_futex);
+
+	/*
+	 * Get ourselves a file descriptor and the corresponding vfs_file_t
+	 * structure.
+	 */
+	int fd = vfs_fd_alloc();
+	if (fd < 0) {
+		vfs_node_put(node);
+		ipc_answer_fast_0(rid, fd);
+		return;
+	}
+	vfs_file_t *file = vfs_file_get(fd);
+	file->node = node;
+
+	/*
+	 * The following increase in reference count is for the fact that the
+	 * file is being opened and that a file structure is pointing to it.
+	 * It is necessary so that the file will not disappear when
+	 * vfs_node_put() is called. The reference will be dropped by the
+	 * respective VFS_CLOSE.
+	 */
+	vfs_node_addref(node);
+	vfs_node_put(node);
+
+	/*
+	 * Success! Return the new file descriptor to the client.
+	 */
+	ipc_answer_fast_1(rid, EOK, fd);
 }
 
Index: uspace/srv/vfs/vfs_unlink.c
===================================================================
--- uspace/srv/vfs/vfs_unlink.c	(revision 320c884ce7849114860dfbac7d5040eb876a08f2)
+++ uspace/srv/vfs/vfs_unlink.c	(revision 320c884ce7849114860dfbac7d5040eb876a08f2)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */ 
+
+/**
+ * @file	vfs_unlink.c
+ * @brief
+ */
+
+#include <atomic.h>
+#include <futex.h>
+
+/**
+ * This futex serializes concurrent VFS_CREATE, VFS_OPEN and VFS_UNLINK
+ * operations.
+ */
+atomic_t unlink_futex = FUTEX_INITIALIZER;
+
+/**
+ * @}
+ */ 
