summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexis211 <alexis211@gmail.com>2009-11-15 13:17:58 +0100
committerAlexis211 <alexis211@gmail.com>2009-11-15 13:17:58 +0100
commit21bfca4ad4b84768f05eb4fa2bc0ad7a76b6c536 (patch)
tree7e68b92e80aadec75b5263bd9058c8336d29b77b
parente48f1166ae7402f973ea4aab8e53c7612459048c (diff)
downloadMelon-21bfca4ad4b84768f05eb4fa2bc0ad7a76b6c536.tar.gz
Melon-21bfca4ad4b84768f05eb4fa2bc0ad7a76b6c536.zip
Mount points seem to work, mostly owing to dark magic.
-rw-r--r--Source/Kernel/Core/kmain.wtf.cpp5
-rw-r--r--Source/Kernel/FileSystems/RamFS/RamFS.class.cpp11
-rw-r--r--Source/Kernel/FileSystems/RamFS/RamFS.class.h4
-rw-r--r--Source/Kernel/FileSystems/RamFS/RamFileNode.class.h2
-rw-r--r--Source/Kernel/Shell/KernelShell.class.cpp47
-rw-r--r--Source/Kernel/VFS/DirectoryNode.class.cpp45
-rw-r--r--Source/Kernel/VFS/DirectoryNode.class.h15
-rw-r--r--Source/Kernel/VFS/FSNode.proto.h4
-rw-r--r--Source/Kernel/VFS/FileSystem.proto.h13
-rw-r--r--Source/Kernel/VFS/VFS.ns.cpp35
-rw-r--r--Source/Kernel/VFS/VFS.ns.h12
11 files changed, 163 insertions, 30 deletions
diff --git a/Source/Kernel/Core/kmain.wtf.cpp b/Source/Kernel/Core/kmain.wtf.cpp
index 0486702..d0751d1 100644
--- a/Source/Kernel/Core/kmain.wtf.cpp
+++ b/Source/Kernel/Core/kmain.wtf.cpp
@@ -182,11 +182,10 @@ void kmain(multiboot_info_t* mbd, u32int magic) {
//*************************************** MOUNT ROOT FILESYSTEM
- FileSystem* fs = RamFS::mount((u8int*)mods[0].mod_start, 1024 * 1024, NULL);
+ RamFS::mount((u8int*)mods[0].mod_start, 1024 * 1024, NULL);
DirectoryNode* cwd;
- cwd = fs->getRootNode();
+ cwd = VFS::getRootNode();
Task::currProcess()->setCwd(cwd);
- VFS::setRootNode(cwd);
if (keymap != "builtin") {
if (!Kbd::loadKeymap(keymap)) *kvt << "\nWARNING : Could not load keymap " << keymap << ", using built-in keymap instead.";
diff --git a/Source/Kernel/FileSystems/RamFS/RamFS.class.cpp b/Source/Kernel/FileSystems/RamFS/RamFS.class.cpp
index 5997841..e6370d0 100644
--- a/Source/Kernel/FileSystems/RamFS/RamFS.class.cpp
+++ b/Source/Kernel/FileSystems/RamFS/RamFS.class.cpp
@@ -1,30 +1,36 @@
#include "RamFS.class.h"
#include <VFS/DirectoryNode.class.h>
#include "RamFileNode.class.h"
+#include <VFS/VFS.ns.h>
RamFS::RamFS() {
}
RamFS::~RamFS() {
- delete m_rootNode;
}
RamFS* RamFS::mount(u32int maxSize, DirectoryNode* mountpoint) {
+ if (mountpoint != 0 and !mountpoint->mountpointable()) return 0;
RamFS* rfs = new RamFS();
rfs->m_maxSize = maxSize;
rfs->m_usedSize = 0;
rfs->m_isWritable = true;
rfs->m_rootNode = new DirectoryNode("/", rfs, mountpoint);
+ if (mountpoint != 0) mountpoint->mount(rfs->m_rootNode);
+ VFS::registerFilesystem(rfs);
return rfs;
}
RamFS* RamFS::mount(u8int *ptr, u32int maxSize, DirectoryNode* mountpoint, bool writable) {
+ if (mountpoint != 0 and !mountpoint->mountpointable()) return 0;
RamFS* rfs = new RamFS();
rfs->m_maxSize = maxSize;
rfs->m_usedSize = 0;
rfs->m_isWritable = true;
rfs->m_rootNode = new DirectoryNode("/", rfs, mountpoint);
+ if (mountpoint != 0) mountpoint->mount(rfs->m_rootNode);
+ VFS::registerFilesystem(rfs);
union {
u8int* c;
@@ -81,7 +87,7 @@ RamFS* RamFS::mount(u8int *ptr, u32int maxSize, DirectoryNode* mountpoint, bool
}
bool RamFS::unmount() {
- return m_rootNode->unmountable();
+ return true;
}
bool RamFS::setName(FSNode* node, String name) { return true; }
@@ -164,6 +170,7 @@ bool RamFS::remove(DirectoryNode* parent, FSNode* node) {
if (node->type() == NT_FILE) {
u8int *d = ((RamFileNode*)node)->m_data;
if (d != 0) Mem::free(d);
+ ((RamFileNode*)node)->m_data = 0;
}
return true;
}
diff --git a/Source/Kernel/FileSystems/RamFS/RamFS.class.h b/Source/Kernel/FileSystems/RamFS/RamFS.class.h
index 1d60796..5ce85f1 100644
--- a/Source/Kernel/FileSystems/RamFS/RamFS.class.h
+++ b/Source/Kernel/FileSystems/RamFS/RamFS.class.h
@@ -17,10 +17,10 @@ struct initrd_file_header {
class RamFS : public FileSystem {
private:
- ~RamFS();
+ virtual ~RamFS();
RamFS(const RamFS& other);
RamFS();
- bool unmount(); //TO BE USED ONLY BY VFS::UNMOUNT (when will exist...)
+ bool unmount();
u32int m_maxSize;
u32int m_usedSize;
diff --git a/Source/Kernel/FileSystems/RamFS/RamFileNode.class.h b/Source/Kernel/FileSystems/RamFS/RamFileNode.class.h
index d600630..2abad64 100644
--- a/Source/Kernel/FileSystems/RamFS/RamFileNode.class.h
+++ b/Source/Kernel/FileSystems/RamFS/RamFileNode.class.h
@@ -11,6 +11,8 @@ class RamFileNode : public FileNode {
u32int uid = 0, u32int gid = 0) :
FileNode(name, fs, parent, 0, permissions, uid, gid), m_data(0) {}
+ ~RamFileNode() { if (m_data != 0) delete m_data; }
+
u8int *m_data; //We don't take care of allocation/freeing here, RamFS:: does that for us
void setLength(u32int length) { m_length = length; }
diff --git a/Source/Kernel/Shell/KernelShell.class.cpp b/Source/Kernel/Shell/KernelShell.class.cpp
index d62d822..8f71b9f 100644
--- a/Source/Kernel/Shell/KernelShell.class.cpp
+++ b/Source/Kernel/Shell/KernelShell.class.cpp
@@ -4,6 +4,7 @@
#include <SimpleList.class.h>
#include <MemoryManager/PhysMem.ns.h>
#include <VFS/VFS.ns.h>
+#include <FileSystems/RamFS/RamFS.class.h>
#include <TaskManager/Task.ns.h>
u32int KernelShell::m_instances = 0;
@@ -92,6 +93,52 @@ u32int KernelShell::run() {
} else if (tokens[0] == "exit") {
if (tokens.size() == 1) return 0;
return tokens[1].toInt();
+ } else if (tokens[0] == "mount") {
+ if (tokens.size() == 1) {
+ for (u32int i = 0; i < VFS::filesystems.size(); i++) {
+ *m_vt << VFS::path(VFS::filesystems[i]->getRootNode()) << "\n";
+ }
+ } else if (tokens.size() == 3) {
+ if (tokens[1] == "ramfs") {
+ FSNode* n = VFS::find(tokens[2], m_cwd);
+ if (n == 0) {
+ *m_vt << "No such directory.\n";
+ } else if (n->type() != NT_DIRECTORY) {
+ *m_vt << "Not a directory.\n";
+ } else {
+ if (RamFS::mount(100000, (DirectoryNode*)n) != 0) {
+ *m_vt << "Ok...\n";
+ } else {
+ *m_vt << "Error !\n";
+ }
+ }
+ } else {
+ *m_vt << "Not supported yet.\n";
+ }
+ } else {
+ *m_vt << "Usage: mount [<device> <mountpoint>\n";
+ }
+ } else if (tokens[0] == "unmount") {
+ if (tokens.size() == 2) {
+ FSNode* n = VFS::find(tokens[1], m_cwd);
+ bool ok = false;
+ if (n == 0) {
+ ok = false;
+ } else {
+ String p = VFS::path(n);
+ for (u32int i = 0; i < VFS::filesystems.size(); i++) {
+ if (VFS::path(VFS::filesystems[i]->getRootNode()) == p) {
+ VFS::unmount(VFS::filesystems[i]);
+ ok = true;
+ break;
+ }
+ }
+ }
+ if (ok) *m_vt << "Ok, filesystem unmounted.\n";
+ else *m_vt << "Error.\n";
+ } else {
+ *m_vt << "Usage: unmount <mountpoint>\n";
+ }
} else if (tokens[0] != "" or tokens.size() != 1) {
u32int i = 0;
bool found = false;
diff --git a/Source/Kernel/VFS/DirectoryNode.class.cpp b/Source/Kernel/VFS/DirectoryNode.class.cpp
index 74c1ff8..7da6fe6 100644
--- a/Source/Kernel/VFS/DirectoryNode.class.cpp
+++ b/Source/Kernel/VFS/DirectoryNode.class.cpp
@@ -6,6 +6,15 @@ call_t DirectoryNode::m_callTable[] = {
CALL0(0, 0)
};
+DirectoryNode::~DirectoryNode() {
+ if (m_contentLoaded) {
+ for (u32int i = 0; i < m_children.size(); i++) {
+ delete m_children[i];
+ }
+ }
+ if (m_name == "/") ((DirectoryNode*)(m_parent))->unmount();
+}
+
u32int DirectoryNode::getIdxChildSC(u32int idx) {
if (!runnable()) return (u32int) - 1;
FSNode* n = getChild(idx);
@@ -21,15 +30,29 @@ u32int DirectoryNode::getNameChildSC(u32int name) {
return (u32int) - 1;
}
+u64int DirectoryNode::getLength() {
+ if (m_mounts != 0) return m_mounts->getLength();
+ if (!m_contentLoaded)
+ if (!loadContent())
+ return 0;
+ return m_length;
+}
+
+FSNode* DirectoryNode::getParent() {
+ //if (m_name == "/" and m_parent != 0) return m_parent->getParent();
+ return m_parent;
+}
+
bool DirectoryNode::removable() {
if (!m_contentLoaded)
if (!loadContent())
return false;
- return m_children.empty();
+ return m_children.empty() && (m_mounts == 0);
}
bool DirectoryNode::unmountable() {
if (!m_contentLoaded) return true;
+ if (m_mounts != 0) return false;
for (u32int i = 0; i < m_children.size(); i++) {
if (m_children[i]->type() == NT_DIRECTORY) {
if (!((DirectoryNode*)m_children[i])->unmountable()) return false;
@@ -40,7 +63,22 @@ bool DirectoryNode::unmountable() {
return true;
}
+bool DirectoryNode::mountpointable() {
+ if (!m_contentLoaded)
+ if (!loadContent()) return false;
+ return m_children.empty();
+}
+
+void DirectoryNode::mount(DirectoryNode* childRoot) {
+ m_mounts = childRoot;
+}
+
+void DirectoryNode::unmount() {
+ m_mounts = 0;
+}
+
bool DirectoryNode::loadContent() {
+ if (m_mounts != 0) return m_mounts->loadContent();
if (m_contentLoaded) return true;
bool b = m_fs->loadContents(this);
if (!b) return false;
@@ -50,6 +88,7 @@ bool DirectoryNode::loadContent() {
}
FSNode* DirectoryNode::getChild(u32int index) {
+ if (m_mounts != 0) return m_mounts->getChild(index);
if (!m_contentLoaded)
if (!loadContent())
return NULL;
@@ -58,6 +97,7 @@ FSNode* DirectoryNode::getChild(u32int index) {
}
FSNode* DirectoryNode::getChild(const String& name) {
+ if (m_mounts != 0) return m_mounts->getChild(name);
if (!m_contentLoaded)
if (!loadContent())
return NULL;
@@ -69,18 +109,21 @@ FSNode* DirectoryNode::getChild(const String& name) {
}
FileNode* DirectoryNode::createFile(const String& name) {
+ if (m_mounts != 0) return m_mounts->createFile(name);
FileNode* n = m_fs->createFile(this, name);
m_length = m_children.size();
return n;
}
DirectoryNode* DirectoryNode::createDirectory(const String& name) {
+ if (m_mounts != 0) return m_mounts->createDirectory(name);
DirectoryNode* n = m_fs->createDirectory(this, name);
m_length = m_children.size();
return n;
}
bool DirectoryNode::remove(FSNode* child) {
+ if (m_mounts != 0) return m_mounts->remove(child);
//Check node is indeed one of our childs
if (!m_contentLoaded)
if (!loadContent())
diff --git a/Source/Kernel/VFS/DirectoryNode.class.h b/Source/Kernel/VFS/DirectoryNode.class.h
index 4d9b211..1fc4c52 100644
--- a/Source/Kernel/VFS/DirectoryNode.class.h
+++ b/Source/Kernel/VFS/DirectoryNode.class.h
@@ -8,6 +8,7 @@ class DirectoryNode : public FSNode {
protected:
Vector<FSNode*> m_children;
bool m_contentLoaded;
+ DirectoryNode* m_mounts; //Root node of the filesystem mounted here, null if none
//Syscalls
static call_t m_callTable[];
@@ -19,20 +20,20 @@ class DirectoryNode : public FSNode {
u32int uid = 0, u32int gid = 0) :
FSNode(name, fs, parent, 0, permissions, uid, gid), m_children(), m_contentLoaded(false) {
addCallTable(m_callTable);
+ m_mounts = 0;
}
- virtual ~DirectoryNode() {
- if (m_contentLoaded) {
- for (u32int i = 0; i < m_children.size(); i++) {
- delete m_children[i];
- }
- }
- }
+ virtual ~DirectoryNode();
Vector<FSNode*> &getChildren() { return m_children; } //MUST BE USED ONLY BY FILESYSTEMS
u8int type() { return NT_DIRECTORY; }
+ u64int getLength();
+ FSNode* getParent();
bool removable();
bool unmountable();
+ bool mountpointable();
+ void mount(DirectoryNode* childRoot);
+ void unmount();
bool loadContent();
FSNode* getChild(u32int index);
diff --git a/Source/Kernel/VFS/FSNode.proto.h b/Source/Kernel/VFS/FSNode.proto.h
index 0aafc8a..a46c79d 100644
--- a/Source/Kernel/VFS/FSNode.proto.h
+++ b/Source/Kernel/VFS/FSNode.proto.h
@@ -44,12 +44,12 @@ class FSNode : public Ressource {
virtual bool used() { return false; } //True if file is read/written from/to
const String& getName() { return m_name; }
- u64int getLength() { return m_length; }
+ virtual u64int getLength() { return m_length; }
u32int getPermissions() { return m_permissions; }
u32int getUid() { return m_uid; }
u32int getGid() { return m_gid; }
FileSystem *getFS() { return m_fs; }
- FSNode* getParent() { return m_parent; }
+ virtual FSNode* getParent() { return m_parent; }
//Helper functions
bool readable(User* user = 0);
diff --git a/Source/Kernel/VFS/FileSystem.proto.h b/Source/Kernel/VFS/FileSystem.proto.h
index a614c13..93b37f8 100644
--- a/Source/Kernel/VFS/FileSystem.proto.h
+++ b/Source/Kernel/VFS/FileSystem.proto.h
@@ -5,17 +5,24 @@
class FSNode;
class FileNode;
class DirectoryNode;
+class FileSystem;
+
+namespace VFS {
+ bool unmount(FileSystem*);
+}
//This abstract class describes a filesystem
class FileSystem {
+ friend bool VFS::unmount(FileSystem*);
+
protected:
- virtual ~FileSystem() {}
+ virtual ~FileSystem();
bool m_isWritable; //false = read only
DirectoryNode* m_rootNode;
- public:
- bool unmount();
+ virtual bool unmount() = 0; //Sync data with the disk
+ public:
bool isWritable() { return m_isWritable; }
DirectoryNode* getRootNode() { return m_rootNode; }
diff --git a/Source/Kernel/VFS/VFS.ns.cpp b/Source/Kernel/VFS/VFS.ns.cpp
index e95b911..5ebb697 100644
--- a/Source/Kernel/VFS/VFS.ns.cpp
+++ b/Source/Kernel/VFS/VFS.ns.cpp
@@ -1,19 +1,40 @@
#include "VFS.ns.h"
#include <VFS/FileNode.class.h>
+#include <Vector.class.h>
+
+FileSystem::~FileSystem() { delete m_rootNode; }
namespace VFS {
-DirectoryNode *rootNode;
+DirectoryNode *rootNode = 0;
+Vector<FileSystem*> filesystems;
-//TODO : mount stuff
+DirectoryNode* getRootNode() {
+ return rootNode;
+}
-bool setRootNode(DirectoryNode* node) {
- rootNode = node;
- return true;
+void registerFilesystem(FileSystem* fs) {
+ unregisterFilesystem(fs);
+ filesystems.push(fs);
+ if (rootNode == 0) rootNode = fs->getRootNode();
}
-DirectoryNode* getRootNode() {
- return rootNode;
+void unregisterFilesystem(FileSystem* fs) {
+ for (u32int i = 0; i < filesystems.size(); i++) {
+ if (filesystems[i] == fs) {
+ filesystems[i] = filesystems.back();
+ filesystems.pop();
+ break;
+ }
+ }
+}
+
+bool unmount(FileSystem* fs) {
+ if (!fs->getRootNode()->unmountable()) return false;
+ if (fs->getRootNode() == rootNode) return false;
+ if (!fs->unmount()) return false;
+ delete fs; //Will automatically delete the root node (destructor is in this file);
+ return true;
}
FSNode* find(const String& path, FSNode* start) {
diff --git a/Source/Kernel/VFS/VFS.ns.h b/Source/Kernel/VFS/VFS.ns.h
index f1d628f..21a1e77 100644
--- a/Source/Kernel/VFS/VFS.ns.h
+++ b/Source/Kernel/VFS/VFS.ns.h
@@ -3,15 +3,21 @@
#include <VFS/DirectoryNode.class.h>
#include <VFS/FileSystem.proto.h>
+#include <Vector.class.h>
-typedef FileSystem* (* mountcallback)(Partition* partition);
+typedef FileSystem* (* mount_callback_t)(Partition* partition);
namespace VFS {
- void registerMountCallback(mountcallback mcb);
+ extern Vector<FileSystem*> filesystems;
+
+ void registerMountCallback(mount_callback_t mcb);
bool mount(Partition* partition, DirectoryNode *mountpoint);
- bool setRootNode(DirectoryNode* root);
DirectoryNode* getRootNode();
+ void registerFilesystem(FileSystem* fs);
+ void unregisterFilesystem(FileSystem* fs);
+ bool unmount(FileSystem* fs);
+
FSNode* find(const String& path, FSNode* start = 0);
FSNode* createFile(const String& path, FSNode* start = 0, bool vrfyperm = false);
FSNode* createDirectory(const String& path, FSNode* start = 0, bool vrfyperm = false);