#include #include #include "vfs.h" #include "kprintf.h" #include "spinlock/spinlock.h" #include "hal/hal.h" #include "util/util.h" #include "hshtb.h" #include "assert.h" #include "errors.h" #include "fs/kvfs/kvfs.h" #include "storedev/storedev.h" VfsTable VFS_TABLE; void vfs_init_kvfs(VfsMountPoint *mp) { mp->read = &kvfs_read; mp->write = &kvfs_write; mp->remove = &kvfs_remove; mp->check = &kvfs_check; mp->cleanup = &kvfs_cleanup; } int32_t vfs_mount(char *mountpoint, int32_t fstype, StoreDev *backingsd) { VfsMountPoint *mp = NULL; spinlock_acquire(&VFS_TABLE.spinlock); HSHTB_ALLOC(&VFS_TABLE, mountpoints, mountpoint, label, mp); spinlock_release(&VFS_TABLE.spinlock); if (mp == NULL) { return E_NOMEMORY; } hal_memcpy(mp->label, mountpoint, hal_strlen(mountpoint)); mp->backingsd = backingsd; mp->fstype = fstype; switch (fstype) { case VFS_KVFS: vfs_init_kvfs(mp); break; default: return E_UNKNOWN_FSTYPE; } return E_OK; } int32_t vfs_unmount(char *mountpoint) { VfsMountPoint *mp = NULL; spinlock_acquire(&VFS_TABLE.spinlock); HSHTB_GET(&VFS_TABLE, mountpoints, mountpoint, label, mp); spinlock_release(&VFS_TABLE.spinlock); if (mp == NULL) { return E_NOENTRY; } spinlock_acquire(&mp->spinlock); int32_t err = mp->cleanup(mp); if (err != E_OK) { spinlock_release(&mp->spinlock); return err; } hal_memset(mp, 0, sizeof(*mp)); spinlock_release(&mp->spinlock); return E_OK; } int32_t vfs_read(char *mountpoint, const char *path, uint8_t *const buffer, size_t n, size_t off) { VfsMountPoint *mp = NULL; spinlock_acquire(&VFS_TABLE.spinlock); HSHTB_GET(&VFS_TABLE, mountpoints, mountpoint, label, mp); spinlock_release(&VFS_TABLE.spinlock); if (mp == NULL) { return E_NOENTRY; } return mp->read(mp, path, buffer, n, off); } int32_t vfs_write(char *mountpoint, const char *path, const uint8_t *const buffer, size_t n, size_t off) { VfsMountPoint *mp = NULL; spinlock_acquire(&VFS_TABLE.spinlock); HSHTB_GET(&VFS_TABLE, mountpoints, mountpoint, label, mp); spinlock_release(&VFS_TABLE.spinlock); if (mp == NULL) { return E_NOENTRY; } return mp->write(mp, path, buffer, n, off); } int32_t vfs_remove(char *mountpoint, const char *path) { VfsMountPoint *mp = NULL; spinlock_acquire(&VFS_TABLE.spinlock); HSHTB_GET(&VFS_TABLE, mountpoints, mountpoint, label, mp); spinlock_release(&VFS_TABLE.spinlock); if (mp == NULL) { return E_NOENTRY; } return mp->remove(mp, path); } int32_t tmpvars_init(void) { RamSdInitExtra extra = { .capacity = KVFS_NODES_MAX * KVFS_BUFFER_SIZE }; StoreDev *backingsd = storedev_create(STOREDEV_RAMSD, &extra); if (backingsd == NULL) { return E_NOMEMORY; } return vfs_mount("tmpvars", VFS_KVFS, backingsd); } void vfs_init(void) { hal_memset(&VFS_TABLE, 0, sizeof(VFS_TABLE)); spinlock_init(&VFS_TABLE.spinlock); tmpvars_init(); LOG("vfs", "init done\n"); for (size_t i = 0; i < LEN(VFS_TABLE.mountpoints); i++) { if (!VFS_TABLE.mountpoints[i].taken) continue; VfsMountPoint *vmp = &VFS_TABLE.mountpoints[i]; LOG("vfs", "mount point %s: %s, backing device: %s\n", vmp->label, vfs_strings[vmp->fstype], storedev_strings[vmp->backingsd->sdtype]); if (vmp->check != NULL) { LOG("vfs", "check = %s\n", vmp->check() ? "OK" : "FAIL"); } else { LOG("vfs", "check skipped\n"); } } }