Mount EXT2 to VFS
diff --git a/.dir-locals.el b/.dir-locals.el
index 14d2bd3..0f6ea64 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -1,5 +1,6 @@
 ((nil . ((eval
-		  . (setq-local flycheck-clang-include-path
-						(jmk-includes-for (expand-file-name buffer-file-name))
+		  . (let ((path (expand-file-name (or buffer-file-name "."))))
+			  (setq-local flycheck-clang-include-path
+						(jmk-includes-for path)
 						flycheck-clang-args
-						(jmk-other-flags-for (expand-file-name buffer-file-name)))))))
+						(jmk-other-flags-for path)))))))
diff --git a/share/jmk/dir-locals.el b/share/jmk/dir-locals.el
index 14d2bd3..0f6ea64 100644
--- a/share/jmk/dir-locals.el
+++ b/share/jmk/dir-locals.el
@@ -1,5 +1,6 @@
 ((nil . ((eval
-		  . (setq-local flycheck-clang-include-path
-						(jmk-includes-for (expand-file-name buffer-file-name))
+		  . (let ((path (expand-file-name (or buffer-file-name "."))))
+			  (setq-local flycheck-clang-include-path
+						(jmk-includes-for path)
 						flycheck-clang-args
-						(jmk-other-flags-for (expand-file-name buffer-file-name)))))))
+						(jmk-other-flags-for path)))))))
diff --git a/src/kernel/dri/fs/ext2/ext2.c b/src/kernel/dri/fs/ext2/ext2.c
index 9952948..99d5e9d 100644
--- a/src/kernel/dri/fs/ext2/ext2.c
+++ b/src/kernel/dri/fs/ext2/ext2.c
@@ -1,6 +1,8 @@
 #include <alloc.h>
 #include <dri/ata_pio/ata_pio.h>
 #include <dri/fs/ext2/ext2.h>
+#include <dri/fs/ext2/ext2_vfs.h>
+#include <vfs.h>
 #include <io.h>
 #include <kint.h>
 #include <log.h>
@@ -145,38 +147,17 @@
 
 void ext2_mount(struct fs_node *where)
 {
-	UNUSED(where)
 
-	struct ext2_superblock sb = ext2_read_superblock();
+	struct ext2_superblock *sb = malloc(sizeof(struct ext2_superblock));
+	*sb = ext2_read_superblock();
 
-	kprintf(DEBUG "EXT2 magic = 0x%x\n", sb.signature);
+	struct fs_node *ext2_root = ext2_inode2vfs(sb, 2, "/", 1);
+	uint err;
 
-	// Read the root inode 2
-	struct ext2_inode root;
-
-	if (ext2_find_inode(&sb, 2, &root))
+	if ((err = fs_mount(where, ext2_root)))
 	{
-		kprintf(OKAY "Found root inode 2 (size=0x%x, num_blocks=0x%x)\n",
-				root.size, root.num_blocks);
-		// kprintf(DEBUG "Root.mode = 0x%x\n", root.mode & 0xf000);
-		kassert((root.mode & 0xf000) == EXT2_S_IFDIR,
-				"Root (inode 2) is not a directory.");
-
-		char *name = "hello-hl.txt";
-		kprintf(INFO "Creating hard link %s -> hello.txt\n", name);
-		ext2_hard_link(&sb, &root, name, strlen(name), 12);
-
-		kprintf("ls /\n");
-		kprintf("inode\t name\n");
-		kprintf("--------------------\n");
-		ext2_dir_ls(&sb, &root, print_entry, &sb);
+		kprintf(WARN "Failed to mount EXT2: error %d\n", err);
 	}
-	else
-	{
-		kprintf(WARN "Failed to find root inode 2\n");
-	}
-
-	kprintf(INFO "First free inode is %d\n", ext2_first_free_inode(&sb));
 }
 
 bool ext2_valid_filesystem()
diff --git a/src/kernel/dri/fs/ext2/ext2_vfs.c b/src/kernel/dri/fs/ext2/ext2_vfs.c
index a612a4d..d5c8d3f 100644
--- a/src/kernel/dri/fs/ext2/ext2_vfs.c
+++ b/src/kernel/dri/fs/ext2/ext2_vfs.c
@@ -196,6 +196,12 @@
 	struct ext2_fs_dirent *dent =
 		malloc(sizeof(struct ext2_fs_dirent));
 
+	if (strncmp(".", name, name_len) == 0 ||
+		strncmp("..", name, name_len) == 0)
+	{
+		return true;
+	}
+
 	dent->node = ext2_inode2vfs(d->sb, inode, (char *)name, name_len);
 	dent->name_len = name_len;
 	memcpy(dent->name, name, MIN(name_len, 256));
@@ -263,6 +269,7 @@
 		struct ext2_fs_dirent_to_fs_data data;
 		data.d = d;
 		data.last = NULL;
+		data.sb = sb;
 
 		ext2_dir_ls(sb, &in, ext2_dirent_to_fs_node_cb, &data);
 
diff --git a/src/kernel/main.c b/src/kernel/main.c
index ab013fd..befb64b 100644
--- a/src/kernel/main.c
+++ b/src/kernel/main.c
@@ -59,20 +59,7 @@
 	kprintf(DEBUG "initrd is at 0x%x to 0x%x\n", initrd_loc);
 
 	init_initrd_vfs(initrd_loc);
-#endif
-
 	kprintf(OKAY "VFS initialized\n");
-
-	kprintf(OKAY "Initial setup complete!\n");
-
-#ifdef TEST_VFS_INITRD
-	kprintf(INFO "fs_readdir(\"/dev/initrd\")\n");
-
-	struct fs_dirent dirent;
-	for (int i = 0; fs_readdir(&root, i, &dirent); i++)
-	{
-		kprintf(INFO "name: %s, inode: %d\n", dirent.name, dirent.inode);
-	}
 #endif
 
 	asm("sti");
@@ -116,6 +103,14 @@
 			"Filesystem is not a valid EXT2 format, only EXT2 is supported\n");
 	}
 
+	kprintf(INFO "fs_readdir(\"/\") mnt=%p\n", root.mount);
+
+	struct fs_dirent dirent;
+	for (int i = 0; fs_readdir(&root, i, &dirent); i++)
+	{
+		kprintf(INFO "name: %s, inode: %d\n", dirent.name, dirent.inode);
+	}
+
 	while (true)
 		asm("hlt");
 
diff --git a/src/kernel/vfs.c b/src/kernel/vfs.c
index e3c06a0..9c0ca9a 100644
--- a/src/kernel/vfs.c
+++ b/src/kernel/vfs.c
@@ -6,6 +6,9 @@
 
 uint fs_read(struct fs_node *node, size_t offset, size_t size, uchar *buffer)
 {
+	if (node->mount)
+		node = node->mount;
+
 	if (!node || !node->vtable || !node->vtable->read)
 		return 0;
 
@@ -14,6 +17,9 @@
 
 uint fs_write(struct fs_node *node, size_t offset, size_t size, uchar *buffer)
 {
+	if (node->mount)
+		node = node->mount;
+
 	if (!node || !node->vtable || !node->vtable->write)
 		return 0;
 
@@ -22,6 +28,9 @@
 
 void fs_open(struct fs_node *node)
 {
+	if (node->mount)
+		node = node->mount;
+
 	if (!node || !node->vtable || !node->vtable->open)
 		return;
 
@@ -30,6 +39,9 @@
 
 void fs_close(struct fs_node *node)
 {
+	if (node->mount)
+		node = node->mount;
+
 	if (!node || !node->vtable || !node->vtable->close)
 		return;
 
@@ -38,6 +50,9 @@
 
 bool fs_readdir(struct fs_node *node, uint index, struct fs_dirent *out)
 {
+	if (node->mount)
+		node = node->mount;
+
 	if (!node || !node->vtable || !node->vtable->readdir ||
 		(node->flags & 7) != FS_DIRECTORY)
 		return false;
@@ -47,6 +62,9 @@
 
 struct fs_node *fs_finddir(struct fs_node *node, char *name, uint name_len)
 {
+	if (node->mount)
+		node = node->mount;
+
 	if (!node || !node->vtable || !node->vtable->finddir ||
 		(node->flags & 7) != FS_DIRECTORY)
 		return NULL;
@@ -103,24 +121,20 @@
 	return NULL;
 }
 
+static struct fs_vtable root_vt =
+{
+	NULL,
+};
+
 void init_vfs()
 {
-	memset(&root_v, 0, sizeof(root_v));
-	memset(&dev_v, 0, sizeof(root_v));
-	memset(&root, 0, sizeof(root));
-	memset(&dev, 0, sizeof(dev));
-
+	root.mount = NULL;
+	root.inode = 0; // fake inode
 	root.flags = FS_DIRECTORY;
-	root.vtable = &root_v;
-	dev.flags = FS_DIRECTORY;
-	dev.vtable = &dev_v;
-	initrd.flags = FS_DIRECTORY;
-
-	root_v.readdir = root_readdir;
-	root_v.finddir = root_finddir;
-
-	dev_v.readdir = dev_readdir;
-	dev_v.finddir = dev_finddir;
+	root.mask = ~0;
+	root.gid = root.uid = 0;
+	root.size = 0;
+	root.vtable = &root_vt;
 }
 
 uint fs_mount(struct fs_node *target, struct fs_node *source)