feat: implement fsync(2) and hard link support [link(2)]
authorMinep <zelong56@gmail.com>
Sun, 31 Jul 2022 14:21:25 +0000 (15:21 +0100)
committerMinep <zelong56@gmail.com>
Sun, 31 Jul 2022 14:21:25 +0000 (15:21 +0100)
chore: update readme
chore: re-organise the syscall to appropriate header file
chore: minor refactoring and code cleaning

12 files changed:
README.md
lunaix-os/includes/lunaix/ds/hstr.h
lunaix-os/includes/lunaix/fctrl.h
lunaix-os/includes/lunaix/fs.h
lunaix-os/includes/lunaix/lunistd.h
lunaix-os/includes/lunaix/status.h
lunaix-os/includes/lunaix/syscall.h
lunaix-os/kernel/asm/x86/syscall.S
lunaix-os/kernel/demos/dir_read.c
lunaix-os/kernel/demos/iotest.c
lunaix-os/kernel/fs/twifs.c
lunaix-os/kernel/fs/vfs.c

index 5edd52f62db2926ebfc9b7acf401e5f6d4c51a8e..de08a2ed0f214051112b851d069fc189deb7dba4 100644 (file)
--- 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自有
 
index 5fb84d94bc36f0354b0088d761f53ccea0c8df49..f3fa89efd39deb3f07504517766c58b433ee4a16 100644 (file)
@@ -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
index 2f58f0df1717bd08ec37d610a8df8111fcb75e61..b8bb08ff3ba4c891eb348223a8192dcaab3562df 100644 (file)
@@ -5,25 +5,13 @@
 #include <lunaix/syscall.h>
 #include <stddef.h>
 
-__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,
index fffb26f5cd07f69db888544436dc450d14e74e18..d233ff09e0289d05f84e2a3c9578254766b7b7bf 100644 (file)
@@ -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;
 };
 
index c16f2b09fc6d14c4c326dd7397805ba4fcbc09a0..9095c37dd2d2aefc5e063c83f29d7e6009a93a2f 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <lunaix/syscall.h>
 #include <lunaix/types.h>
+#include <stddef.h>
 
 __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 */
index d6cb3eb1d57bf6290a1e8474910efe5b7f5ce141..df1a1d8c3e0ff2f220af32ce2cacee2791a570ed 100644 (file)
@@ -23,5 +23,6 @@
 #define EROFS -18
 #define EISDIR -19
 #define EBUSY -20
+#define EXDEV -21
 
 #endif /* __LUNAIX_CODE_H */
index bccfb3bb5ec2ea67b559b1daa43a67fefed1d1bf..82986ab5f83783c73fe5acf75ba8c6ccbf1847dd 100644 (file)
 #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();
index 083f5ceec61ed9b552b6ac28c93fa999740427b0..be5660f1a8e7c78196bac1e0449f03fdb675b1bd 100644 (file)
@@ -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
index a0ef65f41ab542b777ad3fbf3842d67603af6e2f..bc4e024fd6701ed5b7b4f0aef40f152d3fceb44e 100644 (file)
@@ -1,5 +1,6 @@
 #include <lunaix/dirent.h>
 #include <lunaix/fctrl.h>
+#include <lunaix/lunistd.h>
 #include <lunaix/proc.h>
 #include <lunaix/syslog.h>
 
@@ -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);
 
index 2ddeb1a2f29c0593b54208d7d62785edcf2786ce..f51abcc230e5c552b275ecb8441c64ba560e8f28 100644 (file)
@@ -1,5 +1,6 @@
 #include <lunaix/fctrl.h>
 #include <lunaix/foptions.h>
+#include <lunaix/lunistd.h>
 #include <lunaix/proc.h>
 #include <lunaix/syslog.h>
 
index a67300b81548b37bed3e5840b8bd1de55524fd51..e3abe4b4c2a682577effbfd965c06ea15f318a91 100644 (file)
@@ -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()
 {
index 0fbf6529df93295f851e13b690f827479daa5d69..de08cec798db3118efa96f230ed3bde4650dd578 100644 (file)
@@ -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