new: rootfs

This commit is contained in:
fslongjin 2022-09-14 23:48:19 +08:00
parent c80f572db7
commit 72f9c430c5
12 changed files with 322 additions and 43 deletions

View File

@ -137,7 +137,8 @@
"internal.h": "c",
"devfs.h": "c",
"devfs-types.h": "c",
"chardev.h": "c"
"chardev.h": "c",
"rootfs.h": "c"
},
"C_Cpp.errorSquiggles": "Enabled",
"esbonio.sphinx.confDir": ""

View File

@ -3,7 +3,7 @@ CFLAGS += -I .
kernel_fs_objs:= $(shell find ./*.c)
kernel_fs_subdirs:= devfs VFS fat32
kernel_fs_subdirs:= devfs VFS fat32 rootfs
ECHO:
@echo "$@"

View File

@ -10,9 +10,7 @@
#include <mm/slab.h>
#include <process/ptrace.h>
#include <process/process.h>
// todo: devfs完善后删除这个
extern struct vfs_file_operations_t ps2_keyboard_fops;
#include <filesystem/rootfs/rootfs.h>
// 为filesystem_type_t结构体实例化一个链表头
static struct vfs_filesystem_type_t vfs_fs = {"filesystem", 0};
@ -30,16 +28,13 @@ struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size);
*/
struct vfs_superblock_t *vfs_mount_fs(const char *path, char *name, struct block_device *blk)
{
// todo: 选择挂载点
// 判断挂载点是否存在
struct vfs_dir_entry_t *target_dentry = NULL;
// 由于目前还没有rootfs因此挂载根目录时不需要path walk
if (strcmp(path, "/") != 0)
{
target_dentry = vfs_path_walk(path, 0);
if (target_dentry == NULL)
return NULL;
}
struct vfs_filesystem_type_t *p = NULL;
for (p = &vfs_fs; p; p = p->next)
@ -282,7 +277,7 @@ int64_t vfs_mkdir(const char *path, mode_t mode, bool from_userland)
else
strncpy(buf, path, last_slash);
buf[last_slash + 1] = '\0';
// kdebug("to walk: %s", buf);
// 查找父目录
struct vfs_dir_entry_t *parent_dir = vfs_path_walk(buf, 0);
@ -368,10 +363,9 @@ uint64_t do_open(const char *filename, int flags)
}
// 为待拷贝文件路径字符串分配内存空间
char *path = (char *)kmalloc(path_len, 0);
char *path = (char *)kzalloc(path_len, 0);
if (path == NULL)
return -ENOMEM;
memset(path, 0, path_len);
strncpy_from_user(path, filename, path_len);
// 去除末尾的 '/'
@ -384,11 +378,6 @@ uint64_t do_open(const char *filename, int flags)
// 寻找文件
struct vfs_dir_entry_t *dentry = vfs_path_walk(path, 0);
// if (dentry != NULL)
// printk_color(ORANGE, BLACK, "Found %s\nDIR_FstClus:%#018lx\tDIR_FileSize:%#018lx\n", path, ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus, dentry->dir_inode->file_size);
// else
// printk_color(ORANGE, BLACK, "Can`t find file\n");
// kdebug("flags=%#018lx", flags);
if (dentry == NULL && flags & O_CREAT)
{
// 先找到倒数第二级目录
@ -420,12 +409,10 @@ uint64_t do_open(const char *filename, int flags)
parent_dentry = vfs_root_sb->root;
// 创建新的文件
dentry = (struct vfs_dir_entry_t *)kmalloc(sizeof(struct vfs_dir_entry_t), 0);
memset(dentry, 0, sizeof(struct vfs_dir_entry_t));
dentry = (struct vfs_dir_entry_t *)kzalloc(sizeof(struct vfs_dir_entry_t), 0);
dentry->name_length = path_len - tmp_index - 1;
dentry->name = (char *)kmalloc(dentry->name_length, 0);
memset(dentry->name, 0, dentry->name_length);
dentry->name = (char *)kzalloc(dentry->name_length + 1, 0);
strncpy(dentry->name, path + tmp_index + 1, dentry->name_length);
// kdebug("to create new file:%s namelen=%d", dentry->name, dentry->name_length)
dentry->parent = parent_dentry;
@ -524,6 +511,8 @@ struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size)
if (unlikely(name_size > VFS_MAX_PATHLEN))
return NULL;
struct vfs_dir_entry_t *dentry = (struct vfs_dir_entry_t *)kzalloc(sizeof(struct vfs_dir_entry_t), 0);
if (unlikely(dentry == NULL))
return NULL;
dentry->name = (char *)kzalloc(name_size, 0);
list_init(&dentry->child_node_list);
list_init(&dentry->subdirs_list);
@ -667,5 +656,6 @@ struct vfs_index_node_t *vfs_alloc_inode()
int vfs_init()
{
mount_init();
rootfs_init();
return 0;
}

View File

@ -47,7 +47,7 @@ struct vfs_dir_entry_operations_t;
struct vfs_dir_entry_t
{
char *name;
int name_length;
int name_length; // 名字的长度(不包含字符串末尾的'\0'
uint32_t d_flags; // dentry标志位
struct List child_node_list;
struct List subdirs_list;

View File

@ -30,9 +30,9 @@ int do_mount(struct vfs_dir_entry_t *old_dentry, struct vfs_dir_entry_t *new_den
mp->dentry = old_dentry;
mp->parent_dentry = old_dentry->parent;
// kdebug("&new_dentry->name=%#018lx, &old_dentry->name=%#018lx", &new_dentry->name, &old_dentry->name);
// 拷贝名称
strncpy(new_dentry->name, old_dentry->name, old_dentry->name_length);
kdebug("new_dentry->name=%s, old_dentry->name=%s, old_dentry->name_length=%d", new_dentry->name, old_dentry->name, old_dentry->name_length);
new_dentry->d_flags |= VFS_DF_MOUNTED; // 标记新的dentry是一个挂载点
@ -61,3 +61,39 @@ int do_umount(struct vfs_dir_entry_t *dentry)
return 0;
}
/**
* @brief mountpoint的父目录dentry查找第一个符合条件的mountpoint结构体
*
* @param dentry dentry
* @return struct mountpoint* mountpoint结构体的指针
*/
struct mountpoint *mount_find_mnt_list_by_parent(struct vfs_dir_entry_t *dentry)
{
struct List *list = &mnt_list_head;
struct mountpoint *ret = NULL;
if (list_empty(list))
return NULL;
while (list_next(list) != &mnt_list_head)
{
list = list_next(list);
struct mountpoint *tmp = container_of(list, struct mountpoint, mnt_list);
if (dentry == tmp->parent_dentry)
return tmp;
}
return NULL;
}
/**
* @brief
*
* @param mp mountpoint结构体
* @return int
*/
int mount_release_mountpoint(struct mountpoint *mp)
{
list_del(&mp->mnt_list);
return kfree(mp);
}

View File

@ -58,3 +58,19 @@ static inline void detach_mounts(struct vfs_dir_entry_t *dentry)
// todo:如果当前文件夹是一个挂载点则对同样挂载在当前文件夹下的dentry进行清理。以免造成内存泄露
// 可参考 linux5.17或以上的detach_mounts()函数
}
/**
* @brief mountpoint的父目录dentry查找第一个符合条件的mountpoint结构体
*
* @param dentry dentry
* @return struct mountpoint* mountpoint结构体的指针
*/
struct mountpoint *mount_find_mnt_list_by_parent(struct vfs_dir_entry_t *dentry);
/**
* @brief
*
* @param mp mountpoint结构体
* @return int
*/
int mount_release_mountpoint(struct mountpoint* mp);

View File

@ -13,7 +13,6 @@ struct vfs_inode_operations_t devfs_inode_ops;
struct vfs_dir_entry_t *devfs_root_dentry; // 根结点的dentry
struct vfs_superblock_t devfs_sb = {0};
const char __devfs_mount_path[] = "/dev";
extern struct vfs_file_operations_t ps2_keyboard_fops;
/**
* @brief devfs的super block
@ -206,11 +205,10 @@ static __always_inline void __devfs_init_root_dentry()
/**
* @brief devfs中注册设备
*
* @param name
* @param device_type
* @param sub_type
* @param file_ops
* @return int
* @param device_type
* @param sub_type
* @param file_ops
* @return int
*/
int devfs_register_device(uint16_t device_type, uint16_t sub_type, struct vfs_file_operations_t *file_ops)
{
@ -254,6 +252,5 @@ void devfs_init()
__devfs_chardev_init();
// todo: 当rootfs实现后将ps/2键盘的注册改为在驱动程序中进行目前没有rootfs因此还不能在不依赖fat32的情况下挂载设备
devfs_register_device(DEV_TYPE_CHAR, CHAR_DEV_STYPE_PS2_KEYBOARD, &ps2_keyboard_fops);
}

View File

@ -7,3 +7,13 @@
*
*/
void devfs_init();
/**
* @brief devfs中注册设备
*
* @param device_type
* @param sub_type
* @param file_ops
* @return int
*/
int devfs_register_device(uint16_t device_type, uint16_t sub_type, struct vfs_file_operations_t *file_ops);

View File

@ -1,6 +1,224 @@
#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);
}

View File

@ -1,3 +1,9 @@
#pragma once
void rootfs_init();
/**
* @brief rootfs所占的空间
*
*/
void rootfs_umount();

View File

@ -20,6 +20,8 @@
#include <sched/sched.h>
#include <filesystem/fat32/fat32.h>
#include <filesystem/VFS/VFS.h>
#include <filesystem/devfs/devfs.h>
#include "driver/multiboot2/multiboot2.h"
#include "driver/acpi/acpi.h"
@ -139,6 +141,8 @@ void system_initialize()
smp_init();
io_mfence();
vfs_init();
devfs_init();
cpu_init();
ps2_keyboard_init();
// ps2_mouse_init();

View File

@ -464,10 +464,11 @@ exec_failed:;
ul initial_kernel_thread(ul arg)
{
// kinfo("initial proc running...\targ:%#018lx", arg);
ahci_init();
vfs_init();
fat32_init();
devfs_init();
rootfs_umount();
// 使用单独的内核线程来初始化usb驱动程序
int usb_pid = kernel_thread(usb_init, 0, 0);