From ac9c5346f3f10ac7adf3772521fa4d18f17c97c7 Mon Sep 17 00:00:00 2001 From: Minep Date: Sun, 31 Jul 2022 15:21:25 +0100 Subject: [PATCH] feat: implement fsync(2) and hard link support [link(2)] chore: update readme chore: re-organise the syscall to appropriate header file chore: minor refactoring and code cleaning --- README.md | 4 +- lunaix-os/includes/lunaix/ds/hstr.h | 6 ++ lunaix-os/includes/lunaix/fctrl.h | 14 +-- lunaix-os/includes/lunaix/fs.h | 19 ++-- lunaix-os/includes/lunaix/lunistd.h | 17 ++++ lunaix-os/includes/lunaix/status.h | 1 + lunaix-os/includes/lunaix/syscall.h | 4 +- lunaix-os/kernel/asm/x86/syscall.S | 2 + lunaix-os/kernel/demos/dir_read.c | 17 ++-- lunaix-os/kernel/demos/iotest.c | 1 + lunaix-os/kernel/fs/twifs.c | 3 + lunaix-os/kernel/fs/vfs.c | 139 ++++++++++++++++++++-------- 12 files changed, 154 insertions(+), 73 deletions(-) diff --git a/README.md b/README.md index 5edd52f..de08a2e 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ LunaixOS - 一个简单的,详细的,POSIX兼容的(但愿!),带有 + 内存管理与按需分页(Demand Paging) + 键盘输入 + 多进程 -+ 二十多个常见的Linux/POSIX系统调用([附录1](#appendix1)) ++ 31个常见的Linux/POSIX系统调用([附录1](#appendix1)) + 用户模式 + 信号机制 + PCI 3.0 @@ -178,6 +178,8 @@ qemu-img create -f vdi machine/disk1.vdi 128M 2. `rmdir(2)` 2. `unlink(2)` 2. `unlinkat(2)` +2. `link(2)` +2. `fsync(2)` ### LunaixOS自有 diff --git a/lunaix-os/includes/lunaix/ds/hstr.h b/lunaix-os/includes/lunaix/ds/hstr.h index 5fb84d9..f3fa89e 100644 --- a/lunaix-os/includes/lunaix/ds/hstr.h +++ b/lunaix-os/includes/lunaix/ds/hstr.h @@ -18,6 +18,12 @@ struct hstr .len = (length), .value = (str) \ } +#define HHSTR(str, length, strhash) \ + (struct hstr) \ + { \ + .len = (length), .value = (str), .hash = (strhash) \ + } + #define HSTR_EQ(str1, str2) ((str1)->hash == (str2)->hash) inline void diff --git a/lunaix-os/includes/lunaix/fctrl.h b/lunaix-os/includes/lunaix/fctrl.h index 2f58f0d..b8bb08f 100644 --- a/lunaix-os/includes/lunaix/fctrl.h +++ b/lunaix-os/includes/lunaix/fctrl.h @@ -5,25 +5,13 @@ #include #include -__LXSYSCALL2(int, open, const char*, path, int, options); - -__LXSYSCALL1(int, close, int, fd); +__LXSYSCALL2(int, open, const char*, path, int, options) __LXSYSCALL1(int, mkdir, const char*, path); -__LXSYSCALL1(int, rmdir, const char*, pathname); -__LXSYSCALL1(int, unlink, const char*, pathname); __LXSYSCALL2(int, unlinkat, int, fd, const char*, pathname); __LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent); -__LXSYSCALL3(int, lseek, int, fd, int, offset, int, options); - -__LXSYSCALL3(int, read, int, fd, void*, buf, unsigned int, count); - -__LXSYSCALL3(int, write, int, fd, void*, buf, unsigned int, count); - -__LXSYSCALL3(int, readlink, const char*, path, char*, buf, size_t, size); - __LXSYSCALL4(int, readlinkat, int, diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index fffb26f..d233ff0 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -13,7 +13,8 @@ #define VFS_INODE_TYPE_DIR 0x1 #define VFS_INODE_TYPE_FILE 0x2 -#define VFS_INODE_TYPE_DEVICE 0x3 +#define VFS_INODE_TYPE_DEVICE 0x4 +#define VFS_INODE_TYPE_SYMLINK 0x8 #define VFS_ENOFS -2 #define VFS_EBADMNT -3 @@ -109,18 +110,20 @@ struct v_inode uint32_t mtime; uint64_t lb_addr; uint32_t open_count; + uint32_t link_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); - int (*rmdir)(struct v_inode* inode); - int (*unlink)(struct v_inode* inode); - int (*dir_lookup)(struct v_inode* inode, struct v_dnode* dnode); + int (*create)(struct v_inode* this, struct v_file* file); + int (*open)(struct v_inode* this, struct v_file* file); + int (*sync)(struct v_inode* this); + int (*mkdir)(struct v_inode* this, struct v_dnode* dnode); + int (*rmdir)(struct v_inode* this); + int (*unlink)(struct v_inode* this); + int (*link)(struct v_inode* this, struct v_dnode* new_name); + int (*dir_lookup)(struct v_inode* this, struct v_dnode* dnode); } ops; }; diff --git a/lunaix-os/includes/lunaix/lunistd.h b/lunaix-os/includes/lunaix/lunistd.h index c16f2b0..9095c37 100644 --- a/lunaix-os/includes/lunaix/lunistd.h +++ b/lunaix-os/includes/lunaix/lunistd.h @@ -3,6 +3,7 @@ #include #include +#include __LXSYSCALL(pid_t, fork) @@ -24,4 +25,20 @@ __LXSYSCALL2(int, kill, pid_t, pid, int, signum) __LXSYSCALL1(unsigned int, alarm, unsigned int, seconds) +__LXSYSCALL2(int, link, const char*, oldpath, const char*, newpath) + +__LXSYSCALL1(int, rmdir, const char*, pathname) + +__LXSYSCALL3(int, read, int, fd, void*, buf, unsigned int, count) + +__LXSYSCALL3(int, write, int, fd, void*, buf, unsigned int, count) + +__LXSYSCALL3(int, readlink, const char*, path, char*, buf, size_t, size) + +__LXSYSCALL3(int, lseek, int, fd, int, offset, int, options) + +__LXSYSCALL1(int, unlink, const char*, pathname) + +__LXSYSCALL1(int, close, int, fd) + #endif /* __LUNAIX_UNISTD_H */ diff --git a/lunaix-os/includes/lunaix/status.h b/lunaix-os/includes/lunaix/status.h index d6cb3eb..df1a1d8 100644 --- a/lunaix-os/includes/lunaix/status.h +++ b/lunaix-os/includes/lunaix/status.h @@ -23,5 +23,6 @@ #define EROFS -18 #define EISDIR -19 #define EBUSY -20 +#define EXDEV -21 #endif /* __LUNAIX_CODE_H */ diff --git a/lunaix-os/includes/lunaix/syscall.h b/lunaix-os/includes/lunaix/syscall.h index bccfb3b..82986ab 100644 --- a/lunaix-os/includes/lunaix/syscall.h +++ b/lunaix-os/includes/lunaix/syscall.h @@ -35,12 +35,14 @@ #define __SYSCALL_rmdir 29 #define __SYSCALL_unlink 30 #define __SYSCALL_unlinkat 31 +#define __SYSCALL_link 32 +#define __SYSCALL_fsync 33 #define __SYSCALL_MAX 0x100 #ifndef __ASM__ -#define SYSCALL_ESTATUS(errno) -(errno != 0) +#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 083f5ce..be5660f 100644 --- a/lunaix-os/kernel/asm/x86/syscall.S +++ b/lunaix-os/kernel/asm/x86/syscall.S @@ -39,6 +39,8 @@ .long __lxsys_rmdir .long __lxsys_unlink /* 30 */ .long __lxsys_unlinkat + .long __lxsys_link + .long __lxsys_fsync 2: .rept __SYSCALL_MAX - (2b - 1b)/4 .long 0 diff --git a/lunaix-os/kernel/demos/dir_read.c b/lunaix-os/kernel/demos/dir_read.c index a0ef65f..bc4e024 100644 --- a/lunaix-os/kernel/demos/dir_read.c +++ b/lunaix-os/kernel/demos/dir_read.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -14,22 +15,20 @@ _readdir_main() return; } - struct dirent ent = { .d_offset = 0 }; - - while (!readdir(fd, &ent)) { - kprintf(KINFO "%s\n", ent.d_name); - } - char path[129]; - int len = readlinkat(fd, ".", path, 128); if (len < 0) { kprintf(KERROR "fail to read (%d)\n", geterrno()); + } else { + path[len] = 0; + kprintf("%s\n", path); } - path[len] = 0; + struct dirent ent = { .d_offset = 0 }; - kprintf("%s\n", path); + while (!readdir(fd, &ent)) { + kprintf(KINFO "%s\n", ent.d_name); + } close(fd); diff --git a/lunaix-os/kernel/demos/iotest.c b/lunaix-os/kernel/demos/iotest.c index 2ddeb1a..f51abcc 100644 --- a/lunaix-os/kernel/demos/iotest.c +++ b/lunaix-os/kernel/demos/iotest.c @@ -1,5 +1,6 @@ #include #include +#include #include #include diff --git a/lunaix-os/kernel/fs/twifs.c b/lunaix-os/kernel/fs/twifs.c index a67300b..e3abe4b 100644 --- a/lunaix-os/kernel/fs/twifs.c +++ b/lunaix-os/kernel/fs/twifs.c @@ -40,6 +40,9 @@ __twifs_mount(struct v_superblock* vsb, struct v_dnode* mount_point); int __twifs_mkdir(struct v_inode* inode, struct v_dnode* dnode); +int +__twifs_rmstuff(struct v_inode* inode); + void twifs_init() { diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index 0fbf652..de08cec 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -176,8 +176,7 @@ vfs_walk(struct v_dnode* start, if (!dnode) { dnode = vfs_d_alloc(); - dnode->name = HSTR(valloc(VFS_NAME_MAXLEN), j); - dnode->name.hash = name.hash; + dnode->name = HHSTR(valloc(VFS_NAME_MAXLEN), j, name.hash); strcpy(dnode->name.value, name_content); @@ -306,6 +305,22 @@ vfs_open(struct v_dnode* dnode, struct v_file** file) return errno; } +int +vfs_link(struct v_dnode* to_link, struct v_dnode* name) +{ + int errno; + if (to_link->super_block->root != name->super_block->root) { + errno = EXDEV; + } else if (!to_link->inode->ops.link) { + errno = ENOTSUP; + } else if (!(errno = to_link->inode->ops.link(to_link->inode, name))) { + name->inode = to_link->inode; + to_link->inode->link_count++; + } + + return errno; +} + int vfs_close(struct v_file* file) { @@ -399,27 +414,48 @@ vfs_i_free(struct v_inode* inode) /* ---- System call definition and support ---- */ +#define FLOCATE_CREATE_EMPTY 1 + +#define DO_STATUS(errno) SYSCALL_ESTATUS(__current->k_status = errno) + int -__vfs_do_open(struct v_file** file_out, const char* path, int options) +__vfs_try_locate_file(const char* path, + struct v_dnode** fdir, + struct v_dnode** file, + int options) { char name_str[VFS_NAME_MAXLEN]; struct hstr name = HSTR(name_str, 0); - struct v_dnode *dentry, *file; int errno; - if ((errno = vfs_walk(NULL, path, &dentry, &name, VFS_WALK_PARENT))) { - return ENOENT; + if (!(errno = vfs_walk(NULL, path, fdir, &name, VFS_WALK_PARENT))) { + errno = vfs_walk(*fdir, name.value, file, NULL, 0); + if (errno == ENOENT && (options & FLOCATE_CREATE_EMPTY)) { + struct v_dnode* file_new; + file_new = vfs_d_alloc(); + file_new->name = + HHSTR(valloc(VFS_NAME_MAXLEN), name.len, name.hash); + strcpy(file_new->name.value, name_str); + *file = file_new; + + llist_append(&(*fdir)->children, &file_new->siblings); + } } - vfs_walk(dentry, name.value, &file, NULL, 0); + return errno; +} +int +__vfs_do_open(struct v_file** file_out, const char* path, int options) +{ + int errno; + struct v_dnode *dentry, *file; struct v_file* opened_file = 0; - if (!file) { - if ((options & FO_CREATE)) { - errno = dentry->inode->ops.create(dentry->inode, opened_file); - } else { - errno = ENOENT; - } - } else { + + errno = __vfs_try_locate_file(path, &dentry, &file, 0); + + if (errno != ENOENT && (options & FO_CREATE)) { + errno = dentry->inode->ops.create(dentry->inode, opened_file); + } else if (!errno) { errno = vfs_open(file, &opened_file); } @@ -440,8 +476,7 @@ __DEFINE_LXSYSCALL2(int, open, const char*, path, int, options) return fd; } - __current->k_status = errno; - return SYSCALL_ESTATUS(errno); + return DO_STATUS(errno); } #define GET_FD(fd, fd_s) \ @@ -458,9 +493,7 @@ __DEFINE_LXSYSCALL1(int, close, int, fd) __current->fdtable->fds[fd] = 0; } - __current->k_status = errno; - - return SYSCALL_ESTATUS(errno); + return DO_STATUS(errno); } void @@ -504,8 +537,7 @@ __DEFINE_LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent) } done: - __current->k_status = errno; - return SYSCALL_ESTATUS(errno); + return DO_STATUS(errno); } __DEFINE_LXSYSCALL1(int, mkdir, const char*, path) @@ -535,8 +567,7 @@ __DEFINE_LXSYSCALL1(int, mkdir, const char*, path) } done: - __current->k_status = errno; - return SYSCALL_ESTATUS(errno); + return DO_STATUS(errno); } __DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count) @@ -553,8 +584,7 @@ __DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count) } } - __current->k_status = errno; - return SYSCALL_ESTATUS(errno); + return DO_STATUS(errno); } __DEFINE_LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count) @@ -571,8 +601,7 @@ __DEFINE_LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count) } } - __current->k_status = errno; - return SYSCALL_ESTATUS(errno); + return DO_STATUS(errno); } __DEFINE_LXSYSCALL3(int, lseek, int, fd, int, offset, int, options) @@ -600,8 +629,7 @@ __DEFINE_LXSYSCALL3(int, lseek, int, fd, int, offset, int, options) fd_s->pos = fpos; } - __current->k_status = errno; - return SYSCALL_ESTATUS(errno); + return DO_STATUS(errno); } int @@ -644,8 +672,7 @@ __DEFINE_LXSYSCALL3(int, readlink, const char*, path, char*, buf, size_t, size) return errno; } - __current->k_status = errno; - return SYSCALL_ESTATUS(errno); + return DO_STATUS(errno); } __DEFINE_LXSYSCALL4(int, @@ -674,8 +701,7 @@ __DEFINE_LXSYSCALL4(int, return errno; } - __current->k_status = errno; - return SYSCALL_ESTATUS(errno); + return DO_STATUS(errno); } __DEFINE_LXSYSCALL1(int, rmdir, const char*, pathname) @@ -695,15 +721,14 @@ __DEFINE_LXSYSCALL1(int, rmdir, const char*, pathname) goto done; } - if (dnode->inode->itype == VFS_INODE_TYPE_DIR) { + if ((dnode->inode->itype & VFS_INODE_TYPE_DIR)) { errno = dnode->inode->ops.rmdir(dnode->inode); } else { errno = ENOTDIR; } done: - __current->k_status = errno; - return SYSCALL_ESTATUS(errno); + return DO_STATUS(errno); } int @@ -712,9 +737,12 @@ __vfs_do_unlink(struct v_inode* inode) int errno; if (inode->open_count) { errno = EBUSY; - } else if (inode->itype != VFS_INODE_TYPE_DIR) { + } else if (!(inode->itype & VFS_INODE_TYPE_DIR)) { // TODO handle symbolic link and type other than regular file errno = inode->ops.unlink(inode); + if (!errno) { + inode->link_count--; + } } else { errno = EISDIR; } @@ -737,8 +765,7 @@ __DEFINE_LXSYSCALL1(int, unlink, const char*, pathname) errno = __vfs_do_unlink(dnode->inode); done: - __current->k_status = errno; - return SYSCALL_ESTATUS(errno); + return DO_STATUS(errno); } __DEFINE_LXSYSCALL2(int, unlinkat, int, fd, const char*, pathname) @@ -755,6 +782,36 @@ __DEFINE_LXSYSCALL2(int, unlinkat, int, fd, const char*, pathname) } done: - __current->k_status = errno; - return SYSCALL_ESTATUS(errno); + return DO_STATUS(errno); +} + +__DEFINE_LXSYSCALL2(int, link, const char*, oldpath, const char*, newpath) +{ + int errno; + struct v_dnode *dentry, *to_link, *name_dentry, *name_file; + + errno = __vfs_try_locate_file(oldpath, &dentry, &to_link, 0); + if (!errno) { + errno = __vfs_try_locate_file( + newpath, &name_dentry, &name_file, FLOCATE_CREATE_EMPTY); + if (!errno) { + errno = EEXIST; + } else if (name_file) { + errno = vfs_link(to_link, name_file); + } + } + return DO_STATUS(errno); +} + +__DEFINE_LXSYSCALL1(int, fsync, int, fildes) +{ + int errno; + struct v_fd* fd_s; + if (!GET_FD(fildes, fd_s)) { + errno = EBADF; + } else { + errno = vfs_fsync(fd_s->file); + } + + return DO_STATUS(errno); } \ No newline at end of file -- 2.27.0