Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 1fe186f2fd88fc8bcd4291c8fe20c9c2a3fa2adb)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 72bde81acaa9c2c39b124ad814001c2046dbb66d)
@@ -212,5 +212,40 @@
     const char *component, int lflag)
 {
-	return 0;
+	assert(dentry->type == TMPFS_DIRECTORY);
+	assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
+
+	tmpfs_dentry_t *node = malloc(sizeof(tmpfs_dentry_t));
+	if (!node)
+		return 0;
+	size_t len = strlen(component);
+	char *name = malloc(len + 1);
+	if (!name) {
+		free(node);
+		return 0;
+	}
+	strcpy(name, component);
+
+	tmpfs_dentry_initialize(node);
+	node->index = tmpfs_next_index++;
+	node->name = name;
+	node->parent = dentry;
+	if (lflag & L_DIRECTORY) 
+		node->type = TMPFS_DIRECTORY;
+	else 
+		node->type = TMPFS_FILE;
+
+	/* Insert the new node into the namespace. */
+	if (dentry->child) {
+		tmpfs_dentry_t *tmp = dentry->child;
+		while (tmp->sibling)
+			tmp = tmp->sibling;
+		tmp->sibling = node;
+	} else {
+		dentry->child = node;
+	}
+
+	/* Insert the new node into the dentry hash table. */
+	hash_table_insert(&dentries, &node->index, &node->dh_link);
+	return node->index;
 }
 
@@ -257,5 +292,5 @@
 			component[len++] = PLB_GET_CHAR(next);
 			next++;	/* process next character */
-			if (next <= last)
+			if (next <= last) 
 				continue;
 		}
@@ -280,5 +315,5 @@
 				unsigned long index = create_node(dcur,
 				    component, lflag);
-				if (index) {
+				if (index > 0) {
 					ipc_answer_4(rid, EOK,
 					    tmpfs_reg.fs_handle, dev_handle,
Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision 1fe186f2fd88fc8bcd4291c8fe20c9c2a3fa2adb)
+++ uspace/srv/vfs/vfs.c	(revision 72bde81acaa9c2c39b124ad814001c2046dbb66d)
@@ -106,11 +106,7 @@
 			vfs_truncate(callid, &call);
 			break;
-		case VFS_UNMOUNT:
-		case VFS_CLOSE:
-		case VFS_UNLINK:
-		case VFS_RENAME:
-		case VFS_OPENDIR:
-		case VFS_READDIR:
-		case VFS_CLOSEDIR:
+		case VFS_MKDIR:
+			vfs_mkdir(callid, &call);
+			break;
 		default:
 			ipc_answer_0(callid, ENOTSUP);
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 1fe186f2fd88fc8bcd4291c8fe20c9c2a3fa2adb)
+++ uspace/srv/vfs/vfs.h	(revision 72bde81acaa9c2c39b124ad814001c2046dbb66d)
@@ -57,4 +57,5 @@
 	VFS_READDIR,
 	VFS_CLOSEDIR,
+	VFS_MKDIR,
 	VFS_UNLINK,
 	VFS_MOUNT,
@@ -262,4 +263,5 @@
 extern void vfs_seek(ipc_callid_t, ipc_call_t *);
 extern void vfs_truncate(ipc_callid_t, ipc_call_t *);
+extern void vfs_mkdir(ipc_callid_t, ipc_call_t *);
 
 #endif
Index: uspace/srv/vfs/vfs_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision 1fe186f2fd88fc8bcd4291c8fe20c9c2a3fa2adb)
+++ uspace/srv/vfs/vfs_lookup.c	(revision 72bde81acaa9c2c39b124ad814001c2046dbb66d)
@@ -58,4 +58,5 @@
  * @param lflag		Flags to be used during lookup.
  * @param result	Empty structure where the lookup result will be stored.
+ *			Can be NULL.
  * @param altroot	If non-empty, will be used instead of rootfs as the root
  *			of the whole VFS tree.
@@ -163,5 +164,5 @@
 	futex_up(&plb_futex);
 
-	if (rc == EOK) {
+	if ((rc == EOK) && result) {
 		result->triplet.fs_handle = (int) IPC_GET_ARG1(answer);
 		result->triplet.dev_handle = (int) IPC_GET_ARG2(answer);
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 1fe186f2fd88fc8bcd4291c8fe20c9c2a3fa2adb)
+++ uspace/srv/vfs/vfs_ops.c	(revision 72bde81acaa9c2c39b124ad814001c2046dbb66d)
@@ -116,7 +116,5 @@
 	}
 
-	/*
-	 * Deliver the file system name.
-	 */
+	/* Deliver the file system name. */
 	char fs_name[FS_NAME_MAXLEN + 1];
 	(void) ipc_data_write_finalize(callid, fs_name, size);
@@ -133,7 +131,5 @@
 	}
 
-	/*
-	 * Now, we want the client to send us the mount point.
-	 */
+	/* Now, we want the client to send us the mount point. */
 	if (!ipc_data_write_receive(&callid, &size)) {
 		ipc_answer_0(callid, EINVAL);
@@ -142,7 +138,5 @@
 	}
 
-	/*
-	 * Check whether size is reasonable wrt. the mount point.
-	 */
+	/* Check whether size is reasonable wrt. the mount point. */
 	if (size < 1 || size > MAX_PATH_LEN) {
 		ipc_answer_0(callid, EINVAL);
@@ -150,7 +144,5 @@
 		return;
 	}
-	/*
-	 * Allocate buffer for the mount point data being received.
-	 */
+	/* Allocate buffer for the mount point data being received. */
 	uint8_t *buf;
 	buf = malloc(size);
@@ -161,7 +153,5 @@
 	}
 
-	/*
-	 * Deliver the mount point.
-	 */
+	/* Deliver the mount point. */
 	(void) ipc_data_write_finalize(callid, buf, size);
 
@@ -187,20 +177,14 @@
 	}
 
-	/*
-	 * Finally, we need to resolve the path to the mountpoint. 
-	 */
+	/* Finally, we need to resolve the path to the mountpoint. */
 	vfs_lookup_res_t mp_res;
 	futex_down(&rootfs_futex);
 	if (rootfs.fs_handle) {
-		/*
-		 * We already have the root FS.
-		 */
+		/* We already have the root FS. */
 		rwlock_write_lock(&namespace_rwlock);
 		rc = vfs_lookup_internal(buf, size, L_DIRECTORY, &mp_res,
 		    NULL);
 		if (rc != EOK) {
-			/*
-			 * The lookup failed for some reason.
-			 */
+			/* The lookup failed for some reason. */
 			rwlock_write_unlock(&namespace_rwlock);
 			futex_up(&rootfs_futex);
@@ -226,11 +210,7 @@
 		rwlock_write_unlock(&namespace_rwlock);
 	} else {
-		/*
-		 * We still don't have the root file system mounted.
-		 */
+		/* We still don't have the root file system mounted. */
 		if ((size == 1) && (buf[0] == '/')) {
-			/*
-			 * For this simple, but important case, we are done.
-			 */
+			/* For this simple, but important case, we are done. */
 			rootfs = mr_res.triplet;
 			futex_up(&rootfs_futex);
@@ -348,7 +328,5 @@
 	rwlock_read_lock(&namespace_rwlock);
 
-	/*
-	 * The path is now populated and we can call vfs_lookup_internal().
-	 */
+	/* The path is now populated and we can call vfs_lookup_internal(). */
 	vfs_lookup_res_t lr;
 	rc = vfs_lookup_internal(path, len, lflag, &lr, NULL);
@@ -360,7 +338,5 @@
 	}
 
-	/*
-	 * Path is no longer needed.
-	 */
+	/** Path is no longer needed. */
 	free(path);
 
@@ -391,7 +367,5 @@
 	vfs_node_put(node);
 
-	/*
-	 * Success! Return the new file descriptor to the client.
-	 */
+	/* Success! Return the new file descriptor to the client. */
 	ipc_answer_1(rid, EOK, fd);
 }
@@ -412,7 +386,5 @@
 	int fd = IPC_GET_ARG1(*request);
 
-	/*
-	 * Lookup the file structure corresponding to the file descriptor.
-	 */
+	/* Lookup the file structure corresponding to the file descriptor. */
 	vfs_file_t *file = vfs_file_get(fd);
 	if (!file) {
@@ -454,7 +426,5 @@
 	int fs_phone = vfs_grab_phone(file->node->fs_handle);	
 	
-	/*
-	 * Make a VFS_READ/VFS_WRITE request at the destination FS server.
-	 */
+	/* Make a VFS_READ/VFS_WRITE request at the destination FS server. */
 	aid_t msg;
 	ipc_call_t answer;
@@ -472,14 +442,10 @@
 	vfs_release_phone(fs_phone);
 
-	/*
-	 * Wait for reply from the FS server.
-	 */
+	/* Wait for reply from the FS server. */
 	ipcarg_t rc;
 	async_wait_for(msg, &rc);
 	size_t bytes = IPC_GET_ARG1(answer);
 
-	/*
-	 * Unlock the VFS node.
-	 */
+	/* Unlock the VFS node. */
 	if (read)
 		rwlock_read_unlock(&file->node->contents_rwlock);
@@ -490,7 +456,5 @@
 	}
 
-	/*
-	 * Update the position pointer and unlock the open file.
-	 */
+	/* Update the position pointer and unlock the open file. */
 	file->pos += bytes;
 	futex_up(&file->lock);
@@ -520,7 +484,5 @@
 
 
-	/*
-	 * Lookup the file structure corresponding to the file descriptor.
-	 */
+	/* Lookup the file structure corresponding to the file descriptor. */
 	vfs_file_t *file = vfs_file_get(fd);
 	if (!file) {
@@ -582,6 +544,7 @@
 	rwlock_write_lock(&file->node->contents_rwlock);
 	int fs_phone = vfs_grab_phone(file->node->fs_handle);
-	rc = async_req_3_0(fs_phone, VFS_TRUNCATE, (ipcarg_t)file->node->dev_handle,
-	    (ipcarg_t)file->node->index, (ipcarg_t)size);
+	rc = async_req_3_0(fs_phone, VFS_TRUNCATE,
+	    (ipcarg_t)file->node->dev_handle, (ipcarg_t)file->node->index,
+	    (ipcarg_t)size);
 	vfs_release_phone(fs_phone);
 	if (rc == EOK)
@@ -593,4 +556,46 @@
 }
 
+void vfs_mkdir(ipc_callid_t rid, ipc_call_t *request)
+{
+	int mode = IPC_GET_ARG1(*request);
+	size_t len;
+
+	ipc_callid_t callid;
+
+	if (!ipc_data_write_receive(&callid, &len)) {
+		ipc_answer_0(callid, EINVAL);
+		ipc_answer_0(rid, EINVAL);
+		return;
+	}
+
+	/*
+	 * Now we are on the verge of accepting the path.
+	 *
+	 * There is one optimization we could do in the future: copy the path
+	 * directly into the PLB using some kind of a callback.
+	 */
+	char *path = malloc(len);
+	
+	if (!path) {
+		ipc_answer_0(callid, ENOMEM);
+		ipc_answer_0(rid, ENOMEM);
+		return;
+	}
+
+	int rc;
+	if ((rc = ipc_data_write_finalize(callid, path, len))) {
+		ipc_answer_0(rid, rc);
+		free(path);
+		return;
+	}
+	
+	rwlock_write_lock(&namespace_rwlock);
+	int lflag = L_DIRECTORY | L_CREATE | L_EXCLUSIVE;
+	rc = vfs_lookup_internal(path, len, lflag, NULL, NULL);
+	rwlock_write_unlock(&namespace_rwlock);
+	free(path);
+	ipc_answer_0(rid, rc);
+}
+
 /**
  * @}
