Index: uspace/app/bdsh/cmds/modules/mount/mount.c
===================================================================
--- uspace/app/bdsh/cmds/modules/mount/mount.c	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/app/bdsh/cmds/modules/mount/mount.c	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -151,5 +151,5 @@
 		mopts = t_argv[4];
 
-	rc = vfs_mount(t_argv[1], t_argv[2], dev, mopts, 0, instance);
+	rc = mount(t_argv[1], t_argv[2], dev, mopts, 0, instance);
 	if (rc != EOK) {
 		printf("Unable to mount %s filesystem to %s on %s (rc=%s)\n",
Index: uspace/app/bdsh/cmds/modules/unmount/unmount.c
===================================================================
--- uspace/app/bdsh/cmds/modules/unmount/unmount.c	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/app/bdsh/cmds/modules/unmount/unmount.c	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -66,5 +66,5 @@
 	}
 
-	rc = vfs_unmount(argv[1]);
+	rc = unmount(argv[1]);
 	if (rc != EOK) {
 		printf("Unable to unmount %s (rc=%d)\n", argv[1], rc);
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/app/init/init.c	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -127,5 +127,5 @@
 		opts = "restore";
 	
-	int rc = vfs_mount(fstype, ROOT_MOUNT_POINT, ROOT_DEVICE, opts,
+	int rc = mount(fstype, ROOT_MOUNT_POINT, ROOT_DEVICE, opts,
 	    IPC_FLAG_BLOCKING, 0);
 	return mount_report("Root filesystem", ROOT_MOUNT_POINT, fstype,
@@ -144,5 +144,5 @@
 static bool mount_locfs(void)
 {
-	int rc = vfs_mount(LOCFS_FS_TYPE, LOCFS_MOUNT_POINT, "", "",
+	int rc = mount(LOCFS_FS_TYPE, LOCFS_MOUNT_POINT, "", "",
 	    IPC_FLAG_BLOCKING, 0);
 	return mount_report("Location service filesystem", LOCFS_MOUNT_POINT,
@@ -300,5 +300,5 @@
 static bool mount_tmpfs(void)
 {
-	int rc = vfs_mount(TMPFS_FS_TYPE, TMPFS_MOUNT_POINT, "", "", 0, 0);
+	int rc = mount(TMPFS_FS_TYPE, TMPFS_MOUNT_POINT, "", "", 0, 0);
 	return mount_report("Temporary filesystem", TMPFS_MOUNT_POINT,
 	    TMPFS_FS_TYPE, NULL, rc);
Index: uspace/app/sysinst/sysinst.c
===================================================================
--- uspace/app/sysinst/sysinst.c	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/app/sysinst/sysinst.c	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -180,5 +180,5 @@
 
 	printf("sysinst_fs_mount(): mount filesystem\n");
-	rc = vfs_mount(FS_TYPE, MOUNT_POINT, dev, "", 0, 0);
+	rc = mount(FS_TYPE, MOUNT_POINT, dev, "", 0, 0);
 	if (rc != EOK)
 		return rc;
@@ -219,5 +219,5 @@
 
 	printf("sysinst_copy_boot_files(): mount CD filesystem\n");
-	rc = vfs_mount(CD_FS_TYPE, CD_MOUNT_POINT, CD_DEV, "", 0, 0);
+	rc = mount(CD_FS_TYPE, CD_MOUNT_POINT, CD_DEV, "", 0, 0);
 	if (rc != EOK)
 		return rc;
@@ -229,5 +229,5 @@
 
 	printf("sysinst_copy_boot_files(): unmount %s\n", MOUNT_POINT);
-	rc = vfs_unmount(MOUNT_POINT);
+	rc = unmount(MOUNT_POINT);
 	if (rc != EOK)
 		return rc;
Index: uspace/app/trace/trace.c
===================================================================
--- uspace/app/trace/trace.c	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/app/trace/trace.c	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -512,5 +512,5 @@
 		goto error;
 
-	/* Send program pathname */
+	/* Send program. */
 	rc = loader_set_program_path(ldr, path);
 	if (rc != EOK)
@@ -523,7 +523,16 @@
 
 	/* Send default files */
+	int fd_root;
 	int fd_stdin;
 	int fd_stdout;
 	int fd_stderr;
+	
+	fd_root = vfs_root();
+	if (fd_root >= 0) {
+		rc = loader_add_inbox(ldr, "root", fd_root);
+		close(fd_root);
+		if (rc != EOK)
+			goto error;
+	}
 	
 	if ((stdin != NULL) && (vfs_fhandle(stdin, &fd_stdin) == EOK)) {
Index: uspace/lib/c/generic/elf/elf_mod.c
===================================================================
--- uspace/lib/c/generic/elf/elf_mod.c	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/lib/c/generic/elf/elf_mod.c	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -115,5 +115,5 @@
     elf_finfo_t *info)
 {
-	int file = vfs_lookup(path);
+	int file = vfs_lookup(path, 0);
 	int rc = elf_load_file(file, so_bias, flags, info);
 	close(file);
Index: uspace/lib/c/generic/libc.c
===================================================================
--- uspace/lib/c/generic/libc.c	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/lib/c/generic/libc.c	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -48,4 +48,6 @@
 #include <task.h>
 #include <loader/pcb.h>
+#include <vfs/vfs.h>
+#include <vfs/inbox.h>
 #include "private/libc.h"
 #include "private/async.h"
@@ -113,4 +115,5 @@
 		__inbox_init(__pcb->inbox, __pcb->inbox_entries);
 		__stdio_init();
+		vfs_root_set(inbox_get("root"));
 		(void) chdir(__pcb->cwd);
 	}
Index: uspace/lib/c/generic/loader.c
===================================================================
--- uspace/lib/c/generic/loader.c	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/lib/c/generic/loader.c	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -198,5 +198,5 @@
 	}
 	
-	int fd = vfs_lookup(path);
+	int fd = vfs_lookup(path, 0);
 	if (fd < 0) {
 		return fd;
Index: uspace/lib/c/generic/task.c
===================================================================
--- uspace/lib/c/generic/task.c	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/lib/c/generic/task.c	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -48,4 +48,5 @@
 #include "private/ns.h"
 #include <vfs/vfs.h>
+#include <unistd.h>
 
 task_id_t task_get_id(void)
@@ -177,4 +178,12 @@
 	
 	/* Send files */
+	int root = vfs_root();
+	if (root >= 0) {
+		rc = loader_add_inbox(ldr, "root", root);
+		close(root);
+		if (rc != EOK)
+			goto error;
+	}
+	
 	if (fd_stdin >= 0) {
 		rc = loader_add_inbox(ldr, "stdin", fd_stdin);
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -65,4 +65,30 @@
 static size_t cwd_size = 0;
 
+static FIBRIL_MUTEX_INITIALIZE(root_mutex);
+static int root_fd = -1;
+
+int vfs_root(void)
+{
+	fibril_mutex_lock(&root_mutex);	
+	int r;
+	if (root_fd < 0) {
+		r = ENOENT;
+	} else {
+		r = vfs_clone(root_fd, true);
+	}
+	fibril_mutex_unlock(&root_mutex);
+	return r;
+}
+
+void vfs_root_set(int nroot)
+{
+	fibril_mutex_lock(&root_mutex);
+	if (root_fd >= 0) {
+		close(root_fd);
+	}
+	root_fd = vfs_clone(nroot, true);
+	fibril_mutex_unlock(&root_mutex);
+}
+
 /** Start an async exchange on the VFS session.
  *
@@ -116,5 +142,5 @@
 }
 
-int vfs_lookup(const char *path)
+int vfs_lookup(const char *path, int flags)
 {
 	size_t size;
@@ -123,5 +149,11 @@
 		return ENOMEM;
 	}
-	int rc = _vfs_walk(-1, p, 0);
+	int root = vfs_root();
+	if (root == -1) {
+		free(p);
+		return ENOENT;
+	}
+	int rc = _vfs_walk(root, p, flags);
+	close(root);
 	free(p);
 	return rc;
@@ -187,5 +219,49 @@
 }
 
-int vfs_mount(const char *fs_name, const char *mp, const char *fqsn,
+int vfs_mount(int mp, const char *fs_name, service_id_t serv, const char *opts,
+unsigned int flags, unsigned int instance, int *mountedfd)
+{
+	sysarg_t rc, rc1;
+	
+	if (!mountedfd) {
+		flags |= VFS_MOUNT_NO_REF;
+	}
+	if (mp < 0) {
+		flags |= VFS_MOUNT_CONNECT_ONLY;
+	}
+	
+	ipc_call_t answer;
+	async_exch_t *exch = vfs_exchange_begin();
+	aid_t req = async_send_4(exch, VFS_IN_MOUNT, mp, serv, flags, instance, &answer);
+
+	rc1 = async_data_write_start(exch, (void *) opts, str_size(opts));
+	
+	if (rc1 == EOK) {
+		rc1 = async_data_write_start(exch, (void *) fs_name, str_size(fs_name));
+	}
+
+	vfs_exchange_end(exch);
+
+	async_wait_for(req, &rc);
+
+	if (mountedfd) {
+		*mountedfd = (int) IPC_GET_ARG1(answer);
+	}
+	
+	if (rc != EOK) {
+		return rc;
+	}
+	return rc1;
+}
+
+int vfs_unmount(int mp)
+{
+	async_exch_t *exch = vfs_exchange_begin();
+	int rc = async_req_1_0(exch, VFS_IN_UNMOUNT, mp);
+	vfs_exchange_end(exch);
+	return rc;
+}
+
+int mount(const char *fs_name, const char *mp, const char *fqsn,
     const char *opts, unsigned int flags, unsigned int instance)
 {
@@ -205,4 +281,10 @@
 	}
 	
+	if (flags & IPC_FLAG_BLOCKING) {
+		flags = VFS_MOUNT_BLOCKING;
+	} else {
+		flags = 0;
+	}
+	
 	service_id_t service_id;
 	int res = loc_service_get_id(fqsn, &service_id, flags);
@@ -223,57 +305,43 @@
 	}
 	
-	async_exch_t *exch = vfs_exchange_begin();
-
-	sysarg_t rc_orig;
-	aid_t req = async_send_3(exch, VFS_IN_MOUNT, service_id, flags,
-	    instance, NULL);
-	sysarg_t rc = async_data_write_start(exch, (void *) mpa, mpa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(exch);
-		free(mpa);
-		async_wait_for(req, &rc_orig);
+	fibril_mutex_lock(&root_mutex);
+	
+	int rc;
+	
+	if (str_cmp(mpa, "/") == 0) {
+		/* Mounting root. */
 		
-		if (null_id != -1)
-			loc_null_destroy(null_id);
+		if (root_fd >= 0) {
+			fibril_mutex_unlock(&root_mutex);
+			if (null_id != -1) {
+				loc_null_destroy(null_id);
+			}
+			return EBUSY;
+		}
 		
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	
-	rc = async_data_write_start(exch, (void *) opts, str_size(opts));
-	if (rc != EOK) {
-		vfs_exchange_end(exch);
-		free(mpa);
-		async_wait_for(req, &rc_orig);
+		int root;
+		rc = vfs_mount(-1, fs_name, service_id, opts, flags, instance, &root);
+		if (rc == EOK) {
+			root_fd = root;
+		}
+	} else {
+		if (root_fd < 0) {
+			fibril_mutex_unlock(&root_mutex);
+			if (null_id != -1) {
+				loc_null_destroy(null_id);
+			}
+			return EINVAL;
+		}
 		
-		if (null_id != -1)
-			loc_null_destroy(null_id);
-		
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	
-	rc = async_data_write_start(exch, (void *) fs_name, str_size(fs_name));
-	if (rc != EOK) {
-		vfs_exchange_end(exch);
-		free(mpa);
-		async_wait_for(req, &rc_orig);
-		
-		if (null_id != -1)
-			loc_null_destroy(null_id);
-		
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	
-	vfs_exchange_end(exch);
-	free(mpa);
-	async_wait_for(req, &rc);
+		int mpfd = _vfs_walk(root_fd, mpa, WALK_DIRECTORY);
+		if (mpfd >= 0) {
+			rc = vfs_mount(mpfd, fs_name, service_id, opts, flags, instance, NULL);
+			close(mpfd);
+		} else {
+			rc = mpfd;
+		}
+	}
+	
+	fibril_mutex_unlock(&root_mutex);
 	
 	if ((rc != EOK) && (null_id != -1))
@@ -283,36 +351,14 @@
 }
 
-int vfs_unmount(const char *mp)
-{
-	sysarg_t rc;
-	sysarg_t rc_orig;
-	aid_t req;
-	size_t mpa_size;
-	char *mpa;
-	
-	mpa = vfs_absolutize(mp, &mpa_size);
-	if (mpa == NULL)
-		return ENOMEM;
-	
-	async_exch_t *exch = vfs_exchange_begin();
-	
-	req = async_send_0(exch, VFS_IN_UNMOUNT, NULL);
-	rc = async_data_write_start(exch, (void *) mpa, mpa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(exch);
-		free(mpa);
-		async_wait_for(req, &rc_orig);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	
-
-	vfs_exchange_end(exch);
-	free(mpa);
-	async_wait_for(req, &rc);
-	
-	return (int) rc;
+int unmount(const char *mpp)
+{
+	int mp = vfs_lookup(mpp, WALK_MOUNT_POINT | WALK_DIRECTORY);
+	if (mp < 0) {
+		return mp;
+	}
+	
+	int rc = vfs_unmount(mp);
+	close(mp);
+	return rc;
 }
 
@@ -348,11 +394,5 @@
 	assert((((oflag & O_RDONLY) != 0) + ((oflag & O_WRONLY) != 0) + ((oflag & O_RDWR) != 0)) == 1);
 	
-	size_t abs_size;
-	char *abs = vfs_absolutize(path, &abs_size);
-	if (!abs) {
-		return ENOMEM;
-	}
-	
-	int ret = _vfs_walk(-1, abs, walk_flags(oflag) | WALK_REGULAR);
+	int ret = vfs_lookup(path, walk_flags(oflag) | WALK_REGULAR);
 	if (ret < 0) {
 		return ret;
@@ -680,11 +720,5 @@
 int stat(const char *path, struct stat *stat)
 {
-	size_t pa_size;
-	char *pa = vfs_absolutize(path, &pa_size);
-	if (!pa) {
-		return ENOMEM;
-	}
-	
-	int fd = _vfs_walk(-1, pa, 0);
+	int fd = vfs_lookup(path, 0);
 	if (fd < 0) {
 		return fd;
@@ -710,16 +744,6 @@
 	}
 	
-	size_t abs_size;
-	char *abs = vfs_absolutize(dirname, &abs_size);
-	if (abs == NULL) {
-		free(dirp);
-		errno = ENOMEM;
-		return NULL;
-	}
-	
-	int ret = _vfs_walk(-1, abs, WALK_DIRECTORY);
-	free(abs);
-	
-	if (ret < EOK) {
+	int ret = vfs_lookup(dirname, WALK_DIRECTORY);
+	if (ret < 0) {
 		free(dirp);
 		errno = ret;
@@ -793,4 +817,41 @@
 int mkdir(const char *path, mode_t mode)
 {
+	int ret = vfs_lookup(path, WALK_MUST_CREATE | WALK_DIRECTORY);
+	if (ret < 0) {
+		return ret;
+	}
+	
+	close(ret);
+	return EOK;
+}
+
+static int _vfs_unlink2(int parent, const char *path, int expect, int wflag)
+{
+	sysarg_t rc;
+	aid_t req;
+	
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_3(exch, VFS_IN_UNLINK2, parent, expect, wflag, NULL);
+	rc = async_data_write_start(exch, path, str_size(path));
+	
+	vfs_exchange_end(exch);
+	
+	sysarg_t rc_orig;
+	async_wait_for(req, &rc_orig);
+	
+	if (rc_orig != EOK) {
+		return (int) rc_orig;
+	}
+	return rc;
+}
+
+/** Unlink file or directory.
+ *
+ * @param path Path
+ * @return EOk on success, error code on error
+ */
+int unlink(const char *path)
+{
 	size_t pa_size;
 	char *pa = vfs_absolutize(path, &pa_size);
@@ -799,40 +860,23 @@
 	}
 	
-	int ret = _vfs_walk(-1, pa, WALK_MUST_CREATE | WALK_DIRECTORY);
-	if (ret < 0) {
-		return ret;
-	}
-	
-	close(ret);
-	return EOK;
-}
-
-static int _vfs_unlink2(int parent, const char *path, int expect, int wflag)
-{
-	sysarg_t rc;
-	aid_t req;
-	
-	async_exch_t *exch = vfs_exchange_begin();
-	
-	req = async_send_3(exch, VFS_IN_UNLINK2, parent, expect, wflag, NULL);
-	rc = async_data_write_start(exch, path, str_size(path));
-	
-	vfs_exchange_end(exch);
-	
-	sysarg_t rc_orig;
-	async_wait_for(req, &rc_orig);
-	
-	if (rc_orig != EOK) {
-		return (int) rc_orig;
-	}
+	int root = vfs_root();
+	if (root < 0) {
+		free(pa);
+		return ENOENT;
+	}
+	
+	int rc = _vfs_unlink2(root, pa, -1, 0);
+	
+	free(pa);
+	close(root);
 	return rc;
 }
 
-/** Unlink file or directory.
+/** Remove empty directory.
  *
  * @param path Path
- * @return EOk on success, error code on error
- */
-int unlink(const char *path)
+ * @return 0 on success. On error returns -1 and sets errno.
+ */
+int rmdir(const char *path)
 {
 	size_t pa_size;
@@ -842,21 +886,15 @@
 	}
 	
-	return _vfs_unlink2(-1, pa, -1, 0);
-}
-
-/** Remove empty directory.
- *
- * @param path Path
- * @return 0 on success. On error returns -1 and sets errno.
- */
-int rmdir(const char *path)
-{
-	size_t pa_size;
-	char *pa = vfs_absolutize(path, &pa_size);
-	if (!pa) {
-		return ENOMEM;
-	}
-	
-	return _vfs_unlink2(-1, pa, -1, WALK_DIRECTORY);
+	int root = vfs_root();
+	if (root < 0) {
+		free(pa);
+		return ENOENT;
+	}
+	
+	int rc = _vfs_unlink2(root, pa, -1, WALK_DIRECTORY);
+	
+	free(pa);
+	close(root);
+	return rc;
 }
 
@@ -890,6 +928,12 @@
 	
 	async_exch_t *exch = vfs_exchange_begin();
-	
-	req = async_send_1(exch, VFS_IN_RENAME, -1, NULL);
+	int root = vfs_root();
+	if (root < 0) {
+		free(olda);
+		free(newa);
+		return ENOENT;
+	}
+	
+	req = async_send_1(exch, VFS_IN_RENAME, root, NULL);
 	rc = async_data_write_start(exch, olda, olda_size);
 	if (rc != EOK) {
@@ -897,4 +941,5 @@
 		free(olda);
 		free(newa);
+		close(root);
 		async_wait_for(req, &rc_orig);
 		if (rc_orig != EOK)
@@ -911,4 +956,5 @@
 		free(olda);
 		free(newa);
+		close(root);
 		async_wait_for(req, &rc_orig);
 		if (rc_orig != EOK)
@@ -923,4 +969,5 @@
 	free(olda);
 	free(newa);
+	close(root);
 	async_wait_for(req, &rc);
 
@@ -955,5 +1002,5 @@
 		return ENOMEM;
 	
-	int fd = _vfs_walk(-1, abs, WALK_DIRECTORY);
+	int fd = vfs_lookup(abs, WALK_DIRECTORY);
 	if (fd < 0) {
 		free(abs);
@@ -964,9 +1011,11 @@
 	fibril_mutex_lock(&cwd_mutex);
 	
-	if (cwd_fd >= 0)
+	if (cwd_fd >= 0) {
 		close(cwd_fd);
-	
-	if (cwd_path)
+	}
+	
+	if (cwd_path) {
 		free(cwd_path);
+	}
 	
 	cwd_fd = fd;
@@ -1124,19 +1173,9 @@
 int statfs(const char *path, struct statfs *st)
 {
-	size_t pa_size;
-	char *pa = vfs_absolutize(path, &pa_size);
-	if (!pa) {
-		errno = ENOMEM;
-		return -1;
-	}
-	
-	int fd = _vfs_walk(-1, pa, 0);
+	int fd = vfs_lookup(path, 0);
 	if (fd < 0) {
-		free(pa);
 		errno = fd;
 		return -1;
 	}
-
-	free(pa);
 	
 	sysarg_t rc, ret;
Index: uspace/lib/c/include/ipc/vfs.h
===================================================================
--- uspace/lib/c/include/ipc/vfs.h	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/lib/c/include/ipc/vfs.h	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -183,6 +183,13 @@
 	WALK_REGULAR = (1 << 3),
 	WALK_DIRECTORY = (1 << 4),
+	WALK_MOUNT_POINT = (1 << 5),
 	
 	WALK_ALL_FLAGS = WALK_MAY_CREATE | WALK_MUST_CREATE | WALK_REGULAR | WALK_DIRECTORY,
+};
+
+enum {
+	VFS_MOUNT_BLOCKING = 1,
+	VFS_MOUNT_CONNECT_ONLY = 2,
+	VFS_MOUNT_NO_REF = 4,
 };
 
Index: uspace/lib/c/include/vfs/vfs.h
===================================================================
--- uspace/lib/c/include/vfs/vfs.h	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/lib/c/include/vfs/vfs.h	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -52,7 +52,7 @@
 extern char *vfs_absolutize(const char *, size_t *);
 
-extern int vfs_mount(const char *, const char *, const char *, const char *,
+extern int mount(const char *, const char *, const char *, const char *,
     unsigned int, unsigned int);
-extern int vfs_unmount(const char *);
+extern int unmount(const char *);
 
 extern int vfs_fhandle(FILE *, int *);
@@ -65,5 +65,5 @@
 extern int _vfs_walk(int, const char *, int);
 extern int _vfs_open(int, int);
-extern int vfs_lookup(const char *);
+extern int vfs_lookup(const char *, int);
 
 extern int vfs_pass_handle(async_exch_t *, int, async_exch_t *);
@@ -71,4 +71,9 @@
 
 extern int vfs_clone(int, bool);
+extern int vfs_root(void);
+extern void vfs_root_set(int);
+
+int vfs_mount(int, const char *, service_id_t, const char *, unsigned, unsigned, int *);
+int vfs_unmount(int);
 
 #endif
Index: uspace/srv/vfs/vfs_file.c
===================================================================
--- uspace/srv/vfs/vfs_file.c	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/srv/vfs/vfs_file.c	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -178,8 +178,11 @@
 		 * endpoint FS and drop our reference to the underlying VFS node.
 		 */
-		if (file->open_read || file->open_write) {
-			rc = vfs_file_close_remote(file);
-		}
-		vfs_node_delref(file->node);
+		
+		if (file->node != NULL) {
+			if (file->open_read || file->open_write) {
+				rc = vfs_file_close_remote(file);
+			}
+			vfs_node_delref(file->node);
+ 		}
 		free(file);
 	}
@@ -312,4 +315,13 @@
 }
 
+static void _vfs_file_put(vfs_client_data_t *vfs_data, vfs_file_t *file)
+{
+	fibril_mutex_unlock(&file->_lock);
+	
+	fibril_mutex_lock(&vfs_data->lock);
+	vfs_file_delref(vfs_data, file);
+	fibril_mutex_unlock(&vfs_data->lock);
+}
+
 static vfs_file_t *_vfs_file_get(vfs_client_data_t *vfs_data, int fd)
 {
@@ -323,5 +335,12 @@
 			vfs_file_addref(vfs_data, file);
 			fibril_mutex_unlock(&vfs_data->lock);
+			
 			fibril_mutex_lock(&file->_lock);
+			if (file->node == NULL) {
+				_vfs_file_put(vfs_data, file);
+				return NULL;
+			}
+			assert(file != NULL);
+			assert(file->node != NULL);
 			return file;
 		}
@@ -341,13 +360,4 @@
 {
 	return _vfs_file_get(VFS_DATA, fd);
-}
-
-static void _vfs_file_put(vfs_client_data_t *vfs_data, vfs_file_t *file)
-{
-	fibril_mutex_unlock(&file->_lock);
-	
-	fibril_mutex_lock(&vfs_data->lock);
-	vfs_file_delref(vfs_data, file);
-	fibril_mutex_unlock(&vfs_data->lock);
 }
 
Index: uspace/srv/vfs/vfs_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/srv/vfs/vfs_lookup.c	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -330,5 +330,5 @@
 	if (result != NULL) {
 		/* The found file may be a mount point. Try to cross it. */
-		if (!(lflag & L_MP)) {
+		if (!(lflag & (L_MP|L_DISABLE_MOUNTS))) {
 			base = vfs_node_peek(&res);
 			if (base != NULL && base->mount != NULL) {
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision a737667eb9d8e74c8717a21d8a1dd6c60dd7d91d)
+++ uspace/srv/vfs/vfs_ops.c	(revision 5126f801cf167ce675ecc93b5079c64358dcbacb)
@@ -68,8 +68,6 @@
 FIBRIL_RWLOCK_INITIALIZE(namespace_rwlock);
 
-vfs_node_t *root = NULL;
-
 static int vfs_connect_internal(service_id_t service_id, unsigned flags, unsigned instance,
-	char *options, char *fsname, vfs_node_t **root)
+    char *options, char *fsname, vfs_node_t **root)
 {
 	fs_handle_t fs_handle = 0;
@@ -79,5 +77,5 @@
 		fs_handle = fs_name_to_handle(instance, fsname, false);
 		
-		if (fs_handle != 0 || !(flags & IPC_FLAG_BLOCKING)) {
+		if (fs_handle != 0 || !(flags & VFS_MOUNT_BLOCKING)) {
 			break;
 		}
@@ -123,71 +121,8 @@
 }
 
-static int vfs_mount_internal(service_id_t service_id, unsigned flags, unsigned instance,
-	char *opts, char *fs_name, char *mp)
-{
-	/* Resolve the path to the mountpoint. */
-	
-	if (root == NULL) {
-		/* We still don't have the root file system mounted. */
-		if (str_cmp(mp, "/") != 0) {
-			/*
-			 * We can't resolve this without the root filesystem
-			 * being mounted first.
-			 */
-			return ENOENT;
-		}
-		
-		return vfs_connect_internal(service_id, flags, instance, opts, fs_name, &root);
-	}
-	
-	/* We already have the root FS. */
-	if (str_cmp(mp, "/") == 0) {
-		/* Trying to mount root FS over root FS */
-		return EBUSY;
-	}
-	
-	vfs_lookup_res_t mp_res;
-	int rc = vfs_lookup_internal(root, mp, L_DIRECTORY, &mp_res);
-	if (rc != EOK) {
-		/* The lookup failed. */
-		return rc;
-	}
-	
-	vfs_node_t *mp_node;
-	mp_node = vfs_node_get(&mp_res);
-	if (!mp_node) {
-		return ENOMEM;
-	}
-	
-	if (mp_node->mount != NULL) {
-		return EBUSY;
-	}
-	
-	if (mp_node->type != VFS_NODE_DIRECTORY) {
-		printf("%s node not a directory, type=%d\n", mp, mp_node->type);
-		return ENOTDIR;
-	}
-	
-	if (vfs_node_has_children(mp_node)) {
-		return ENOTEMPTY;
-	}
-	
-	vfs_node_t *mountee;
-	
-	rc = vfs_connect_internal(service_id, flags, instance, opts, fs_name, &mountee);
-	if (rc != EOK) {
-		vfs_node_put(mp_node);
-		return ENOMEM;
-	}
-	
-	mp_node->mount = mountee;
-	/* The two references to nodes are held by the mount so that they cannot be freed.
-	 * They are removed in detach_internal().
-	 */
-	return EOK;
-}
-
 void vfs_mount_srv(ipc_callid_t rid, ipc_call_t *request)
 {
+	int mpfd = IPC_GET_ARG1(*request);
+	
 	/*
 	 * We expect the library to do the device-name to device-handle
@@ -195,33 +130,29 @@
 	 * in the request.
 	 */
-	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*request);
+	service_id_t service_id = (service_id_t) IPC_GET_ARG2(*request);
 	
 	/*
 	 * Mount flags are passed as ARG2.
 	 */
-	unsigned int flags = (unsigned int) IPC_GET_ARG2(*request);
+	unsigned int flags = (unsigned int) IPC_GET_ARG3(*request);
 	
 	/*
 	 * Instance number is passed as ARG3.
 	 */
-	unsigned int instance = IPC_GET_ARG3(*request);
-
-	/* We want the client to send us the mount point. */
-	char *mp;
-	int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
+	unsigned int instance = IPC_GET_ARG4(*request);
+	
+	char *opts = NULL;
+	char *fs_name = NULL;
+	vfs_file_t *mp = NULL;
+	vfs_file_t *file = NULL;
+	int fd = -1;
+	mtab_ent_t *mtab_ent = NULL;
+
+	/* Now we expect to receive the mount options. */
+	int rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN,
 	    0, NULL);
 	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	
-	/* Now we expect to receive the mount options. */
-	char *opts;
-	rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN,
-	    0, NULL);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		free(mp);
-		return;
+		async_data_write_void(rc);
+		goto out;
 	}
 	
@@ -230,32 +161,80 @@
 	 * system.
 	 */
-	char *fs_name;
 	rc = async_data_write_accept((void **) &fs_name, true, 0,
 	    FS_NAME_MAXLEN, 0, NULL);
 	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		free(mp);
-		free(opts);
-		return;
+		goto out;
+	}
+	
+	if (!(flags & VFS_MOUNT_CONNECT_ONLY)) {
+		mp = vfs_file_get(mpfd);
+		if (mp == NULL) {
+			rc = EBADF;
+			goto out;
+		}
+		
+		if (mp->node->mount != NULL) {
+			rc = EBUSY;
+			goto out;
+		}
+		
+		if (mp->node->type != VFS_NODE_DIRECTORY) {
+			rc = ENOTDIR;
+			goto out;
+		}
+		
+		if (vfs_node_has_children(mp->node)) {
+			rc = ENOTEMPTY;
+			goto out;
+		}
+	}
+	
+	if (!(flags & VFS_MOUNT_NO_REF)) {
+		fd = vfs_fd_alloc(&file, false);
+		if (fd < 0) {
+			rc = fd;
+			goto out;
+		}
 	}
 	
 	/* Add the filesystem info to the list of mounted filesystems */
-	mtab_ent_t *mtab_ent = malloc(sizeof(mtab_ent_t));
+	mtab_ent = malloc(sizeof(mtab_ent_t));
 	if (!mtab_ent) {
-		async_answer_0(rid, ENOMEM);
-		free(mp);
-		free(fs_name);
-		free(opts);
-		return;
-	}
-	
-	/* Mount the filesystem. */
+		rc = ENOMEM;
+		goto out;
+	}
+	
+	vfs_node_t *root = NULL;
+	
 	fibril_rwlock_write_lock(&namespace_rwlock);
-	rc = vfs_mount_internal(service_id, flags, instance, opts, fs_name, mp);
+
+	rc = vfs_connect_internal(service_id, flags, instance, opts, fs_name, &root);
+	if (rc == EOK && !(flags & VFS_MOUNT_CONNECT_ONLY)) {
+		vfs_node_addref(mp->node);
+		vfs_node_addref(root);
+		mp->node->mount = root;
+	}
+	
 	fibril_rwlock_write_unlock(&namespace_rwlock);
-
+	
+	if (rc != EOK) {
+		goto out;
+	}
+	
+	
+	if (flags & VFS_MOUNT_NO_REF) {
+		vfs_node_delref(root);
+	} else {
+		assert(file != NULL);
+		
+		file->node = root;
+		file->permissions = MODE_READ | MODE_WRITE | MODE_APPEND;
+		file->open_read = false;
+		file->open_write = false;
+	}
+	
 	/* Add the filesystem info to the list of mounted filesystems */
 	if (rc == EOK) {
-		str_cpy(mtab_ent->mp, MAX_PATH_LEN, mp);
+		str_cpy(mtab_ent->mp, MAX_PATH_LEN, "fixme");
 		str_cpy(mtab_ent->fs_name, FS_NAME_MAXLEN, fs_name);
 		str_cpy(mtab_ent->opts, MAX_MNTOPTS_LEN, opts);
@@ -269,127 +248,75 @@
 		mtab_size++;
 		fibril_mutex_unlock(&mtab_list_lock);
-	}
-	
-	async_answer_0(rid, rc);
-
-	free(mp);
-	free(fs_name);
-	free(opts);
+	}	
+	
+	rc = EOK;
+
+out:
+	async_answer_1(rid, rc, rc == EOK ? fd : 0);
+
+	if (opts) {
+		free(opts);
+	}
+	if (fs_name) {
+		free(fs_name);
+	}
+	if (mp) {
+		vfs_file_put(mp);
+	}
+	if (file) {
+		vfs_file_put(file);
+	}
+	if (rc != EOK && fd >= 0) {
+		vfs_fd_free(fd);
+	}
 }
 
 void vfs_unmount_srv(ipc_callid_t rid, ipc_call_t *request)
 {
-	/*
-	 * Receive the mount point path.
-	 */
-	char *mp;
-	int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
-	    0, NULL);
-	if (rc != EOK)
-		async_answer_0(rid, rc);
-	
-	/*
-	 * Taking the namespace lock will do two things for us. First, it will
-	 * prevent races with other lookup operations. Second, it will stop new
-	 * references to already existing VFS nodes and creation of new VFS
-	 * nodes. This is because new references are added as a result of some
-	 * lookup operation or at least of some operation which is protected by
-	 * the namespace lock.
-	 */
+	int mpfd = IPC_GET_ARG1(*request);
+	
+	vfs_file_t *mp = vfs_file_get(mpfd);
+	if (mp == NULL) {
+		async_answer_0(rid, EBADF);
+		return;
+	}
+	
+	if (mp->node->mount == NULL) {
+		async_answer_0(rid, ENOENT);
+		vfs_file_put(mp);
+		return;
+	}
+	
 	fibril_rwlock_write_lock(&namespace_rwlock);
-		
-	if (str_cmp(mp, "/") == 0) {
-		free(mp);
-		
-		/*
-		 * Unmounting the root file system.
-		 *
-		 * In this case, there is no mount point node and we send
-		 * VFS_OUT_UNMOUNTED directly to the mounted file system.
-		 */
-		
-		if (!root) {
-			fibril_rwlock_write_unlock(&namespace_rwlock);
-			async_answer_0(rid, ENOENT);
-			return;
-		}
-		
-		/*
-		 * Count the total number of references for the mounted file system. We
-		 * are expecting at least one, which we got when the file system was mounted.
-		 * If we find more, it means that
-		 * the file system cannot be gracefully unmounted at the moment because
-		 * someone is working with it.
-		 */
-		if (vfs_nodes_refcount_sum_get(root->fs_handle, root->service_id) != 1) {
-			fibril_rwlock_write_unlock(&namespace_rwlock);
-			async_answer_0(rid, EBUSY);
-			return;
-		}
-		
-		async_exch_t *exch = vfs_exchange_grab(root->fs_handle);
-		rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED, root->service_id);
-		vfs_exchange_release(exch);
-		
-		fibril_rwlock_write_unlock(&namespace_rwlock);
-		if (rc == EOK) {
-			vfs_node_forget(root);
-			root = NULL;
-		}
-		async_answer_0(rid, rc);
-		return;
-	}
-	
-	/*
-	 * Lookup the mounted root and instantiate it.
-	 */
-	vfs_lookup_res_t mp_res;
-	rc = vfs_lookup_internal(root, mp, L_MP, &mp_res);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&namespace_rwlock);
-		free(mp);
-		async_answer_0(rid, rc);
-		return;
-	}
-	vfs_node_t *mp_node = vfs_node_get(&mp_res);
-	if (!mp_node) {
-		fibril_rwlock_write_unlock(&namespace_rwlock);
-		free(mp);
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
-	
-	if (mp_node->mount == NULL) {
-		fibril_rwlock_write_unlock(&namespace_rwlock);
-		vfs_node_put(mp_node);
-		free(mp);
-		async_answer_0(rid, ENOENT);
-		return;
-	}
 	
 	/*
 	 * Count the total number of references for the mounted file system. We
-	 * are expecting at least one, which we got when the file system was mounted.
+	 * are expecting at least one, which is held by the mount point.
 	 * If we find more, it means that
 	 * the file system cannot be gracefully unmounted at the moment because
 	 * someone is working with it.
 	 */
-	if (vfs_nodes_refcount_sum_get(mp_node->mount->fs_handle, mp_node->mount->service_id) != 1) {
+	if (vfs_nodes_refcount_sum_get(mp->node->mount->fs_handle, mp->node->mount->service_id) != 1) {
+		async_answer_0(rid, EBUSY);
+		vfs_file_put(mp);
 		fibril_rwlock_write_unlock(&namespace_rwlock);
-		vfs_node_put(mp_node);
-		free(mp);
-		async_answer_0(rid, EBUSY);
-		return;
-	}
-	
-	/* Unmount the filesystem. */
-	async_exch_t *exch = vfs_exchange_grab(mp_node->mount->fs_handle);
-	rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED, mp_node->mount->service_id);
+		return;
+	}
+	
+	async_exch_t *exch = vfs_exchange_grab(mp->node->mount->fs_handle);
+	int rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED, mp->node->mount->service_id);
 	vfs_exchange_release(exch);
 	
-	vfs_node_forget(mp_node->mount);
-	mp_node->mount = NULL;
-	
-	vfs_node_put(mp_node);
+	if (rc != EOK) {
+		async_answer_0(rid, rc);
+		vfs_file_put(mp);
+		fibril_rwlock_write_unlock(&namespace_rwlock);
+		return;
+	}
+	
+	vfs_node_forget(mp->node->mount);
+	vfs_node_put(mp->node);
+	mp->node->mount = NULL;
+	
 	fibril_rwlock_write_unlock(&namespace_rwlock);
 	
@@ -398,5 +325,6 @@
 
 	list_foreach(mtab_list, link, mtab_ent_t, mtab_ent) {
-		if (str_cmp(mtab_ent->mp, mp) == 0) {
+		// FIXME: mp name
+		if (str_cmp(mtab_ent->mp, "fixme") == 0) {
 			list_remove(&mtab_ent->link);
 			mtab_size--;
@@ -408,9 +336,7 @@
 	assert(found);
 	fibril_mutex_unlock(&mtab_list_lock);
-
-	free(mp);	
-	
+	
+	vfs_file_put(mp);
 	async_answer_0(rid, EOK);
-	return;
 }
 
@@ -448,4 +374,7 @@
 	if (flags&WALK_DIRECTORY) {
 		lflags |= L_DIRECTORY;
+	}
+	if (flags&WALK_MOUNT_POINT) {
+		lflags |= L_MP;
 	}
 	return lflags;
@@ -470,15 +399,9 @@
 	
 	/* Lookup the file structure corresponding to the file descriptor. */
-	vfs_file_t *parent = NULL;
-	vfs_node_t *parent_node = root;
-	// TODO: Client-side root.
-	if (parentfd != -1) {
-		parent = vfs_file_get(parentfd);
-		if (!parent) {
-			free(path);
-			async_answer_0(rid, EBADF);
-			return;
-		}
-		parent_node = parent->node;
+	vfs_file_t *parent = vfs_file_get(parentfd);
+	if (!parent) {
+		free(path);
+		async_answer_0(rid, EBADF);
+		return;
 	}
 	
@@ -486,5 +409,5 @@
 	
 	vfs_lookup_res_t lr;
-	rc = vfs_lookup_internal(parent_node, path, walk_lookup_flags(flags), &lr);
+	rc = vfs_lookup_internal(parent->node, path, walk_lookup_flags(flags), &lr);
 	free(path);
 
@@ -963,5 +886,4 @@
 	vfs_file_t *parent = NULL;
 	vfs_file_t *expect = NULL;
-	vfs_node_t *parent_node = root;
 	
 	int parentfd = IPC_GET_ARG1(*request);
@@ -974,4 +896,8 @@
 		return;
 	}
+	if (parentfd == expectfd) {
+		async_answer_0(rid, EINVAL);
+		return;
+	}
 	
 	fibril_rwlock_write_lock(&namespace_rwlock);
@@ -980,8 +906,8 @@
 
 	/* Files are retrieved in order of file descriptors, to prevent deadlock. */
-	if (parentfd >= 0 && parentfd < expectfd) {
+	if (parentfd < expectfd) {
 		parent = vfs_file_get(parentfd);
 		if (!parent) {
-			rc = ENOENT;
+			rc = EBADF;
 			goto exit;
 		}
@@ -996,19 +922,17 @@
 	}
 	
-	if (parentfd >= 0 && parentfd >= expectfd) {
+	if (parentfd > expectfd) {
 		parent = vfs_file_get(parentfd);
 		if (!parent) {
-			rc = ENOENT;
+			rc = EBADF;
 			goto exit;
 		}
 	}
 	
-	if (parent) {
-		parent_node = parent->node;
-	}
+	assert(parent != NULL);
 	
 	if (expectfd >= 0) {
 		vfs_lookup_res_t lr;
-		rc = vfs_lookup_internal(parent_node, path, lflag, &lr);
+		rc = vfs_lookup_internal(parent->node, path, lflag, &lr);
 		if (rc != EOK) {
 			goto exit;
@@ -1026,5 +950,5 @@
 	
 	vfs_lookup_res_t lr;
-	rc = vfs_lookup_internal(parent_node, path, lflag | L_UNLINK, &lr);
+	rc = vfs_lookup_internal(parent->node, path, lflag | L_UNLINK, &lr);
 	if (rc != EOK) {
 		goto exit;
@@ -1188,16 +1112,11 @@
 	
 	/* Lookup the file structure corresponding to the file descriptor. */
-	vfs_node_t *base_node = root;
-	// TODO: Client-side root.
-	if (basefd != -1) {
-		base = vfs_file_get(basefd);
-		if (!base) {
-			rc = EBADF;
-			goto out;
-		}
-		base_node = base->node;
-	}
-	
-	rc = vfs_rename_internal(base_node, oldc, newc);
+	base = vfs_file_get(basefd);
+	if (!base) {
+		rc = EBADF;
+		goto out;
+	}
+	
+	rc = vfs_rename_internal(base->node, oldc, newc);
 
 out:
@@ -1358,5 +1277,5 @@
 	/* Lookup the file structure corresponding to fd. */
 	vfs_file_t *oldfile = vfs_file_get(oldfd);
-	if (!oldfile) {
+	if (oldfile == NULL) {
 		async_answer_0(rid, EBADF);
 		return;
@@ -1365,6 +1284,7 @@
 	vfs_file_t *newfile;
 	int newfd = vfs_fd_alloc(&newfile, desc);
+	async_answer_0(rid, newfd);
+	
 	if (newfd < 0) {
-		async_answer_0(rid, newfd);
 		vfs_file_put(oldfile);
 		return;
@@ -1379,6 +1299,4 @@
 	vfs_file_put(oldfile);
 	vfs_file_put(newfile);
-	
-	async_answer_0(rid, newfd);
 }
 
