Răsfoiți Sursa

refactor: divide vfs.hpp into four

greatbridf 11 luni în urmă
părinte
comite
dbda9e3578

+ 4 - 0
CMakeLists.txt

@@ -72,6 +72,10 @@ set(KERNEL_MAIN_SOURCES src/fs/fat.cpp
                         include/kernel/module.hpp
                         include/kernel/utsname.hpp
                         include/kernel/vfs.hpp
+                        include/kernel/vfs/dentry.hpp
+                        include/kernel/vfs/file.hpp
+                        include/kernel/vfs/inode.hpp
+                        include/kernel/vfs/vfs.hpp
                         include/kernel/vga.hpp
                         include/kernel/signal.hpp
                         include/kernel/hw/keyboard.h

+ 2 - 1
include/fs/fat.hpp

@@ -167,9 +167,10 @@ public:
     ~fat32();
 
     virtual size_t read(inode* file, char* buf, size_t buf_size, size_t offset, size_t n) override;
+    virtual int readdir(fs::inode* dir, size_t offset, const fs::vfs::filldir_func& callback) override;
+
     virtual int inode_statx(dentry* ent, statx* st, unsigned int mask) override;
     virtual int inode_stat(dentry* ent, struct stat* st) override;
-    virtual int inode_readdir(fs::inode* dir, size_t offset, const fs::vfs::filldir_func& callback) override;
 };
 
 }; // namespace fs::fat

+ 1 - 1
include/kernel/process.hpp

@@ -259,7 +259,7 @@ public:
     pid_t sid {};
 
     tty* control_tty {};
-    fs::vfs::dentry* root { fs::fs_root };
+    fs::dentry* root { fs::fs_root };
     std::set<pid_t> children;
 
 public:

+ 12 - 268
include/kernel/vfs.hpp

@@ -1,48 +1,22 @@
 #pragma once
 
-#include <map>
-#include <list>
-#include <vector>
-#include <functional>
+#include <kernel/vfs/dentry.hpp>
+#include <kernel/vfs/file.hpp>
+#include <kernel/vfs/inode.hpp>
+#include <kernel/vfs/vfs.hpp>
 
-#include <errno.h>
-#include <fcntl.h>
+#include <stdint.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <bits/alltypes.h>
 
-#include <assert.h>
-#include <kernel/event/evtqueue.hpp>
-#include <stdint.h>
-#include <sys/types.h>
-#include <types/allocator.hpp>
-#include <types/buffer.hpp>
-#include <types/cplusplus.hpp>
-#include <types/hash_map.hpp>
 #include <types/path.hpp>
-#include <types/lock.hpp>
-#include <types/types.h>
-#include <types/string.hpp>
 
 #define NODE_MAJOR(node) ((node) >> 16)
 #define NODE_MINOR(node) ((node) & 0xffffU)
 
 namespace fs {
 
-class vfs;
-
-struct inode {
-    ino_t ino;
-    vfs* fs;
-    size_t size;
-
-    nlink_t nlink;
-
-    mode_t mode;
-    uid_t uid;
-    gid_t gid;
-};
-
 constexpr dev_t make_device(uint32_t major, uint32_t minor)
 {
     return (major << 16) | (minor & 0xffff);
@@ -86,237 +60,7 @@ struct user_dirent64 {
     char d_name[1]; // file name with a padding zero
 };
 
-class vfs {
-public:
-    struct dentry {
-    public:
-        using name_type = types::string<>;
-
-    private:
-        std::list<dentry>* children = nullptr;
-        types::hash_map<name_type, dentry*>* idx_children = nullptr;
-
-public:
-        dentry* parent;
-        inode* ind;
-        struct {
-            uint32_t dir : 1; // whether the dentry is a directory.
-            // if dir is 1, whether children contains valid data.
-            // otherwise, ignored
-            uint32_t present : 1;
-        } flags;
-        name_type name;
-
-        explicit dentry(dentry* parent, inode* ind, name_type name);
-        dentry(const dentry& val) = delete;
-        constexpr dentry(dentry&& val)
-            : children(std::exchange(val.children, nullptr))
-            , idx_children(std::exchange(val.idx_children, nullptr))
-            , parent(std::exchange(val.parent, nullptr))
-            , ind(std::exchange(val.ind, nullptr))
-            , flags { val.flags }
-            , name(std::move(val.name))
-        {
-            if (children) {
-                for (auto& item : *children)
-                    item.parent = this;
-            }
-        }
-
-        dentry& operator=(const dentry& val) = delete;
-        dentry& operator=(dentry&& val) = delete;
-
-        constexpr ~dentry()
-        {
-            if (children) {
-                delete children;
-                children = nullptr;
-            }
-            if (idx_children) {
-                delete idx_children;
-                idx_children = nullptr;
-            }
-        }
-
-        dentry* append(inode* ind, name_type name);
-
-        dentry* find(const name_type& name);
-
-        dentry* replace(dentry* val);
-
-        void remove(const name_type& name);
-
-        // out_dst SHOULD be empty
-        void path(const dentry& root, types::path& out_dst) const;
-    };
-
-public:
-    using filldir_func = std::function<int(const char*, size_t, ino_t, uint8_t)>;
-
-private:
-    // TODO: use allocator designed for small objects
-    using inode_list = std::map<ino_t, inode>;
-
-private:
-    inode_list _inodes;
-    types::hash_map<dentry*, dentry*> _mount_recover_list;
-
-protected:
-    dentry _root;
-
-protected:
-    inode* cache_inode(size_t size, ino_t ino, mode_t mode, uid_t uid, gid_t gid);
-    void free_inode(ino_t ino);
-    inode* get_inode(ino_t ino);
-    void register_root_node(inode* root);
-
-    int load_dentry(dentry* ent);
-
-public:
-    vfs();
-
-    vfs(const vfs&) = delete;
-    vfs& operator=(const vfs&) = delete;
-    vfs(vfs&&) = delete;
-    vfs& operator=(vfs&&) = delete;
-
-    constexpr dentry* root(void)
-    {
-        return &_root;
-    }
-
-    int mount(dentry* mnt, vfs* new_fs);
-
-    // directory operations
-
-    virtual int inode_mkfile(dentry* dir, const char* filename, mode_t mode);
-    virtual int inode_mknode(dentry* dir, const char* filename, mode_t mode, dev_t sn);
-    virtual int inode_rmfile(dentry* dir, const char* filename);
-    virtual int inode_mkdir(dentry* dir, const char* dirname, mode_t mode);
-
-    // metadata operation
-
-    virtual int inode_statx(dentry* dent, statx* buf, unsigned int mask);
-    virtual int inode_stat(dentry* dent, struct stat* stat);
-
-    // file operations
-
-    virtual size_t read(inode* file, char* buf, size_t buf_size, size_t offset, size_t n);
-    virtual size_t write(inode* file, const char* buf, size_t offset, size_t n);
-    virtual int dev_id(inode* file, dev_t& out_dev);
-    virtual int truncate(inode* file, size_t size);
-
-    // parameter 'length' in callback:
-    // if 0, 'name' should be null terminated
-    // else, 'name' size
-    //
-    // @return
-    // return -1 if an error occurred
-    // return 0 if no more entry available
-    // otherwise, return bytes to be added to the offset
-    virtual int inode_readdir(inode* dir, size_t offset, const filldir_func& callback) = 0;
-};
-
-class pipe : public types::non_copyable {
-private:
-    static constexpr size_t PIPE_SIZE = 4096;
-    static constexpr uint32_t READABLE = 1;
-    static constexpr uint32_t WRITABLE = 2;
-
-private:
-    types::buffer buf;
-    kernel::cond_var m_cv;
-    uint32_t flags;
-
-public:
-    pipe(void);
-
-    void close_read(void);
-    void close_write(void);
-
-    int write(const char* buf, size_t n);
-    int read(char* buf, size_t n);
-
-    constexpr bool is_readable(void) const
-    {
-        return flags & READABLE;
-    }
-
-    constexpr bool is_writeable(void) const
-    {
-        return flags & WRITABLE;
-    }
-
-    constexpr bool is_free(void) const
-    {
-        return !(flags & (READABLE | WRITABLE));
-    }
-};
-
-struct file {
-    mode_t mode; // stores the file type in the same format as inode::mode
-    vfs::dentry* parent {};
-    struct file_flags {
-        uint32_t read : 1;
-        uint32_t write : 1;
-        uint32_t append : 1;
-    } flags {};
-
-    file(mode_t mode, vfs::dentry* parent, file_flags flags)
-        : mode(mode) , parent(parent), flags(flags) { }
-
-    virtual ~file() = default;
-
-    virtual ssize_t read(char* __user buf, size_t n) = 0;
-    virtual ssize_t do_write(const char* __user buf, size_t n) = 0;
-
-    virtual off_t seek(off_t n, int whence)
-    { return (void)n, (void)whence, -ESPIPE; }
-
-    ssize_t write(const char* __user buf, size_t n)
-    {
-        if (!flags.write)
-            return -EBADF;
-
-        if (flags.append) {
-            seek(0, SEEK_END);
-        }
-
-        return do_write(buf, n);
-    }
-
-    // regular files should override this method
-    virtual int getdents(char* __user buf, size_t cnt)
-    { return (void)buf, (void)cnt, -ENOTDIR; }
-    virtual int getdents64(char* __user buf, size_t cnt)
-    { return (void)buf, (void)cnt, -ENOTDIR; }
-};
-
-struct regular_file : public virtual file {
-    virtual ~regular_file() = default;
-    std::size_t cursor { };
-    inode* ind { };
-
-    regular_file(vfs::dentry* parent, file_flags flags, size_t cursor, inode* ind);
-
-    virtual ssize_t read(char* __user buf, size_t n) override;
-    virtual ssize_t do_write(const char* __user buf, size_t n) override;
-    virtual off_t seek(off_t n, int whence) override;
-    virtual int getdents(char* __user buf, size_t cnt) override;
-    virtual int getdents64(char* __user buf, size_t cnt) override;
-};
-
-struct fifo_file : public virtual file {
-    virtual ~fifo_file() override;
-    std::shared_ptr<pipe> ppipe;
-
-    fifo_file(vfs::dentry* parent, file_flags flags, std::shared_ptr<fs::pipe> ppipe);
-
-    virtual ssize_t read(char* __user buf, size_t n) override;
-    virtual ssize_t do_write(const char* __user buf, size_t n) override;
-};
-
-inline fs::vfs::dentry* fs_root;
+inline dentry* fs_root;
 
 int register_block_device(dev_t node, blkdev_ops ops);
 int register_char_device(dev_t node, chrdev_ops ops);
@@ -344,11 +88,11 @@ ssize_t char_device_write(dev_t node, const char* buf, size_t n);
 
 size_t vfs_read(inode* file, char* buf, size_t buf_size, size_t offset, size_t n);
 size_t vfs_write(inode* file, const char* buf, size_t offset, size_t n);
-int vfs_mkfile(fs::vfs::dentry* dir, const char* filename, mode_t mode);
-int vfs_mknode(fs::vfs::dentry* dir, const char* filename, mode_t mode, dev_t sn);
-int vfs_rmfile(fs::vfs::dentry* dir, const char* filename);
-int vfs_mkdir(fs::vfs::dentry* dir, const char* dirname, mode_t mode);
-int vfs_stat(fs::vfs::dentry* dent, statx* stat, unsigned int mask);
+int vfs_mkfile(dentry* dir, const char* filename, mode_t mode);
+int vfs_mknode(dentry* dir, const char* filename, mode_t mode, dev_t sn);
+int vfs_rmfile(dentry* dir, const char* filename);
+int vfs_mkdir(dentry* dir, const char* dirname, mode_t mode);
+int vfs_stat(dentry* dent, statx* stat, unsigned int mask);
 int vfs_truncate(inode* file, size_t size);
 
 /**
@@ -359,7 +103,7 @@ int vfs_truncate(inode* file, size_t size);
  * @return A pointer to the opened file or directory entry if found.
  *         Otherwise, nullptr is returned.
  */
-fs::vfs::dentry* vfs_open(fs::vfs::dentry& root, const types::path& path);
+dentry* vfs_open(dentry& root, const types::path& path);
 
 } // namespace fs
 

+ 77 - 0
include/kernel/vfs/dentry.hpp

@@ -0,0 +1,77 @@
+#pragma once
+
+#include <list>
+
+#include <types/string.hpp>
+#include <types/hash_map.hpp>
+#include <types/path.hpp>
+
+#include <kernel/vfs/inode.hpp>
+
+namespace fs {
+
+struct dentry {
+public:
+    using name_type = types::string<>;
+
+private:
+    std::list<dentry>* children = nullptr;
+    types::hash_map<name_type, dentry*>* idx_children = nullptr;
+
+public:
+    dentry* parent;
+    inode* ind;
+    struct {
+        uint32_t dir : 1; // whether the dentry is a directory.
+        // if dir is 1, whether children contains valid data.
+        // otherwise, ignored
+        uint32_t present : 1;
+    } flags;
+    name_type name;
+
+    explicit dentry(dentry* parent, inode* ind, name_type name);
+    dentry(const dentry& val) = delete;
+    constexpr dentry(dentry&& val)
+        : children(std::exchange(val.children, nullptr))
+        , idx_children(std::exchange(val.idx_children, nullptr))
+        , parent(std::exchange(val.parent, nullptr))
+        , ind(std::exchange(val.ind, nullptr))
+        , flags { val.flags }
+        , name(std::move(val.name))
+    {
+        if (children) {
+            for (auto& item : *children)
+                item.parent = this;
+        }
+    }
+
+    dentry& operator=(const dentry& val) = delete;
+    dentry& operator=(dentry&& val) = delete;
+
+    constexpr ~dentry()
+    {
+        if (children) {
+            delete children;
+            children = nullptr;
+        }
+        if (idx_children) {
+            delete idx_children;
+            idx_children = nullptr;
+        }
+    }
+
+    int load();
+
+    dentry* append(inode* ind, name_type name);
+
+    dentry* find(const name_type& name);
+
+    dentry* replace(dentry* val);
+
+    void remove(const name_type& name);
+
+    // out_dst SHOULD be empty
+    void path(const dentry& root, types::path& out_dst) const;
+};
+
+} // namespace fs

+ 114 - 0
include/kernel/vfs/file.hpp

@@ -0,0 +1,114 @@
+#pragma once
+
+#include <kernel/vfs/dentry.hpp>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include <types/types.h>
+#include <types/buffer.hpp>
+#include <kernel/event/evtqueue.hpp>
+
+namespace fs {
+
+class pipe : public types::non_copyable {
+private:
+    static constexpr size_t PIPE_SIZE = 4096;
+    static constexpr uint32_t READABLE = 1;
+    static constexpr uint32_t WRITABLE = 2;
+
+private:
+    types::buffer buf;
+    kernel::cond_var m_cv;
+    uint32_t flags;
+
+public:
+    pipe(void);
+
+    void close_read(void);
+    void close_write(void);
+
+    int write(const char* buf, size_t n);
+    int read(char* buf, size_t n);
+
+    constexpr bool is_readable(void) const
+    {
+        return flags & READABLE;
+    }
+
+    constexpr bool is_writeable(void) const
+    {
+        return flags & WRITABLE;
+    }
+
+    constexpr bool is_free(void) const
+    {
+        return !(flags & (READABLE | WRITABLE));
+    }
+};
+
+struct file {
+    mode_t mode; // stores the file type in the same format as inode::mode
+    dentry* parent {};
+    struct file_flags {
+        uint32_t read : 1;
+        uint32_t write : 1;
+        uint32_t append : 1;
+    } flags {};
+
+    file(mode_t mode, dentry* parent, file_flags flags)
+        : mode(mode) , parent(parent), flags(flags) { }
+
+    virtual ~file() = default;
+
+    virtual ssize_t read(char* __user buf, size_t n) = 0;
+    virtual ssize_t do_write(const char* __user buf, size_t n) = 0;
+
+    virtual off_t seek(off_t n, int whence)
+    { return (void)n, (void)whence, -ESPIPE; }
+
+    ssize_t write(const char* __user buf, size_t n)
+    {
+        if (!flags.write)
+            return -EBADF;
+
+        if (flags.append) {
+            seek(0, SEEK_END);
+        }
+
+        return do_write(buf, n);
+    }
+
+    // regular files should override this method
+    virtual int getdents(char* __user buf, size_t cnt)
+    { return (void)buf, (void)cnt, -ENOTDIR; }
+    virtual int getdents64(char* __user buf, size_t cnt)
+    { return (void)buf, (void)cnt, -ENOTDIR; }
+};
+
+struct regular_file : public virtual file {
+    virtual ~regular_file() = default;
+    std::size_t cursor { };
+    inode* ind { };
+
+    regular_file(dentry* parent, file_flags flags, size_t cursor, inode* ind);
+
+    virtual ssize_t read(char* __user buf, size_t n) override;
+    virtual ssize_t do_write(const char* __user buf, size_t n) override;
+    virtual off_t seek(off_t n, int whence) override;
+    virtual int getdents(char* __user buf, size_t cnt) override;
+    virtual int getdents64(char* __user buf, size_t cnt) override;
+};
+
+struct fifo_file : public virtual file {
+    virtual ~fifo_file() override;
+    std::shared_ptr<pipe> ppipe;
+
+    fifo_file(dentry* parent, file_flags flags, std::shared_ptr<fs::pipe> ppipe);
+
+    virtual ssize_t read(char* __user buf, size_t n) override;
+    virtual ssize_t do_write(const char* __user buf, size_t n) override;
+};
+
+} // namespace fs

+ 22 - 0
include/kernel/vfs/inode.hpp

@@ -0,0 +1,22 @@
+#pragma once
+
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace fs {
+
+class vfs;
+
+struct inode {
+    ino_t ino;
+    vfs* fs;
+    size_t size;
+
+    nlink_t nlink;
+
+    mode_t mode;
+    uid_t uid;
+    gid_t gid;
+};
+
+} // namespace fs

+ 87 - 0
include/kernel/vfs/vfs.hpp

@@ -0,0 +1,87 @@
+#pragma once
+
+#include <kernel/vfs/inode.hpp>
+#include <kernel/vfs/dentry.hpp>
+
+#include <functional>
+#include <map>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <types/hash_map.hpp>
+
+namespace fs {
+
+class vfs {
+public:
+
+public:
+    using filldir_func = std::function<int(const char*, size_t, inode*, uint8_t)>;
+
+private:
+    // TODO: use allocator designed for small objects
+    using inode_list = std::map<ino_t, inode>;
+
+private:
+    inode_list _inodes;
+    types::hash_map<dentry*, dentry*> _mount_recover_list;
+
+protected:
+    dentry _root;
+
+protected:
+    inode* cache_inode(size_t size, ino_t ino, mode_t mode, uid_t uid, gid_t gid);
+    void free_inode(ino_t ino);
+    inode* get_inode(ino_t ino);
+    void register_root_node(inode* root);
+
+    int load_dentry(dentry* ent);
+
+public:
+    vfs();
+
+    vfs(const vfs&) = delete;
+    vfs& operator=(const vfs&) = delete;
+    vfs(vfs&&) = delete;
+    vfs& operator=(vfs&&) = delete;
+
+    constexpr dentry* root(void)
+    {
+        return &_root;
+    }
+
+    int mount(dentry* mnt, vfs* new_fs);
+
+    // directory operations
+
+    virtual int inode_mkfile(dentry* dir, const char* filename, mode_t mode);
+    virtual int inode_mknode(dentry* dir, const char* filename, mode_t mode, dev_t sn);
+    virtual int inode_rmfile(dentry* dir, const char* filename);
+    virtual int inode_mkdir(dentry* dir, const char* dirname, mode_t mode);
+
+    // metadata operation
+
+    virtual int inode_statx(dentry* dent, statx* buf, unsigned int mask);
+    virtual int inode_stat(dentry* dent, struct stat* stat);
+
+    // file operations
+
+    virtual size_t read(inode* file, char* buf, size_t buf_size, size_t offset, size_t n);
+    virtual size_t write(inode* file, const char* buf, size_t offset, size_t n);
+    virtual int dev_id(inode* file, dev_t& out_dev);
+    virtual int truncate(inode* file, size_t size);
+
+    // parameter 'length' in callback:
+    // if 0, 'name' should be null terminated
+    // else, 'name' size
+    //
+    // @return
+    // return -1 if an error occurred
+    // return 0 if no more entry available
+    // otherwise, return bytes to be added to the offset
+    virtual int readdir(inode* dir, size_t offset, const filldir_func& callback) = 0;
+};
+
+} // namespace fs

+ 1 - 1
include/types/elf.hpp

@@ -136,7 +136,7 @@ struct PACKED elf32_section_header_entry {
 };
 
 struct elf32_load_data {
-    const fs::vfs::dentry* exec_dent;
+    const fs::dentry* exec_dent;
     const char* const* argv;
     const char* const* envp;
     int errcode;

+ 2 - 2
src/fs/fat.cpp

@@ -64,7 +64,7 @@ void fat32::release_cluster(cluster_t no)
         --iter->second.ref;
 }
 
-int fat32::inode_readdir(fs::inode* dir, size_t offset, const fs::vfs::filldir_func& filldir)
+int fat32::readdir(fs::inode* dir, size_t offset, const fs::vfs::filldir_func& filldir)
 {
     cluster_t next = cl(dir);
     for (size_t i = 0; i < (offset / (sectors_per_cluster * SECTOR_SIZE)); ++i) {
@@ -116,7 +116,7 @@ int fat32::inode_readdir(fs::inode* dir, size_t offset, const fs::vfs::filldir_f
                 else
                     fname += toupper(d->extension[i]);
             }
-            auto ret = filldir(fname.c_str(), 0, ind->ino, ind->mode & S_IFMT);
+            auto ret = filldir(fname.c_str(), 0, ind, ind->mode & S_IFMT);
 
             if (ret != GB_OK) {
                 release_cluster(next);

+ 66 - 55
src/kernel/vfs.cpp

@@ -21,9 +21,9 @@
 #include <types/path.hpp>
 #include <types/string.hpp>
 
-using fs::vfs;
+using fs::vfs, fs::dentry;
 
-vfs::dentry::dentry(dentry* _parent, inode* _ind, name_type _name)
+dentry::dentry(dentry* _parent, inode* _ind, name_type _name)
     : parent(_parent) , ind(_ind) , flags { } , name(_name)
 {
     // the dentry is filesystem root or _ind MUST be non null
@@ -35,13 +35,44 @@ vfs::dentry::dentry(dentry* _parent, inode* _ind, name_type _name)
     }
 }
 
-vfs::dentry* vfs::dentry::append(inode* ind, name_type name)
+int dentry::load()
+{
+    if (!flags.dir || !S_ISDIR(ind->mode))
+        return -ENOTDIR;
+
+    size_t offset = 0;
+    vfs* fs = ind->fs;
+
+    while (true) {
+        int ret = fs->readdir(ind, offset,
+            [this](const char* name, size_t len, inode* ind, uint8_t) -> int {
+                if (!len)
+                    append(ind, name);
+                else
+                    append(ind, dentry::name_type(name, len));
+
+                return GB_OK;
+            });
+
+        if (ret == 0)
+            break;
+
+        offset += ret;
+    }
+
+    flags.present = 1;
+
+    return 0;
+}
+
+dentry* dentry::append(inode* ind, name_type name)
 {
     auto& ent = children->emplace_back(this, ind, name);
     idx_children->emplace(ent.name, &ent);
     return &ent;
 }
-vfs::dentry* vfs::dentry::find(const name_type& name)
+
+dentry* dentry::find(const name_type& name)
 {
     if (!flags.dir)
         return nullptr;
@@ -53,8 +84,13 @@ vfs::dentry* vfs::dentry::find(const name_type& name)
             return parent ? parent : this;
     }
 
-    if (!flags.present)
-        ind->fs->load_dentry(this);
+    if (!flags.present) {
+        int ret = load();
+        if (ret != 0) {
+            errno = -ret;
+            return nullptr;
+        }
+    }
 
     auto iter = idx_children->find(name);
     if (!iter) {
@@ -64,14 +100,15 @@ vfs::dentry* vfs::dentry::find(const name_type& name)
 
     return iter->second;
 }
-vfs::dentry* vfs::dentry::replace(dentry* val)
+
+dentry* dentry::replace(dentry* val)
 {
     // TODO: prevent the dirent to be swapped out of memory
     parent->idx_children->find(this->name)->second = val;
     return this;
 }
 
-void vfs::dentry::remove(const name_type& name)
+void dentry::remove(const name_type& name)
 {
     for (auto iter = children->begin(); iter != children->end(); ++iter) {
         if (iter->name != name)
@@ -83,12 +120,7 @@ void vfs::dentry::remove(const name_type& name)
     idx_children->remove(name);
 }
 
-vfs::vfs()
-    : _root { nullptr, nullptr, "" }
-{
-}
-
-void vfs::dentry::path(
+void dentry::path(
     const dentry& root, types::path &out_dst) const
 {
     const dentry* dents[32];
@@ -106,6 +138,11 @@ void vfs::dentry::path(
         out_dst.append(dents[i]->name.c_str());
 }
 
+vfs::vfs()
+    : _root { nullptr, nullptr, "" }
+{
+}
+
 fs::inode* vfs::cache_inode(size_t size, ino_t ino,
     mode_t mode, uid_t uid, gid_t gid)
 {
@@ -134,33 +171,7 @@ void vfs::register_root_node(inode* root)
     if (!_root.ind)
         _root.ind = root;
 }
-int vfs::load_dentry(dentry* ent)
-{
-    auto* ind = ent->ind;
-
-    if (!ent->flags.dir || !S_ISDIR(ind->mode)) {
-        errno = ENOTDIR;
-        return GB_FAILED;
-    }
-
-    size_t offset = 0;
 
-    for (int ret = 1; ret > 0; offset += ret) {
-        ret = this->inode_readdir(ind, offset,
-            [ent, this](const char* name, size_t len, ino_t ino, uint8_t) -> int {
-                if (!len)
-                    ent->append(get_inode(ino), name);
-                else
-                    ent->append(get_inode(ino), dentry::name_type(name, len));
-
-                return GB_OK;
-            });
-    }
-
-    ent->flags.present = 1;
-
-    return GB_OK;
-}
 int vfs::mount(dentry* mnt, vfs* new_fs)
 {
     if (!mnt->flags.dir) {
@@ -233,7 +244,7 @@ int vfs::truncate(inode*, size_t)
     return -EINVAL;
 }
 
-fs::regular_file::regular_file(vfs::dentry* parent,
+fs::regular_file::regular_file(dentry* parent,
     file_flags flags, size_t cursor, inode* ind)
     : file(ind->mode, parent, flags), cursor(cursor), ind(ind) { }
 
@@ -298,8 +309,8 @@ int fs::regular_file::getdents(char* __user buf, size_t cnt)
         return -ENOTDIR;
 
     size_t orig_cnt = cnt;
-    int nread = ind->fs->inode_readdir(ind, cursor,
-        [&buf, &cnt](const char* fn, size_t len, ino_t ino, uint8_t type) {
+    int nread = ind->fs->readdir(ind, cursor,
+        [&buf, &cnt](const char* fn, size_t len, inode* ind, uint8_t type) {
             if (!len)
                 len = strlen(fn);
 
@@ -308,7 +319,7 @@ int fs::regular_file::getdents(char* __user buf, size_t cnt)
                 return GB_FAILED;
 
             auto* dirp = (fs::user_dirent*)buf;
-            dirp->d_ino = ino;
+            dirp->d_ino = ind->ino;
             dirp->d_reclen = reclen;
             // TODO: show offset
             // dirp->d_off = 0;
@@ -334,8 +345,8 @@ int fs::regular_file::getdents64(char* __user buf, size_t cnt)
         return -ENOTDIR;
 
     size_t orig_cnt = cnt;
-    int nread = ind->fs->inode_readdir(ind, cursor,
-        [&buf, &cnt](const char* fn, size_t len, ino_t ino, uint8_t type) {
+    int nread = ind->fs->readdir(ind, cursor,
+        [&buf, &cnt](const char* fn, size_t len, inode* ind, uint8_t type) {
             if (!len)
                 len = strlen(fn);
 
@@ -344,7 +355,7 @@ int fs::regular_file::getdents64(char* __user buf, size_t cnt)
                 return GB_FAILED;
 
             auto* dirp = (fs::user_dirent64*)buf;
-            dirp->d_ino = ino;
+            dirp->d_ino = ind->ino;
             dirp->d_off = 114514;
             dirp->d_reclen = reclen;
             dirp->d_type = type;
@@ -363,7 +374,7 @@ int fs::regular_file::getdents64(char* __user buf, size_t cnt)
     return orig_cnt - cnt;
 }
 
-fs::fifo_file::fifo_file(vfs::dentry* parent, file_flags flags,
+fs::fifo_file::fifo_file(dentry* parent, file_flags flags,
     std::shared_ptr<fs::pipe> ppipe)
     : file(S_IFIFO, parent, flags), ppipe(ppipe) { }
 
@@ -460,26 +471,26 @@ size_t fs::vfs_write(fs::inode* file, const char* buf, size_t offset, size_t n)
     errno = EINVAL;
     return -1U;
 }
-int fs::vfs_mkfile(vfs::dentry* dir, const char* filename, mode_t mode)
+int fs::vfs_mkfile(dentry* dir, const char* filename, mode_t mode)
 {
     return dir->ind->fs->inode_mkfile(dir, filename, mode);
 }
-int fs::vfs_mknode(vfs::dentry* dir, const char* filename, mode_t mode, dev_t dev)
+int fs::vfs_mknode(dentry* dir, const char* filename, mode_t mode, dev_t dev)
 {
     return dir->ind->fs->inode_mknode(dir, filename, mode, dev);
 }
-int fs::vfs_rmfile(vfs::dentry* dir, const char* filename)
+int fs::vfs_rmfile(dentry* dir, const char* filename)
 {
     return dir->ind->fs->inode_rmfile(dir, filename);
 }
-int fs::vfs_mkdir(vfs::dentry* dir, const char* dirname, mode_t mode)
+int fs::vfs_mkdir(dentry* dir, const char* dirname, mode_t mode)
 {
     return dir->ind->fs->inode_mkdir(dir, dirname, mode);
 }
 
-vfs::dentry* fs::vfs_open(vfs::dentry& root, const types::path& path)
+dentry* fs::vfs_open(dentry& root, const types::path& path)
 {
-    vfs::dentry* cur = &root;
+    dentry* cur = &root;
 
     for (const auto& item : path) {
         if (item.empty())
@@ -492,7 +503,7 @@ vfs::dentry* fs::vfs_open(vfs::dentry& root, const types::path& path)
     return cur;
 }
 
-int fs::vfs_stat(vfs::dentry* ent, statx* stat, unsigned int mask)
+int fs::vfs_stat(dentry* ent, statx* stat, unsigned int mask)
 {
     return ent->ind->fs->inode_statx(ent, stat, mask);
 }

+ 3 - 3
src/kernel/vfs/tmpfs.cc

@@ -5,7 +5,7 @@
 #include <vector>
 #include <map>
 
-using fs::vfs, fs::inode;
+using fs::vfs, fs::inode, fs::dentry;
 
 struct tmpfs_file_entry {
     size_t ino;
@@ -75,7 +75,7 @@ protected:
         ++inode->nlink;
     }
 
-    virtual int inode_readdir(inode* dir, size_t offset, const fs::vfs::filldir_func& filldir) override
+    virtual int readdir(inode* dir, size_t offset, const fs::vfs::filldir_func& filldir) override
     {
         if (!S_ISDIR(dir->mode)) {
             return -1;
@@ -91,7 +91,7 @@ protected:
             auto* ind = get_inode(entry.ino);
 
             // inode mode filetype is compatible with user dentry filetype
-            auto ret = filldir(entry.filename, 0, entry.ino, ind->mode & S_IFMT);
+            auto ret = filldir(entry.filename, 0, ind, ind->mode & S_IFMT);
             if (ret != GB_OK)
                 break;
         }