summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-02-28 21:14:30 -0500
committerIan Moffett <ian@osmora.org>2024-02-28 21:15:49 -0500
commit39a923f6c3c471f169552cf4e98b02c5173c2283 (patch)
tree682f539066e5a5fead2e19ad1114e354113c8b43 /sys
parent4f9c41c5bbf029e1b616d0cf3e1d2e28f9321718 (diff)
kernel: Add initial VFS implementation
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/initramfs.c125
-rw-r--r--sys/fs/initramfs_vfsops.c42
-rw-r--r--sys/include/fs/initramfs.h39
-rw-r--r--sys/include/sys/mount.h76
-rw-r--r--sys/include/sys/vfs.h51
-rw-r--r--sys/include/sys/vnode.h61
-rw-r--r--sys/kern/init_main.c3
-rw-r--r--sys/kern/vfs_cache.c96
-rw-r--r--sys/kern/vfs_init.c78
-rw-r--r--sys/kern/vfs_lookup.c123
-rw-r--r--sys/kern/vfs_subr.c193
11 files changed, 887 insertions, 0 deletions
diff --git a/sys/fs/initramfs.c b/sys/fs/initramfs.c
new file mode 100644
index 0000000..7812b9c
--- /dev/null
+++ b/sys/fs/initramfs.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ */
+
+#include <fs/initramfs.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/limine.h>
+#include <sys/panic.h>
+#include <string.h>
+
+__MODULE_NAME("initramfs");
+__KERNEL_META("$Hyra$: initramfs.c, Ian Marco Moffett, "
+ "Initial ram filesystem");
+
+static volatile struct limine_module_request mod_req = {
+ .id = LIMINE_MODULE_REQUEST,
+ .revision = 0
+};
+
+static const char *initramfs = NULL;
+static size_t initramfs_size = 0;
+
+struct tar_hdr {
+ char filename[100];
+ char mode[8];
+ char uid[8];
+ char gid[8];
+ char size[12];
+ char mtime[12];
+ char chksum[8];
+ char typeflag[1];
+};
+
+static char *
+get_module(const char *path, uint64_t *size) {
+ for (uint64_t i = 0; i < mod_req.response->module_count; ++i) {
+ if (strcmp(mod_req.response->modules[i]->path, path) == 0) {
+ *size = mod_req.response->modules[i]->size;
+ return mod_req.response->modules[i]->address;
+ }
+ }
+
+ return NULL;
+}
+
+static size_t
+getsize(const char *in)
+{
+ size_t size = 0, count = 1;
+
+ for (size_t j = 11; j > 0; --j, count *= 8) {
+ size += (in[j-1]-'0')*count;
+ }
+
+ return size;
+}
+
+static int
+initramfs_init(void)
+{
+ initramfs = get_module("/boot/initramfs.tar", &initramfs_size);
+
+ if (initramfs == NULL) {
+ panic("Failed to load initramfs\n");
+ }
+
+ return 0;
+}
+
+const char *
+initramfs_open(const char *path)
+{
+ uintptr_t addr, size;
+ struct tar_hdr *hdr;
+
+ if (initramfs == NULL) {
+ initramfs_init();
+ }
+
+ if (strlen(path) > 99) {
+ return NULL;
+ }
+
+ addr = (uintptr_t)initramfs + 0x200;
+ hdr = (struct tar_hdr *)addr;
+
+ while (hdr->filename[0] != '\0') {
+ hdr = (struct tar_hdr *)addr;
+ size = getsize(hdr->size);
+
+ if (strcmp(hdr->filename, path) == 0) {
+ return ((char*)addr) + 0x200;
+ }
+
+ addr += (((size + 511) / 512) + 1) * 512;
+ }
+
+ return NULL;
+}
diff --git a/sys/fs/initramfs_vfsops.c b/sys/fs/initramfs_vfsops.c
new file mode 100644
index 0000000..780315d
--- /dev/null
+++ b/sys/fs/initramfs_vfsops.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ */
+
+#include <fs/initramfs.h>
+#include <sys/mount.h>
+#include <string.h>
+
+static int
+initramfs_init(struct fs_info *info)
+{
+ return 0;
+}
+
+struct vfsops g_initramfs_ops = {
+ .init = initramfs_init,
+};
diff --git a/sys/include/fs/initramfs.h b/sys/include/fs/initramfs.h
new file mode 100644
index 0000000..c507e3d
--- /dev/null
+++ b/sys/include/fs/initramfs.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ */
+
+#ifndef _FS_INITRAMFS_H_
+#define _FS_INITRAMFS_H_
+
+#include <sys/mount.h>
+
+extern struct vfsops g_initramfs_ops;
+
+const char *initramfs_open(const char *path);
+
+#endif /* !_FS_INITRAMFS_H_ */
diff --git a/sys/include/sys/mount.h b/sys/include/sys/mount.h
new file mode 100644
index 0000000..014ce89
--- /dev/null
+++ b/sys/include/sys/mount.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ */
+
+#ifndef _SYS_MOUNT_H_
+#define _SYS_MOUNT_H_
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#define FS_NAME_MAX 16 /* Max length of FS type name including nul */
+
+struct fs_info;
+struct mount;
+
+struct vfsops {
+ int(*init)(struct fs_info *info);
+ int(*vget_name)(struct fs_info *info, const char *name);
+};
+
+struct mount {
+ int flags;
+ size_t phash; /* Path hash */
+ TAILQ_ENTRY(mount) link;
+};
+
+struct fs_info {
+ char name[FS_NAME_MAX]; /* Filesystem type name */
+ struct vfsops *vfsops; /* Filesystem operations */
+ struct mount *mp_root;
+};
+
+/*
+ * Mount flags
+ */
+#define MNT_RDONLY 0x00000001
+
+#if defined(_KERNEL)
+
+/* For caching */
+#define MOUNTLIST_SIZE 8
+
+/* Mountlist cache entry */
+struct mountlist_entry {
+ TAILQ_HEAD(, mount) buckets;
+};
+
+int vfs_mount(struct mount **mp_out, const char *path, int mnt_flags);
+#endif /* defined(_KERNEL) */
+
+#endif /* !_SYS_MOUNT_H_ */
diff --git a/sys/include/sys/vfs.h b/sys/include/sys/vfs.h
new file mode 100644
index 0000000..2c056a1
--- /dev/null
+++ b/sys/include/sys/vfs.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ */
+
+#ifndef _SYS_VFS_H_
+#define _SYS_VFS_H_
+
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/types.h>
+
+#if defined(_KERNEL)
+void vfs_init(void);
+struct fs_info *vfs_byname(const char *name);
+
+struct vnode *vfs_path_to_node(const char *path);
+char *vfs_get_fname_at(const char *path, size_t idx);
+bool vfs_is_valid_path(const char *path);
+size_t vfs_hash_path(const char *path);
+
+void vfs_init_cache(void);
+int vfs_cache_mp(struct mount *mp, const char *path);
+int vfs_cache_fetch_mp(const char *path, struct mount **mp);
+#endif /* defined(_KERNEL) */
+
+#endif /* !_SYS_VFS_H_ */
diff --git a/sys/include/sys/vnode.h b/sys/include/sys/vnode.h
new file mode 100644
index 0000000..3cfcc7a
--- /dev/null
+++ b/sys/include/sys/vnode.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ */
+
+#ifndef _SYS_VNODE_H_
+#define _SYS_VNODE_H_
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/mount.h>
+
+/* Vnode cache entry */
+struct vnode_cache {
+ const char *path;
+ struct vnode *vnode;
+};
+
+struct vnode {
+ int type;
+ int flags;
+ int usecount; /* Ref count of uses */
+ struct mount *mp; /* Ptr to vfs vnode is in */
+ TAILQ_ENTRY(vnode) freelist;
+};
+
+/*
+ * Vnode v_type flags
+ */
+#define VREG 0x01 /* Regular file */
+#define VDIR 0x02 /* Directory */
+
+#if defined(_KERNEL)
+int vfs_alloc_vnode(struct vnode **vnode, struct mount *mp, int type);
+#endif
+
+#endif
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 5f7cafa..c55ece2 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -32,6 +32,7 @@
#include <sys/machdep.h>
#include <sys/timer.h>
#include <sys/sched.h>
+#include <sys/vfs.h>
#include <machine/cpu_mp.h>
#include <firmware/acpi/acpi.h>
#include <vm/physseg.h>
@@ -89,6 +90,8 @@ main(void)
processor_init();
list_timers();
+ vfs_init();
+
sched_init();
ci = this_cpu();
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
new file mode 100644
index 0000000..44a8e27
--- /dev/null
+++ b/sys/kern/vfs_cache.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/mount.h>
+#include <sys/vfs.h>
+#include <sys/errno.h>
+#include <vm/dynalloc.h>
+#include <assert.h>
+
+static struct mountlist_entry *mountlist = NULL;
+
+int
+vfs_cache_mp(struct mount *mp, const char *path)
+{
+ size_t hash = vfs_hash_path(path);
+ struct mountlist_entry *entry;
+
+ if (hash == 0) {
+ /* Something is wrong with the path */
+ return -EINVAL;
+ }
+
+ if (vfs_cache_fetch_mp(path, NULL) == 0) {
+ /* Cache hit, do not duplicate this entry */
+ return -EEXIST;
+ }
+
+ mp->phash = hash;
+ entry = &mountlist[hash % MOUNTLIST_SIZE];
+ TAILQ_INSERT_TAIL(&entry->buckets, mp, link);
+ return 0;
+}
+
+int
+vfs_cache_fetch_mp(const char *path, struct mount **mp)
+{
+ size_t hash = vfs_hash_path(path);
+ struct mountlist_entry *entry;
+ struct mount *mount_iter;
+
+ if (hash == 0) {
+ /* Something is wrong with the path */
+ return -EINVAL;
+ }
+
+ entry = &mountlist[hash % MOUNTLIST_SIZE];
+ TAILQ_FOREACH(mount_iter, &entry->buckets, link) {
+ if (mount_iter->phash == hash) {
+ /* Cache hit */
+ if (mp != NULL) *mp = mount_iter;
+ return 0;
+ }
+ }
+
+ /* Cache miss */
+ return -ENOENT;
+}
+
+void
+vfs_init_cache(void)
+{
+ mountlist = dynalloc(sizeof(struct mount) * MOUNTLIST_SIZE);
+ __assert(mountlist != NULL);
+
+ for (size_t i = 0; i < MOUNTLIST_SIZE; ++i) {
+ TAILQ_INIT(&mountlist[i].buckets);
+ }
+}
diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c
new file mode 100644
index 0000000..bcda0dd
--- /dev/null
+++ b/sys/kern/vfs_init.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ */
+
+#include <sys/vfs.h>
+#include <sys/cdefs.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <fs/initramfs.h>
+#include <assert.h>
+#include <string.h>
+
+__MODULE_NAME("vfs");
+__KERNEL_META("$Hyra$: vfs.c, Ian Marco Moffett, "
+ "Hyra Virtual File System");
+
+struct fs_info filesystems[] = {
+ { "initramfs", &g_initramfs_ops }
+};
+
+struct fs_info *
+vfs_byname(const char *name)
+{
+ for (int i = 0; i < __ARRAY_COUNT(filesystems); ++i) {
+ if (strcmp(filesystems[i].name, name) == 0) {
+ return &filesystems[i];
+ }
+ }
+
+ return NULL;
+}
+
+void
+vfs_init(void)
+{
+ struct fs_info *info;
+ struct vfsops *vfsops;
+
+ vfs_init_cache();
+
+ for (int i = 0; i < __ARRAY_COUNT(filesystems); ++i) {
+ info = &filesystems[i];
+ vfsops = info->vfsops;
+
+ __assert(vfsops->init != NULL);
+ vfsops->init(info);
+
+ if (strcmp(info->name, "initramfs") == 0) {
+ /* Initramfs must be mounted */
+ vfs_mount(&info->mp_root, "/ramdisk", MNT_RDONLY);
+ }
+ }
+}
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
new file mode 100644
index 0000000..748d5e2
--- /dev/null
+++ b/sys/kern/vfs_lookup.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ */
+
+#include <sys/types.h>
+#include <sys/vfs.h>
+#include <vm/dynalloc.h>
+#include <string.h>
+
+/*
+ * Fetches the filename within a past at
+ * the nth index denoted by `idx'
+ *
+ * Returns memory allocated by dynalloc()
+ * containing the filename.
+ *
+ * XXX: MUST FREE RETURN VALUE WITH dynfree() WHEN
+ * DONE!
+ */
+char *
+vfs_get_fname_at(const char *path, size_t idx)
+{
+ size_t pathlen = strlen(path);
+ size_t fname_len;
+
+ char *path_tmp = dynalloc(pathlen + 2);
+ char *ret = NULL;
+ char *start_ptr, *ptr;
+
+ /* Make one-based */
+ ++idx;
+
+ if (path_tmp == NULL) {
+ return NULL;
+ }
+
+ ptr = path_tmp;
+ memcpy(path_tmp, path, pathlen + 1);
+
+ /*
+ * We want to by default have a '/' at the end
+ * to keep the parsing logic from getting more
+ * complicated than it needs to be.
+ */
+ path_tmp[pathlen] = '/';
+ path_tmp[pathlen + 1] = '\0';
+
+ /* Skip any leading slashes */
+ while (*ptr == '/')
+ ++ptr;
+
+ start_ptr = ptr;
+
+ /* Get each filename */
+ while (*ptr != '\0') {
+ /* Handle duplicate delimiter */
+ if (*ptr == '/' && *(ptr + 1) == '/') {
+ /*
+ * Snip this delimiter and skip, the next
+ * will be read and filename returned (if of course
+ * the index is reached).
+ */
+ *(ptr++) = '\0';
+ continue;
+ }
+
+ if (*ptr == '/') {
+ *(ptr++) = '\0';
+
+ /* Continue if index not reached */
+ if ((--idx) != 0) {
+ start_ptr = ptr;
+ continue;
+ }
+
+ /* Index has been reached, start_ptr contains name */
+ fname_len = strlen(start_ptr);
+ ret = dynalloc(fname_len + 1);
+
+ if (ret != NULL) {
+ memcpy(ret, start_ptr, fname_len + 1);
+ }
+ break;
+ }
+
+ ++ptr;
+ }
+
+ dynfree(path_tmp);
+ return ret;
+}
+
+struct vnode *
+vfs_path_to_node(const char *path)
+{
+ /* TODO */
+ return NULL;
+}
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
new file mode 100644
index 0000000..04b644e
--- /dev/null
+++ b/sys/kern/vfs_subr.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ */
+
+#include <sys/types.h>
+#include <sys/vfs.h>
+#include <sys/errno.h>
+#include <sys/mount.h>
+#include <vm/dynalloc.h>
+#include <string.h>
+
+/* FNV-1a defines */
+#define FNV_OFFSET 14695981039346656037ULL
+#define FNV_PRIME 1099511628211ULL
+
+/*
+ * 32-bit FNV-1a hash function
+ * https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function
+ */
+static size_t
+vfs_hash(const char *data)
+{
+ size_t hash = FNV_OFFSET;
+ const char *p = data;
+
+ while (*p) {
+ hash ^= (size_t)(uint8_t)(*p);
+ hash *= FNV_PRIME;
+ ++p;
+ }
+
+ return hash;
+}
+
+/*
+ * Hashes a path
+ *
+ * @path: Path to hash.
+ *
+ * Returns 0 on failure, non-zero return values
+ * are valid.
+ */
+size_t
+vfs_hash_path(const char *path)
+{
+ char *name = NULL;
+ size_t i = 0, hash = 0;
+
+ if (strcmp(path, "/") == 0 || !vfs_is_valid_path(path)) {
+ return 0;
+ } else if (*path != '/') {
+ return 0;
+ }
+
+ do {
+ name = vfs_get_fname_at(path, i++);
+ if (name != NULL)
+ hash += vfs_hash(name);
+ } while (name != NULL);
+
+ return hash;
+}
+
+
+/*
+ * This function checks if a path is valid.
+ *
+ * @path: Path to check.
+ *
+ * Returns true if valid, otherwise false.
+ */
+bool
+vfs_is_valid_path(const char *path)
+{
+ const char *ptr = path;
+ char c;
+
+ while (*ptr != '\0') {
+ c = *(ptr++);
+ switch (c) {
+ case '/':
+ case '-':
+ case '_':
+ /* Valid char, can continue */
+ continue;
+ default:
+ /*
+ * This could be an alphabetical or "numeric" char which
+ * is valid. We want to handle this too. To make things
+ * easier we'll OR the char by 0x20 to convert it to
+ * lowercase if it is alphabetical.
+ */
+ c |= 0x20;
+ if (c >= 'a' && c <= 'z')
+ continue;
+ else if (c >= '0' && c <= '9')
+ continue;
+
+ /* We got an invalid char */
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*
+ * Allocates a vnode
+ *
+ * @vnode: Pointer to vnode pointer where newly allocated
+ * vnode will be stored.
+ *
+ * @mp: Mountpoint this vnode is associated with.
+ * @type: Vnode type.
+ *
+ * This function will return 0 upon success and < 0 on failure.
+ */
+int
+vfs_alloc_vnode(struct vnode **vnode, struct mount *mp, int type)
+{
+ struct vnode *new_vnode = dynalloc(sizeof(struct vnode));
+
+ if (new_vnode == NULL) {
+ return -ENOMEM;
+ }
+
+ memset(new_vnode, 0, sizeof(struct vnode));
+ new_vnode->type = type;
+ new_vnode->mp = mp;
+
+ *vnode = new_vnode;
+ return 0;
+}
+
+/*
+ * This function mounts a `mount' structure
+ * at a specific path.
+ *
+ * @mp_out: Where to store copy of new mountpoint (NULL if none)
+ * @path: Path to mount on.
+ * @mnt_flags: Mount flags (MNT_* from sys/mount.h)
+ *
+ * Returns 0 upon success, otherwise a < 0 value.
+ *
+ * XXX: This function assumes the mountpoint has its mount
+ * routine set in its vfsops.
+ */
+int
+vfs_mount(struct mount **mp_out, const char *path, int mnt_flags)
+{
+ struct mount *mp;
+ int cache_status;
+
+ mp = dynalloc(sizeof(struct mount));
+ if (mp == NULL) {
+ return -ENOMEM;
+ }
+
+ mp->flags = mnt_flags;
+ cache_status = vfs_cache_mp(mp, path);
+
+ if (cache_status != 0) {
+ return cache_status;
+ }
+
+ *mp_out = mp;
+ return 0;
+}