22 file_data_pool_used_(0),
24 dir_data_pool_used_(0),
41 if (device !=
nullptr) {
49 for (
int i = kMaxInodes - 1; i >= 0; --i) {
50 inodes_[i].next_free = free_list_;
51 free_list_ = &inodes_[i];
55 auto root_result = AllocateInode();
56 if (!root_result.has_value()) {
57 return std::unexpected(root_result.error());
60 root_inode_ = root_result.value();
61 root_inode_->type = FileType::kDirectory;
62 root_inode_->permissions = 0755;
66 ram_root->
data =
nullptr;
85 for (
size_t i = 0; i < kMaxInodes; ++i) {
86 if (inodes_[i].inode.type != FileType::kUnknown &&
87 inodes_[i].data !=
nullptr) {
88 inodes_[i].data =
nullptr;
94 root_inode_ =
nullptr;
97 file_data_pool_used_ = 0;
98 dir_data_pool_used_ = 0;
110 if (free_list_ ==
nullptr) {
118 ram_inode->
inode.
ino =
reinterpret_cast<uint64_t
>(&ram_inode->
inode);
119 ram_inode->
inode.
type = FileType::kUnknown;
127 ram_inode->
data =
nullptr;
133 return &ram_inode->
inode;
137 if (inode ==
nullptr) {
144 if (ram_inode->
data !=
nullptr) {
145 ram_inode->
data =
nullptr;
149 ram_inode->
inode.
type = FileType::kUnknown;
159 free_list_ = ram_inode;
173 if (dir ==
nullptr || name ==
nullptr) {
179 RamDirEntry* entry = fs_->FindInDirectory(ram_dir, name);
181 if (entry ==
nullptr) {
190 if (dir ==
nullptr || name ==
nullptr) {
194 if (type != FileType::kRegular && type != FileType::kDirectory) {
201 auto alloc_result = fs_->AllocateInode();
202 if (!alloc_result.has_value()) {
203 return std::unexpected(alloc_result.error());
206 Inode* new_inode = alloc_result.value();
207 new_inode->
type = type;
210 auto add_result = fs_->AddToDirectory(ram_dir, name, new_inode);
211 if (!add_result.has_value()) {
212 fs_->FreeInode(new_inode);
213 return std::unexpected(add_result.error());
221 if (dir ==
nullptr || name ==
nullptr) {
228 RamDirEntry* entry = fs_->FindInDirectory(ram_dir, name);
229 if (entry ==
nullptr) {
234 if (entry->
inode !=
nullptr && entry->
inode->
type == FileType::kDirectory) {
239 auto remove_result = fs_->RemoveFromDirectory(ram_dir, name);
240 if (!remove_result.has_value()) {
241 return remove_result;
246 fs_->FreeInode(entry->
inode);
255 return Create(dir, name, FileType::kDirectory);
260 if (dir ==
nullptr || name ==
nullptr) {
267 RamDirEntry* entry = fs_->FindInDirectory(ram_dir, name);
268 if (entry ==
nullptr) {
273 if (entry->
inode ==
nullptr || entry->
inode->
type != FileType::kDirectory) {
279 if (!fs_->IsDirectoryEmpty(target)) {
284 auto remove_result = fs_->RemoveFromDirectory(ram_dir, name);
285 if (!remove_result.has_value()) {
286 return remove_result;
291 fs_->FreeInode(entry->
inode);
301 if (file ==
nullptr || buf ==
nullptr) {
305 if (file->inode ==
nullptr) {
309 if (file->inode->type != FileType::kRegular) {
316 if (file->offset >= file->inode->size) {
320 size_t available = file->
inode->
size - file->offset;
321 size_t to_read = (count < available) ? count : available;
328 memcpy(buf,
static_cast<uint8_t*
>(ram_inode->
data) + file->offset, to_read);
330 file->offset += to_read;
336 if (file ==
nullptr || buf ==
nullptr) {
340 if (file->inode ==
nullptr) {
344 if (file->inode->type != FileType::kRegular) {
351 size_t new_size = file->offset + count;
352 if (new_size > ram_inode->
capacity) {
353 auto expand_result = fs_->ExpandFile(ram_inode, new_size);
354 if (!expand_result.has_value()) {
355 return std::unexpected(expand_result.error());
360 memcpy(
static_cast<uint8_t*
>(ram_inode->
data) + file->offset, buf, count);
362 file->offset += count;
365 if (file->offset > file->inode->size) {
366 file->inode->size = file->offset;
374 if (file ==
nullptr) {
378 uint64_t new_offset = 0;
381 case SeekWhence::kSet:
385 new_offset =
static_cast<uint64_t
>(offset);
388 case SeekWhence::kCur:
389 if (offset < 0 &&
static_cast<uint64_t
>(-offset) > file->offset) {
393 static_cast<uint64_t
>(
static_cast<int64_t
>(file->offset) + offset);
396 case SeekWhence::kEnd:
397 if (file->inode ==
nullptr) {
400 if (offset < 0 &&
static_cast<uint64_t
>(-offset) > file->inode->size) {
403 new_offset =
static_cast<uint64_t
>(
404 static_cast<int64_t
>(file->inode->size) + offset);
411 file->offset = new_offset;
416 if (file ==
nullptr) {
427 if (file ==
nullptr || dirent ==
nullptr) {
431 if (file->inode ==
nullptr || file->inode->type != FileType::kDirectory) {
439 size_t read_count = 0;
440 size_t offset = file->offset;
443 if (offset == 0 && read_count < count) {
444 dirent[read_count].ino = file->
inode->
ino;
445 dirent[read_count].type =
static_cast<uint8_t
>(FileType::kDirectory);
446 strncpy(dirent[read_count].name,
".",
sizeof(dirent[read_count].name));
451 if (offset == 1 && read_count < count) {
452 Inode* parent_inode =
453 (file->dentry !=
nullptr && file->dentry->parent !=
nullptr)
454 ? file->dentry->parent->inode
456 dirent[read_count].ino = parent_inode->
ino;
457 dirent[read_count].type =
static_cast<uint8_t
>(FileType::kDirectory);
458 strncpy(dirent[read_count].name,
"..",
sizeof(dirent[read_count].name));
464 size_t entry_idx = (offset > 2) ? offset - 2 : 0;
465 while (read_count < count && entry_idx < ram_dir->child_count) {
466 dirent[read_count].ino = entries[entry_idx].
inode->
ino;
467 dirent[read_count].type =
468 static_cast<uint8_t
>(entries[entry_idx].
inode->
type);
469 strncpy(dirent[read_count].name, entries[entry_idx].name,
470 sizeof(dirent[read_count].name));
475 file->offset = offset + read_count;
482 if (dir ==
nullptr || dir->inode.type != FileType::kDirectory ||
483 dir->data ==
nullptr) {
488 for (
size_t i = 0; i < dir->child_count; ++i) {
489 if (
strcmp(entries[i].name, name) == 0) {
499 if (dir ==
nullptr || name ==
nullptr || inode ==
nullptr) {
503 if (dir->inode.type != FileType::kDirectory) {
508 if (FindInDirectory(dir, name) !=
nullptr) {
513 size_t current_entries = dir->capacity /
sizeof(
RamDirEntry);
514 if (dir->child_count >= current_entries) {
515 size_t new_capacity = (current_entries == 0) ? 16 : current_entries * 2;
516 RamDirEntry* new_data = AllocateDirEntries(new_capacity);
517 if (new_data ==
nullptr) {
522 if (dir->data !=
nullptr) {
527 dir->data = new_data;
528 dir->capacity = new_capacity *
sizeof(
RamDirEntry);
533 RamDirEntry* new_entry = &entries[dir->child_count];
535 new_entry->
name[
sizeof(new_entry->
name) - 1] =
'\0';
536 new_entry->
inode = inode;
546 if (dir ==
nullptr || name ==
nullptr) {
551 if (entry ==
nullptr) {
556 if (entry->
inode !=
nullptr) {
562 size_t last_idx = dir->child_count - 1;
563 if (entry != &entries[last_idx]) {
564 *entry = entries[last_idx];
572 if (dir ==
nullptr || dir->inode.type != FileType::kDirectory) {
577 return dir->child_count == 0;
581 if (inode ==
nullptr) {
585 if (new_size <= inode->capacity) {
590 size_t new_capacity = ((new_size + 255) / 256) * 256;
592 uint8_t* new_data =
static_cast<uint8_t*
>(AllocateFileData(new_capacity));
593 if (new_data ==
nullptr) {
598 if (inode->data !=
nullptr) {
599 memcpy(new_data, inode->data, inode->inode.size);
603 inode->data = new_data;
604 inode->capacity = new_capacity;
611 size_t aligned = (size + 15UL) & ~15UL;
612 if (file_data_pool_used_ + aligned > kFileDataPoolSize) {
615 void* ptr = &file_data_pool_[file_data_pool_used_];
616 file_data_pool_used_ += aligned;
623 static constexpr size_t kAlign =
alignof(
RamDirEntry);
624 size_t aligned = (bytes + kAlign - 1UL) & ~(kAlign - 1UL);
625 if (dir_data_pool_used_ + aligned > kDirDataPoolSize) {
630 reinterpret_cast<RamDirEntry*
>(&dir_data_pool_[dir_data_pool_used_]);
631 dir_data_pool_used_ += aligned;
auto Read(vfs::File *file, void *buf, size_t count) -> Expected< size_t > override
从文件读取数据
auto Write(vfs::File *file, const void *buf, size_t count) -> Expected< size_t > override
向文件写入数据
auto Close(vfs::File *file) -> Expected< void > override
关闭文件
auto ReadDir(vfs::File *file, vfs::DirEntry *dirent, size_t count) -> Expected< size_t > override
读取目录项
auto Seek(vfs::File *file, int64_t offset, vfs::SeekWhence whence) -> Expected< uint64_t > override
调整文件偏移量
auto Unlink(vfs::Inode *dir, const char *name) -> Expected< void > override
删除文件(解除链接)
auto Rmdir(vfs::Inode *dir, const char *name) -> Expected< void > override
删除目录
auto Create(vfs::Inode *dir, const char *name, vfs::FileType type) -> Expected< vfs::Inode * > override
在目录中创建新文件
auto Mkdir(vfs::Inode *dir, const char *name) -> Expected< vfs::Inode * > override
创建目录
auto Lookup(vfs::Inode *dir, const char *name) -> Expected< vfs::Inode * > override
在目录中查找指定名称的 inode
vfs::Inode * root_inode_
根目录 inode
auto IsDirectoryEmpty(RamInode *dir) -> bool
auto AllocateFileData(size_t size) -> void *
Bump-allocate size bytes from the file data pool.
auto AllocateInode() -> Expected< vfs::Inode * > override
分配新 inode
auto Unmount() -> Expected< void > override
卸载 ramfs
auto FindInDirectory(RamInode *dir, const char *name) -> RamDirEntry *
auto Sync() -> Expected< void > override
同步数据到磁盘(ramfs 无操作)
auto Mount(vfs::BlockDevice *device) -> Expected< vfs::Inode * > override
挂载 ramfs
auto GetFileOps() -> vfs::FileOps *
获取文件操作实例
auto AddToDirectory(RamInode *dir, const char *name, vfs::Inode *inode) -> Expected< void >
auto GetRootInode() const -> vfs::Inode *
获取根 inode
auto GetName() const -> const char *override
获取文件系统类型名
auto ExpandFile(RamInode *inode, size_t new_size) -> Expected< void >
auto FreeInode(vfs::Inode *inode) -> Expected< void > override
释放 inode
auto AllocateDirEntries(size_t count) -> RamDirEntry *
Bump-allocate space for count RamDirEntry from the dir pool.
auto RemoveFromDirectory(RamInode *dir, const char *name) -> Expected< void >
std::expected< T, Error > Expected
std::expected 别名模板
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
RamInode * next_free
空闲链表指针
void * data
文件数据(普通文件)或子项列表(目录)
size_t child_count
子项数量(仅目录)
File — 打开的文件实例(每次 open 产生一个)
uint32_t permissions
权限位(简化版)
uint64_t ino
inode 编号(文件系统内唯一)
void * fs_private
文件系统私有数据指针