|
@@ -21,12 +21,9 @@
|
|
|
#include <types/path.hpp>
|
|
|
#include <types/string.hpp>
|
|
|
|
|
|
-struct tmpfs_file_entry {
|
|
|
- size_t ino;
|
|
|
- char filename[128];
|
|
|
-};
|
|
|
+using fs::vfs;
|
|
|
|
|
|
-fs::vfs::dentry::dentry(dentry* _parent, inode* _ind, name_type _name)
|
|
|
+vfs::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
|
|
@@ -38,13 +35,13 @@ fs::vfs::dentry::dentry(dentry* _parent, inode* _ind, name_type _name)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-fs::vfs::dentry* fs::vfs::dentry::append(inode* ind, name_type name)
|
|
|
+vfs::dentry* vfs::dentry::append(inode* ind, name_type name)
|
|
|
{
|
|
|
auto& ent = children->emplace_back(this, ind, name);
|
|
|
idx_children->emplace(ent.name, &ent);
|
|
|
return &ent;
|
|
|
}
|
|
|
-fs::vfs::dentry* fs::vfs::dentry::find(const name_type& name)
|
|
|
+vfs::dentry* vfs::dentry::find(const name_type& name)
|
|
|
{
|
|
|
if (!flags.dir)
|
|
|
return nullptr;
|
|
@@ -67,14 +64,14 @@ fs::vfs::dentry* fs::vfs::dentry::find(const name_type& name)
|
|
|
|
|
|
return iter->second;
|
|
|
}
|
|
|
-fs::vfs::dentry* fs::vfs::dentry::replace(dentry* val)
|
|
|
+vfs::dentry* vfs::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 fs::vfs::dentry::remove(const name_type& name)
|
|
|
+void vfs::dentry::remove(const name_type& name)
|
|
|
{
|
|
|
for (auto iter = children->begin(); iter != children->end(); ++iter) {
|
|
|
if (iter->name != name)
|
|
@@ -86,12 +83,12 @@ void fs::vfs::dentry::remove(const name_type& name)
|
|
|
idx_children->remove(name);
|
|
|
}
|
|
|
|
|
|
-fs::vfs::vfs()
|
|
|
+vfs::vfs()
|
|
|
: _root { nullptr, nullptr, "" }
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-void fs::vfs::dentry::path(
|
|
|
+void vfs::dentry::path(
|
|
|
const dentry& root, types::path &out_dst) const
|
|
|
{
|
|
|
const dentry* dents[32];
|
|
@@ -109,7 +106,7 @@ void fs::vfs::dentry::path(
|
|
|
out_dst.append(dents[i]->name.c_str());
|
|
|
}
|
|
|
|
|
|
-fs::inode* fs::vfs::cache_inode(size_t size, ino_t ino,
|
|
|
+fs::inode* vfs::cache_inode(size_t size, ino_t ino,
|
|
|
mode_t mode, uid_t uid, gid_t gid)
|
|
|
{
|
|
|
auto [ iter, inserted ] =
|
|
@@ -117,12 +114,12 @@ fs::inode* fs::vfs::cache_inode(size_t size, ino_t ino,
|
|
|
return &iter->second;
|
|
|
}
|
|
|
|
|
|
-void fs::vfs::free_inode(ino_t ino)
|
|
|
+void vfs::free_inode(ino_t ino)
|
|
|
{
|
|
|
assert(_inodes.erase(ino) == 1);
|
|
|
}
|
|
|
|
|
|
-fs::inode* fs::vfs::get_inode(ino_t ino)
|
|
|
+fs::inode* vfs::get_inode(ino_t ino)
|
|
|
{
|
|
|
auto iter = _inodes.find(ino);
|
|
|
// TODO: load inode from disk if not found
|
|
@@ -131,12 +128,13 @@ fs::inode* fs::vfs::get_inode(ino_t ino)
|
|
|
else
|
|
|
return nullptr;
|
|
|
}
|
|
|
-void fs::vfs::register_root_node(inode* root)
|
|
|
+
|
|
|
+void vfs::register_root_node(inode* root)
|
|
|
{
|
|
|
if (!_root.ind)
|
|
|
_root.ind = root;
|
|
|
}
|
|
|
-int fs::vfs::load_dentry(dentry* ent)
|
|
|
+int vfs::load_dentry(dentry* ent)
|
|
|
{
|
|
|
auto* ind = ent->ind;
|
|
|
|
|
@@ -163,7 +161,7 @@ int fs::vfs::load_dentry(dentry* ent)
|
|
|
|
|
|
return GB_OK;
|
|
|
}
|
|
|
-int fs::vfs::mount(dentry* mnt, vfs* new_fs)
|
|
|
+int vfs::mount(dentry* mnt, vfs* new_fs)
|
|
|
{
|
|
|
if (!mnt->flags.dir) {
|
|
|
errno = ENOTDIR;
|
|
@@ -180,329 +178,60 @@ int fs::vfs::mount(dentry* mnt, vfs* new_fs)
|
|
|
|
|
|
return GB_OK;
|
|
|
}
|
|
|
-size_t fs::vfs::inode_read(inode*, char*, size_t, size_t, size_t)
|
|
|
-{ return -EINVAL; }
|
|
|
-size_t fs::vfs::inode_write(inode*, const char*, size_t, size_t)
|
|
|
-{ return -EINVAL; }
|
|
|
-int fs::vfs::inode_mkfile(dentry*, const char*, mode_t)
|
|
|
-{ return -EINVAL; }
|
|
|
-int fs::vfs::inode_mknode(dentry*, const char*, mode_t, dev_t)
|
|
|
-{ return -EINVAL; }
|
|
|
-int fs::vfs::inode_rmfile(dentry*, const char*)
|
|
|
-{ return -EINVAL; }
|
|
|
-int fs::vfs::inode_mkdir(dentry*, const char*, mode_t)
|
|
|
-{ return -EINVAL; }
|
|
|
-int fs::vfs::inode_statx(dentry*, statx*, unsigned int)
|
|
|
-{ return -EINVAL; }
|
|
|
-int fs::vfs::inode_stat(dentry*, struct stat*)
|
|
|
-{ return -EINVAL; }
|
|
|
-int fs::vfs::inode_devid(fs::inode*, dev_t&)
|
|
|
-{ return -EINVAL; }
|
|
|
-int fs::vfs::truncate(inode*, size_t)
|
|
|
-{ return -EINVAL; }
|
|
|
-
|
|
|
-class tmpfs : public virtual fs::vfs {
|
|
|
-private:
|
|
|
- using fe_t = tmpfs_file_entry;
|
|
|
- using vfe_t = std::vector<fe_t>;
|
|
|
- using fdata_t = std::vector<char>;
|
|
|
-
|
|
|
-private:
|
|
|
- std::map<ino_t, void*> inode_data;
|
|
|
- ino_t _next_ino;
|
|
|
-
|
|
|
-private:
|
|
|
- ino_t _assign_ino(void)
|
|
|
- {
|
|
|
- return _next_ino++;
|
|
|
- }
|
|
|
-
|
|
|
- static constexpr vfe_t* as_vfe(void* data)
|
|
|
- {
|
|
|
- return static_cast<vfe_t*>(data);
|
|
|
- }
|
|
|
- static constexpr fdata_t* as_fdata(void* data)
|
|
|
- {
|
|
|
- return static_cast<fdata_t*>(data);
|
|
|
- }
|
|
|
- static constexpr ptr_t as_val(void* data)
|
|
|
- {
|
|
|
- return std::bit_cast<ptr_t>(data);
|
|
|
- }
|
|
|
- inline void* _getdata(ino_t ino) const
|
|
|
- {
|
|
|
- return inode_data.find(ino)->second;
|
|
|
- }
|
|
|
- inline ino_t _savedata(void* data)
|
|
|
- {
|
|
|
- ino_t ino = _assign_ino();
|
|
|
- inode_data.insert(std::make_pair(ino, data));
|
|
|
- return ino;
|
|
|
- }
|
|
|
- inline ino_t _savedata(ptr_t data)
|
|
|
- {
|
|
|
- return _savedata((void*)data);
|
|
|
- }
|
|
|
-
|
|
|
-protected:
|
|
|
- inline vfe_t* mk_fe_vector() { return new vfe_t{}; }
|
|
|
- inline fdata_t* mk_data_vector() { return new fdata_t{}; }
|
|
|
-
|
|
|
- void mklink(fs::inode* dir, fs::inode* inode, const char* filename)
|
|
|
- {
|
|
|
- auto* fes = as_vfe(_getdata(dir->ino));
|
|
|
- fes->emplace_back(fe_t {
|
|
|
- .ino = inode->ino,
|
|
|
- .filename = {} });
|
|
|
- dir->size += sizeof(fe_t);
|
|
|
-
|
|
|
- auto& emplaced = fes->back();
|
|
|
-
|
|
|
- strncpy(emplaced.filename, filename, sizeof(emplaced.filename));
|
|
|
- emplaced.filename[sizeof(emplaced.filename) - 1] = 0;
|
|
|
-
|
|
|
- ++inode->nlink;
|
|
|
- }
|
|
|
-
|
|
|
- virtual int inode_readdir(fs::inode* dir, size_t offset, const fs::vfs::filldir_func& filldir) override
|
|
|
- {
|
|
|
- if (!S_ISDIR(dir->mode)) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- auto& entries = *as_vfe(_getdata(dir->ino));
|
|
|
- size_t off = offset / sizeof(fe_t);
|
|
|
-
|
|
|
- size_t nread = 0;
|
|
|
-
|
|
|
- for (; (off + 1) <= entries.size(); ++off, nread += sizeof(fe_t)) {
|
|
|
- const auto& entry = entries[off];
|
|
|
- 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);
|
|
|
- if (ret != GB_OK)
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return nread;
|
|
|
- }
|
|
|
-
|
|
|
-public:
|
|
|
- explicit tmpfs(void)
|
|
|
- : _next_ino(1)
|
|
|
- {
|
|
|
- auto& in = *cache_inode(0, _savedata(mk_fe_vector()), S_IFDIR | 0777, 0, 0);
|
|
|
-
|
|
|
- mklink(&in, &in, ".");
|
|
|
- mklink(&in, &in, "..");
|
|
|
-
|
|
|
- register_root_node(&in);
|
|
|
- }
|
|
|
-
|
|
|
- virtual int inode_mkfile(dentry* dir, const char* filename, mode_t mode) override
|
|
|
- {
|
|
|
- if (!dir->flags.dir)
|
|
|
- return -ENOTDIR;
|
|
|
-
|
|
|
- auto& file = *cache_inode(0, _savedata(mk_data_vector()), S_IFREG | mode, 0, 0);
|
|
|
- mklink(dir->ind, &file, filename);
|
|
|
-
|
|
|
- if (dir->flags.present)
|
|
|
- dir->append(get_inode(file.ino), filename);
|
|
|
-
|
|
|
- return GB_OK;
|
|
|
- }
|
|
|
-
|
|
|
- virtual int inode_mknode(dentry* dir, const char* filename, mode_t mode, dev_t dev) override
|
|
|
- {
|
|
|
- if (!dir->flags.dir)
|
|
|
- return -ENOTDIR;
|
|
|
-
|
|
|
- if (!S_ISBLK(mode) && !S_ISCHR(mode))
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- auto& node = *cache_inode(0, _savedata(dev), mode, 0, 0);
|
|
|
- mklink(dir->ind, &node, filename);
|
|
|
-
|
|
|
- if (dir->flags.present)
|
|
|
- dir->append(get_inode(node.ino), filename);
|
|
|
-
|
|
|
- return GB_OK;
|
|
|
- }
|
|
|
-
|
|
|
- virtual int inode_mkdir(dentry* dir, const char* dirname, mode_t mode) override
|
|
|
- {
|
|
|
- if (!dir->flags.dir)
|
|
|
- return -ENOTDIR;
|
|
|
-
|
|
|
- auto new_dir = cache_inode(0, _savedata(mk_fe_vector()), S_IFDIR | (mode & 0777), 0, 0);
|
|
|
- mklink(new_dir, new_dir, ".");
|
|
|
-
|
|
|
- mklink(dir->ind, new_dir, dirname);
|
|
|
- mklink(new_dir, dir->ind, "..");
|
|
|
-
|
|
|
- if (dir->flags.present)
|
|
|
- dir->append(new_dir, dirname);
|
|
|
-
|
|
|
- return GB_OK;
|
|
|
- }
|
|
|
-
|
|
|
- virtual size_t inode_read(fs::inode* file, char* buf, size_t buf_size, size_t offset, size_t n) override
|
|
|
- {
|
|
|
- if (!S_ISREG(file->mode))
|
|
|
- return 0;
|
|
|
-
|
|
|
- auto* data = as_fdata(_getdata(file->ino));
|
|
|
- size_t fsize = data->size();
|
|
|
-
|
|
|
- if (offset + n > fsize)
|
|
|
- n = fsize - offset;
|
|
|
-
|
|
|
- if (buf_size < n) {
|
|
|
- n = buf_size;
|
|
|
- }
|
|
|
-
|
|
|
- memcpy(buf, data->data() + offset, n);
|
|
|
-
|
|
|
- return n;
|
|
|
- }
|
|
|
-
|
|
|
- virtual size_t inode_write(fs::inode* file, const char* buf, size_t offset, size_t n) override
|
|
|
- {
|
|
|
- if (!S_ISREG(file->mode))
|
|
|
- return 0;
|
|
|
-
|
|
|
- auto* data = as_fdata(_getdata(file->ino));
|
|
|
-
|
|
|
- if (data->size() < offset + n)
|
|
|
- data->resize(offset+n);
|
|
|
- memcpy(data->data() + offset, buf, n);
|
|
|
-
|
|
|
- file->size = data->size();
|
|
|
-
|
|
|
- return n;
|
|
|
- }
|
|
|
-
|
|
|
- virtual int inode_statx(dentry* dent, statx* st, unsigned int mask) override
|
|
|
- {
|
|
|
- auto* ind = dent->ind;
|
|
|
- const mode_t mode = ind->mode;
|
|
|
|
|
|
- st->stx_mask = 0;
|
|
|
+// default behavior is to
|
|
|
+// return -EINVAL to show that the operation
|
|
|
+// is not supported by the fs
|
|
|
|
|
|
- if (mask & STATX_NLINK) {
|
|
|
- st->stx_nlink = ind->nlink;
|
|
|
- st->stx_mask |= STATX_NLINK;
|
|
|
- }
|
|
|
-
|
|
|
- // TODO: set modification time
|
|
|
- if (mask & STATX_MTIME) {
|
|
|
- st->stx_mtime = {};
|
|
|
- st->stx_mask |= STATX_MTIME;
|
|
|
- }
|
|
|
-
|
|
|
- if (mask & STATX_SIZE) {
|
|
|
- st->stx_size = ind->size;
|
|
|
- st->stx_mask |= STATX_SIZE;
|
|
|
- }
|
|
|
-
|
|
|
- st->stx_mode = 0;
|
|
|
- if (mask & STATX_MODE) {
|
|
|
- st->stx_mode |= ind->mode & ~S_IFMT;
|
|
|
- st->stx_mask |= STATX_MODE;
|
|
|
- }
|
|
|
-
|
|
|
- if (mask & STATX_TYPE) {
|
|
|
- st->stx_mode |= ind->mode & S_IFMT;
|
|
|
- if (S_ISBLK(mode) || S_ISCHR(mode)) {
|
|
|
- auto nd = (dev_t)as_val(_getdata(ind->ino));
|
|
|
- st->stx_rdev_major = NODE_MAJOR(nd);
|
|
|
- st->stx_rdev_minor = NODE_MINOR(nd);
|
|
|
- }
|
|
|
- st->stx_mask |= STATX_TYPE;
|
|
|
- }
|
|
|
-
|
|
|
- if (mask & STATX_INO) {
|
|
|
- st->stx_ino = ind->ino;
|
|
|
- st->stx_mask |= STATX_INO;
|
|
|
- }
|
|
|
-
|
|
|
- if (mask & STATX_BLOCKS) {
|
|
|
- st->stx_blocks = align_up<9>(ind->size) / 512;
|
|
|
- st->stx_blksize = 4096;
|
|
|
- st->stx_mask |= STATX_BLOCKS;
|
|
|
- }
|
|
|
-
|
|
|
- if (mask & STATX_UID) {
|
|
|
- st->stx_uid = ind->uid;
|
|
|
- st->stx_mask |= STATX_UID;
|
|
|
- }
|
|
|
-
|
|
|
- if (mask & STATX_GID) {
|
|
|
- st->stx_gid = ind->gid;
|
|
|
- st->stx_mask |= STATX_GID;
|
|
|
- }
|
|
|
-
|
|
|
- return GB_OK;
|
|
|
- }
|
|
|
-
|
|
|
- virtual int inode_rmfile(dentry* dir, const char* filename) override
|
|
|
- {
|
|
|
- if (!dir->flags.dir)
|
|
|
- return -ENOTDIR;
|
|
|
-
|
|
|
- auto* vfe = as_vfe(_getdata(dir->ind->ino));
|
|
|
- assert(vfe);
|
|
|
-
|
|
|
- auto* dent = dir->find(filename);
|
|
|
- if (!dent)
|
|
|
- return -ENOENT;
|
|
|
-
|
|
|
- for (auto iter = vfe->begin(); iter != vfe->end(); ) {
|
|
|
- if (iter->ino != dent->ind->ino) {
|
|
|
- ++iter;
|
|
|
- continue;
|
|
|
- }
|
|
|
+size_t vfs::read(inode*, char*, size_t, size_t, size_t)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
|
|
|
- if (S_ISREG(dent->ind->mode)) {
|
|
|
- // since we do not allow hard links in tmpfs, there is no need
|
|
|
- // to check references, we remove the file data directly
|
|
|
- auto* filedata = as_fdata(_getdata(iter->ino));
|
|
|
- assert(filedata);
|
|
|
+size_t vfs::write(inode*, const char*, size_t, size_t)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
|
|
|
- delete filedata;
|
|
|
- }
|
|
|
+int vfs::inode_mkfile(dentry*, const char*, mode_t)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
|
|
|
- free_inode(iter->ino);
|
|
|
- dir->remove(filename);
|
|
|
+int vfs::inode_mknode(dentry*, const char*, mode_t, dev_t)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
|
|
|
- vfe->erase(iter);
|
|
|
+int vfs::inode_rmfile(dentry*, const char*)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
|
|
|
- return 0;
|
|
|
- }
|
|
|
+int vfs::inode_mkdir(dentry*, const char*, mode_t)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
|
|
|
- kmsg("[tmpfs] warning: file entry not found in vfe\n");
|
|
|
- return -EIO;
|
|
|
- }
|
|
|
+int vfs::inode_statx(dentry*, statx*, unsigned int)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
|
|
|
- virtual int inode_devid(fs::inode* file, dev_t& out_dev) override
|
|
|
- {
|
|
|
- out_dev = as_val(_getdata(file->ino));
|
|
|
- return 0;
|
|
|
- }
|
|
|
+int vfs::inode_stat(dentry*, struct stat*)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
|
|
|
- virtual int truncate(fs::inode* file, size_t size) override
|
|
|
- {
|
|
|
- if (!S_ISREG(file->mode))
|
|
|
- return -EINVAL;
|
|
|
+int vfs::dev_id(inode*, dev_t&)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
|
|
|
- auto* data = as_fdata(_getdata(file->ino));
|
|
|
- data->resize(size);
|
|
|
- file->size = size;
|
|
|
- return GB_OK;
|
|
|
- }
|
|
|
-};
|
|
|
+int vfs::truncate(inode*, size_t)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
|
|
|
fs::regular_file::regular_file(vfs::dentry* parent,
|
|
|
file_flags flags, size_t cursor, inode* ind)
|
|
@@ -671,11 +400,11 @@ size_t fs::vfs_read(fs::inode* file, char* buf, size_t buf_size, size_t offset,
|
|
|
}
|
|
|
|
|
|
if (S_ISREG(file->mode))
|
|
|
- return file->fs->inode_read(file, buf, buf_size, offset, n);
|
|
|
+ return file->fs->read(file, buf, buf_size, offset, n);
|
|
|
|
|
|
if (S_ISBLK(file->mode) || S_ISCHR(file->mode)) {
|
|
|
dev_t dev;
|
|
|
- if (file->fs->inode_devid(file, dev) != 0) {
|
|
|
+ if (file->fs->dev_id(file, dev) != 0) {
|
|
|
errno = EINVAL;
|
|
|
return -1U;
|
|
|
}
|
|
@@ -705,11 +434,11 @@ size_t fs::vfs_write(fs::inode* file, const char* buf, size_t offset, size_t n)
|
|
|
}
|
|
|
|
|
|
if (S_ISREG(file->mode))
|
|
|
- return file->fs->inode_write(file, buf, offset, n);
|
|
|
+ return file->fs->write(file, buf, offset, n);
|
|
|
|
|
|
if (S_ISBLK(file->mode) || S_ISCHR(file->mode)) {
|
|
|
dev_t dev;
|
|
|
- if (file->fs->inode_devid(file, dev) != 0) {
|
|
|
+ if (file->fs->dev_id(file, dev) != 0) {
|
|
|
errno = EINVAL;
|
|
|
return -1U;
|
|
|
}
|
|
@@ -731,26 +460,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(fs::vfs::dentry* dir, const char* filename, mode_t mode)
|
|
|
+int fs::vfs_mkfile(vfs::dentry* dir, const char* filename, mode_t mode)
|
|
|
{
|
|
|
return dir->ind->fs->inode_mkfile(dir, filename, mode);
|
|
|
}
|
|
|
-int fs::vfs_mknode(fs::vfs::dentry* dir, const char* filename, mode_t mode, dev_t dev)
|
|
|
+int fs::vfs_mknode(vfs::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(fs::vfs::dentry* dir, const char* filename)
|
|
|
+int fs::vfs_rmfile(vfs::dentry* dir, const char* filename)
|
|
|
{
|
|
|
return dir->ind->fs->inode_rmfile(dir, filename);
|
|
|
}
|
|
|
-int fs::vfs_mkdir(fs::vfs::dentry* dir, const char* dirname, mode_t mode)
|
|
|
+int fs::vfs_mkdir(vfs::dentry* dir, const char* dirname, mode_t mode)
|
|
|
{
|
|
|
return dir->ind->fs->inode_mkdir(dir, dirname, mode);
|
|
|
}
|
|
|
|
|
|
-fs::vfs::dentry* fs::vfs_open(fs::vfs::dentry& root, const types::path& path)
|
|
|
+vfs::dentry* fs::vfs_open(vfs::dentry& root, const types::path& path)
|
|
|
{
|
|
|
- fs::vfs::dentry* cur = &root;
|
|
|
+ vfs::dentry* cur = &root;
|
|
|
|
|
|
for (const auto& item : path) {
|
|
|
if (item.empty())
|
|
@@ -763,7 +492,7 @@ fs::vfs::dentry* fs::vfs_open(fs::vfs::dentry& root, const types::path& path)
|
|
|
return cur;
|
|
|
}
|
|
|
|
|
|
-int fs::vfs_stat(fs::vfs::dentry* ent, statx* stat, unsigned int mask)
|
|
|
+int fs::vfs_stat(vfs::dentry* ent, statx* stat, unsigned int mask)
|
|
|
{
|
|
|
return ent->ind->fs->inode_statx(ent, stat, mask);
|
|
|
}
|
|
@@ -773,7 +502,7 @@ int fs::vfs_truncate(inode *file, size_t size)
|
|
|
return file->fs->truncate(file, size);
|
|
|
}
|
|
|
|
|
|
-static std::list<fs::vfs*, types::memory::ident_allocator<fs::vfs*>> fs_es;
|
|
|
+static std::list<fs::vfs*> fs_es;
|
|
|
|
|
|
int fs::register_block_device(dev_t node, fs::blkdev_ops ops)
|
|
|
{
|
|
@@ -795,6 +524,32 @@ int fs::register_char_device(dev_t node, fs::chrdev_ops ops)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static std::list<std::pair<types::string<>, fs::create_fs_func_t>> fs_list;
|
|
|
+
|
|
|
+int fs::register_fs(const char* name, fs::create_fs_func_t func)
|
|
|
+{
|
|
|
+ fs_list.push_back({ {name}, func });
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int fs::create_fs(const char* name, dev_t device, vfs*& out_vfs)
|
|
|
+{
|
|
|
+ for (const auto& [ fsname, func ] : fs_list) {
|
|
|
+ if (fsname != name)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ vfs* created_vfs = func(device);
|
|
|
+ fs_es.emplace_back(created_vfs);
|
|
|
+
|
|
|
+ out_vfs = created_vfs;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return -ENODEV;
|
|
|
+}
|
|
|
+
|
|
|
// MBR partition table, used by partprobe()
|
|
|
|
|
|
struct PACKED mbr_part_entry {
|
|
@@ -922,12 +677,6 @@ ssize_t fs::char_device_write(dev_t node, const char* buf, size_t n)
|
|
|
return iter->second.write(buf, n);
|
|
|
}
|
|
|
|
|
|
-fs::vfs* fs::register_fs(vfs* fs)
|
|
|
-{
|
|
|
- fs_es.push_back(fs);
|
|
|
- return fs;
|
|
|
-}
|
|
|
-
|
|
|
ssize_t b_null_read(char* buf, size_t buf_size, size_t n)
|
|
|
{
|
|
|
if (n >= buf_size)
|
|
@@ -1053,8 +802,13 @@ void init_vfs(void)
|
|
|
// TODO: add interface to bind console device to other devices
|
|
|
register_char_device(make_device(2, 0), { console_read, console_write });
|
|
|
|
|
|
- auto* rootfs = new tmpfs;
|
|
|
- fs_es.push_back(rootfs);
|
|
|
+ // register tmpfs
|
|
|
+ fs::register_tmpfs();
|
|
|
+
|
|
|
+ vfs* rootfs;
|
|
|
+ int ret = create_fs("tmpfs", make_device(0, 0), rootfs);
|
|
|
+
|
|
|
+ assert(ret == 0);
|
|
|
fs_root = rootfs->root();
|
|
|
|
|
|
vfs_mkdir(fs_root, "dev", 0755);
|