diff --git a/ce/ce.c b/ce/ce.c index 1f7f6f6..6f6b7a6 100644 --- a/ce/ce.c +++ b/ce/ce.c @@ -72,16 +72,15 @@ static void cmd_cat (struct list_node_link* tokens) { struct list_node_link *token_link, *token_tmp_link; list_foreach (tokens, token_link, token_tmp_link) { struct token* token = list_entry (token_link, struct token, tokens_link); - int ret; - ret = open (token->buffer); + int handle = open (token->buffer); - if (ret < 0) { - printf ("ERROR opening %s: %s\n", token->buffer, str_status[-ret]); + if (handle < 0) { + printf ("ERROR opening %s: %s\n", token->buffer, str_status[-handle]); continue; } - describe (token->buffer, &desc); + describe (handle, &desc); if (desc.type != FS_FILE) goto close1; @@ -92,21 +91,13 @@ static void cmd_cat (struct list_node_link* tokens) { goto close1; memset (buffer, 0, desc.size + 1); - - ret = read (token->buffer, 0, (uint8_t*)buffer, desc.size); - - if (ret < 0) { - printf ("ERROR reading%s: %s\n", token->buffer, str_status[-ret]); - goto close1; - } - + read (handle, 0, (uint8_t*)buffer, desc.size); printf ("%s\n", buffer); close1: if (buffer != NULL) free (buffer); - - close (token->buffer); + close (handle); } } diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index 4224260..a950f9f 100644 --- a/kernel/fs/vfs.c +++ b/kernel/fs/vfs.c @@ -46,7 +46,6 @@ int vfs_create_mountpoint (const char* key, int fs_type, struct device* back_dev memcpy (mountpoint->key, key, strlen_null (key)); mountpoint->fs_type = fs_type; - mountpoint->lock = SPIN_LOCK_INIT; mountpoint->back_device = back_device; switch (mountpoint->fs_type) { @@ -81,111 +80,137 @@ int vfs_create_mountpoint (const char* key, int fs_type, struct device* back_dev } 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); + struct vfs_handle* handle = malloc (sizeof (*handle)); - vmp->ownerpg = procgroup; - vmp->locked = true; + if (handle == NULL) + return -ST_OOM_ERROR; - spin_unlock (&vmp->lock); + 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 = procgroup->sys_vfs_handles++; + + 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; + } + + rbtree_delete (&procgroup->vfs_handle_tree, &handle->handle_tree_link); + + spin_unlock (&procgroup->lock); + + free (handle); return ST_OK; } -int vfs_close (struct procgroup* procgroup, const char* mountpoint, const char* path) { - (void)path; +int vfs_describe (struct procgroup* procgroup, int id, struct desc* desc) { + struct vfs_handle* handle = NULL; - struct vfs_mountpoint* vmp = vfs_find_mountpoint (mountpoint); + spin_lock (&procgroup->lock); - if (vmp == NULL) + 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 (&vmp->lock); - - if (procgroup != NULL && vmp->ownerpg != procgroup) { - spin_unlock (&vmp->lock); - return -ST_PERMISSION_ERROR; } - vmp->locked = false; - vmp->ownerpg = NULL; + spin_unlock (&procgroup->lock); - spin_unlock (&vmp->lock); - - return ST_OK; -} - -int vfs_describe (struct procgroup* procgroup, const char* mountpoint, const char* path, - struct desc* 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); + 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, const char* mountpoint, const char* path, - uint8_t* buffer, size_t off, size_t size) { +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; - spin_lock (&vmp->lock); + return vmp->driver_ops.read (vmp, path, buffer, off, size); +} - if ((procgroup != NULL && vmp->ownerpg != procgroup) && vmp->locked) { - spin_unlock (&vmp->lock); - return -ST_PERMISSION_ERROR; - } +int vfs_kernel_describe (const char* mountpoint, const char* path, struct desc* desc) { + struct vfs_mountpoint* vmp = vfs_find_mountpoint (mountpoint); - int ret = vmp->driver_ops.read (vmp, path, buffer, off, size); + if (vmp == NULL) + return -ST_NOT_FOUND; - spin_unlock (&vmp->lock); - - return ret; + return vmp->driver_ops.describe (vmp, path, desc); } void vfs_procgroup_cleanup (struct procgroup* procgroup) { - spin_lock (&mount_table.lock); + struct list_node_link* handle_cleanup_list = NULL; + struct vfs_handle* handle; - for (size_t i = 0; i < lengthof (mount_table.mountpoint_buckets); i++) { - struct hash_node_link* link = mount_table.mountpoint_buckets[i]; + struct rb_node_link* node; + rbtree_first (&procgroup->vfs_handle_tree, node); - while (link != NULL) { - 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); - - link = link->next; - } + while (node != NULL) { + struct rb_node_link* next; + rbtree_next (node, next); + handle = rbtree_entry (node, struct vfs_handle, handle_tree_link); + node = next; + list_append (handle_cleanup_list, &handle->handle_cleanup_link); } - spin_unlock (&mount_table.lock); + struct list_node_link *cleanup_link, *cleanup_tmp_link; + list_foreach (handle_cleanup_list, cleanup_link, cleanup_tmp_link) { + handle = list_entry (cleanup_link, struct vfs_handle, handle_cleanup_link); + list_remove (handle_cleanup_list, &handle->handle_cleanup_link); + free (handle); + } } void vfs_init (void) { diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h index ea5f014..86a8a29 100644 --- a/kernel/fs/vfs.h +++ b/kernel/fs/vfs.h @@ -5,7 +5,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -13,13 +15,22 @@ #define VFS_TARFS 0 +struct vfs_mountpoint; + +struct vfs_handle { + int id; + struct vfs_mountpoint* mountpoint; + char path[MAX_PATH]; + struct procgroup* ownerpg; + struct rb_node_link handle_tree_link; + struct list_node_link handle_cleanup_link; + spin_lock_t lock; +}; + struct vfs_mountpoint { char key[0x100]; struct hash_node_link mount_table_link; int fs_type; - spin_lock_t lock; - bool locked; - struct procgroup* ownerpg; struct { int (*mount) (struct vfs_mountpoint* mountpoint, struct proc* proc, struct reschedule_ctx* rctx); @@ -41,16 +52,19 @@ struct vfs_mount_table { int vfs_create_mountpoint (const char* key, int fs_type, struct device* back_device, struct proc* proc, struct reschedule_ctx* rctx); -int vfs_describe (struct procgroup* procgroup, const char* mountpoint, const char* path, - struct desc* desc); +int vfs_describe (struct procgroup* procgroup, int id, struct desc* desc); -int vfs_read (struct procgroup* procgroup, const char* mountpoint, const char* path, - uint8_t* buffer, size_t off, size_t size); +int vfs_read (struct procgroup* procgroup, int id, uint8_t* buffer, size_t off, size_t size); -int vfs_close (struct procgroup* procgroup, const char* mountpoint, const char* path); +int vfs_close (struct procgroup* procgroup, int id); int vfs_open (struct procgroup* procgroup, const char* mountpoint, const char* path); +int vfs_kernel_read (const char* mountpoint, const char* path, uint8_t* buffer, size_t off, + size_t size); + +int vfs_kernel_describe (const char* mountpoint, const char* path, struct desc* desc); + void vfs_procgroup_cleanup (struct procgroup* procgroup); void vfs_init (void); diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index 2e82b82..2479bc0 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -108,47 +108,73 @@ struct proc* proc_from_file (struct procgroup* procgroup, const char* mountpoint const char* path) { struct desc desc; - if (vfs_open (procgroup, mountpoint, path) != ST_OK) - return NULL; + if (procgroup == NULL) { + if (vfs_kernel_describe (mountpoint, path, &desc) < 0) + return NULL; - if (vfs_describe (procgroup, mountpoint, path, &desc) != ST_OK) { - vfs_close (procgroup, mountpoint, path); - return NULL; - } + if (desc.type != FS_FILE) + return NULL; - if (desc.type != FS_FILE) { - vfs_close (procgroup, mountpoint, path); - return NULL; - } + uint8_t* temp_buffer = malloc (desc.size); - uint8_t* temp_buffer = malloc (desc.size); + if (temp_buffer == NULL) + return NULL; - if (temp_buffer == NULL) { - vfs_close (procgroup, mountpoint, path); - return NULL; - } + if (vfs_kernel_read (mountpoint, path, temp_buffer, 0, desc.size) < 0) { + free (temp_buffer); + return NULL; + } + + if (!proc_check_elf (temp_buffer)) { + free (temp_buffer); + return NULL; + } + + struct proc* proc = proc_from_elf (temp_buffer); - if (vfs_read (procgroup, mountpoint, path, temp_buffer, 0, desc.size) != ST_OK) { free (temp_buffer); - vfs_close (procgroup, mountpoint, path); - return NULL; - } + return proc; + } else { + int handle = vfs_open (procgroup, mountpoint, path); - vfs_close (procgroup, mountpoint, path); + if (handle < 0) + return NULL; - bool ok = proc_check_elf (temp_buffer); + if (vfs_describe (procgroup, handle, &desc) != ST_OK) { + vfs_close (procgroup, handle); + return NULL; + } - DEBUG ("Spawning %s:%s, elf header %s\n", mountpoint, path, ok ? "ok" : "bad"); + if (desc.type != FS_FILE) { + vfs_close (procgroup, handle); + return NULL; + } + + uint8_t* temp_buffer = malloc (desc.size); + + if (temp_buffer == NULL) { + vfs_close (procgroup, handle); + return NULL; + } + + if (vfs_read (procgroup, handle, temp_buffer, 0, desc.size) != ST_OK) { + free (temp_buffer); + vfs_close (procgroup, handle); + return NULL; + } + + vfs_close (procgroup, handle); + + if (!proc_check_elf (temp_buffer)) { + free (temp_buffer); + return NULL; + } + + struct proc* proc = proc_from_elf (temp_buffer); - if (!ok) { free (temp_buffer); - return NULL; + return proc; } - - struct proc* proc = proc_from_elf (temp_buffer); - - free (temp_buffer); - return proc; } struct proc* proc_find_pid (int pid) { diff --git a/kernel/proc/procgroup.c b/kernel/proc/procgroup.c index 4bc9dbc..7926fcf 100644 --- a/kernel/proc/procgroup.c +++ b/kernel/proc/procgroup.c @@ -197,6 +197,8 @@ void procgroup_detach (struct procgroup* procgroup, struct proc* proc, spin_unlock (&procgroup->lock); spin_unlock (&procgroup_tree_lock); + struct list_node_link* resource_delete_list = NULL; + /* delete resources */ struct rb_node_link* rnode; rbtree_first (&procgroup->resource_tree, rnode); @@ -209,6 +211,16 @@ void procgroup_detach (struct procgroup* procgroup, struct proc* proc, rnode = next; + list_append (resource_delete_list, &resource->delete_list_link); + } + + struct list_node_link *resource_delete_link, *resource_delete_tmp_link; + list_foreach (resource_delete_list, resource_delete_link, resource_delete_tmp_link) { + struct proc_resource* resource = + list_entry (resource_delete_link, struct proc_resource, delete_list_link); + + list_remove (resource_delete_list, &resource->delete_list_link); + proc_delete_resource (resource, rctx); } diff --git a/kernel/proc/procgroup.h b/kernel/proc/procgroup.h index a83e28f..b283909 100644 --- a/kernel/proc/procgroup.h +++ b/kernel/proc/procgroup.h @@ -33,6 +33,8 @@ struct procgroup { uintptr_t map_base; struct procgroup_tls tls; uint64_t capabilities; + struct rb_node_link* vfs_handle_tree; + int sys_vfs_handles; }; struct procgroup* procgroup_create (void); diff --git a/kernel/proc/resource.h b/kernel/proc/resource.h index 9e982bb..94fdeb7 100644 --- a/kernel/proc/resource.h +++ b/kernel/proc/resource.h @@ -21,6 +21,7 @@ struct proc_resource { int rid; spin_lock_t lock; struct rb_node_link resource_tree_link; + struct list_node_link delete_list_link; union { struct proc_mutex mutex; struct proc_mail mail; diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 8220081..40b46ae 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -324,35 +324,16 @@ DEFINE_SYSCALL (sys_open) { return SYSRESULT (vfs_open (proc->procgroup, mountpoint, subpath)); } -/* int close (char* path) */ +/* int close (int handle) */ DEFINE_SYSCALL (sys_close) { - uintptr_t uvaddr_path = a1; + int handle = (int)a1; - struct limine_hhdm_response* hhdm = limine_hhdm_request.response; - - uintptr_t out_paddr; - - spin_lock (&proc->procgroup->lock); - out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_path); - spin_unlock (&proc->procgroup->lock); - - if (out_paddr == 0) - return SYSRESULT (-ST_BAD_ADDRESS_SPACE); - - const char* path = (const char*)((uintptr_t)hhdm->offset + out_paddr); - - char mountpoint[fieldsizeof (struct vfs_mountpoint, key)]; - const char* subpath = NULL; - - if (!path_parse (path, mountpoint, &subpath)) - return SYSRESULT (-ST_BAD_PATH); - - return SYSRESULT (vfs_close (proc->procgroup, mountpoint, subpath)); + return SYSRESULT (vfs_close (proc->procgroup, handle)); } -/* int read (char* path, size_t off, uint8_t* buffer, size_t size) */ +/* int read (int handle, size_t off, uint8_t* buffer, size_t size) */ DEFINE_SYSCALL (sys_read) { - uintptr_t uvaddr_path = a1; + int handle = (int)a1; size_t off = (size_t)a2; uintptr_t uvaddr_buffer = a3; size_t size = (size_t)a4; @@ -362,31 +343,12 @@ DEFINE_SYSCALL (sys_read) { if (buffer == NULL) return SYSRESULT (-ST_BAD_ADDRESS_SPACE); - struct limine_hhdm_response* hhdm = limine_hhdm_request.response; - - uintptr_t out_paddr; - - spin_lock (&proc->procgroup->lock); - out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_path); - spin_unlock (&proc->procgroup->lock); - - if (out_paddr == 0) - return SYSRESULT (-ST_BAD_ADDRESS_SPACE); - - const char* path = (const char*)((uintptr_t)hhdm->offset + out_paddr); - - char mountpoint[fieldsizeof (struct vfs_mountpoint, key)]; - const char* subpath = NULL; - - if (!path_parse (path, mountpoint, &subpath)) - return SYSRESULT (-ST_BAD_PATH); - - return SYSRESULT (vfs_read (proc->procgroup, mountpoint, subpath, buffer, off, size)); + return SYSRESULT (vfs_read (proc->procgroup, handle, buffer, off, size)); } -/* int describe (char* path, struct desc* desc) */ +/* int describe (int handle, struct desc* desc) */ DEFINE_SYSCALL (sys_describe) { - uintptr_t uvaddr_path = a1; + int handle = (int)a1; uintptr_t uvaddr_desc = a2; struct desc* desc = sys_get_user_buffer (proc, uvaddr_desc, sizeof (struct desc)); @@ -394,26 +356,7 @@ DEFINE_SYSCALL (sys_describe) { if (desc == NULL) return SYSRESULT (-ST_BAD_ADDRESS_SPACE); - struct limine_hhdm_response* hhdm = limine_hhdm_request.response; - - uintptr_t out_paddr; - - spin_lock (&proc->procgroup->lock); - out_paddr = mm_v2p (&proc->procgroup->pd, uvaddr_path); - spin_unlock (&proc->procgroup->lock); - - if (out_paddr == 0) - return SYSRESULT (-ST_BAD_ADDRESS_SPACE); - - const char* path = (const char*)((uintptr_t)hhdm->offset + out_paddr); - - char mountpoint[fieldsizeof (struct vfs_mountpoint, key)]; - const char* subpath = NULL; - - if (!path_parse (path, mountpoint, &subpath)) - return SYSRESULT (-ST_BAD_PATH); - - return SYSRESULT (vfs_describe (proc->procgroup, mountpoint, subpath, desc)); + return SYSRESULT (vfs_describe (proc->procgroup, handle, desc)); } /* int get_procgroup (int pid) */ diff --git a/libsystem/system.c b/libsystem/system.c index d1b02d6..2fd48f4 100644 --- a/libsystem/system.c +++ b/libsystem/system.c @@ -43,14 +43,14 @@ int exec (const char* path) { return (int)do_syscall (SYS_EXEC, path); } int open (const char* path) { return (int)do_syscall (SYS_OPEN, path); } -int close (const char* path) { return (int)do_syscall (SYS_CLOSE, path); } +int close (int handle) { return (int)do_syscall (SYS_CLOSE, handle); } -int read (const char* path, size_t off, uint8_t* buffer, size_t size) { - return (int)do_syscall (SYS_READ, path, off, buffer, size); +int read (int handle, size_t off, uint8_t* buffer, size_t size) { + return (int)do_syscall (SYS_READ, handle, off, buffer, size); } -int describe (const char* path, struct desc* desc) { - return (int)do_syscall (SYS_DESCRIBE, path, desc); +int describe (int handle, struct desc* desc) { + return (int)do_syscall (SYS_DESCRIBE, handle, desc); } int mail_send (int pgid, void* mesg, size_t mesg_size) { diff --git a/libsystem/system.h b/libsystem/system.h index b0b3d08..f84fa79 100644 --- a/libsystem/system.h +++ b/libsystem/system.h @@ -57,13 +57,13 @@ int exec (const char* path); int open (const char* path); /* Close a file */ -int close (const char* path); +int close (int handle); /* Read a file */ -int read (const char* path, size_t off, uint8_t* buffer, size_t size); +int read (int handle, size_t off, uint8_t* buffer, size_t size); /* describe a file */ -int describe (const char* path, struct desc* desc); +int describe (int handle, struct desc* desc); /* send a message to a procgroup's mail */ int mail_send (int pgid, void* mesg, size_t mesg_size);