feat: mount point flags check
authorMinep <zelong56@gmail.com>
Sat, 20 Aug 2022 18:48:37 +0000 (19:48 +0100)
committerMinep <zelong56@gmail.com>
Sat, 20 Aug 2022 18:48:37 +0000 (19:48 +0100)
refactor: eliminate edge case when try to access parent of root.
chore: minor refactoring, clean-up and small fixes.

lunaix-os/includes/lunaix/fctrl.h
lunaix-os/includes/lunaix/foptions.h
lunaix-os/includes/lunaix/fs.h
lunaix-os/includes/lunaix/status.h
lunaix-os/kernel/fs/mount.c
lunaix-os/kernel/fs/path_walk.c
lunaix-os/kernel/fs/vfs.c
lunaix-os/kernel/k_init.c

index 8a46058b8764e015edf8a657a0e18629ee454479..5ec0eef3d7891a6ad59c89db7ca59ec444842e93 100644 (file)
@@ -25,14 +25,16 @@ __LXSYSCALL4(int,
 
 __LXSYSCALL3(int, realpathat, int, fd, char*, buf, size_t, size)
 
-__LXSYSCALL3(int,
+__LXSYSCALL4(int,
              mount,
              const char*,
              source,
              const char*,
              target,
              const char*,
-             fstype)
+             fstype,
+             int,
+             options)
 
 __LXSYSCALL1(int, unmount, const char*, target)
 
index f43fb10fb884e500245fb88c72f847813895946e..0bb6ac4821a8951ac3258bc01cde2c4d93297266 100644 (file)
@@ -9,4 +9,6 @@
 #define FSEEK_CUR 0x2
 #define FSEEK_END 0x3
 
+#define MNT_RO 0x1
+
 #endif /* __LUNAIX_FOPTIONS_H */
index c86c6bc3aed5a27ecd7d8b6236a55fae40d5b9c6..099d47ed94378936e164f02f7566a22b80a66eba 100644 (file)
@@ -120,7 +120,7 @@ struct v_file_ops
     int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
     int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
     int (*readdir)(struct v_file* file, struct dir_context* dctx);
-    int (*seek)(struct v_inode* inode, size_t offset);
+    int (*seek)(struct v_inode* inode, size_t offset); // optional
     int (*close)(struct v_file* file);
     int (*sync)(struct v_file* file);
 };
@@ -140,9 +140,12 @@ struct v_inode_ops
     int (*rename)(struct v_inode* from_inode,
                   struct v_dnode* from_dnode,
                   struct v_dnode* to_dnode);
-    int (*getxattr)(struct v_inode* this, struct v_xattr_entry* entry);
-    int (*setxattr)(struct v_inode* this, struct v_xattr_entry* entry);
-    int (*delxattr)(struct v_inode* this, struct v_xattr_entry* entry);
+    int (*getxattr)(struct v_inode* this,
+                    struct v_xattr_entry* entry); // optional
+    int (*setxattr)(struct v_inode* this,
+                    struct v_xattr_entry* entry); // optional
+    int (*delxattr)(struct v_inode* this,
+                    struct v_xattr_entry* entry); // optional
 };
 
 struct v_xattr_entry
@@ -202,6 +205,7 @@ struct v_mount
     struct v_dnode* mnt_point;
     struct v_superblock* super_block;
     uint32_t busy_counter;
+    int flags;
 };
 
 struct v_dnode
@@ -291,7 +295,10 @@ vfs_walk_proc(const char* path,
               int options);
 
 int
-vfs_mount(const char* target, const char* fs_name, struct device* device);
+vfs_mount(const char* target,
+          const char* fs_name,
+          struct device* device,
+          int options);
 
 int
 vfs_unmount(const char* target);
@@ -299,7 +306,8 @@ vfs_unmount(const char* target);
 int
 vfs_mount_at(const char* fs_name,
              struct device* device,
-             struct v_dnode* mnt_point);
+             struct v_dnode* mnt_point,
+             int options);
 
 int
 vfs_unmount_at(struct v_dnode* mnt_point);
@@ -407,6 +415,9 @@ vfs_mount_root(const char* fs_name, struct device* device);
 struct v_mount*
 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point);
 
+int
+vfs_check_writable(struct v_dnode* dnode);
+
 int
 default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
 
index 2368156726bf615e31bffbb9312ea5fc9ee0a0c1..0e381b48a63d5e54dbca6abfa3f87fb5a81c3365 100644 (file)
@@ -28,5 +28,6 @@
 #define ERANGE -23
 #define ENOMEM LXOUTOFMEM
 #define ENOTDEV -24
+#define EOVERFLOW -25
 
 #endif /* __LUNAIX_CODE_H */
index aa4acef20254d94cda3b2646d5392ec7c5078be6..7b83757e91b26740ac43426bbda421934a226750 100644 (file)
@@ -1,3 +1,4 @@
+#include <lunaix/foptions.h>
 #include <lunaix/fs.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/process.h>
@@ -95,18 +96,21 @@ vfs_mount_root(const char* fs_name, struct device* device)
     if (vfs_sysroot->mnt && (errno = vfs_unmount_at(vfs_sysroot))) {
         return errno;
     }
-    return vfs_mount_at(fs_name, device, vfs_sysroot);
+    return vfs_mount_at(fs_name, device, vfs_sysroot, 0);
 }
 
 int
-vfs_mount(const char* target, const char* fs_name, struct device* device)
+vfs_mount(const char* target,
+          const char* fs_name,
+          struct device* device,
+          int options)
 {
     int errno;
     struct v_dnode* mnt;
 
     if (!(errno =
             vfs_walk(__current->cwd, target, &mnt, NULL, VFS_WALK_MKPARENT))) {
-        errno = vfs_mount_at(fs_name, device, mnt);
+        errno = vfs_mount_at(fs_name, device, mnt, options);
     }
 
     return errno;
@@ -128,7 +132,8 @@ vfs_unmount(const char* target)
 int
 vfs_mount_at(const char* fs_name,
              struct device* device,
-             struct v_dnode* mnt_point)
+             struct v_dnode* mnt_point,
+             int options)
 {
     if (mnt_point->inode && !(mnt_point->inode->itype & VFS_IFDIR)) {
         return ENOTDIR;
@@ -153,6 +158,8 @@ vfs_mount_at(const char* fs_name,
             errno = ENOMEM;
             goto cleanup;
         }
+
+        mnt_point->mnt->flags = options;
     } else {
         goto cleanup;
     }
@@ -188,14 +195,25 @@ vfs_unmount_at(struct v_dnode* mnt_point)
     return errno;
 }
 
-__DEFINE_LXSYSCALL3(int,
+int
+vfs_check_writable(struct v_dnode* dnode)
+{
+    if ((dnode->mnt->flags & MNT_RO)) {
+        return EROFS;
+    }
+    return 0;
+}
+
+__DEFINE_LXSYSCALL4(int,
                     mount,
                     const char*,
                     source,
                     const char*,
                     target,
                     const char*,
-                    fstype)
+                    fstype,
+                    int,
+                    options)
 {
     struct v_dnode *dev, *mnt;
     int errno = 0;
@@ -222,7 +240,7 @@ __DEFINE_LXSYSCALL3(int,
         goto done;
     }
 
-    errno = vfs_mount_at(fstype, device, mnt);
+    errno = vfs_mount_at(fstype, device, mnt, options);
 
 done:
     return DO_STATUS(errno);
index 0ffbabb84bb36fe1b763a6a2a23d6a69f9fffc41..ea5b1c59b4aa5da7e54d59d467d8875025ac632c 100644 (file)
@@ -21,7 +21,7 @@ __vfs_walk(struct v_dnode* start,
     int i = 0, j = 0;
 
     if (depth >= VFS_SYMLINK_DEPTH) {
-        return ENAMETOOLONG;
+        return ELOOP;
     }
 
     if (path[0] == VFS_PATH_DELIM || !start) {
@@ -36,6 +36,8 @@ __vfs_walk(struct v_dnode* start,
         i++;
     }
 
+    assert(start);
+
     struct v_dnode* dnode;
     struct v_inode* current_inode;
     struct v_dnode* current_level = start;
@@ -43,7 +45,7 @@ __vfs_walk(struct v_dnode* start,
     struct hstr name = HSTR(fname_buffer, 0);
 
     char current = path[i++], lookahead;
-    while (current && current_level) {
+    while (current) {
         lookahead = path[i++];
         if (current != VFS_PATH_DELIM) {
             if (j >= VFS_NAME_MAXLEN - 1) {
index a69803ef6a3be08d68e9ea2ad6d784b44c10b3b5..83bd0bd26a3271e6d2719e591d8ee9caa48a36e0 100644 (file)
@@ -104,6 +104,7 @@ vfs_init()
 
     // 创建一个根dnode。
     vfs_sysroot = vfs_d_alloc(NULL, &vfs_empty);
+    vfs_sysroot->parent = vfs_sysroot;
     atomic_fetch_add(&vfs_sysroot->ref_count, 1);
 }
 
@@ -126,7 +127,7 @@ vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str)
         return parent;
 
     if (HSTR_EQ(str, &vfs_ddot)) {
-        return parent->parent ? parent->parent : parent;
+        return parent->parent;
     }
 
     uint32_t hash = str->hash;
@@ -235,6 +236,10 @@ vfs_link(struct v_dnode* to_link, struct v_dnode* name)
 {
     int errno;
 
+    if ((errno = vfs_check_writable(to_link))) {
+        return errno;
+    }
+
     lock_inode(to_link->inode);
     if (to_link->super_block->root != name->super_block->root) {
         errno = EXDEV;
@@ -266,11 +271,16 @@ vfs_close(struct v_file* file)
 int
 vfs_fsync(struct v_file* file)
 {
+    int errno;
+    if ((errno = vfs_check_writable(file->dnode))) {
+        return errno;
+    }
+
     lock_inode(file->inode);
 
-    int errno = ENOTSUP;
     pcache_commit_all(file->inode);
 
+    errno = ENOTSUP;
     if (file->ops->sync) {
         errno = file->ops->sync(file);
     }
@@ -476,8 +486,7 @@ __vfs_try_locate_file(const char* path,
     char name_str[VFS_NAME_MAXLEN];
     struct hstr name = HSTR(name_str, 0);
     int errno;
-    if ((errno =
-           vfs_walk(__current->cwd, path, fdir, &name, VFS_WALK_PARENT))) {
+    if ((errno = vfs_walk_proc(path, fdir, &name, VFS_WALK_PARENT))) {
         return errno;
     }
 
@@ -663,6 +672,11 @@ __DEFINE_LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count)
     }
 
     struct v_file* file = fd_s->file;
+
+    if ((errno = vfs_check_writable(file->dnode))) {
+        goto done;
+    }
+
     if ((file->inode->itype & VFS_IFDIR)) {
         errno = EISDIR;
         goto done;
@@ -702,21 +716,30 @@ __DEFINE_LXSYSCALL3(int, lseek, int, fd, int, offset, int, options)
 
     struct v_file* file = fd_s->file;
 
+    if (!file->ops->seek) {
+        errno = ENOTSUP;
+        goto done;
+    }
+
     lock_inode(file->inode);
 
-    size_t fpos = file->f_pos;
+    int overflow = 0;
+    int fpos = file->f_pos;
     switch (options) {
         case FSEEK_CUR:
-            fpos = (size_t)((int)file->f_pos + offset);
+            overflow = __builtin_sadd_overflow((int)file->f_pos, offset, &fpos);
             break;
         case FSEEK_END:
-            fpos = (size_t)((int)file->inode->fsize + offset);
+            overflow =
+              __builtin_sadd_overflow((int)file->inode->fsize, offset, &fpos);
             break;
         case FSEEK_SET:
             fpos = offset;
             break;
     }
-    if (!(errno = file->ops->seek(file->inode, fpos))) {
+    if (overflow) {
+        errno = EOVERFLOW;
+    } else if (!(errno = file->ops->seek(file->inode, fpos))) {
         file->f_pos = fpos;
     }
 
@@ -729,12 +752,12 @@ done:
 int
 vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth)
 {
-    if (!dnode) {
+    if (!dnode || dnode->parent == dnode) {
         return 0;
     }
 
     if (depth > 64) {
-        return ELOOP;
+        return ENAMETOOLONG;
     }
 
     size_t len = vfs_get_path(dnode->parent, buf, size, depth + 1);
@@ -743,14 +766,12 @@ vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth)
         return len;
     }
 
+    buf[len++] = VFS_PATH_DELIM;
+
     size_t cpy_size = MIN(dnode->name.len, size - len);
     strncpy(buf + len, dnode->name.value, cpy_size);
     len += cpy_size;
 
-    if (len < size) {
-        buf[len++] = VFS_PATH_DELIM;
-    }
-
     return len;
 }
 
@@ -794,8 +815,7 @@ __DEFINE_LXSYSCALL3(int, readlink, const char*, path, char*, buf, size_t, size)
 {
     int errno;
     struct v_dnode* dnode;
-    if (!(errno =
-            vfs_walk(__current->cwd, path, &dnode, NULL, VFS_WALK_NOFOLLOW))) {
+    if (!(errno = vfs_walk_proc(path, &dnode, NULL, VFS_WALK_NOFOLLOW))) {
         errno = vfs_readlink(dnode, buf, size);
     }
 
@@ -849,12 +869,16 @@ __DEFINE_LXSYSCALL1(int, rmdir, const char*, pathname)
 {
     int errno;
     struct v_dnode* dnode;
-    if ((errno = vfs_walk(__current->cwd, pathname, &dnode, NULL, 0))) {
+    if ((errno = vfs_walk_proc(pathname, &dnode, NULL, 0))) {
         return DO_STATUS(errno);
     }
 
     lock_dnode(dnode);
 
+    if ((errno = vfs_check_writable(dnode))) {
+        goto done;
+    }
+
     if ((dnode->super_block->fs->types & FSTYPE_ROFS)) {
         errno = EROFS;
         goto done;
@@ -904,17 +928,18 @@ __DEFINE_LXSYSCALL1(int, mkdir, const char*, path)
     char name_value[VFS_NAME_MAXLEN];
     struct hstr name = HHSTR(name_value, 0, 0);
 
-    if (!dir) {
-        errno = ENOMEM;
+    if ((errno = vfs_walk_proc(path, &parent, &name, VFS_WALK_PARENT))) {
         goto done;
     }
 
-    if ((errno =
-           vfs_walk(__current->cwd, path, &parent, &name, VFS_WALK_PARENT))) {
+    if ((errno = vfs_check_writable(parent))) {
         goto done;
     }
 
-    dir = vfs_d_alloc(parent, &name);
+    if (!(dir = vfs_d_alloc(parent, &name))) {
+        errno = ENOMEM;
+        goto done;
+    }
 
     lock_dnode(parent);
     lock_inode(parent->inode);
@@ -942,15 +967,19 @@ done:
 int
 __vfs_do_unlink(struct v_dnode* dnode)
 {
+    int errno;
     struct v_inode* inode = dnode->inode;
 
     if (dnode->ref_count > 1) {
         return EBUSY;
     }
 
+    if ((errno = vfs_check_writable(dnode))) {
+        return errno;
+    }
+
     lock_inode(inode);
 
-    int errno;
     if (inode->open_count) {
         errno = EBUSY;
     } else if (!(inode->itype & VFS_IFDIR)) {
@@ -973,11 +1002,7 @@ __DEFINE_LXSYSCALL1(int, unlink, const char*, pathname)
 {
     int errno;
     struct v_dnode* dnode;
-    if ((errno = vfs_walk(__current->cwd, pathname, &dnode, NULL, 0))) {
-        goto done;
-    }
-    if ((dnode->super_block->fs->types & FSTYPE_ROFS)) {
-        errno = EROFS;
+    if ((errno = vfs_walk_proc(pathname, &dnode, NULL, 0))) {
         goto done;
     }
 
@@ -1026,6 +1051,7 @@ __DEFINE_LXSYSCALL1(int, fsync, int, fildes)
 {
     int errno;
     struct v_fd* fd_s;
+
     if (!(errno = vfs_getfd(fildes, &fd_s))) {
         errno = vfs_fsync(fd_s->file);
     }
@@ -1112,13 +1138,14 @@ __DEFINE_LXSYSCALL2(int,
 {
     int errno;
     struct v_dnode* dnode;
-    if ((errno = vfs_walk(__current->cwd, pathname, &dnode, NULL, 0))) {
+    if ((errno = vfs_walk_proc(pathname, &dnode, NULL, 0))) {
         goto done;
     }
-    if ((dnode->super_block->fs->types & FSTYPE_ROFS)) {
-        errno = EROFS;
+
+    if (errno = vfs_check_writable(dnode)) {
         goto done;
     }
+
     if (!dnode->inode->ops->set_symlink) {
         errno = ENOTSUP;
         goto done;
@@ -1166,7 +1193,7 @@ __DEFINE_LXSYSCALL1(int, chdir, const char*, path)
     struct v_dnode* dnode;
     int errno = 0;
 
-    if ((errno = vfs_walk(__current->cwd, path, &dnode, NULL, 0))) {
+    if ((errno = vfs_walk_proc(path, &dnode, NULL, 0))) {
         goto done;
     }
 
@@ -1225,11 +1252,16 @@ done:
 int
 vfs_do_rename(struct v_dnode* current, struct v_dnode* target)
 {
+    int errno = 0;
     if (current->inode->id == target->inode->id) {
         // hard link
         return 0;
     }
 
+    if (errno = vfs_check_writable(current)) {
+        return errno;
+    }
+
     if (current->ref_count > 1 || target->ref_count > 1) {
         return EBUSY;
     }
@@ -1238,8 +1270,6 @@ vfs_do_rename(struct v_dnode* current, struct v_dnode* target)
         return EXDEV;
     }
 
-    int errno = 0;
-
     struct v_dnode* oldparent = current->parent;
     struct v_dnode* newparent = target->parent;
 
@@ -1287,7 +1317,7 @@ __DEFINE_LXSYSCALL2(int, rename, const char*, oldpath, const char*, newpath)
     struct hstr name = HSTR(valloc(VFS_NAME_MAXLEN), 0);
     int errno = 0;
 
-    if ((errno = vfs_walk(__current->cwd, oldpath, &cur, NULL, 0))) {
+    if ((errno = vfs_walk_proc(oldpath, &cur, NULL, 0))) {
         goto done;
     }
 
index 1682859fe766e7ba78ede2f04376578a6eaa7bac..30e06ca731f1d8ee96d2c413c3a8894a852e0303 100644 (file)
@@ -2,6 +2,7 @@
 #include <lunaix/tty/tty.h>
 
 #include <lunaix/device.h>
+#include <lunaix/foptions.h>
 #include <lunaix/lxconsole.h>
 #include <lunaix/mm/page.h>
 #include <lunaix/mm/pmm.h>
@@ -81,7 +82,7 @@ _kernel_init()
     }
 
     // FIXME replace with more specific fs for device.
-    vfs_mount("/dev", "twifs", NULL);
+    vfs_mount("/dev", "twifs", NULL, MNT_RO);
 
     lxconsole_init();