mirror of
https://github.com/usatiuk/ficus.git
synced 2025-10-28 16:17:51 +01:00
VFS: less crazy design
with actual inodes now
This commit is contained in:
@@ -43,6 +43,7 @@ void templates_tester() {
|
||||
void vfs_tester() {
|
||||
VFSTester vfsTester;
|
||||
vfsTester.test();
|
||||
GlobalTtyManager.all_tty_putstr("Testing vfs OK\n");
|
||||
}
|
||||
|
||||
void ktask_main() {
|
||||
@@ -54,7 +55,7 @@ void ktask_main() {
|
||||
(new Task(Task::TaskMode::TASKMODE_KERN, templates_tester, "templates_tester2"))->start();
|
||||
VFSGlobals::mounts.add_mount(new MemFs(&VFSGlobals::root));
|
||||
(new Task(Task::TaskMode::TASKMODE_KERN, vfs_tester, "vfs_tester"))->start();
|
||||
|
||||
Task *init;
|
||||
for (int i = 0; i < saved_modules_size; i++) {
|
||||
auto &mod = saved_modules[i];
|
||||
|
||||
@@ -64,23 +65,20 @@ void ktask_main() {
|
||||
f->write(static_cast<const char *>(mod.address), mod.size);
|
||||
|
||||
if (strcmp(saved_modules_names[i], "/init") == 0) {
|
||||
GlobalTtyManager.all_tty_putstr("Starting ");
|
||||
GlobalTtyManager.all_tty_putstr(saved_modules_names[i]);
|
||||
GlobalTtyManager.all_tty_putchar('\n');
|
||||
|
||||
Vector<char> read_data(mod.size);
|
||||
memcpy(read_data.begin(), mod.address, mod.size);
|
||||
ElfParser elfParser(std::move(read_data));
|
||||
|
||||
Task *utask = new Task(Task::TaskMode::TASKMODE_USER, (void (*)()) elfParser.get_entrypoint(), saved_modules_names[i]);
|
||||
if (elfParser.copy_to(utask))
|
||||
utask->start();
|
||||
else
|
||||
init = new Task(Task::TaskMode::TASKMODE_USER, (void (*)()) elfParser.get_entrypoint(), saved_modules_names[i]);
|
||||
if (!elfParser.copy_to(init))
|
||||
assert2(false, "Init couldn't be loaded!");
|
||||
}
|
||||
|
||||
VFSApi::close(fd);
|
||||
}
|
||||
GlobalTtyManager.all_tty_putstr("Setup finished \n");
|
||||
GlobalTtyManager.all_tty_putstr("Starting init \n");
|
||||
init->start();
|
||||
}
|
||||
|
||||
void dummy_task() {
|
||||
|
||||
@@ -269,11 +269,13 @@ int64_t syscall_getdents(int fd, struct dirent *dp, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
auto &child = children[i + f->pos()];
|
||||
dp[i].d_fileno = i + f->pos() + 1;
|
||||
strncpy(dp[i].d_name, child->name().c_str(), 255);
|
||||
dp[i].d_name[child->name().length() + 1] = '\0';
|
||||
dp[i].d_namlen = child->name().length();
|
||||
dp[i].d_reclen = sizeof(dirent);
|
||||
dp[i].d_type = child->type() == Node::DIR ? 4 : 8;
|
||||
strncpy(dp[i].d_name, child.name.c_str(), 255);
|
||||
dp[i].d_name[child.name.length() + 1] = '\0';
|
||||
dp[i].d_namlen = child.name.length();
|
||||
dp[i].d_reclen = sizeof(dirent);
|
||||
// FIXME:
|
||||
// dp[i].d_type = child.type() == Node::DIR ? 4 : 8;
|
||||
dp[i].d_type = 4;
|
||||
}
|
||||
f->seek(count + f->pos());
|
||||
return count * sizeof(dirent);
|
||||
|
||||
@@ -7,12 +7,15 @@
|
||||
|
||||
#include "Node.hpp"
|
||||
|
||||
#include "PointersCollection.hpp"
|
||||
|
||||
class Filesystem {
|
||||
public:
|
||||
Filesystem(NodeDir *mounted_on);
|
||||
Filesystem(NodeDir *mounted_on);
|
||||
virtual ~Filesystem() = 0;
|
||||
|
||||
virtual NodeDir *root() = 0;
|
||||
virtual ~Filesystem() = 0;
|
||||
virtual SharedPtr<NodeDir> root() = 0;
|
||||
virtual SharedPtr<Node> get_node(ino_t inode) = 0;
|
||||
|
||||
NodeDir *_mounted_on;
|
||||
};
|
||||
|
||||
@@ -7,45 +7,110 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
Vector<SharedPtr<Node>> MemFs::MemFsNodeDir::children() {
|
||||
Vector<DirEntry> MemFs::MemFsNodeDir::children() {
|
||||
LockGuard l(_lock);
|
||||
LockGuard l2(_fs_node->lock);
|
||||
|
||||
Vector<SharedPtr<Node>> out;
|
||||
for (auto c: _children) {
|
||||
out.emplace_back(c.second);
|
||||
Vector<DirEntry> out;
|
||||
for (auto c: _fs_node->entries) {
|
||||
out.emplace_back(c.first, c.second);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
SharedPtr<NodeDir> MemFs::MemFsNodeDir::mkdir(const String &name) {
|
||||
ino_t MemFs::MemFsNodeDir::mkdir(const String &name) {
|
||||
LockGuard l(_lock);
|
||||
auto newnode = MemFsNodeDir::create(name);
|
||||
_children.emplace(name, static_ptr_cast<Node>(newnode));
|
||||
return static_ptr_cast<NodeDir>(newnode);
|
||||
|
||||
MemFs *mem_fs = static_cast<MemFs *>(_fs);
|
||||
ino_t res;
|
||||
{
|
||||
LockGuard l3(mem_fs->_files_lock);
|
||||
|
||||
SharedPtr<DirInode> new_inode = SharedPtr<DirInode>(new DirInode{++mem_fs->_top_inode});
|
||||
mem_fs->_files.emplace(new_inode->id, static_ptr_cast<Inode>(new_inode));
|
||||
res = new_inode->id;
|
||||
}
|
||||
|
||||
{
|
||||
LockGuard l2(_fs_node->lock);
|
||||
|
||||
_fs_node->entries.emplace(name, res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
SharedPtr<NodeFile> MemFs::MemFsNodeDir::mkfile(const String &name) {
|
||||
ino_t MemFs::MemFsNodeDir::mkfile(const String &name) {
|
||||
LockGuard l(_lock);
|
||||
auto newfile = MemFsNodeFile::create(name);
|
||||
_children.emplace(name, static_ptr_cast<Node>(newfile));
|
||||
return static_ptr_cast<NodeFile>(newfile);
|
||||
|
||||
MemFs *mem_fs = static_cast<MemFs *>(_fs);
|
||||
ino_t res;
|
||||
{
|
||||
LockGuard l3(mem_fs->_files_lock);
|
||||
|
||||
SharedPtr<FileInode> new_inode = SharedPtr<FileInode>(new FileInode{++mem_fs->_top_inode});
|
||||
mem_fs->_files.emplace(new_inode->id, static_ptr_cast<Inode>(new_inode));
|
||||
res = new_inode->id;
|
||||
}
|
||||
|
||||
{
|
||||
LockGuard l2(_fs_node->lock);
|
||||
|
||||
_fs_node->entries.emplace(name, res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
int64_t MemFs::MemFsNodeFile::read(char *buf, size_t start, size_t num) {
|
||||
LockGuard l(_lock);
|
||||
num = std::min(num, _bytes.size() - start);
|
||||
LockGuard l2(_fs_node->lock);
|
||||
num = std::min(num, _fs_node->data.size() - start);
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
buf[i] = _bytes[start + i];
|
||||
buf[i] = _fs_node->data[start + i];
|
||||
}
|
||||
return num;
|
||||
}
|
||||
int64_t MemFs::MemFsNodeFile::write(const char *buf, size_t start, size_t num) {
|
||||
LockGuard l(_lock);
|
||||
while (_bytes.size() <= start + num) _bytes.emplace_back(0);
|
||||
LockGuard l2(_fs_node->lock);
|
||||
while (_fs_node->data.size() <= start + num) _fs_node->data.emplace_back(0);
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
_bytes[start + i] = buf[i];
|
||||
_fs_node->data[start + i] = buf[i];
|
||||
}
|
||||
return num;
|
||||
}
|
||||
size_t MemFs::MemFsNodeFile::size() {
|
||||
LockGuard l(_lock);
|
||||
return _bytes.size();
|
||||
LockGuard l2(_fs_node->lock);
|
||||
return _fs_node->data.size();
|
||||
}
|
||||
MemFs::MemFs(NodeDir *mounted_on) : Filesystem(mounted_on) {
|
||||
_files.emplace(1, new DirInode{1});
|
||||
_top_inode = 2;
|
||||
}
|
||||
SharedPtr<NodeDir> MemFs::root() {
|
||||
SharedPtr<Inode> root;
|
||||
{
|
||||
LockGuard l(_files_lock);
|
||||
root = _files.find(1)->second;
|
||||
}
|
||||
assert(root.get() != nullptr);
|
||||
{
|
||||
LockGuard l(root->lock);
|
||||
return static_ptr_cast<NodeDir>(MemFsNodeDir::create(this, static_ptr_cast<DirInode>(root)));
|
||||
}
|
||||
}
|
||||
SharedPtr<Node> MemFs::get_node(ino_t inode) {
|
||||
LockGuard l(_files_lock);
|
||||
auto found = _files.find(inode);
|
||||
if (found == _files.end()) return nullptr;
|
||||
if (found->second->type == InodeType::Dir) {
|
||||
return static_ptr_cast<Node>(MemFsNodeDir::create(this, static_ptr_cast<DirInode>(found->second)));
|
||||
} else if (found->second->type == InodeType::File) {
|
||||
return static_ptr_cast<Node>(MemFsNodeFile::create(this, static_ptr_cast<FileInode>(found->second)));
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
|
||||
MemFs::Inode::~Inode() = default;
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef FICUS_MEMFS_HPP
|
||||
#define FICUS_MEMFS_HPP
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "Filesystem.hpp"
|
||||
#include "Node.hpp"
|
||||
|
||||
@@ -12,48 +14,92 @@
|
||||
#include "Vector.hpp"
|
||||
|
||||
class MemFs : public Filesystem {
|
||||
private:
|
||||
enum class InodeType {
|
||||
File,
|
||||
Dir
|
||||
};
|
||||
|
||||
// FIXME: refcount
|
||||
struct Inode {
|
||||
explicit Inode(InodeType type, ino_t id)
|
||||
: type(type), id(id) {}
|
||||
virtual ~Inode() = 0;
|
||||
|
||||
ino_t id;
|
||||
InodeType type;
|
||||
mutable Mutex lock;
|
||||
};
|
||||
|
||||
struct FileInode final : public Inode {
|
||||
explicit FileInode(ino_t id)
|
||||
: Inode(InodeType::File, id) {}
|
||||
|
||||
~FileInode() override = default;
|
||||
|
||||
Vector<uint8_t> data;
|
||||
};
|
||||
|
||||
struct DirInode final : public Inode {
|
||||
explicit DirInode(ino_t id)
|
||||
: Inode(InodeType::Dir, id) {}
|
||||
|
||||
~DirInode() override = default;
|
||||
|
||||
SkipListMap<String, ino_t> entries;
|
||||
};
|
||||
|
||||
struct MemFsNodeDir : public NodeDir {
|
||||
public:
|
||||
Vector<SharedPtr<Node>> children() override;
|
||||
SharedPtr<NodeDir> mkdir(const String &name) override;
|
||||
SharedPtr<NodeFile> mkfile(const String &name) override;
|
||||
~MemFsNodeDir() override = default;
|
||||
|
||||
static SharedPtr<MemFsNodeDir> create(const String &name) {
|
||||
auto shared = SharedPtr(new MemFsNodeDir(name));
|
||||
Vector<DirEntry> children() override;
|
||||
ino_t mkdir(const String &name) override;
|
||||
ino_t mkfile(const String &name) override;
|
||||
|
||||
static SharedPtr<MemFsNodeDir> create(Filesystem *fs, SharedPtr<DirInode> fs_node) {
|
||||
auto shared = SharedPtr(new MemFsNodeDir(fs, std::move(fs_node)));
|
||||
shared->_self_weak = static_ptr_cast<Node>(shared);
|
||||
return shared;
|
||||
}
|
||||
|
||||
private:
|
||||
MemFsNodeDir(const String &name) { _name = name; }
|
||||
SkipListMap<String, SharedPtr<Node>> _children;
|
||||
MemFsNodeDir(Filesystem *fs, SharedPtr<DirInode> fs_node) : NodeDir(fs, fs_node->id), _fs_node(std::move(fs_node)) {}
|
||||
|
||||
SharedPtr<DirInode> _fs_node;
|
||||
};
|
||||
|
||||
struct MemFsNodeFile : public NodeFile {
|
||||
public:
|
||||
~MemFsNodeFile() override = default;
|
||||
|
||||
int64_t read(char *buf, size_t start, size_t num) override;
|
||||
int64_t write(const char *buf, size_t start, size_t num) override;
|
||||
size_t size() override;
|
||||
bool is_tty() override { return false; }
|
||||
|
||||
static SharedPtr<MemFsNodeFile> create(const String &name) {
|
||||
auto shared = SharedPtr(new MemFsNodeFile(name));
|
||||
static SharedPtr<MemFsNodeFile> create(Filesystem *fs, SharedPtr<FileInode> fs_node) {
|
||||
auto shared = SharedPtr(new MemFsNodeFile(fs, std::move(fs_node)));
|
||||
shared->_self_weak = static_ptr_cast<Node>(shared);
|
||||
return shared;
|
||||
}
|
||||
|
||||
private:
|
||||
MemFsNodeFile(const String &name) { _name = name; }
|
||||
Vector<uint8_t> _bytes;
|
||||
MemFsNodeFile(Filesystem *fs, SharedPtr<FileInode> fs_node) : NodeFile(fs, fs_node->id), _fs_node(std::move(fs_node)) {}
|
||||
|
||||
SharedPtr<FileInode> _fs_node;
|
||||
};
|
||||
|
||||
public:
|
||||
MemFs(NodeDir *mounted_on) : Filesystem(mounted_on) {}
|
||||
MemFs(NodeDir *mounted_on);
|
||||
|
||||
NodeDir *root() override { return _rootNode.get(); }
|
||||
SharedPtr<NodeDir> root() override;
|
||||
SharedPtr<Node> get_node(ino_t inode) override;
|
||||
|
||||
private:
|
||||
SharedPtr<MemFsNodeDir> _rootNode = MemFsNodeDir::create("");
|
||||
ino_t _top_inode;
|
||||
SkipListMap<ino_t, SharedPtr<Inode>> _files;
|
||||
Mutex _files_lock;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "Filesystem.hpp"
|
||||
|
||||
Node::~Node() = default;
|
||||
Node::~ Node() = default;
|
||||
SharedPtr<Node> Node::traverse(const Path &path) {
|
||||
|
||||
Filesystem *mnt;
|
||||
@@ -23,13 +23,12 @@ SharedPtr<Node> Node::traverse(const Path &path) {
|
||||
return *ret;
|
||||
}
|
||||
|
||||
|
||||
if (type() == DIR) {
|
||||
// Horribly inefficient
|
||||
auto children = static_cast<NodeDir *>(this)->children();
|
||||
for (size_t i = 0; i < children.size(); i++) {
|
||||
if (children[i]->name() == path[0]) {
|
||||
return children[i]->traverse(path.subvector(1, path.size()));
|
||||
if (children[i].name == path[0]) {
|
||||
return _fs->get_node(children[i].inode)->traverse(path.subvector(1, path.size()));
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
@@ -25,37 +25,41 @@ public:
|
||||
};
|
||||
virtual ~Node() = 0;
|
||||
|
||||
Type type() const { return _type; }
|
||||
const String &name() const {
|
||||
LockGuard l(_lock);
|
||||
return _name;
|
||||
}
|
||||
Type type() const { return _type; }
|
||||
virtual SharedPtr<Node> traverse(const Path &path);
|
||||
|
||||
protected:
|
||||
Node(Type type) : _type(type) {}
|
||||
Node(Type type, Filesystem *fs, ino_t ino) : _type(type), _fs(fs), _ino(ino) {}
|
||||
|
||||
const Type _type = Type::INVALID;
|
||||
|
||||
// This is uuugly
|
||||
mutable Mutex _lock;
|
||||
|
||||
String _name;
|
||||
Filesystem *_mount = nullptr;
|
||||
Filesystem *_mount = nullptr;
|
||||
Filesystem *_fs = nullptr;
|
||||
|
||||
ino_t _ino;
|
||||
|
||||
// TODO: enable_shared_from_this or something prettier
|
||||
WeakPtr<Node> _self_weak = nullptr;
|
||||
};
|
||||
|
||||
class NodeFile;
|
||||
|
||||
struct DirEntry {
|
||||
String name;
|
||||
ino_t inode;
|
||||
};
|
||||
|
||||
class NodeDir : public Node {
|
||||
public:
|
||||
virtual Vector<SharedPtr<Node>> children() = 0;
|
||||
virtual SharedPtr<NodeDir> mkdir(const String &name) = 0;
|
||||
virtual SharedPtr<NodeFile> mkfile(const String &name) = 0;
|
||||
virtual void set_mounted(Filesystem *mount);
|
||||
virtual Vector<DirEntry> children() = 0;
|
||||
virtual ino_t mkdir(const String &name) = 0;
|
||||
virtual ino_t mkfile(const String &name) = 0;
|
||||
virtual void set_mounted(Filesystem *mount);
|
||||
|
||||
protected:
|
||||
NodeDir() : Node(Type::DIR) {}
|
||||
NodeDir(Filesystem *fs, ino_t ino) : Node(Type::DIR, fs, ino) {}
|
||||
};
|
||||
|
||||
class NodeFile : public Node {
|
||||
@@ -66,7 +70,7 @@ public:
|
||||
virtual bool is_tty() = 0;
|
||||
|
||||
protected:
|
||||
NodeFile() : Node(Type::FILE) {}
|
||||
NodeFile(Filesystem *fs, ino_t ino) : Node(Type::FILE, fs, ino) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -15,13 +15,14 @@ public:
|
||||
bool is_tty() override { return true; }
|
||||
|
||||
static SharedPtr<TtyPipe> create() {
|
||||
auto shared = SharedPtr(new TtyPipe());
|
||||
auto shared = SharedPtr(new TtyPipe(nullptr, -1));
|
||||
shared->_self_weak = static_ptr_cast<Node>(shared);
|
||||
return shared;
|
||||
}
|
||||
|
||||
private:
|
||||
TtyPipe() = default;
|
||||
TtyPipe(Filesystem *fs, ino_t ino)
|
||||
: NodeFile(fs, ino) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
//
|
||||
|
||||
#include "VFSGlobals.hpp"
|
||||
Vector<SharedPtr<Node>> RootNode::children() {
|
||||
Vector<DirEntry> RootNode::children() {
|
||||
assert(false);
|
||||
return {};
|
||||
}
|
||||
SharedPtr<NodeDir> RootNode::mkdir(const String &name) {
|
||||
ino_t RootNode::mkdir(const String &name) {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
return -1;
|
||||
}
|
||||
SharedPtr<NodeFile> RootNode::mkfile(const String &name) {
|
||||
ino_t RootNode::mkfile(const String &name) {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,15 +10,18 @@
|
||||
|
||||
class RootNode : public NodeDir {
|
||||
public:
|
||||
Vector<SharedPtr<Node>> children() override;
|
||||
SharedPtr<NodeDir> mkdir(const String &name) override;
|
||||
SharedPtr<NodeFile> mkfile(const String &name) override;
|
||||
RootNode()
|
||||
: NodeDir(nullptr, -1) {}
|
||||
|
||||
Vector<DirEntry> children() override;
|
||||
ino_t mkdir(const String &name) override;
|
||||
ino_t mkfile(const String &name) override;
|
||||
};
|
||||
|
||||
namespace VFSGlobals {
|
||||
extern RootNode root;
|
||||
extern MountTable mounts;
|
||||
}; // namespace VFSGlobals
|
||||
}; // namespace VFSGlobals
|
||||
|
||||
|
||||
#endif //FICUS_VFSGLOBALS_HPP
|
||||
|
||||
Reference in New Issue
Block a user