SimpleKernel 1.17.0
Loading...
Searching...
No Matches
mount.cpp
Go to the documentation of this file.
1
5#include "mount.hpp"
6
7#include "kernel_log.hpp"
8#include "kstd_cstring"
9#include "kstd_memory"
10#include "spinlock.hpp"
11#include "vfs.hpp"
12#include "vfs_internal.hpp"
13
14namespace vfs {
15
16auto MountTable::Mount(const char* path, FileSystem* fs, BlockDevice* device)
18 if (path == nullptr || fs == nullptr) {
19 return std::unexpected(Error(ErrorCode::kInvalidArgument));
20 }
21
22 LockGuard<SpinLock> guard(GetVfsState().vfs_lock_);
23 // 检查挂载点数量
24 if (mount_count_ >= kMaxMounts) {
25 return std::unexpected(Error(ErrorCode::kFsMountFailed));
26 }
27
28 // 规范化路径(确保以 / 开头)
29 if (path[0] != '/') {
30 return std::unexpected(Error(ErrorCode::kFsInvalidPath));
31 }
32
33 // 检查路径是否已被挂载
34 for (size_t i = 0; i < mount_count_; ++i) {
35 if (mounts_[i].active && strcmp(mounts_[i].mount_path, path) == 0) {
36 return std::unexpected(Error(ErrorCode::kFsAlreadyMounted));
37 }
38 }
39
40 // 挂载文件系统
41 auto mount_result = fs->Mount(device);
42 if (!mount_result.has_value()) {
43 klog::Err("MountTable: failed to mount filesystem '{}': {}", fs->GetName(),
44 mount_result.error().message());
45 return std::unexpected(Error(ErrorCode::kFsMountFailed));
46 }
47
48 Inode* root_inode = mount_result.value();
49 if (root_inode == nullptr || root_inode->type != FileType::kDirectory) {
50 return std::unexpected(Error(ErrorCode::kFsCorrupted));
51 }
52
53 // 为根 inode 创建 dentry
54 auto root_dentry_ptr = kstd::make_unique<Dentry>();
55 if (!root_dentry_ptr) {
56 fs->Unmount();
57 return std::unexpected(Error(ErrorCode::kOutOfMemory));
58 }
59
60 root_dentry_ptr->inode = root_inode;
61 strncpy(root_dentry_ptr->name, "/", sizeof(root_dentry_ptr->name));
62
63 // 查找挂载点 dentry(如果是非根挂载)
64 Dentry* mount_dentry = nullptr;
65 if (strcmp(path, "/") != 0) {
66 // 需要找到父文件系统中对应的 dentry
67 // 这里简化处理,实际应该通过 VFS Lookup 找到
68 // 暂时设置为 nullptr,表示根挂载
69 }
70
71 // 找到空闲挂载点槽位
72 size_t slot = 0;
73 for (; slot < kMaxMounts; ++slot) {
74 if (!mounts_[slot].active) {
75 break;
76 }
77 }
78
79 if (slot >= kMaxMounts) {
80 // root_dentry_ptr 自动释放(RAII)
81 fs->Unmount();
82 return std::unexpected(Error(ErrorCode::kFsMountFailed));
83 }
84
85 // 填充挂载点信息
86 mounts_[slot].mount_path = path;
87 mounts_[slot].mount_dentry = mount_dentry;
88 mounts_[slot].filesystem = fs;
89 mounts_[slot].device = device;
90 mounts_[slot].root_inode = root_inode;
91 mounts_[slot].root_dentry = root_dentry_ptr.release();
92 mounts_[slot].active = true;
93
94 ++mount_count_;
95
96 // 如果是根挂载,设置 root_mount_
97 if (strcmp(path, "/") == 0) {
98 root_mount_ = &mounts_[slot];
99 // 更新 VFS 根 dentry
100 extern void SetRootDentry(Dentry*);
101 SetRootDentry(mounts_[slot].root_dentry);
102 }
103
104 klog::Info("MountTable: mounted '{}' on '{}'", fs->GetName(), path);
105 return {};
106}
107
108auto MountTable::Unmount(const char* path) -> Expected<void> {
109 if (path == nullptr) {
110 return std::unexpected(Error(ErrorCode::kInvalidArgument));
111 }
112
113 // 查找挂载点
114 MountPoint* mp = nullptr;
115 size_t mp_index = 0;
116 for (size_t i = 0; i < kMaxMounts; ++i) {
117 if (mounts_[i].active && strcmp(mounts_[i].mount_path, path) == 0) {
118 mp = &mounts_[i];
119 mp_index = i;
120 break;
121 }
122 }
123
124 if (mp == nullptr) {
125 return std::unexpected(Error(ErrorCode::kFsNotMounted));
126 }
127
128 // 卸载文件系统
129 auto result = mp->filesystem->Unmount();
130 if (!result.has_value()) {
131 return std::unexpected(result.error());
132 }
133
134 // 清理挂载点(RAII)
135 etl::unique_ptr<Dentry> root_guard(mp->root_dentry);
136
137 mp->active = false;
138 mp->mount_path = nullptr;
139 mp->mount_dentry = nullptr;
140 mp->filesystem = nullptr;
141 mp->device = nullptr;
142 mp->root_inode = nullptr;
143 mp->root_dentry = nullptr;
144
145 --mount_count_;
146
147 // 如果是根挂载,清除 root_mount_
148 if (root_mount_ == &mounts_[mp_index]) {
149 root_mount_ = nullptr;
150 extern void SetRootDentry(Dentry*);
151 SetRootDentry(nullptr);
152 }
153
154 klog::Info("MountTable: unmounted '{}'", path);
155 return {};
156}
157
158auto MountTable::Lookup(const char* path) -> MountPoint* {
159 if (path == nullptr || path[0] != '/') {
160 return nullptr;
161 }
162
163 MountPoint* best_match = nullptr;
164 size_t best_match_len = 0;
165
166 for (size_t i = 0; i < kMaxMounts; ++i) {
167 if (!mounts_[i].active) {
168 continue;
169 }
170
171 const char* mp_path = mounts_[i].mount_path;
172 if (mp_path == nullptr) {
173 continue;
174 }
175
176 size_t mp_len = strlen(mp_path);
177
178 // 检查路径是否以挂载路径开头
179 if (strncmp(path, mp_path, mp_len) == 0) {
180 // 确保是完整匹配或下一个字符是 /,或者是根目录挂载
181 char next_char = path[mp_len];
182 if (next_char == '\0' || next_char == '/' ||
183 (mp_len == 1 && mp_path[0] == '/')) {
184 // 选择最长的匹配
185 if (mp_len > best_match_len) {
186 best_match = &mounts_[i];
187 best_match_len = mp_len;
188 }
189 }
190 }
191 }
192
193 return best_match;
194}
195
197 if (mp == nullptr || !mp->active) {
198 return nullptr;
199 }
200 return mp->root_dentry;
201}
202
204 if (dentry == nullptr) {
205 return nullptr;
206 }
207
208 for (size_t i = 0; i < kMaxMounts; ++i) {
209 if (mounts_[i].active && mounts_[i].mount_dentry == dentry) {
210 return &mounts_[i];
211 }
212 }
213
214 return nullptr;
215}
216
217auto MountTable::IsMountPoint(const char* path) -> bool {
218 if (path == nullptr) {
219 return false;
220 }
221
222 for (size_t i = 0; i < kMaxMounts; ++i) {
223 if (mounts_[i].active && mounts_[i].mount_path != nullptr &&
224 strcmp(mounts_[i].mount_path, path) == 0) {
225 return true;
226 }
227 }
228
229 return false;
230}
231
232auto MountTable::GetRootMount() -> MountPoint* { return root_mount_; }
233
235 static MountTable instance;
236 return instance;
237}
238
239} // namespace vfs
RAII 风格的锁守卫模板类
Definition spinlock.hpp:131
块设备抽象基类
文件系统类型基类
virtual auto Unmount() -> Expected< void >=0
卸载文件系统
挂载表管理器
Definition mount.hpp:34
auto FindByMountDentry(const Dentry *dentry) -> MountPoint *
根据 dentry 查找挂载在其上的文件系统
Definition mount.cpp:203
auto Unmount(const char *path) -> Expected< void >
卸载指定路径的文件系统
Definition mount.cpp:108
auto GetRootMount() -> MountPoint *
获取根挂载点
Definition mount.cpp:232
auto IsMountPoint(const char *path) -> bool
检查路径是否是挂载点
Definition mount.cpp:217
auto GetRootDentry(MountPoint *mp) -> Dentry *
获取指定挂载点的根 dentry
Definition mount.cpp:196
auto Mount(const char *path, FileSystem *fs, BlockDevice *device) -> Expected< void >
挂载文件系统到指定路径
Definition mount.cpp:16
auto Lookup(const char *path) -> MountPoint *
根据路径查找对应的挂载点
Definition mount.cpp:158
@ kInvalidArgument
@ kFsAlreadyMounted
std::expected< T, Error > Expected
std::expected 别名模板
Definition expected.hpp:365
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
@ kDirectory
目录
auto SetRootDentry(Dentry *dentry) -> void
Definition vfs.cpp:99
auto GetVfsState() -> VfsState &
Definition vfs.cpp:17
auto GetMountTable() -> MountTable &
获取全局挂载表实例
Definition mount.cpp:234
#define strlen
#define strncpy
#define strcmp
#define strncmp
错误类型,用于 std::expected
Definition expected.hpp:343
Dentry — 目录项缓存(路径名 ↔ Inode 的映射)
Definition vfs.hpp:41
Inode — 文件元数据(独立于路径名)
Definition vfs.hpp:16
FileType type
文件类型
Definition vfs.hpp:20
挂载点
Definition mount.hpp:15
Dentry * root_dentry
该文件系统的根 dentry
Definition mount.hpp:27
BlockDevice * device
关联的块设备(可为 nullptr)
Definition mount.hpp:23
Dentry * mount_dentry
挂载点在父文件系统中的 dentry
Definition mount.hpp:19
const char * mount_path
挂载路径(如 "/mnt/disk")
Definition mount.hpp:17
bool active
是否处于活动状态
Definition mount.hpp:29
Inode * root_inode
该文件系统的根 inode
Definition mount.hpp:25
FileSystem * filesystem
挂载的文件系统实例
Definition mount.hpp:21