|
@@ -1,6 +1,224 @@
|
|
#include "rootfs.h"
|
|
#include "rootfs.h"
|
|
#include <filesystem/VFS/VFS.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()
|
|
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);
|
|
}
|
|
}
|