2022-09-14 23:51:58 +08:00

224 lines
7.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "rootfs.h"
#include <filesystem/VFS/VFS.h>
#include <common/string.h>
#include <filesystem/VFS/mount.h>
static struct vfs_superblock_t rootfs_sb = {0};
extern struct vfs_superblock_t *vfs_root_sb;
/**
* @brief 释放dentry本身所占的内存
*
* @param dentry
*/
static inline void __release_dentry(struct vfs_dir_entry_t *dentry)
{
kfree(dentry->name);
kfree(dentry);
}
struct vfs_super_block_operations_t rootfs_sb_ops = {
.put_superblock = NULL,
.write_inode = NULL,
.write_superblock = NULL,
};
static struct vfs_dir_entry_t *rootfs_lookup(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry)
{
return NULL;
}
struct vfs_inode_operations_t rootfs_inode_ops = {
.create = NULL,
.getAttr = NULL,
.lookup = NULL,
.lookup = &rootfs_lookup,
.mkdir = NULL,
.rename = NULL,
.rmdir = NULL,
.setAttr = NULL,
};
static long rootfs_open(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr)
{
return 0;
}
static long rootfs_close(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr) { return 0; }
static long rootfs_read(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position) { return 0; }
static long rootfs_write(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position) { return 0; }
static long rootfs_lseek(struct vfs_file_t *file_ptr, long offset, long origin) { return 0; }
static long rootfs_ioctl(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr, uint64_t cmd, uint64_t arg) { return 0; }
static long rootfs_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t filler)
{
// 循环读取目录下的目录项
struct vfs_dir_entry_t *dentry = file_ptr->dEntry;
struct List *list = &dentry->subdirs_list;
// 先切换到position处
for (int i = 0; i <= file_ptr->position; ++i)
{
list = list_next(list);
if (list == &dentry->subdirs_list) // 找完了
goto failed;
}
// 存在目录项
// 增加偏移量
++file_ptr->position;
// 获取目标dentry由于是子目录项因此是child_node_list
struct vfs_dir_entry_t *target_dent = container_of(list, struct vfs_dir_entry_t, child_node_list);
// kdebug("target name=%s, namelen=%d", target_dent->name, target_dent->name_length);
char *name = (char *)kzalloc(target_dent->name_length + 1, 0);
strncpy(name, target_dent->name, target_dent->name_length);
uint32_t dentry_type = target_dent->dir_inode->attribute;
return filler(dirent, file_ptr->position - 1, name, target_dent->name_length, dentry_type, file_ptr->position - 1);
failed:;
return 0;
}
static long rootfs_compare(struct vfs_dir_entry_t *parent_dEntry, char *source_filename, char *dest_filename) { return 0; }
static long rootfs_hash(struct vfs_dir_entry_t *dEntry, char *filename) { return 0; }
static long rootfs_release(struct vfs_dir_entry_t *dEntry) { return 0; }
static long rootfs_iput(struct vfs_dir_entry_t *dEntry, struct vfs_index_node_t *inode) { return 0; }
struct vfs_dir_entry_operations_t rootfs_dentry_ops =
{
.compare = &rootfs_compare,
.hash = &rootfs_hash,
.release = &rootfs_release,
.iput = &rootfs_iput,
};
struct vfs_file_operations_t rootfs_file_ops = {
.open = &rootfs_open,
.close = &rootfs_close,
.read = &rootfs_read,
.write = &rootfs_write,
.lseek = &rootfs_lseek,
.ioctl = &rootfs_ioctl,
.readdir = &rootfs_readdir,
};
/**
* @brief 为在rootfs下创建目录仅仅是形式上的目录为了支持文件系统挂载
*
* @param name 目录名称
* @return int
*/
static int rootfs_add_dir(const char *name)
{
{
// 检查名称重复
struct List *list = &rootfs_sb.root->subdirs_list;
while (list_next(list) != &rootfs_sb.root->subdirs_list)
{
list = list_next(list);
struct vfs_dir_entry_t *tmp = container_of(list, struct vfs_dir_entry_t, child_node_list);
if (strcmp(tmp->name, name) == 0)
return -EEXIST;
}
}
struct vfs_dir_entry_t *dentry = vfs_alloc_dentry(strlen(name) + 1);
strcpy(dentry->name, name);
dentry->name_length = strlen(name);
dentry->parent = rootfs_sb.root;
list_append(&rootfs_sb.root->subdirs_list, &dentry->child_node_list);
return 0;
}
void rootfs_init()
{
// 初始化超级块
rootfs_sb.blk_device = NULL;
rootfs_sb.private_sb_info = NULL;
rootfs_sb.sb_ops = &rootfs_sb_ops;
rootfs_sb.dir_ops = &rootfs_dentry_ops;
// 初始化dentry
rootfs_sb.root = vfs_alloc_dentry(sizeof("/"));
struct vfs_dir_entry_t *dentry = rootfs_sb.root;
strncpy(dentry->name, "/", 2);
dentry->name_length = 1;
dentry->parent = dentry;
// 初始化root inode
dentry->dir_inode = vfs_alloc_inode();
dentry->dir_inode->sb = &rootfs_sb;
dentry->dir_inode->inode_ops = &rootfs_inode_ops;
dentry->dir_inode->file_ops = &rootfs_file_ops;
dentry->dir_inode->attribute = VFS_IF_DIR;
// 直接将vfs的根superblock设置为rootfs的超级块
vfs_root_sb = &rootfs_sb;
// 创建/dev等目录的dentry以便文件系统的mount
if (rootfs_add_dir("dev") != 0)
kerror("create dir 'dev' in rootfs failed");
}
/**
* @brief 当新的根文件系统被挂载后将原有的挂载在rootfs下的文件系统迁移到新的根文件系统上
*
*/
static void rootfs_migrate()
{
kdebug("Migrating rootfs's dentries...");
struct List *list = &rootfs_sb.root->subdirs_list;
if (unlikely(list_empty(list)))
return;
list = list_next(list);
while (list != &rootfs_sb.root->subdirs_list)
{
struct vfs_dir_entry_t *tmp = container_of(list, struct vfs_dir_entry_t, child_node_list);
if (tmp->dir_inode != NULL)
{
list = list_next(list); // 获取下一个列表结点(不然的话下面的几行代码就覆盖掉了正确的值了)
tmp->parent = vfs_root_sb->root;
list_init(&tmp->child_node_list);
list_append(&vfs_root_sb->root->subdirs_list, &tmp->child_node_list);
}
else
{
list = list_next(list); // 不迁移空的dentry直接释放他们
list_del(&tmp->child_node_list);
__release_dentry(tmp);
}
}
}
/**
* @brief 当磁盘文件系统被成功挂载后释放rootfs所占的空间
*
*/
void rootfs_umount()
{
// 将原有的“dev”文件夹等进行迁移
rootfs_migrate();
kinfo("Umounting rootfs...");
// 遍历mount链表删除所有父目录是rootfs的dentry
struct mountpoint *mp = NULL;
while (1)
{
mp = mount_find_mnt_list_by_parent(rootfs_sb.root);
if (mp == NULL)
break;
// 释放dentry由于没有创建inode因此不需要释放
__release_dentry(mp->dentry);
// 释放mountpoint结构体
mount_release_mountpoint(mp);
}
// 释放root dentry及其inode
kfree(rootfs_sb.root->dir_inode);
__release_dentry(rootfs_sb.root);
}