#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); } struct vfs_mountpoint* vfs_create_mountpoint (const char* key, int fs_type) { if (strlen_null (key) > fieldsizeof (struct vfs_mountpoint, key)) return NULL; struct vfs_mountpoint* mountpoint = malloc (sizeof (*mountpoint)); if (mountpoint == NULL) return NULL; memset (mountpoint, 0, sizeof (*mountpoint)); memcpy (mountpoint->key, key, strlen_null (key)); mountpoint->fs_type = fs_type; mountpoint->lock = SPIN_LOCK_INIT; switch (mountpoint->fs_type) { case VFS_RAMDISKFS: { mountpoint->driver_ops.mount = &ramdiskfs_mount; mountpoint->driver_ops.describe = &ramdiskfs_describe; mountpoint->driver_ops.read = &ramdiskfs_read; } break; default: { free (mountpoint); return NULL; } break; } bool ok = mountpoint->driver_ops.mount (mountpoint); if (!ok) { free (mountpoint); return NULL; } 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 mountpoint; } int vfs_open (struct procgroup* procgroup, const char* mountpoint, const char* path) { (void)path; struct vfs_mountpoint* vmp = vfs_find_mountpoint (mountpoint); if (vmp == NULL) return -ST_NOT_FOUND; spin_lock (&vmp->lock); vmp->ownerpg = procgroup; vmp->locked = true; spin_unlock (&vmp->lock); return ST_OK; } int vfs_close (struct procgroup* procgroup, const char* mountpoint, const char* path) { (void)path; struct vfs_mountpoint* vmp = vfs_find_mountpoint (mountpoint); if (vmp == NULL) return -ST_NOT_FOUND; spin_lock (&vmp->lock); if (procgroup != NULL && vmp->ownerpg != procgroup) { spin_unlock (&vmp->lock); return -ST_PERMISSION_ERROR; } vmp->locked = false; vmp->ownerpg = NULL; spin_unlock (&vmp->lock); return ST_OK; } int vfs_describe (struct procgroup* procgroup, const char* mountpoint, const char* path, struct fs_desc_buffer* desc) { struct vfs_mountpoint* vmp = vfs_find_mountpoint (mountpoint); if (vmp == NULL) return -ST_NOT_FOUND; spin_lock (&vmp->lock); if ((procgroup != NULL && vmp->ownerpg != procgroup) && vmp->locked) { spin_unlock (&vmp->lock); return -ST_PERMISSION_ERROR; } int ret = vmp->driver_ops.describe (vmp, path, desc); spin_unlock (&vmp->lock); return ret; } int vfs_read (struct procgroup* procgroup, 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; spin_lock (&vmp->lock); if ((procgroup != NULL && vmp->ownerpg != procgroup) && vmp->locked) { spin_unlock (&vmp->lock); return -ST_PERMISSION_ERROR; } int ret = vmp->driver_ops.read (vmp, path, buffer, off, size); spin_unlock (&vmp->lock); return ret; } void vfs_procgroup_cleanup (struct procgroup* procgroup) { spin_lock (&mount_table.lock); for (size_t i = 0; i < lengthof (mount_table.mountpoint_buckets); i++) { struct hash_node_link* link = mount_table.mountpoint_buckets[i]; struct vfs_mountpoint* vmp = hash_entry (link, struct vfs_mountpoint, mount_table_link); spin_lock (&vmp->lock); if (vmp->ownerpg == procgroup) { vmp->locked = false; vmp->ownerpg = NULL; } spin_unlock (&vmp->lock); } spin_unlock (&mount_table.lock); } void vfs_init (void) { memset (&mount_table, 0, sizeof (mount_table)); mount_table.lock = SPIN_LOCK_INIT; }