#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct vfs_mount_table mount_table; static struct vfs_mountpoint* vfs_find_mountpoint (const char* mountpoint) { struct hash_node_link* found_link = NULL; size_t mountpoint_len = strlen (mountpoint); uint32_t hash = hash_fnv32 (mountpoint, strlen (mountpoint)); spin_lock (&mount_table.lock); hash_find (&mount_table, mountpoint, mountpoint_len, hash, lengthof (mount_table.mountpoint_buckets), mountpoint_buckets, struct vfs_mountpoint, mount_table_link, key, found_link); spin_unlock (&mount_table.lock); if (found_link == NULL) return NULL; return hash_entry (found_link, struct vfs_mountpoint, mount_table_link); } int vfs_create_mountpoint (const char* key, int fs_type, struct device* back_device, struct proc* proc, struct reschedule_ctx* rctx) { if (strlen_null (key) > fieldsizeof (struct vfs_mountpoint, key)) return -ST_OOB_ERROR; struct vfs_mountpoint* mountpoint = malloc (sizeof (*mountpoint)); if (mountpoint == NULL) return -ST_OOM_ERROR; memset (mountpoint, 0, sizeof (*mountpoint)); memcpy (mountpoint->key, key, strlen_null (key)); mountpoint->fs_type = fs_type; mountpoint->back_device = back_device; switch (mountpoint->fs_type) { case VFS_TARFS: { mountpoint->driver_ops.mount = &tarfs_mount; mountpoint->driver_ops.describe = &tarfs_describe; mountpoint->driver_ops.read = &tarfs_read; } break; default: { free (mountpoint); return -ST_MOUNT_ERROR; } break; } int ret = mountpoint->driver_ops.mount (mountpoint, proc, rctx); if (ret < 0) { free (mountpoint); return ret; } uint32_t mp_hash = hash_fnv32 (mountpoint->key, strlen (mountpoint->key)); spin_lock (&mount_table.lock); hash_insert (&mount_table, &mountpoint->mount_table_link, mp_hash, lengthof (mount_table.mountpoint_buckets), mountpoint_buckets); spin_unlock (&mount_table.lock); return ST_OK; } int vfs_open (struct procgroup* procgroup, const char* mountpoint, const char* path) { struct vfs_mountpoint* vmp = vfs_find_mountpoint (mountpoint); if (vmp == NULL) return -ST_NOT_FOUND; struct vfs_handle* handle = malloc (sizeof (*handle)); if (handle == NULL) return -ST_OOM_ERROR; memset (handle, 0, sizeof (*handle)); handle->mountpoint = vmp; handle->ownerpg = procgroup; strncpy (handle->path, path, sizeof (handle->path)); spin_lock (&procgroup->lock); int id = handle->id = id_alloc (&procgroup->vfs_handle_id_alloc); rbtree_insert (struct vfs_handle, &procgroup->vfs_handle_tree, &handle->handle_tree_link, handle_tree_link, id); spin_unlock (&procgroup->lock); return id; } int vfs_close (struct procgroup* procgroup, int id) { struct vfs_handle* handle = NULL; spin_lock (&procgroup->lock); rbtree_find (struct vfs_handle, &procgroup->vfs_handle_tree, id, handle, handle_tree_link, id); if (handle == NULL) { spin_unlock (&procgroup->lock); return -ST_NOT_FOUND; } spin_lock (&handle->lock); rbtree_delete (&procgroup->vfs_handle_tree, &handle->handle_tree_link); id_free (&procgroup->vfs_handle_id_alloc, handle->id); spin_unlock (&handle->lock); spin_unlock (&procgroup->lock); free (handle); return ST_OK; } int vfs_describe (struct procgroup* procgroup, int id, struct desc* desc) { struct vfs_handle* handle = NULL; spin_lock (&procgroup->lock); rbtree_find (struct vfs_handle, &procgroup->vfs_handle_tree, id, handle, handle_tree_link, id); if (handle == NULL) { spin_unlock (&procgroup->lock); return -ST_NOT_FOUND; } spin_unlock (&procgroup->lock); spin_lock (&handle->lock); int ret = handle->mountpoint->driver_ops.describe (handle->mountpoint, handle->path, desc); spin_unlock (&handle->lock); return ret; } int vfs_read (struct procgroup* procgroup, int id, uint8_t* buffer, size_t off, size_t size) { struct vfs_handle* handle = NULL; spin_lock (&procgroup->lock); rbtree_find (struct vfs_handle, &procgroup->vfs_handle_tree, id, handle, handle_tree_link, id); if (handle == NULL) { spin_unlock (&procgroup->lock); return -ST_NOT_FOUND; } spin_unlock (&procgroup->lock); spin_lock (&handle->lock); int ret = handle->mountpoint->driver_ops.read (handle->mountpoint, handle->path, buffer, off, size); spin_unlock (&handle->lock); return ret; } int vfs_kernel_read (const char* mountpoint, const char* path, uint8_t* buffer, size_t off, size_t size) { struct vfs_mountpoint* vmp = vfs_find_mountpoint (mountpoint); if (vmp == NULL) return -ST_NOT_FOUND; return vmp->driver_ops.read (vmp, path, buffer, off, size); } int vfs_kernel_describe (const char* mountpoint, const char* path, struct desc* desc) { struct vfs_mountpoint* vmp = vfs_find_mountpoint (mountpoint); if (vmp == NULL) return -ST_NOT_FOUND; return vmp->driver_ops.describe (vmp, path, desc); } void vfs_procgroup_cleanup (struct procgroup* procgroup) { struct vfs_handle* handle; struct rb_node_link* node; rbtree_first (&procgroup->vfs_handle_tree, node); while (node != NULL) { struct rb_node_link* next; rbtree_next (node, next); handle = rbtree_entry (node, struct vfs_handle, handle_tree_link); node = next; vfs_close (procgroup, handle->id); } } void vfs_init (void) { memset (&mount_table, 0, sizeof (mount_table)); mount_table.lock = SPIN_LOCK_INIT; }