Second Extended Filesystem (ext2) and other improvements (#33)
[lunaix-os.git] / lunaix-os / kernel / fs / mount.c
index 2b996d413c8b304dfb6e7efc71454ddbd9a8c226..c5b7344be4f2723f45961f53705a10c395f67fe0 100644 (file)
@@ -1,5 +1,5 @@
 #include <lunaix/foptions.h>
 #include <lunaix/foptions.h>
-#include <lunaix/fs.h>
+#include <lunaix/fs/api.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/process.h>
 #include <lunaix/spike.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/process.h>
 #include <lunaix/spike.h>
@@ -25,7 +25,7 @@ vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point)
 
     mnt->parent = parent;
     mnt->mnt_point = mnt_point;
 
     mnt->parent = parent;
     mnt->mnt_point = mnt_point;
-    mnt->super_block = mnt_point->super_block;
+    vfs_vmnt_assign_sb(mnt, mnt_point->super_block);
 
     if (parent) {
         mnt_mkbusy(parent);
 
     if (parent) {
         mnt_mkbusy(parent);
@@ -39,6 +39,21 @@ vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point)
     return mnt;
 }
 
     return mnt;
 }
 
+void
+__vfs_release_vmnt(struct v_mount* mnt)
+{
+    assert(llist_empty(&mnt->submnts));
+
+    if (mnt->parent) {
+        mnt_chillax(mnt->parent);
+    }
+
+    llist_delete(&mnt->sibmnts);
+    llist_delete(&mnt->list);
+    atomic_fetch_sub(&mnt->mnt_point->ref_count, 1);
+    vfree(mnt);
+}
+
 int
 __vfs_do_unmount(struct v_mount* mnt)
 {
 int
 __vfs_do_unmount(struct v_mount* mnt)
 {
@@ -49,9 +64,6 @@ __vfs_do_unmount(struct v_mount* mnt)
         return errno;
     }
 
         return errno;
     }
 
-    llist_delete(&mnt->list);
-    llist_delete(&mnt->sibmnts);
-
     // detached the inodes from cache, and let lru policy to recycle them
     for (size_t i = 0; i < VFS_HASHTABLE_SIZE; i++) {
         struct hbucket* bucket = &sb->i_cache[i];
     // detached the inodes from cache, and let lru policy to recycle them
     for (size_t i = 0; i < VFS_HASHTABLE_SIZE; i++) {
         struct hbucket* bucket = &sb->i_cache[i];
@@ -61,13 +73,10 @@ __vfs_do_unmount(struct v_mount* mnt)
         bucket->head->pprev = 0;
     }
 
         bucket->head->pprev = 0;
     }
 
-    mnt_chillax(mnt->parent);
-
     mnt->mnt_point->mnt = mnt->parent;
 
     vfs_sb_free(sb);
     mnt->mnt_point->mnt = mnt->parent;
 
     vfs_sb_free(sb);
-    atomic_fetch_sub(&mnt->mnt_point->ref_count, 1);
-    vfree(mnt);
+    __vfs_release_vmnt(mnt);
 
     return errno;
 }
 
     return errno;
 }
@@ -139,7 +148,7 @@ vfs_mount_at(const char* fs_name,
         return ENOTBLK;
     }
 
         return ENOTBLK;
     }
 
-    if (mnt_point->inode && (mnt_point->inode->itype & F_MFILE)) {
+    if (mnt_point->inode && !check_directory_node(mnt_point->inode)) {
         return ENOTDIR;
     }
 
         return ENOTDIR;
     }
 
@@ -148,47 +157,55 @@ vfs_mount_at(const char* fs_name,
         return ENODEV;
     }
 
         return ENODEV;
     }
 
-    if (fs->types == FSTYPE_ROFS) {
+    if ((fs->types & FSTYPE_ROFS)) {
         options |= MNT_RO;
     }
 
         options |= MNT_RO;
     }
 
+    if (!(fs->types & FSTYPE_PSEUDO) && !device) {
+        return ENODEV;
+    }
+
+    int errno = 0;
     char* dev_name = "sys";
     struct v_mount* parent_mnt = mnt_point->mnt;
     char* dev_name = "sys";
     struct v_mount* parent_mnt = mnt_point->mnt;
-    struct v_superblock *sb = vfs_sb_alloc(), *old_sb = mnt_point->super_block;
-    sb->dev = device;
-    mnt_point->super_block = sb;
+    struct v_superblock *sb = vfs_sb_alloc(), 
+                        *old_sb = mnt_point->super_block;
 
     if (device) {
         dev_name = device->name_val;
     }
 
 
     if (device) {
         dev_name = device->name_val;
     }
 
-    int errno = 0;
-    if (!(errno = fs->mount(sb, mnt_point))) {
-        sb->fs = fs;
-        sb->root = mnt_point;
+    // prepare v_superblock for fs::mount invoke
+    sb->dev = device;
+    sb->fs = fs;
+    sb->root = mnt_point;
+    vfs_d_assign_sb(mnt_point, sb);
 
 
-        if (!(mnt_point->mnt = vfs_create_mount(parent_mnt, mnt_point))) {
-            errno = ENOMEM;
-            goto cleanup;
-        }
+    if (!(mnt_point->mnt = vfs_create_mount(parent_mnt, mnt_point))) {
+        errno = ENOMEM;
+        goto cleanup;
+    }
 
 
+    mnt_point->mnt->flags = options;
+    if (!(errno = fs->mount(sb, mnt_point))) {
         kprintf("mount: dev=%s, fs=%s, mode=%d", dev_name, fs_name, options);
         kprintf("mount: dev=%s, fs=%s, mode=%d", dev_name, fs_name, options);
-
-        mnt_point->mnt->flags = options;
     } else {
         goto cleanup;
     }
 
     } else {
         goto cleanup;
     }
 
+    vfs_sb_free(old_sb);
     return errno;
 
 cleanup:
     return errno;
 
 cleanup:
-    ERROR("mount: dev=%s, fs=%s, mode=%d, err=%d",
+    ERROR("failed mount: dev=%s, fs=%s, mode=%d, err=%d",
           dev_name,
           fs_name,
           options,
           errno);
           dev_name,
           fs_name,
           options,
           errno);
-    mnt_point->super_block = old_sb;
+    vfs_d_assign_sb(mnt_point, old_sb);
     vfs_sb_free(sb);
     vfs_sb_free(sb);
+    __vfs_release_vmnt(mnt_point->mnt);
+
     return errno;
 }
 
     return errno;
 }
 
@@ -261,7 +278,7 @@ __DEFINE_LXSYSCALL4(int,
     struct device* device = NULL;
 
     if (dev) {
     struct device* device = NULL;
 
     if (dev) {
-        if (!(dev->inode->itype & VFS_IFVOLDEV)) {
+        if (!check_voldev_node(dev->inode)) {
             errno = ENOTDEV;
             goto done;
         }
             errno = ENOTDEV;
             goto done;
         }