aboutsummaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern')
-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
5 files changed, 493 insertions, 0 deletions
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;
+}