Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision 798f3644648816f32e8d38c8788b3427a334235d)
+++ uspace/srv/vfs/vfs.c	(revision b818cffb2cdbbb47bb911eb1870da1165d104a9f)
@@ -125,4 +125,12 @@
 
 	/*
+	 * Initialize VFS node hash table.
+	 */
+	if (!vfs_nodes_init()) {
+		printf("Failed to initialize the VFS node hash table.\n");
+		return ENOMEM;
+	}
+
+	/*
 	 * Allocate and initialize the Path Lookup Buffer.
 	 */
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 798f3644648816f32e8d38c8788b3427a334235d)
+++ uspace/srv/vfs/vfs.h	(revision b818cffb2cdbbb47bb911eb1870da1165d104a9f)
@@ -179,7 +179,9 @@
 extern int vfs_lookup_internal(char *, size_t, vfs_triplet_t *, vfs_pair_t *);
 
-
+extern bool vfs_nodes_init(void);
 extern vfs_node_t *vfs_node_get(vfs_triplet_t *);
 extern void vfs_node_put(vfs_node_t *);
+
+#define MAX_OPEN_FILES	128
 
 extern bool vfs_files_init(void);
@@ -194,6 +196,4 @@
 extern void vfs_node_delref(vfs_node_t *);
 
-#define MAX_OPEN_FILES	128	
-
 extern void vfs_register(ipc_callid_t, ipc_call_t *);
 extern void vfs_mount(ipc_callid_t, ipc_call_t *);
Index: uspace/srv/vfs/vfs_node.c
===================================================================
--- uspace/srv/vfs/vfs_node.c	(revision 798f3644648816f32e8d38c8788b3427a334235d)
+++ uspace/srv/vfs/vfs_node.c	(revision b818cffb2cdbbb47bb911eb1870da1165d104a9f)
@@ -37,4 +37,47 @@
 
 #include "vfs.h"
+#include <stdlib.h>
+#include <string.h>
+#include <atomic.h>
+#include <futex.h>
+#include <libadt/hash_table.h>
+
+/** Futex protecting the VFS node hash table. */
+atomic_t nodes_futex = FUTEX_INITIALIZER;
+
+#define NODES_BUCKETS_LOG	8
+#define NODES_BUCKETS		(1 << NODES_BUCKETS_LOG)
+
+/** VFS node hash table containing all active, in-memory VFS nodes. */
+hash_table_t nodes;
+
+#define KEY_FS_HANDLE	0
+#define KEY_DEV_HANDLE	1
+#define KEY_INDEX	2
+
+static hash_index_t nodes_hash(unsigned long []);
+static int nodes_compare(unsigned long [], hash_count_t, link_t *);
+static void nodes_remove_callback(link_t *);
+
+/** VFS node hash table operations. */
+hash_table_operations_t nodes_ops = {
+	.hash = nodes_hash,
+	.compare = nodes_compare,
+	.remove_callback = nodes_remove_callback
+};
+
+/** Initialize the VFS node hash table.
+ *
+ * @return		Return true on success, false on failure.
+ */
+bool vfs_nodes_init(void)
+{
+	return hash_table_create(&nodes, NODES_BUCKETS, 3, &nodes_ops);
+}
+
+static inline void _vfs_node_addref(vfs_node_t *node)
+{
+	node->refcnt++;
+}
 
 /** Increment reference count of a VFS node.
@@ -44,5 +87,7 @@
 void vfs_node_addref(vfs_node_t *node)
 {
-	/* TODO */
+	futex_down(&nodes_futex);
+	_vfs_node_addref(node);
+	futex_up(&nodes_futex);
 }
 
@@ -55,5 +100,14 @@
 void vfs_node_delref(vfs_node_t *node)
 {
-	/* TODO */
+	futex_down(&nodes_futex);
+	if (node->refcnt-- == 1) {
+		unsigned long key[] = {
+			[KEY_FS_HANDLE] = node->fs_handle,
+			[KEY_DEV_HANDLE] = node->dev_handle,
+			[KEY_INDEX] = node->index
+		};
+		hash_table_remove(&nodes, key, 3);
+	}
+	futex_up(&nodes_futex);
 }
 
@@ -72,6 +126,33 @@
 vfs_node_t *vfs_node_get(vfs_triplet_t *triplet)
 {
-	/* TODO */
-	return NULL;
+	unsigned long key[] = {
+		[KEY_FS_HANDLE] = triplet->fs_handle,
+		[KEY_DEV_HANDLE] = triplet->dev_handle,
+		[KEY_INDEX] = triplet->index
+	};
+	link_t *tmp;
+	vfs_node_t *node;
+
+	futex_down(&nodes_futex);
+	tmp = hash_table_find(&nodes, key);
+	if (!tmp) {
+		node = (vfs_node_t *) malloc(sizeof(vfs_node_t));
+		if (!node) {
+			futex_up(&nodes_futex);
+			return NULL;
+		}
+		memset(node, 0, sizeof(vfs_node_t));
+		node->fs_handle = triplet->fs_handle;
+		node->dev_handle = triplet->fs_handle;
+		node->index = triplet->index;
+		link_initialize(&node->nh_link);
+		hash_table_insert(&nodes, key, &node->nh_link);
+	} else {
+		node = hash_table_get_instance(tmp, vfs_node_t, nh_link);	
+	}
+	_vfs_node_addref(node);
+	futex_up(&nodes_futex);
+
+	return node;
 }
 
@@ -89,4 +170,26 @@
 }
 
+hash_index_t nodes_hash(unsigned long key[])
+{
+	hash_index_t a = key[KEY_FS_HANDLE] << (NODES_BUCKETS_LOG / 4);
+	hash_index_t b = (a | key[KEY_DEV_HANDLE]) << (NODES_BUCKETS_LOG / 2);
+	
+	return (b | key[KEY_INDEX]) & ~(NODES_BUCKETS - 1);
+}
+
+int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item)
+{
+	vfs_node_t *node = hash_table_get_instance(item, vfs_node_t, nh_link);
+	return (node->fs_handle == key[KEY_FS_HANDLE]) &&
+	    (node->dev_handle == key[KEY_DEV_HANDLE]) &&
+	    (node->index == key[KEY_INDEX]);
+}
+
+void nodes_remove_callback(link_t *item)
+{
+	vfs_node_t *node = hash_table_get_instance(item, vfs_node_t, nh_link);
+	free(node);
+}
+
 /**
  * @}
