feat: owloysius - dynamic init function invocator
[lunaix-os.git] / lunaix-os / kernel / fs / mount.c
index aa4acef20254d94cda3b2646d5392ec7c5078be6..96cc7418cec8a702573120a70b824d79fcaf89ac 100644 (file)
@@ -1,9 +1,15 @@
+#include <lunaix/foptions.h>
 #include <lunaix/fs.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/process.h>
 #include <lunaix/fs.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/process.h>
+#include <lunaix/spike.h>
+#include <lunaix/syscall_utils.h>
+#include <lunaix/syslog.h>
 #include <lunaix/types.h>
 
 #include <lunaix/types.h>
 
-static struct llist_header all_mnts = { .next = &all_mnts, .prev = &all_mnts };
+LOG_MODULE("fs")
+
+struct llist_header all_mnts = { .next = &all_mnts, .prev = &all_mnts };
 
 struct v_mount*
 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point)
 
 struct v_mount*
 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point)
@@ -17,17 +23,17 @@ vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point)
     llist_append(&all_mnts, &mnt->list);
     mutex_init(&mnt->lock);
 
     llist_append(&all_mnts, &mnt->list);
     mutex_init(&mnt->lock);
 
-    mnt_mkbusy(parent);
     mnt->parent = parent;
     mnt->mnt_point = mnt_point;
     mnt->super_block = mnt_point->super_block;
 
     if (parent) {
     mnt->parent = parent;
     mnt->mnt_point = mnt_point;
     mnt->super_block = mnt_point->super_block;
 
     if (parent) {
+        mnt_mkbusy(parent);
         mutex_lock(&mnt->parent->lock);
         llist_append(&parent->submnts, &mnt->sibmnts);
         mutex_unlock(&mnt->parent->lock);
     }
         mutex_lock(&mnt->parent->lock);
         llist_append(&parent->submnts, &mnt->sibmnts);
         mutex_unlock(&mnt->parent->lock);
     }
-
+    
     atomic_fetch_add(&mnt_point->ref_count, 1);
 
     return mnt;
     atomic_fetch_add(&mnt_point->ref_count, 1);
 
     return mnt;
@@ -58,7 +64,7 @@ __vfs_do_unmount(struct v_mount* mnt)
     mnt_chillax(mnt->parent);
 
     vfs_sb_free(sb);
     mnt_chillax(mnt->parent);
 
     vfs_sb_free(sb);
-    vfs_d_free(mnt->mnt_point);
+    atomic_fetch_sub(&mnt->mnt_point->ref_count, 1);
     vfree(mnt);
 
     return errno;
     vfree(mnt);
 
     return errno;
@@ -67,46 +73,42 @@ __vfs_do_unmount(struct v_mount* mnt)
 void
 mnt_mkbusy(struct v_mount* mnt)
 {
 void
 mnt_mkbusy(struct v_mount* mnt)
 {
-    while (mnt) {
-        mutex_lock(&mnt->lock);
-        mnt->busy_counter++;
-        mutex_unlock(&mnt->lock);
-
-        mnt = mnt->parent;
-    }
+    mutex_lock(&mnt->lock);
+    mnt->busy_counter++;
+    mutex_unlock(&mnt->lock);
 }
 
 void
 mnt_chillax(struct v_mount* mnt)
 {
 }
 
 void
 mnt_chillax(struct v_mount* mnt)
 {
-    while (mnt) {
-        mutex_lock(&mnt->lock);
-        mnt->busy_counter--;
-        mutex_unlock(&mnt->lock);
-
-        mnt = mnt->parent;
-    }
+    mutex_lock(&mnt->lock);
+    mnt->busy_counter--;
+    mutex_unlock(&mnt->lock);
 }
 
 int
 vfs_mount_root(const char* fs_name, struct device* device)
 {
 }
 
 int
 vfs_mount_root(const char* fs_name, struct device* device)
 {
+    extern struct v_dnode* vfs_sysroot;
     int errno = 0;
     if (vfs_sysroot->mnt && (errno = vfs_unmount_at(vfs_sysroot))) {
         return errno;
     }
     int errno = 0;
     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
 }
 
 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))) {
 {
     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;
     }
 
     return errno;
@@ -128,9 +130,14 @@ vfs_unmount(const char* target)
 int
 vfs_mount_at(const char* fs_name,
              struct device* device,
 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)) {
+    if (device && device->dev_type != DEV_IFVOL) {
+        return ENOTBLK;
+    }
+
+    if (mnt_point->inode && (mnt_point->inode->itype & F_MFILE)) {
         return ENOTDIR;
     }
 
         return ENOTDIR;
     }
 
@@ -139,13 +146,22 @@ vfs_mount_at(const char* fs_name,
         return ENODEV;
     }
 
         return ENODEV;
     }
 
+    if (fs->types == FSTYPE_ROFS) {
+        options |= MNT_RO;
+    }
+
+    char* dev_name = "sys";
     struct v_mount* parent_mnt = mnt_point->mnt;
     struct v_mount* parent_mnt = mnt_point->mnt;
-    struct v_superblock* sb = vfs_sb_alloc();
+    struct v_superblock *sb = vfs_sb_alloc(), *old_sb = mnt_point->super_block;
     sb->dev = device;
     sb->dev = device;
+    mnt_point->super_block = sb;
+
+    if (device) {
+        dev_name = device->name_val;
+    }
 
     int errno = 0;
     if (!(errno = fs->mount(sb, mnt_point))) {
 
     int errno = 0;
     if (!(errno = fs->mount(sb, mnt_point))) {
-        mnt_point->super_block = sb;
         sb->fs = fs;
         sb->root = mnt_point;
 
         sb->fs = fs;
         sb->root = mnt_point;
 
@@ -153,6 +169,10 @@ vfs_mount_at(const char* fs_name,
             errno = ENOMEM;
             goto cleanup;
         }
             errno = ENOMEM;
             goto cleanup;
         }
+
+        kprintf("mount: dev=%s, fs=%s, mode=%d", dev_name, fs_name, options);
+
+        mnt_point->mnt->flags = options;
     } else {
         goto cleanup;
     }
     } else {
         goto cleanup;
     }
@@ -160,6 +180,12 @@ vfs_mount_at(const char* fs_name,
     return errno;
 
 cleanup:
     return errno;
 
 cleanup:
+    ERROR("mount: dev=%s, fs=%s, mode=%d, err=%d",
+          dev_name,
+          fs_name,
+          options,
+          errno);
+    mnt_point->super_block = old_sb;
     vfs_sb_free(sb);
     return errno;
 }
     vfs_sb_free(sb);
     return errno;
 }
@@ -188,21 +214,31 @@ vfs_unmount_at(struct v_dnode* mnt_point)
     return errno;
 }
 
     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*,
                     mount,
                     const char*,
                     source,
                     const char*,
                     target,
                     const char*,
-                    fstype)
+                    fstype,
+                    int,
+                    options)
 {
 {
-    struct v_dnode *dev, *mnt;
+    struct v_dnode *dev = NULL, *mnt = NULL;
     int errno = 0;
 
     int errno = 0;
 
-    if ((errno = vfs_walk(__current->cwd, source, &dev, NULL, 0))) {
-        goto done;
-    }
+    // It is fine if source is not exist, as some mounting don't require it
+    vfs_walk(__current->cwd, source, &dev, NULL, 0);
 
     if ((errno = vfs_walk(__current->cwd, target, &mnt, NULL, 0))) {
         goto done;
 
     if ((errno = vfs_walk(__current->cwd, target, &mnt, NULL, 0))) {
         goto done;
@@ -215,14 +251,17 @@ __DEFINE_LXSYSCALL3(int,
 
     // By our convention.
     // XXX could we do better?
 
     // By our convention.
     // XXX could we do better?
-    struct device* device = (struct device*)dev->data;
+    struct device* device = NULL;
 
 
-    if (!(dev->inode->itype & VFS_IFVOLDEV) || !device) {
-        errno = ENOTDEV;
-        goto done;
+    if (dev) {
+        if (!(dev->inode->itype & VFS_IFVOLDEV)) {
+            errno = ENOTDEV;
+            goto done;
+        }
+        device = (struct device*)dev->inode->data;
     }
 
     }
 
-    errno = vfs_mount_at(fstype, device, mnt);
+    errno = vfs_mount_at(fstype, device, mnt, options);
 
 done:
     return DO_STATUS(errno);
 
 done:
     return DO_STATUS(errno);