From 003db17f7a36a8098827f40df8fedc087b5a26f6 Mon Sep 17 00:00:00 2001 From: Minep Date: Wed, 27 Jul 2022 17:01:23 +0100 Subject: [PATCH] feat: open(2), close(2), mkdir(2) and readdir(2) syscall feat: file descriptor support feat: fast interge base 2 logarithm. fix: incorrect cake piece number calculation in cake allocator fix: incomplete refactoring in ahci code base fix: file system mounting. chores: code refactoring and cleaning --- lunaix-os/hal/ahci/ahci.c | 2 +- lunaix-os/includes/hal/ahci/sata.h | 4 +- lunaix-os/includes/hal/ahci/scsi.h | 4 +- lunaix-os/includes/lunaix/dirent.h | 12 ++ lunaix-os/includes/lunaix/fctrl.h | 15 ++ lunaix-os/includes/lunaix/foptions.h | 7 + lunaix-os/includes/lunaix/fs.h | 30 ++-- lunaix-os/includes/lunaix/fs/twifs.h | 6 +- lunaix-os/includes/lunaix/process.h | 2 + lunaix-os/includes/lunaix/spike.h | 42 ++++++ lunaix-os/includes/lunaix/status.h | 11 +- lunaix-os/includes/lunaix/syscall.h | 10 ++ lunaix-os/kernel/asm/x86/syscall.S | 6 + lunaix-os/kernel/fs/fsm.c | 4 +- lunaix-os/kernel/fs/twifs.c | 77 ++++++++-- lunaix-os/kernel/fs/vfs.c | 218 +++++++++++++++++++++++---- lunaix-os/kernel/k_init.c | 3 + lunaix-os/kernel/mm/cake.c | 6 +- lunaix-os/kernel/mm/valloc.c | 46 +++--- lunaix-os/kernel/proc0.c | 30 ++-- lunaix-os/kernel/process.c | 4 +- lunaix-os/kernel/sched.c | 6 +- lunaix-os/kernel/signal.c | 6 +- lunaix-os/libs/crc.c | 3 +- lunaix-os/libs/hash.c | 5 +- 25 files changed, 446 insertions(+), 113 deletions(-) create mode 100644 lunaix-os/includes/lunaix/dirent.h create mode 100644 lunaix-os/includes/lunaix/fctrl.h create mode 100644 lunaix-os/includes/lunaix/foptions.h diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index 1562676..e892858 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -277,7 +277,7 @@ hba_prepare_cmd(struct hba_port* port, // 构建命令头(Command Header)和命令表(Command Table) struct hba_cmdh* cmd_header = &port->cmdlst[slot]; - struct hba_cmdt* cmd_table = vcalloc_dma(sizeof(struct hba_cmdt)); + struct hba_cmdt* cmd_table = vzalloc_dma(sizeof(struct hba_cmdt)); memset(cmd_header, 0, sizeof(*cmd_header)); diff --git a/lunaix-os/includes/hal/ahci/sata.h b/lunaix-os/includes/hal/ahci/sata.h index 99a45bc..dc93448 100644 --- a/lunaix-os/includes/hal/ahci/sata.h +++ b/lunaix-os/includes/hal/ahci/sata.h @@ -54,13 +54,13 @@ sata_create_fis(struct sata_reg_fis* cmd_fis, uint16_t sector_count); int -sata_read_buffer(struct hba_port* port, +sata_read_buffer(struct hba_device* dev, uint64_t lba, void* buffer, uint32_t size); int -sata_write_buffer(struct hba_port* port, +sata_write_buffer(struct hba_device* dev, uint64_t lba, void* buffer, uint32_t size); diff --git a/lunaix-os/includes/hal/ahci/scsi.h b/lunaix-os/includes/hal/ahci/scsi.h index cce9af4..6ba0fc2 100644 --- a/lunaix-os/includes/hal/ahci/scsi.h +++ b/lunaix-os/includes/hal/ahci/scsi.h @@ -48,13 +48,13 @@ scsi_create_packet16(struct scsi_cdb16* cdb, uint32_t alloc_size); void -scsi_read_buffer(struct hba_port* port, +scsi_read_buffer(struct hba_device* dev, uint64_t lba, void* buffer, uint32_t size); void -scsi_write_buffer(struct hba_port* port, +scsi_write_buffer(struct hba_device* dev, uint64_t lba, void* buffer, uint32_t size); diff --git a/lunaix-os/includes/lunaix/dirent.h b/lunaix-os/includes/lunaix/dirent.h new file mode 100644 index 0000000..5fce397 --- /dev/null +++ b/lunaix-os/includes/lunaix/dirent.h @@ -0,0 +1,12 @@ +#ifndef __LUNAIX_DIRENT_H +#define __LUNAIX_DIRENT_H + +struct dirent +{ + unsigned int d_type; + unsigned int d_offset; + unsigned int d_nlen; + char* d_name; +}; + +#endif /* __LUNAIX_DIRENT_H */ diff --git a/lunaix-os/includes/lunaix/fctrl.h b/lunaix-os/includes/lunaix/fctrl.h new file mode 100644 index 0000000..978553e --- /dev/null +++ b/lunaix-os/includes/lunaix/fctrl.h @@ -0,0 +1,15 @@ +#ifndef __LUNAIX_FCTRL_H +#define __LUNAIX_FCTRL_H + +#include +#include + +__LXSYSCALL2(int, open, const char*, path, int, options); + +__LXSYSCALL1(int, close, int, fd); + +__LXSYSCALL1(int, mkdir, const char*, path); + +__LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent); + +#endif /* __LUNAIX_FCTRL_H */ diff --git a/lunaix-os/includes/lunaix/foptions.h b/lunaix-os/includes/lunaix/foptions.h new file mode 100644 index 0000000..6d6d2d3 --- /dev/null +++ b/lunaix-os/includes/lunaix/foptions.h @@ -0,0 +1,7 @@ +#ifndef __LUNAIX_FOPTIONS_H +#define __LUNAIX_FOPTIONS_H + +#define FO_CREATE 0x1 +#define FO_APPEND 0x2 + +#endif /* __LUNAIX_FOPTIONS_H */ diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index 0f8d0d5..fce04ca 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -6,6 +6,7 @@ #include #include #include +#include #define VFS_NAME_MAXLEN 128 #define VFS_MAX_FD 32 @@ -14,19 +15,17 @@ #define VFS_INODE_TYPE_FILE 0x2 #define VFS_INODE_TYPE_DEVICE 0x4 -#define VFS_ETOOLONG -1 #define VFS_ENOFS -2 #define VFS_EBADMNT -3 -#define VFS_ENODIR -4 + #define VFS_EENDOFDIR -5 -#define VFS_ENOTFOUND -6 -#define VFS_ENOOPS -7 + #define VFS_EINVLD -8 #define VFS_EEOF -9 #define VFS_WALK_MKPARENT 0x1 #define VFS_WALK_FSRELATIVE 0x2 -#define VFS_WALK_MKDIR 0x4 +#define VFS_WALK_PARENT 0x4 #define VFS_IOBUF_FDIRTY 0x1 @@ -66,6 +65,7 @@ struct dir_context void* cb_data; void (*read_complete_callback)(struct dir_context* dctx, const char* name, + const int len, const int dtype); }; @@ -103,9 +103,11 @@ struct v_inode uint64_t lb_addr; uint32_t ref_count; uint32_t lb_usage; + uint32_t fsize; void* data; // 允许底层FS绑定他的一些专有数据 struct { + int (*create)(struct v_inode* inode, struct v_file* file); int (*open)(struct v_inode* inode, struct v_file* file); int (*sync)(struct v_inode* inode); int (*mkdir)(struct v_inode* inode, struct v_dnode* dnode); @@ -143,6 +145,9 @@ fsm_register(struct filesystem* fs); struct filesystem* fsm_get(const char* fs_name); +void +vfs_init(); + struct v_dnode* vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str); @@ -153,18 +158,23 @@ int vfs_walk(struct v_dnode* start, const char* path, struct v_dnode** dentry, + struct hstr* component, int walk_options); int -vfs_mount(const char* fs_name, bdev_t device, struct v_dnode* mnt_point); +vfs_mount(const char* target, const char* fs_name, bdev_t device); + +int +vfs_unmount(const char* target); + +int +vfs_mount_at(const char* fs_name, bdev_t device, struct v_dnode* mnt_point); int -vfs_unmount(struct v_dnode* mnt_point); +vfs_unmount_at(struct v_dnode* mnt_point); int -vfs_mkdir(const char* parent_path, - const char* component, - struct v_dnode** dentry); +vfs_mkdir(const char* path, struct v_dnode** dentry); int vfs_open(struct v_dnode* dnode, struct v_file** file); diff --git a/lunaix-os/includes/lunaix/fs/twifs.h b/lunaix-os/includes/lunaix/fs/twifs.h index 48b35b9..8df3ddc 100644 --- a/lunaix-os/includes/lunaix/fs/twifs.h +++ b/lunaix-os/includes/lunaix/fs/twifs.h @@ -5,6 +5,7 @@ struct twifs_node { + struct v_inode* inode; struct hstr name; uint32_t itype; struct llist_header children; @@ -16,7 +17,10 @@ void twifs_init(); struct twifs_node* -twifs_child_node(struct twifs_node* parent, const char* name, int name_len); +twifs_file_node(struct twifs_node* parent, const char* name, int name_len); + +struct twifs_node* +twifs_dir_node(struct twifs_node* parent, const char* name, int name_len); struct twifs_node* twifs_toplevel_node(const char* name, int name_len); diff --git a/lunaix-os/includes/lunaix/process.h b/lunaix-os/includes/lunaix/process.h index d35bfe7..7c8c114 100644 --- a/lunaix-os/includes/lunaix/process.h +++ b/lunaix-os/includes/lunaix/process.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -77,6 +78,7 @@ struct proc_info sigset_t sig_inprogress; int flags; void* sig_handler[_SIG_NUM]; + struct v_fdtable* fdtable; pid_t pgid; }; diff --git a/lunaix-os/includes/lunaix/spike.h b/lunaix-os/includes/lunaix/spike.h index 8297f0e..4e17993 100644 --- a/lunaix-os/includes/lunaix/spike.h +++ b/lunaix-os/includes/lunaix/spike.h @@ -20,6 +20,48 @@ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) +/** + * @brief Fast log base 2 for integer, utilizing constant unfolding. + * Adopted from + * https://elixir.bootlin.com/linux/v4.4/source/include/linux/log2.h#L85 + * + */ +#define ILOG2(x) \ + __builtin_constant_p(x) ? ((x) == 0 ? 0 \ + : ((x) & (1ul << 31)) ? 31 \ + : ((x) & (1ul << 30)) ? 30 \ + : ((x) & (1ul << 29)) ? 29 \ + : ((x) & (1ul << 28)) ? 28 \ + : ((x) & (1ul << 27)) ? 27 \ + : ((x) & (1ul << 26)) ? 26 \ + : ((x) & (1ul << 25)) ? 25 \ + : ((x) & (1ul << 24)) ? 24 \ + : ((x) & (1ul << 23)) ? 23 \ + : ((x) & (1ul << 22)) ? 22 \ + : ((x) & (1ul << 21)) ? 21 \ + : ((x) & (1ul << 20)) ? 20 \ + : ((x) & (1ul << 19)) ? 19 \ + : ((x) & (1ul << 18)) ? 18 \ + : ((x) & (1ul << 17)) ? 17 \ + : ((x) & (1ul << 16)) ? 16 \ + : ((x) & (1ul << 15)) ? 15 \ + : ((x) & (1ul << 14)) ? 14 \ + : ((x) & (1ul << 13)) ? 13 \ + : ((x) & (1ul << 12)) ? 12 \ + : ((x) & (1ul << 11)) ? 11 \ + : ((x) & (1ul << 10)) ? 10 \ + : ((x) & (1ul << 9)) ? 9 \ + : ((x) & (1ul << 8)) ? 8 \ + : ((x) & (1ul << 7)) ? 7 \ + : ((x) & (1ul << 6)) ? 6 \ + : ((x) & (1ul << 5)) ? 5 \ + : ((x) & (1ul << 4)) ? 4 \ + : ((x) & (1ul << 3)) ? 3 \ + : ((x) & (1ul << 2)) ? 2 \ + : ((x) & (1ul << 1)) ? 1 \ + : 0) \ + : (31 - __builtin_clz(x)) + #define __USER__ __attribute__((section(".usrtext"))) inline static void diff --git a/lunaix-os/includes/lunaix/status.h b/lunaix-os/includes/lunaix/status.h index aeef93e..dd353fe 100644 --- a/lunaix-os/includes/lunaix/status.h +++ b/lunaix-os/includes/lunaix/status.h @@ -5,10 +5,17 @@ #define LXHEAPFULL -(2) #define LXINVLDPTR -(2) #define LXOUTOFMEM -(3) -#define LXINVLDPID -(4) #define LXSEGFAULT -(5) -#define LXINVL -(6) +#define EINVAL -(6) #define EINTR -(7) +#define EMFILE -8 +#define ENOENT -9 +#define ENAMETOOLONG -10 +#define ENOTDIR -11 +#define EEXIST -12 +#define EBADF -13 +#define ENOTSUP -14 + #endif /* __LUNAIX_CODE_H */ diff --git a/lunaix-os/includes/lunaix/syscall.h b/lunaix-os/includes/lunaix/syscall.h index 8e145e5..42bc85b 100644 --- a/lunaix-os/includes/lunaix/syscall.h +++ b/lunaix-os/includes/lunaix/syscall.h @@ -22,9 +22,19 @@ #define __SYSCALL_sigpending 17 #define __SYSCALL_sigsuspend 18 +#define __SYSCALL_open 19 +#define __SYSCALL_close 20 +#define __SYSCALL_read 21 +#define __SYSCALL_write 22 +#define __SYSCALL_readdir 23 +#define __SYSCALL_mkdir 24 + #define __SYSCALL_MAX 0x100 #ifndef __ASM__ + +#define SYSCALL_ESTATUS(errno) -(errno != 0) + void syscall_install(); diff --git a/lunaix-os/kernel/asm/x86/syscall.S b/lunaix-os/kernel/asm/x86/syscall.S index b13dee0..ab9e79f 100644 --- a/lunaix-os/kernel/asm/x86/syscall.S +++ b/lunaix-os/kernel/asm/x86/syscall.S @@ -26,6 +26,12 @@ .long __lxsys_alarm .long __lxsys_sigpending .long __lxsys_sigsuspend + .long __lxsys_open + .long __lxsys_close + // .long __lxsys_read + // .long __lxsys_write + .long __lxsys_readdir + .long __lxsys_mkdir 2: .rept __SYSCALL_MAX - (2b - 1b)/4 .long 0 diff --git a/lunaix-os/kernel/fs/fsm.c b/lunaix-os/kernel/fs/fsm.c index 95e12e3..10e766a 100644 --- a/lunaix-os/kernel/fs/fsm.c +++ b/lunaix-os/kernel/fs/fsm.c @@ -26,7 +26,7 @@ fsm_init() void fsm_register(struct filesystem* fs) { - hstr_rehash(&fs->fs_name, HASH_BUCKET_BITS); + hstr_rehash(&fs->fs_name, HSTR_FULL_HASH); hashtable_hash_in(fs_registry, &fs->fs_list, fs->fs_name.hash); } @@ -35,7 +35,7 @@ fsm_get(const char* fs_name) { struct filesystem *pos, *next; struct hstr str = HSTR(fs_name, 0); - hstr_rehash(&str, HASH_BUCKET_BITS); + hstr_rehash(&str, HSTR_FULL_HASH); hashtable_hash_foreach(fs_registry, str.hash, pos, next, fs_list) { diff --git a/lunaix-os/kernel/fs/twifs.c b/lunaix-os/kernel/fs/twifs.c index d24b6a0..a024c32 100644 --- a/lunaix-os/kernel/fs/twifs.c +++ b/lunaix-os/kernel/fs/twifs.c @@ -15,7 +15,7 @@ #include #include -static struct twifs_node fs_root; +static struct twifs_node* fs_root; static struct cake_pile* twi_pile; @@ -28,6 +28,12 @@ __twifs_openfile(struct v_inode* inode, struct v_file* file); struct twifs_node* __twifs_get_node(struct twifs_node* parent, struct hstr* name); +struct v_inode* +__twifs_create_inode(struct twifs_node* twi_node); + +int +__twifs_mount(struct v_superblock* vsb, struct v_dnode* mount_point); + void twifs_init() { @@ -39,8 +45,7 @@ twifs_init() fsm_register(twifs); - memset(&fs_root, 0, sizeof(fs_root)); - llist_init_head(&fs_root.children); + fs_root = twifs_dir_node(NULL, NULL, 0); // 预备一些常用的类别 twifs_toplevel_node("kernel", 6); @@ -49,7 +54,7 @@ twifs_init() } struct twifs_node* -twifs_child_node(struct twifs_node* parent, const char* name, int name_len) +__twifs_new_node(struct twifs_node* parent, const char* name, int name_len) { struct hstr hname = HSTR(name, name_len); hstr_rehash(&hname, HSTR_FULL_HASH); @@ -64,21 +69,57 @@ twifs_child_node(struct twifs_node* parent, const char* name, int name_len) node->name = hname; llist_init_head(&node->children); - llist_append(&parent->children, &node->siblings); + + if (parent) { + llist_append(&parent->children, &node->siblings); + } return node; } +struct twifs_node* +twifs_file_node(struct twifs_node* parent, const char* name, int name_len) +{ + struct twifs_node* twi_node = __twifs_new_node(parent, name, name_len); + twi_node->itype = VFS_INODE_TYPE_FILE; + + struct v_inode* twi_inode = __twifs_create_inode(twi_node); + twi_node->inode = twi_inode; + + return twi_inode; +} + +struct twifs_node* +twifs_dir_node(struct twifs_node* parent, const char* name, int name_len) +{ + struct twifs_node* twi_node = __twifs_new_node(parent, name, name_len); + twi_node->itype = VFS_INODE_TYPE_DIR; + + struct v_inode* twi_inode = __twifs_create_inode(twi_node); + struct twifs_node* dot = __twifs_new_node(twi_node, ".", 1); + struct twifs_node* ddot = __twifs_new_node(twi_node, "..", 2); + + dot->itype = VFS_INODE_TYPE_DIR; + ddot->itype = VFS_INODE_TYPE_DIR; + + twi_node->inode = twi_inode; + dot->inode = twi_inode; + ddot->inode = parent->inode; + + return twi_node; +} + struct twifs_node* twifs_toplevel_node(const char* name, int name_len) { - return twifs_child_node(&fs_root, name, name_len); + return twifs_dir_node(fs_root, name, name_len); } -void +int __twifs_mount(struct v_superblock* vsb, struct v_dnode* mount_point) { - mount_point->inode = __twifs_create_inode(&fs_root); + mount_point->inode = fs_root->inode; + return 0; } struct v_inode* @@ -94,11 +135,16 @@ __twifs_create_inode(struct twifs_node* twi_node) .ref_count = 0 }; inode->ops.dir_lookup = __twifs_dirlookup; inode->ops.open = __twifs_openfile; + + return inode; } struct twifs_node* __twifs_get_node(struct twifs_node* parent, struct hstr* name) { + if (!parent) + return NULL; + struct twifs_node *pos, *n; llist_for_each(pos, n, &parent->children, siblings) { @@ -116,10 +162,10 @@ __twifs_dirlookup(struct v_inode* inode, struct v_dnode* dnode) struct twifs_node* child_node = __twifs_get_node(twi_node, &dnode->name); if (child_node) { - dnode->inode = __twifs_create_inode(child_node); + dnode->inode = child_node->inode; return 0; } - return VFS_ENODIR; + return ENOENT; } int @@ -133,12 +179,13 @@ __twifs_iterate_dir(struct v_file* file, struct dir_context* dctx) { if (counter++ >= dctx->index) { dctx->index = counter; - dctx->read_complete_callback(dctx, pos->name.value, pos->itype); - return 0; + dctx->read_complete_callback( + dctx, pos->name.value, pos->name.len, pos->itype); + return 1; } } - return VFS_EENDOFDIR; + return 0; } int @@ -147,7 +194,7 @@ __twifs_openfile(struct v_inode* inode, struct v_file* file) struct twifs_node* twi_node = (struct twifs_node*)inode->data; if (twi_node) { file->ops = twi_node->fops; - return 1; + return 0; } - return 0; + return ENOTSUP; } diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index 4640dbd..902f21e 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -1,9 +1,24 @@ +/** + * @file vfs.c + * @author Lunaixsky (zelong56@gmail.com) + * @brief Lunaix virtual file system - an abstraction layer for all file system. + * @version 0.1 + * @date 2022-07-24 + * + * @copyright Copyright (c) 2022 + * + */ + #include +#include +#include #include #include #include #include +#include #include +#include #define PATH_DELIM '/' #define DNODE_HASHTABLE_BITS 10 @@ -15,6 +30,7 @@ static struct cake_pile* dnode_pile; static struct cake_pile* inode_pile; static struct cake_pile* file_pile; static struct cake_pile* superblock_pile; +static struct cake_pile* fd_pile; static struct v_superblock* root_sb; static struct hbucket* dnode_cache; @@ -39,16 +55,16 @@ vfs_init() // 为他们专门创建一个蛋糕堆,而不使用valloc,这样我们可以最小化内碎片的产生 dnode_pile = cake_new_pile("dnode_cache", sizeof(struct v_dnode), 1, 0); inode_pile = cake_new_pile("inode_cache", sizeof(struct v_inode), 1, 0); - inode_pile = cake_new_pile("file_cache", sizeof(struct v_file), 1, 0); + file_pile = cake_new_pile("file_cache", sizeof(struct v_file), 1, 0); + fd_pile = cake_new_pile("fd_cache", sizeof(struct v_fd), 1, 0); superblock_pile = cake_new_pile("sb_cache", sizeof(struct v_superblock), 1, 0); - dnode_cache = valloc(DNODE_HASHTABLE_SIZE * sizeof(struct hbucket)); + dnode_cache = vzalloc(DNODE_HASHTABLE_SIZE * sizeof(struct hbucket)); - // 挂载Lunaix的根文件系统,TwiFS! - struct filesystem* rootfs = fsm_get("twifs"); + // 创建一个根superblock,用来蕴含我们的根目录。 root_sb = vfs_sb_alloc(); - rootfs->mount(root_sb, NULL); + root_sb->root = vfs_d_alloc(); } inline struct hbucket* @@ -87,13 +103,14 @@ int vfs_walk(struct v_dnode* start, const char* path, struct v_dnode** dentry, + struct hstr* component, int walk_options) { int errno = 0; int i = 0, j = 0; if (path[0] == PATH_DELIM) { - if ((walk_options & VFS_WALK_FSRELATIVE)) { + if ((walk_options & VFS_WALK_FSRELATIVE) && start) { start = start->super_block->root; } else { start = root_sb->root; @@ -112,7 +129,7 @@ vfs_walk(struct v_dnode* start, lookahead = path[i++]; if (current != PATH_DELIM) { if (j >= VFS_NAME_MAXLEN - 1) { - return VFS_ETOOLONG; + return ENAMETOOLONG; } if (!VFS_VALID_CHAR(current)) { return VFS_EINVLD; @@ -131,6 +148,15 @@ vfs_walk(struct v_dnode* start, name_content[j] = 0; hstr_rehash(&name, HSTR_FULL_HASH); + if (!lookahead && (walk_options & VFS_WALK_PARENT)) { + if (component) { + component->hash = name.hash; + component->len = j; + strcpy(component->value, name_content); + } + break; + } + dnode = vfs_dcache_lookup(current_level, &name); if (!dnode) { @@ -143,16 +169,9 @@ vfs_walk(struct v_dnode* start, errno = current_level->inode->ops.dir_lookup(current_level->inode, dnode); - if (errno == VFS_ENOTFOUND && - ((walk_options & VFS_WALK_MKPARENT) || - ((walk_options & VFS_WALK_MKDIR) && !lookahead))) { - /* - 两种创建文件夹的情况: - 1) VFS_WALK_MKPARENT:沿路创建所有不存在的文件夹 - 2) VFS_WALK_MKDIR:仅创建路径最后一级的不存在文件夹 - */ + if (errno == ENOENT && (walk_options & VFS_WALK_MKPARENT)) { if (!current_level->inode->ops.mkdir) { - errno = VFS_ENOOPS; + errno = ENOTSUP; } else { errno = current_level->inode->ops.mkdir( current_level->inode, dnode); @@ -185,7 +204,33 @@ error: } int -vfs_mount(const char* fs_name, bdev_t device, struct v_dnode* mnt_point) +vfs_mount(const char* target, const char* fs_name, bdev_t device) +{ + int errno; + struct v_dnode* mnt; + + if (!(errno = vfs_walk(NULL, target, &mnt, NULL, 0))) { + errno = vfs_mount_at(fs_name, device, mnt); + } + + return errno; +} + +int +vfs_unmount(const char* target) +{ + int errno; + struct v_dnode* mnt; + + if (!(errno = vfs_walk(NULL, target, &mnt, NULL, 0))) { + errno = vfs_unmount_at(mnt); + } + + return errno; +} + +int +vfs_mount_at(const char* fs_name, bdev_t device, struct v_dnode* mnt_point) { struct filesystem* fs = fsm_get(fs_name); if (!fs) @@ -206,15 +251,7 @@ vfs_mount(const char* fs_name, bdev_t device, struct v_dnode* mnt_point) } int -vfs_mkdir(const char* parent_path, - const char* component, - struct v_dnode** dentry) -{ - return vfs_walk(root_sb->root, parent_path, dentry, VFS_WALK_MKDIR); -} - -int -vfs_unmount(struct v_dnode* mnt_point) +vfs_unmount_at(struct v_dnode* mnt_point) { int errno = 0; struct v_superblock* sb = mnt_point->super_block; @@ -234,7 +271,7 @@ int vfs_open(struct v_dnode* dnode, struct v_file** file) { if (!dnode->inode || !dnode->inode->ops.open) { - return VFS_ENOOPS; + return ENOTSUP; } struct v_file* vfile = cake_grab(file_pile); @@ -253,7 +290,7 @@ int vfs_close(struct v_file* file) { if (!file->ops.close) { - return VFS_ENOOPS; + return ENOTSUP; } int errno = file->ops.close(file); @@ -266,7 +303,7 @@ vfs_close(struct v_file* file) int vfs_fsync(struct v_file* file) { - int errno = VFS_ENOOPS; + int errno = ENOTSUP; if (file->ops.sync) { errno = file->ops.sync(file); } @@ -276,6 +313,18 @@ vfs_fsync(struct v_file* file) return errno; } +int +vfs_alloc_fdslot(int* fd) +{ + for (size_t i = 0; i < VFS_MAX_FD; i++) { + if (!__current->fdtable->fds[i]) { + *fd = i; + return 0; + } + } + return EMFILE; +} + struct v_superblock* vfs_sb_alloc() { @@ -321,3 +370,114 @@ vfs_i_free(struct v_inode* inode) { cake_release(inode_pile, inode); } + +__DEFINE_LXSYSCALL2(int, open, const char*, path, int, options) +{ + char name_str[VFS_NAME_MAXLEN]; + struct hstr name = HSTR(name_str, 0); + struct v_dnode *dentry, *file; + int errno, fd; + if ((errno = vfs_walk(NULL, path, &dentry, &name, VFS_WALK_PARENT))) { + return -1; + } + + struct v_file* opened_file = 0; + if (!(file = vfs_dcache_lookup(dentry, &name)) && (options & FO_CREATE)) { + errno = dentry->inode->ops.create(dentry->inode, opened_file); + } else if (!file) { + errno = EEXIST; + } else { + errno = vfs_open(file, &opened_file); + } + + __current->k_status = errno; + + if (!errno && !(errno = vfs_alloc_fdslot(&fd))) { + struct v_fd* fd_s = vzalloc(sizeof(*fd_s)); + fd_s->file = opened_file; + fd_s->pos = file->inode->fsize & -((options & FO_APPEND) == 0); + __current->fdtable->fds[fd] = fd_s; + } + + return SYSCALL_ESTATUS(errno); +} + +__DEFINE_LXSYSCALL1(int, close, int, fd) +{ + struct v_fd* fd_s; + int errno; + if (fd < 0 || fd >= VFS_MAX_FD || !(fd_s = __current->fdtable->fds[fd])) { + errno = EBADF; + } else if (!(errno = vfs_close(fd_s->file))) { + vfree(fd_s); + } + + __current->k_status = errno; + + return SYSCALL_ESTATUS(errno); +} + +void +__vfs_readdir_callback(struct dir_context* dctx, + const char* name, + const int len, + const int dtype) +{ + struct dirent* dent = (struct dirent*)dctx->cb_data; + strcpy(dent->d_name, name); + dent->d_nlen = len; + dent->d_type = dtype; +} + +__DEFINE_LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent) +{ + struct v_fd* fd_s; + int errno; + if (fd < 0 || fd >= VFS_MAX_FD || !(fd_s = __current->fdtable->fds[fd])) { + errno = EBADF; + } else if (!(fd_s->file->inode->itype & VFS_INODE_TYPE_DIR)) { + errno = ENOTDIR; + } else { + struct dir_context dctx = + (struct dir_context){ .cb_data = dent, + .index = dent->d_offset, + .read_complete_callback = + __vfs_readdir_callback }; + if (!(errno = fd_s->file->ops.readdir(fd_s->file, &dctx))) { + dent->d_offset++; + } + } + + __current->k_status = errno; + return SYSCALL_ESTATUS(errno); +} + +__DEFINE_LXSYSCALL1(int, mkdir, const char*, path) +{ + struct v_dnode *parent, *dir; + struct hstr component = HSTR(valloc(VFS_NAME_MAXLEN), 0); + int errno = + vfs_walk(root_sb->root, path, &parent, &component, VFS_WALK_PARENT); + if (errno) { + goto done; + } + + if (!parent->inode->ops.mkdir) { + errno = ENOTSUP; + } else if (!(parent->inode->itype & VFS_INODE_TYPE_DIR)) { + errno = ENOTDIR; + } else { + dir = vfs_d_alloc(); + dir->name = component; + if (!(errno = parent->inode->ops.mkdir(parent->inode, dir))) { + llist_append(&parent->children, &dir->siblings); + } else { + vfs_d_free(dir); + vfree(component.value); + } + } + +done: + __current->k_status = errno; + return SYSCALL_ESTATUS(errno); +} \ No newline at end of file diff --git a/lunaix-os/kernel/k_init.c b/lunaix-os/kernel/k_init.c index 7acd306..ffc287f 100644 --- a/lunaix-os/kernel/k_init.c +++ b/lunaix-os/kernel/k_init.c @@ -79,6 +79,9 @@ _kernel_init() { lxconsole_init(); + cake_init(); + valloc_init(); + kprintf(KINFO "[MM] Allocated %d pages for stack start at %p\n", KSTACK_SIZE >> PG_SIZE_BITS, KSTACK_START); diff --git a/lunaix-os/kernel/mm/cake.c b/lunaix-os/kernel/mm/cake.c index f6e4340..a64b3ea 100644 --- a/lunaix-os/kernel/mm/cake.c +++ b/lunaix-os/kernel/mm/cake.c @@ -76,10 +76,10 @@ __init_pile(struct cake_pile* pile, (piece_size + sizeof(piece_index_t)), .pg_per_cake = pg_per_cake }; - unsigned int overhead_size = - sizeof(struct cake_s) + pile->pieces_per_cake * sizeof(piece_index_t); + unsigned int free_list_size = pile->pieces_per_cake * sizeof(piece_index_t); - pile->offset = ROUNDUP(overhead_size, offset); + pile->offset = ROUNDUP(sizeof(struct cake_s) + free_list_size, offset); + pile->pieces_per_cake -= ICEIL((pile->offset - free_list_size), piece_size); strncpy(&pile->pile_name, name, PILE_NAME_MAXLEN); diff --git a/lunaix-os/kernel/mm/valloc.c b/lunaix-os/kernel/mm/valloc.c index 02384ef..5191a1a 100644 --- a/lunaix-os/kernel/mm/valloc.c +++ b/lunaix-os/kernel/mm/valloc.c @@ -2,42 +2,42 @@ #include #include -#define MAX_CLASS 6 +#define CLASS_LEN(class) (sizeof(class) / sizeof(class[0])) -static char piles_names[MAX_CLASS][PILE_NAME_MAXLEN] = { - "valloc_16", "valloc_32", "valloc_64", - "valloc_128", "valloc_256", "valloc_512" +static char piles_names[][PILE_NAME_MAXLEN] = { + "valloc_8", "valloc_16", "valloc_32", "valloc_64", "valloc_128", + "valloc_256", "valloc_512", "valloc_1k", "valloc_2k", "valloc_4k" }; -static char piles_names_dma[MAX_CLASS][PILE_NAME_MAXLEN] = { +static char piles_names_dma[][PILE_NAME_MAXLEN] = { "valloc_dma_128", "valloc_dma_256", "valloc_dma_512", "valloc_dma_1k", "valloc_dma_2k", "valloc_dma_4k" }; -static struct cake_pile* piles[MAX_CLASS]; -static struct cake_pile* piles_dma[MAX_CLASS]; +static struct cake_pile* piles[CLASS_LEN(piles_names)]; +static struct cake_pile* piles_dma[CLASS_LEN(piles_names_dma)]; void valloc_init() { - for (size_t i = 0; i < MAX_CLASS; i++) { - int size = 1 << (i + 4); - piles[i] = cake_new_pile(&piles_names[i], size, 1, 0); + for (size_t i = 0; i < CLASS_LEN(piles_names); i++) { + int size = 1 << (i + 3); + piles[i] = cake_new_pile(&piles_names[i], size, size > 1024 ? 4 : 1, 0); } // DMA 内存保证128字节对齐 - for (size_t i = 0; i < MAX_CLASS; i++) { + for (size_t i = 0; i < CLASS_LEN(piles_names_dma); i++) { int size = 1 << (i + 7); piles_dma[i] = cake_new_pile( - &piles_names_dma[i], size, size > 1024 ? 8 : 1, PILE_CACHELINE); + &piles_names_dma[i], size, size > 1024 ? 4 : 1, PILE_CACHELINE); } } void* -__valloc(unsigned int size, struct cake_pile** segregate_list) +__valloc(unsigned int size, struct cake_pile** segregate_list, size_t len) { size_t i = 0; - for (; i < MAX_CLASS; i++) { + for (; i < len; i++) { if (segregate_list[i]->piece_size >= size) { goto found_class; } @@ -50,10 +50,10 @@ found_class: } void -__vfree(void* ptr, struct cake_pile** segregate_list) +__vfree(void* ptr, struct cake_pile** segregate_list, size_t len) { size_t i = 0; - for (; i < MAX_CLASS; i++) { + for (; i < len; i++) { if (cake_release(segregate_list[i], ptr)) { return; } @@ -63,13 +63,13 @@ __vfree(void* ptr, struct cake_pile** segregate_list) void* valloc(unsigned int size) { - return __valloc(size, &piles); + return __valloc(size, &piles, CLASS_LEN(piles_names)); } void* vzalloc(unsigned int size) { - void* ptr = __valloc(size, &piles); + void* ptr = __valloc(size, &piles, CLASS_LEN(piles_names)); memset(ptr, 0, size); return ptr; } @@ -82,7 +82,7 @@ vcalloc(unsigned int size, unsigned int count) return 0; } - void* ptr = __valloc(alloc_size, &piles); + void* ptr = __valloc(alloc_size, &piles, CLASS_LEN(piles_names)); memset(ptr, 0, alloc_size); return ptr; } @@ -90,19 +90,19 @@ vcalloc(unsigned int size, unsigned int count) void vfree(void* ptr) { - __vfree(ptr, &piles); + __vfree(ptr, &piles, CLASS_LEN(piles_names)); } void* valloc_dma(unsigned int size) { - return __valloc(size, &piles_dma); + return __valloc(size, &piles_dma, CLASS_LEN(piles_names_dma)); } void* vzalloc_dma(unsigned int size) { - void* ptr = __valloc(size, &piles_dma); + void* ptr = __valloc(size, &piles_dma, CLASS_LEN(piles_names_dma)); memset(ptr, 0, size); return ptr; } @@ -110,5 +110,5 @@ vzalloc_dma(unsigned int size) void vfree_dma(void* ptr) { - __vfree(ptr, &piles_dma); + __vfree(ptr, &piles_dma, CLASS_LEN(piles_names_dma)); } \ No newline at end of file diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c index 36d8727..f2a8458 100644 --- a/lunaix-os/kernel/proc0.c +++ b/lunaix-os/kernel/proc0.c @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include #include @@ -119,26 +121,25 @@ void __test_disk_io() { struct hba_port* port = ahci_get_port(0); + struct hba_device* dev = port->device; char* buffer = vzalloc_dma(port->device->block_size); strcpy(buffer, test_sequence); kprintf("WRITE: %s\n", buffer); int result; // 写入第一扇区 (LBA=0) - result = - port->device->ops.write_buffer(port, 0, buffer, port->device->block_size); + result = dev->ops.write_buffer(dev, 0, buffer, dev->block_size); if (!result) { - kprintf(KWARN "fail to write: %x\n", port->device->last_error); + kprintf(KWARN "fail to write: %x\n", dev->last_error); } - memset(buffer, 0, port->device->block_size); + memset(buffer, 0, dev->block_size); // 读出我们刚刚写的内容! - result = - port->device->ops.read_buffer(port, 0, buffer, port->device->block_size); + result = dev->ops.read_buffer(dev, 0, buffer, dev->block_size); kprintf(KDEBUG "%x, %x\n", port->regs[HBA_RPxIS], port->regs[HBA_RPxTFD]); if (!result) { - kprintf(KWARN "fail to read: %x\n", port->device->last_error); + kprintf(KWARN "fail to read: %x\n", dev->last_error); } else { kprint_hex(buffer, 256); } @@ -152,10 +153,7 @@ init_platform() // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射 lock_reserved_memory(); - cake_init(); - assert_msg(kalloc_init(), "Fail to initialize heap"); - valloc_init(); acpi_init(_k_init_mb_info); apic_init(); @@ -165,11 +163,17 @@ init_platform() ps2_kbd_init(); pci_init(); ahci_init(); - ahci_list_device(); + // ahci_list_device(); + + fsm_init(); + vfs_init(); + twifs_init(); + + vfs_mount("/", "twifs", -1); - __test_disk_io(); + //__test_disk_io(); - cake_stats(); + // cake_stats(); syscall_install(); diff --git a/lunaix-os/kernel/process.c b/lunaix-os/kernel/process.c index a783efe..a9baaad 100644 --- a/lunaix-os/kernel/process.c +++ b/lunaix-os/kernel/process.c @@ -114,7 +114,7 @@ __DEFINE_LXSYSCALL2(int, setpgid, pid_t, pid, pid_t, pgid) struct proc_info* proc = pid ? get_process(pid) : __current; if (!proc) { - __current->k_status = LXINVL; + __current->k_status = EINVAL; return -1; } @@ -123,7 +123,7 @@ __DEFINE_LXSYSCALL2(int, setpgid, pid_t, pid, pid_t, pgid) struct proc_info* gruppenfuhrer = get_process(pgid); if (!gruppenfuhrer || proc->pgid == proc->pid) { - __current->k_status = LXINVL; + __current->k_status = EINVAL; return -1; } diff --git a/lunaix-os/kernel/sched.c b/lunaix-os/kernel/sched.c index 8e089d6..ee596b1 100644 --- a/lunaix-os/kernel/sched.c +++ b/lunaix-os/kernel/sched.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -267,6 +268,7 @@ alloc_process() proc->pid = i; proc->created = clock_systime(); proc->pgid = proc->pid; + proc->fdtable = vzalloc(sizeof(struct v_fdtable)); llist_init_head(&proc->mm.regions); llist_init_head(&proc->children); @@ -282,7 +284,7 @@ commit_process(struct proc_info* process) assert(process == &sched_ctx._procs[process->pid]); if (process->state != PS_CREATED) { - __current->k_status = LXINVL; + __current->k_status = EINVAL; return; } @@ -305,7 +307,7 @@ destroy_process(pid_t pid) { int index = pid; if (index <= 0 || index > sched_ctx.ptable_len) { - __current->k_status = LXINVLDPID; + __current->k_status = EINVAL; return; } struct proc_info* proc = &sched_ctx._procs[index]; diff --git a/lunaix-os/kernel/signal.c b/lunaix-os/kernel/signal.c index cb47e8d..db1d4ff 100644 --- a/lunaix-os/kernel/signal.c +++ b/lunaix-os/kernel/signal.c @@ -99,7 +99,7 @@ int signal_send(pid_t pid, int signum) { if (signum < 0 || signum >= _SIG_NUM) { - __current->k_status = LXINVL; + __current->k_status = EINVAL; return -1; } @@ -116,7 +116,7 @@ signal_send(pid_t pid, int signum) } else { // TODO: send to all process. // But I don't want to support it yet. - __current->k_status = LXINVL; + __current->k_status = EINVAL; return -1; } @@ -130,7 +130,7 @@ send_grp: send_single: if (PROC_TERMINATED(proc->state)) { - __current->k_status = LXINVL; + __current->k_status = EINVAL; return -1; } __SIGSET(proc->sig_pending, signum); diff --git a/lunaix-os/libs/crc.c b/lunaix-os/libs/crc.c index 75359d4..06ebbac 100644 --- a/lunaix-os/libs/crc.c +++ b/lunaix-os/libs/crc.c @@ -57,8 +57,7 @@ const unsigned int crc32_tab[] = { unsigned int crc32b(unsigned char* data, unsigned int size) { - int i = 0; - unsigned int crc = (unsigned int)-1; + unsigned int crc = (unsigned int)-1, i = 0; while (i < size) { crc = (crc >> 8) ^ crc32_tab[(crc ^ data[i]) & 0xff]; diff --git a/lunaix-os/libs/hash.c b/lunaix-os/libs/hash.c index 293ec67..c1580ed 100644 --- a/lunaix-os/libs/hash.c +++ b/lunaix-os/libs/hash.c @@ -11,10 +11,13 @@ uint32_t strhash_32(unsigned char* str, uint32_t truncate_to) { + if (!str) + return 0; + uint32_t hash = 5381; int c; - while (c = *str++) + while ((c = *str++)) hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ return hash >> (HASH_SIZE_BITS - truncate_to); -- 2.27.0