From 6f65553ca5d2740738f399d88b3a4eb298255427 Mon Sep 17 00:00:00 2001 From: Lunaixsky Date: Fri, 31 Jan 2025 05:36:46 +0000 Subject: [PATCH] taskfs fix up, minor refactoring * fix task listing * make twimap a separated instance for each inode * refactor the interface for registering attribute mapping * replace children atrribute to mm region enumeration * fix strncpy behaviour, remove the auto null-terminator appendence as it may cause out of bound access. * some minor refactoring --- lunaix-os/includes/lunaix/fs.h | 6 + lunaix-os/includes/lunaix/fs/api.h | 12 ++ lunaix-os/includes/lunaix/fs/taskfs.h | 26 +++- lunaix-os/includes/lunaix/fs/twimap.h | 26 +++- lunaix-os/kernel/fs/twimap.c | 6 +- lunaix-os/kernel/fs/vfs.c | 29 +++- lunaix-os/kernel/process/sched.c | 2 +- lunaix-os/kernel/process/task_attr.c | 145 ++++++++++++------- lunaix-os/kernel/process/taskfs.c | 197 +++++++++++++++++--------- lunaix-os/libs/klibc/string/strcpy.c | 13 +- 10 files changed, 319 insertions(+), 143 deletions(-) diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index 6feb2aa..6a5a92d 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -358,6 +358,12 @@ fsm_itend(struct fs_iter* iterator) iterator->fs = NULL; } +static inline bool +fsm_check_pseudo_fs(struct filesystem* fs) +{ + return !!(fs->types & FSTYPE_PSEUDO); +} + void vfs_init(); diff --git a/lunaix-os/includes/lunaix/fs/api.h b/lunaix-os/includes/lunaix/fs/api.h index d002774..9e8ce2f 100644 --- a/lunaix-os/includes/lunaix/fs/api.h +++ b/lunaix-os/includes/lunaix/fs/api.h @@ -298,4 +298,16 @@ fsapi_fs_finalise(struct filesystem* fs) fsm_register(fs); } +static inline bool +fsapi_check_readdir_pos_pseduo(struct v_file* file) +{ + return file->f_pos < 2; +} + +static inline bool +fsapi_readdir_pos_entries_at(struct v_file* file, unsigned int pos) +{ + return file->f_pos == pos + 2; +} + #endif /* __LUNAIX_FSAPI_H */ diff --git a/lunaix-os/includes/lunaix/fs/taskfs.h b/lunaix-os/includes/lunaix/fs/taskfs.h index b96e0e5..f0ef85f 100644 --- a/lunaix-os/includes/lunaix/fs/taskfs.h +++ b/lunaix-os/includes/lunaix/fs/taskfs.h @@ -3,21 +3,39 @@ #include #include +#include struct task_attribute { - struct llist_header siblings; + struct list_node siblings; struct hlist_node attrs; struct hstr key; - struct twimap* map_file; - char key_val[32]; + struct twimap_ops ops; }; +#define taskfs_export_attr(name) \ + ({ \ + taskfs_export_attr_mapping(stringify(name), \ + (struct twimap_ops) { \ + __task_read_##name, \ + __twimap_default_gonext, __twimap_default_reset \ + }); \ + }) + +#define taskfs_export_list_attr(name) \ + ({ \ + taskfs_export_attr_mapping(stringify(name), \ + (struct twimap_ops) { \ + __task_read_##name, \ + __task_gonext_##name, __task_reset_##name \ + }); \ + }) + void taskfs_init(); void -taskfs_export_attr(const char* key, struct twimap* attr_map_file); +taskfs_export_attr_mapping(const char* key, struct twimap_ops ops); struct task_attribute* taskfs_get_attr(struct hstr* key); diff --git a/lunaix-os/includes/lunaix/fs/twimap.h b/lunaix-os/includes/lunaix/fs/twimap.h index c9d56a2..465c99f 100644 --- a/lunaix-os/includes/lunaix/fs/twimap.h +++ b/lunaix-os/includes/lunaix/fs/twimap.h @@ -8,17 +8,37 @@ extern struct v_file_ops twimap_file_ops; +struct twimap; +struct twimap_ops +{ + void (*read)(struct twimap* mapping); + int (*go_next)(struct twimap* mapping); + void (*reset)(struct twimap* mapping); +}; + struct twimap { void* index; void* buffer; void* data; size_t size_acc; - void (*read)(struct twimap* mapping); - int (*go_next)(struct twimap* mapping); - void (*reset)(struct twimap* mapping); + + union { + struct { + void (*read)(struct twimap* mapping); + int (*go_next)(struct twimap* mapping); + void (*reset)(struct twimap* mapping); + }; + struct twimap_ops ops; + }; }; +void +__twimap_default_reset(struct twimap* map); + +int +__twimap_default_gonext(struct twimap* map); + int twimap_read(struct twimap* map, void* buffer, size_t len, size_t fpos); diff --git a/lunaix-os/kernel/fs/twimap.c b/lunaix-os/kernel/fs/twimap.c index 62bdaed..6a6dd0c 100644 --- a/lunaix-os/kernel/fs/twimap.c +++ b/lunaix-os/kernel/fs/twimap.c @@ -68,12 +68,16 @@ twimap_read(struct twimap* map, void* buffer, size_t len, size_t fpos) size_t acc_size = MIN(len, map->size_acc - (pos - fpos)), rdlen = acc_size; memcpy(buffer, map->buffer + (pos - fpos), acc_size); - while (acc_size < len && map->go_next(map)) { + while (acc_size < len) { map->size_acc = 0; map->read(map); rdlen = MIN(len - acc_size, map->size_acc); memcpy(buffer + acc_size, map->buffer, rdlen); acc_size += rdlen; + + if (!map->go_next(map)) { + break; + } } if (acc_size <= len - 1) { diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index 1696d6e..53c1efa 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -558,6 +558,8 @@ vfs_i_alloc(struct v_superblock* sb) void vfs_i_free(struct v_inode* inode) { + assert(inode->link_count == 0); + if (inode->pg_cache) { pcache_release(inode->pg_cache); vfree(inode->pg_cache); @@ -791,8 +793,12 @@ __vfs_readdir_callback(struct dir_context* dctx, const int dtype) { struct lx_dirent* dent = (struct lx_dirent*)dctx->cb_data; - strncpy(dent->d_name, name, MIN(len, DIRENT_NAME_MAX_LEN)); - dent->d_nlen = len; + int len_ = MIN(len, DIRENT_NAME_MAX_LEN - 1); + + strncpy(dent->d_name, name, len_); + dent->d_name[len_] = 0; + + dent->d_nlen = len_; dent->d_type = dtype; } @@ -832,6 +838,17 @@ done: return DO_STATUS_OR_RETURN(errno); } +static inline bool +check_pcache_eligibility(struct v_fd* fd_s) +{ + struct v_inode* inode; + + inode = fd_s->file->inode; + return !check_seqdev_node(inode) \ + && !fsm_check_pseudo_fs(inode->sb->fs) \ + && !(fd_s->flags & FO_DIRECT); +} + __DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count) { int errno = 0; @@ -850,7 +867,7 @@ __DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count) file->inode->atime = clock_unixtime(); - if (check_seqdev_node(file->inode) || (fd_s->flags & FO_DIRECT)) { + if (!check_pcache_eligibility(fd_s)) { errno = file->ops->read(file->inode, buf, count, file->f_pos); } else { errno = pcache_read(file->inode, buf, count, file->f_pos); @@ -896,7 +913,7 @@ __DEFINE_LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count) file->f_pos = inode->fsize; } - if (check_seqdev_node(inode) || (fd_s->flags & FO_DIRECT)) { + if (!check_pcache_eligibility(fd_s)) { errno = file->ops->write(inode, buf, count, file->f_pos); } else { errno = pcache_write(inode, buf, count, file->f_pos); @@ -993,6 +1010,8 @@ vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth) size_t cpy_size = MIN(dnode->name.len, size - len); strncpy(buf + len, dnode->name.value, cpy_size); + buf[len + cpy_size] = 0; + len += cpy_size; return len; @@ -1453,9 +1472,9 @@ vfs_do_chdir(struct proc_info* proc, struct v_dnode* dnode) vfs_ref_dnode(dnode); proc->cwd = dnode; +done: unlock_dnode(dnode); -done: return errno; } diff --git a/lunaix-os/kernel/process/sched.c b/lunaix-os/kernel/process/sched.c index e9f61b3..be02c57 100644 --- a/lunaix-os/kernel/process/sched.c +++ b/lunaix-os/kernel/process/sched.c @@ -446,7 +446,7 @@ commit_process(struct proc_info* process) assert(!proc_terminated(process->parent)); } - if (sched_ctx.proc_list) { + if (likely(sched_ctx.proc_list)) { llist_append(sched_ctx.proc_list, &process->tasks); } else { sched_ctx.proc_list = &process->tasks; diff --git a/lunaix-os/kernel/process/task_attr.c b/lunaix-os/kernel/process/task_attr.c index 7c4c83d..20d256f 100644 --- a/lunaix-os/kernel/process/task_attr.c +++ b/lunaix-os/kernel/process/task_attr.c @@ -1,92 +1,129 @@ #include #include +#define proc(map) (twimap_data(map, struct proc_info*)) + void -__read_parent(struct twimap* map) +__task_read_parent(struct twimap* map) { - struct proc_info* proc = twimap_data(map, struct proc_info*); - twimap_printf(map, "%d", proc->parent->pid); + twimap_printf(map, "%d", proc(map)->parent->pid); } void -__read_ctimestamp(struct twimap* map) +__task_read_created(struct twimap* map) { - struct proc_info* proc = twimap_data(map, struct proc_info*); - twimap_printf(map, "%d", proc->created); + twimap_printf(map, "%d", proc(map)->created); } void -__read_pgid(struct twimap* map) +__task_read_pgid(struct twimap* map) { - struct proc_info* proc = twimap_data(map, struct proc_info*); - twimap_printf(map, "%d", proc->pgid); + twimap_printf(map, "%d", proc(map)->pgid); } void -__read_children(struct twimap* map) +__task_read_cmdline(struct twimap* map) { - struct llist_header* proc_list = twimap_index(map, struct llist_header*); - struct proc_info* proc = - container_of(proc_list, struct proc_info, siblings); - if (!proc) - return; - twimap_printf(map, "%d ", proc->pid); + twimap_printf(map, "%s", proc(map)->cmd); +} + +static inline void +__get_protection(struct mm_region* vmr, char* prot_buf) +{ + prot_buf[0] = (vmr->attr & REGION_READ) ? 'r' : '-'; + prot_buf[1] = (vmr->attr & REGION_WRITE) ? 'w' : '-'; + prot_buf[2] = (vmr->attr & REGION_EXEC) ? 'x' : '-'; + prot_buf[3] = shared_writable_region(vmr) ? 's' : 'p'; + prot_buf[4] = 0; +} + +static inline void +__get_vmr_name(struct mm_region* vmr, char* buf, unsigned int size) +{ + int region_type; + + region_type = (vmr->attr >> 16) & 0xf; + + if (region_type == REGION_TYPE_STACK) { + strcpy(buf, "[stack]"); + } + + else if (region_type == REGION_TYPE_HEAP) { + strcpy(buf, "[heap]"); + } + + else if (vmr->mfile) { + vfs_get_path(vmr->mfile->dnode, buf, size, 0); + } + + else { + buf[0] = 0; + } +} + +void +__task_read_maps(struct twimap* map) +{ + struct llist_header* vmr_; + struct mm_region* vmr; + unsigned int size; + + vmr_ = twimap_index(map, struct llist_header*); + vmr = container_of(vmr_, struct mm_region, head); + + assert(vmr_); + + char prot[5], name[256]; + + __get_protection(vmr, prot); + __get_vmr_name(vmr, name, 256); + + size = vmr->end - vmr->start; + + twimap_printf(map, "%012lx-%012lx %x %s %s\n", + vmr->start, vmr->end, size, prot, name); } int -__next_children(struct twimap* map) +__task_gonext_maps(struct twimap* map) { - struct llist_header* proc = twimap_index(map, struct llist_header*); - struct proc_info* current = twimap_data(map, struct proc_info*); - if (!proc) + struct proc_mm* mm; + struct llist_header* vmr; + + vmr = twimap_index(map, struct llist_header*); + mm = vmspace(proc(map)); + + if (!vmr) return 0; - map->index = proc->next; - if (map->index == ¤t->children) { + + map->index = vmr->next; + if (map->index == &mm->regions) { return 0; } + return 1; } void -__reset_children(struct twimap* map) +__task_reset_maps(struct twimap* map) { - struct proc_info* proc = twimap_data(map, struct proc_info*); - if (llist_empty(&proc->children)) { + struct proc_mm* mm; + + mm = vmspace(proc(map)); + if (llist_empty(&mm->regions)) { map->index = 0; return; } - map->index = proc->children.next; + + map->index = mm->regions.next; } void export_task_attr() { - struct twimap* map; - - // FIXME goes to thread specific location - // map = twimap_create(NULL); - // map->read = __read_pending_sig; - // taskfs_export_attr("sig_pending", map); - - // map = twimap_create(NULL); - // map->read = __read_masked_sig; - // taskfs_export_attr("sig_masked", map); - - map = twimap_create(NULL); - map->read = __read_parent; - taskfs_export_attr("parent", map); - - map = twimap_create(NULL); - map->read = __read_ctimestamp; - taskfs_export_attr("created", map); - - map = twimap_create(NULL); - map->read = __read_pgid; - taskfs_export_attr("pgid", map); - - map = twimap_create(NULL); - map->read = __read_children; - map->go_next = __next_children; - map->reset = __reset_children; - taskfs_export_attr("children", map); + taskfs_export_attr(parent); + taskfs_export_attr(created); + taskfs_export_attr(pgid); + taskfs_export_attr(cmdline); + taskfs_export_list_attr(maps); } \ No newline at end of file diff --git a/lunaix-os/kernel/process/taskfs.c b/lunaix-os/kernel/process/taskfs.c index 2015aec..b8f0c18 100644 --- a/lunaix-os/kernel/process/taskfs.c +++ b/lunaix-os/kernel/process/taskfs.c @@ -13,16 +13,24 @@ #define COUNTER_MASK ((1 << 16) - 1) static struct hbucket* attr_export_table; -static DEFINE_LLIST(attributes); +static DEFINE_LIST(attributes); static volatile int ino_cnt = 1; -int +extern struct scheduler sched_ctx; + +static void +__destruct_inode(struct v_inode* inode) +{ + vfree_safe(inode->data); +} + +static int taskfs_next_counter() { return (ino_cnt = ((ino_cnt + 1) & COUNTER_MASK) + 1); } -inode_t +static inode_t taskfs_inode_id(pid_t pid, int sub_counter) { return ((pid & (MAX_PROCESS - 1)) << 16) | (sub_counter & COUNTER_MASK); @@ -39,8 +47,10 @@ taskfs_mknod(struct v_dnode* dnode, pid_t pid, int sub_counter, int itype) if (!(inode = vfs_i_alloc(vsb))) { return ENOMEM; } + inode->id = ino; inode->itype = itype; + inode->destruct = __destruct_inode; vfs_i_addhash(inode); } @@ -48,6 +58,47 @@ taskfs_mknod(struct v_dnode* dnode, pid_t pid, int sub_counter, int itype) return 0; } +static inline int +__report_task_entries(struct v_file* file, struct dir_context* dctx) +{ + unsigned int counter = 0; + char name[VFS_NAME_MAXLEN]; + struct proc_info *pos, *n; + + llist_for_each(pos, n, sched_ctx.proc_list, tasks) + { + if (!fsapi_readdir_pos_entries_at(file, counter)) { + counter++; + continue; + } + + ksnprintf(name, VFS_NAME_MAXLEN, "%d", pos->pid); + dctx->read_complete_callback(dctx, name, VFS_NAME_MAXLEN, DT_DIR); + return 1; + } + + return 0; +} + +static inline int +__report_task_attributes(struct v_file* file, struct dir_context* dctx) +{ + unsigned int counter = 0; + struct task_attribute *pos, *n; + + list_for_each(pos, n, attributes.first, siblings) + { + if (fsapi_readdir_pos_entries_at(file, counter)) { + dctx->read_complete_callback( + dctx, HSTR_VAL(pos->key), VFS_NAME_MAXLEN, DT_FILE); + return 1; + } + counter++; + } + + return 0; +} + int taskfs_readdir(struct v_file* file, struct dir_context* dctx) { @@ -64,35 +115,14 @@ taskfs_readdir(struct v_file* file, struct dir_context* dctx) } if (pid) { - struct task_attribute *pos, *n; - llist_for_each(pos, n, &attributes, siblings) - { - if (counter == file->f_pos) { - dctx->read_complete_callback( - dctx, pos->key_val, VFS_NAME_MAXLEN, DT_FILE); - return 1; - } - counter++; - } - return 0; + return __report_task_attributes(file, dctx); } - char name[VFS_NAME_MAXLEN]; - struct proc_info *root = get_process(pid), *pos, *n; - llist_for_each(pos, n, &root->tasks, tasks) - { - if (counter == file->f_pos) { - ksnprintf(name, VFS_NAME_MAXLEN, "%d", pos->pid); - dctx->read_complete_callback(dctx, name, VFS_NAME_MAXLEN, DT_DIR); - return 1; - } - counter++; - } - return 0; + return __report_task_entries(file, dctx); } // ascii to pid -pid_t +static inline pid_t taskfs_atop(const char* str) { pid_t t = 0; @@ -107,50 +137,76 @@ taskfs_atop(const char* str) return t; } +static inline int +__init_task_inode(pid_t pid, struct v_dnode* dnode) +{ + struct twimap* map; + struct proc_info* proc; + struct task_attribute* tattr; + + tattr = taskfs_get_attr(&dnode->name); + if (!tattr || !(proc = get_process(pid))) + return ENOENT; + + map = twimap_create(proc); + map->ops = tattr->ops; + + dnode->inode->data = map; + dnode->inode->default_fops = &twimap_file_ops; + + return 0; +} + +static int +__lookup_attribute(pid_t pid, struct v_dnode* dnode) +{ + int errno; + + errno = taskfs_mknod(dnode, pid, taskfs_next_counter(), VFS_IFFILE); + if (errno) { + return errno; + } + + return __init_task_inode(pid, dnode); +} + int taskfs_dirlookup(struct v_inode* this, struct v_dnode* dnode) { pid_t pid = this->id >> 16; - struct proc_info* proc; if (pid) { - struct task_attribute* tattr = taskfs_get_attr(&dnode->name); - if (!tattr || !(proc = get_process(pid))) - return ENOENT; - - int errno = - taskfs_mknod(dnode, pid, taskfs_next_counter(), VFS_IFSEQDEV); - if (!errno) { - tattr->map_file->data = proc; - dnode->inode->data = tattr->map_file; - dnode->inode->default_fops = &twimap_file_ops; - } - return errno; + return __lookup_attribute(pid, dnode); } pid = taskfs_atop(dnode->name.value); - if (pid <= 0 || !(proc = get_process(pid))) { + if (pid <= 0) { return ENOENT; } - return taskfs_mknod(dnode, pid, 0, F_DIR); + return taskfs_mknod(dnode, pid, 0, VFS_IFDIR); } -static struct v_file_ops taskfs_file_ops = { .close = default_file_close, - .read = default_file_read, - .read_page = - default_file_read_page, - .write = default_file_write, - .write_page = - default_file_write_page, - .readdir = taskfs_readdir, - .seek = default_file_seek }; -static struct v_inode_ops taskfs_inode_ops = { .dir_lookup = taskfs_dirlookup, - .open = default_inode_open, - .mkdir = default_inode_mkdir, - .rmdir = default_inode_rmdir, - .rename = default_inode_rename }; +static struct v_file_ops taskfs_file_ops = { + .close = default_file_close, + .read = default_file_read, + .read_page = default_file_read_page, + .write = default_file_write, + .write_page = default_file_write_page, + .readdir = taskfs_readdir, + .seek = default_file_seek +}; + +static struct v_inode_ops taskfs_inode_ops = { + .dir_lookup = taskfs_dirlookup, + .open = default_inode_open, + .mkdir = default_inode_mkdir, + .rmdir = default_inode_rmdir, + .rename = default_inode_rename +}; + +static volatile struct v_superblock* taskfs_sb; void taskfs_init_inode(struct v_superblock* vsb, struct v_inode* inode) @@ -159,8 +215,6 @@ taskfs_init_inode(struct v_superblock* vsb, struct v_inode* inode) inode->ops = &taskfs_inode_ops; } -static volatile struct v_superblock* taskfs_sb; - int taskfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point) { @@ -180,8 +234,9 @@ void taskfs_invalidate(pid_t pid) { struct v_dnode *pos, *n; - struct v_inode* inode = vfs_i_find(taskfs_sb, taskfs_inode_id(pid, 0)); + struct v_inode* inode; + inode = vfs_i_find(taskfs_sb, taskfs_inode_id(pid, 0)); if (!inode) return; @@ -192,23 +247,33 @@ taskfs_invalidate(pid_t pid) } vfs_d_free(pos); } + + if (!inode->link_count) { + vfs_i_free(inode); + } } #define ATTR_TABLE_LEN 16 +#define ATTR_KEY_LEN 32 void -taskfs_export_attr(const char* key, struct twimap* attr_map_file) +taskfs_export_attr_mapping(const char* key, struct twimap_ops ops) { - struct task_attribute* tattr = valloc(sizeof(*tattr)); + char* key_val; + struct hbucket* slot; + struct task_attribute* tattr; + + tattr = valloc(sizeof(*tattr)); + key_val = valloc(ATTR_KEY_LEN); - tattr->map_file = attr_map_file; - tattr->key = HSTR(tattr->key_val, 0); - strncpy(tattr->key_val, key, 32); + tattr->ops = ops; + tattr->key = HSTR(key_val, 0); + strncpy(key_val, key, ATTR_KEY_LEN); hstr_rehash(&tattr->key, HSTR_FULL_HASH); - struct hbucket* slot = &attr_export_table[tattr->key.hash % ATTR_TABLE_LEN]; + slot = &attr_export_table[tattr->key.hash % ATTR_TABLE_LEN]; hlist_add(&slot->head, &tattr->attrs); - llist_append(&attributes, &tattr->siblings); + list_add(&attributes, &tattr->siblings); } struct task_attribute* diff --git a/lunaix-os/libs/klibc/string/strcpy.c b/lunaix-os/libs/klibc/string/strcpy.c index 7a3b430..400aeec 100644 --- a/lunaix-os/libs/klibc/string/strcpy.c +++ b/lunaix-os/libs/klibc/string/strcpy.c @@ -27,18 +27,13 @@ strcpy(char* dest, const char* src) char* _weak strncpy(char* dest, const char* src, unsigned long n) { - char c; + char c = '\0'; unsigned int i = 0; - while (i <= n && (c = src[i])) + while (i < n && (c = src[i])) dest[i++] = c; - if (!(n < i && src[i - 1])) { - while (i <= n) - dest[i++] = 0; - } - else { - dest[i - 1] = 0; - } + while (i < n) + dest[i++] = 0; return dest; } \ No newline at end of file -- 2.27.0