I'll share my VFS's design on what mountpoints respect.
First of all, some important data structures and functions (Spoiler, C++11 is involved!):
Code:
namespace VFS {
enum class InodeType {
File,
Directory,
SymbolicLink,
ProtocolFile, // i.e: socket
NamedPipe,
TrapFile, // i.e: "special" files
Gateway // Let's leave this for another forum thread...
};
struct Inode {
Size id; // As far as the underlying filesystem knows
UID owner;
Size refs; // (Hard-links)
Size openRefs; // (Open file descriptors)
UInt16 access;
Size size;
InodeType type;
Bool mayBeUncached;
};
class Directory;
struct File {
Byte name[256];
Size mount;
Size inode;
Directory* parent;
File* next;
InodeType type;
};
class Directory : public File {
public:
File* children;
ErrorCode getChild (String name, File **file);
};
ErrorCode Mount (String source, String target, Bool bindMount);
ErrorCode Unmount (String root);
}
Some BTWs:
- typedef unsigned long Size; // For x86
- class ErrorCode; // ...
- typedef bool Bool; // This *has* its reasons
- typedef const char* String; // Did you though it was something like std::string?
The job of
VFS::Mount() is very simple:
If
bindMount is
true, then
source shall be a path pointing to a valid, present directory. That directory and its children shall be copied into a new, fresh tree. The address of that new directory structure is stored in a example pointer named
sourceDir. The bind-mounted directory structure itself may not be copied, it's innecessary.
Else, the trap file pointed to by
source is loaded into kernel memory and its internal filesystem is parsed into the common tree structure in kernel memory. The directory representation of the root of the loaded filesystem is stored in the previously mentioned
sourceDir pointer.
Whatever
*sourceDir contains, the target directory,
target, shall be empty for everything to work correctly. There will be a single change in the original filesystem tree, that is, all first-level nodes from the root (i.e:
/usr counts but
/usr/local doesn't) shall have their parent changed to the directory pointed to by
target, as well as
target shall change its
childs pointer member changed to the address of the first element of the mounted filesystem.
The reverse process,
VFS::Unmount() is even simpler. It just flushes all data in the mounted filesystem, removes it from kernel memory, and sets the host root's
childs pointer member to
nullptr.
This model is simple, yet it addresses bind mounting, nested mounts, and multiple mounts of a single filesystem. BTW, obviously, there is a hidden mountpoint list that avoids
VFS::Unmount()'ing of non-mountpoints, and there are several minimal, but important details that I didn't said here, specially with the "multiple mounts of a single filesystem" feature.
_________________
Happy New Code!
Hello World in Brainfuck :
Code:
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.