superblock_t *ext2_read_super(superblock_t *sb, void *data) { return sb; }
fs_type_t ext2_fs_type = {
- "ext2",
- ext2_read_super,
- 0,
+ .name = "ext2",
+ .read_super = ext2_read_super,
+ .next = 0,
};
+void ext2_setup() { vfs_register_filesystem(&ext2_fs_type); }
+
+//--------------------------------------------------------------------------
struct {
ext2_sb_t ext2_sb;
ext2_gd_t *ext2_gd;
extern void blk_rw(dev_t dev, u64_t offset, u32_t scnt, char *buf);
extern void kmem_cache_free(kmem_cache_t *cache, void *addr);
-#define BLKRW(blkid, blkcnt, buf) \
- do { \
- blk_rw(system.root_dev, 1ULL * (blkid)*EXT2_BLOCK_SIZE, (blkcnt)*EXT2_BLOCK_SIZE, buf); \
+#define BLKRW(blkid, blkcnt, buf) \
+ do { \
+ blk_rw(system.root_dev, 1ULL * (blkid) * EXT2_BLOCK_SIZE, (blkcnt) * EXT2_BLOCK_SIZE, buf); \
} while (0)
kmem_cache_t *ext2_block_cache;
memset(&ext2_fs, 0, sizeof(ext2_fs));
char *buf = kmalloc(EXT2_BLOCK_SIZE, 0);
- if (buf == 0) panic("out of memory");
+ if (buf == 0) {
+ panic("out of memory");
+ }
BLKRW(1, 1, buf); // now blocksize == 1024, so blkid == 1
#include <printk.h>
#include <system.h>
+// void ramfs_setup();
+// void ext2_setup();
+
+// void setup_fs() {
+// ramfs_setup();
+
+// // ext2_setup();
+// }
+
+//--------------------------------------------------------------------------
+
extern chrdev_t cnsl_chrdev;
chrdev_t *chrdev[CHRDEV_SIZE] = {&cnsl_chrdev};
-void ext2_setup_fs();
+// void ext2_setup_fs();
unsigned int ext2_search_inpath(const char *path);
-void setup_fs() { ext2_setup_fs(); }
+// void setup_fs() {
+// ext2_setup_fs();
+// }
unsigned int namei(const char *path) { return ext2_search_inpath(path); }
#include <syscall.h>
#include <types.h>
-int sysc_open(const char *path, int flags, mode_t mode) { return 0; }
+int get_unused_fd() {
+ int fd;
+ task_files_t *files = &(current->files);
+
+ for (int i = 0; i < NR_TASK_OPEN_CNT; i++) {
+ if (files->fds[i] == 0) {
+ return i;
+ }
+ }
+
+ printk("too many open files for %s\n", current->name);
+ return -EMFILE;
+}
+
+file_t *filp_open(const char *path, int flags, mode_t mode) {
+ int ret = 0;
+
+ // ret = open_path(path, flags, mode, nd);
+
+ return NULL;
+}
+
+int sysc_open(const char *path, int flags, mode_t mode) {
+ int fd = 0;
+
+ fd = get_unused_fd();
+
+ if (fd < 0) {
+ return fd;
+ }
+
+ file_t *fp = filp_open(path, flags, mode);
+
+ current->files.fds[fd] = fp;
+
+ return 0;
+}
--- /dev/null
+/*
+ * ------------------------------------------------------------------------
+ * File Name: path.c
+ * Author: Zhao Yanbai
+ * 2024-04-20 19:24:42 Saturday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#include <errno.h>
+#include <fs.h>
+#include <sched.h>
+#include <types.h>
+#include <vfs.h>
+
+bool path_init(const char *path, unsigned int flags, namei_t *ni) {
+ if (path == NULL) {
+ return false;
+ }
+
+ if (*path == '/') {
+ ni->mnt = current->mnt_root;
+ ni->dentry = current->dentry_root;
+ }
+
+ ni->mnt = current->mnt_pwd;
+ ni->dentry = current->dentry_pwd;
+
+ return true;
+}
+
+void follow_dotdot(namei_t *ni) {
+ while (1) {
+ dentry_t *dentry = NULL;
+ vfsmount_t *parent = NULL;
+
+ // 如果当前目录已经是根目录
+ if (ni->dentry == current->dentry_root) {
+ assert(ni->mnt == current->mnt_root);
+ // do nothing
+ return;
+ }
+
+ // 如果当前目录不是挂载的根目录
+ if (ni->dentry != ni->mnt->root) {
+ dentry = ni->dentry->d_parent;
+ ni->dentry = dentry;
+ return;
+ }
+
+ // 当前目录是挂载的根目录,这就需要找到挂载点的上一层目录
+ // 所以先找到挂载点的父挂载点vfsmount
+ parent = ni->mnt->parent;
+
+ // 如果当前挂载点已经是最开始的挂载点vfsmount了
+ if (ni->mnt == parent) {
+ return;
+ }
+
+ // 如果当前挂载点有父挂载点
+ // 就记录当前挂载点的dentry和它所在的挂载vfsmount
+ dentry = ni->mnt->mount_point;
+ ni->dentry = dentry;
+ ni->mnt = parent;
+
+ // 此时有两种情况
+ // 1. dentry 是根目录,就需要继续往上找
+ // 2. dentry 不是根目录,也需要再往上找一层dentry
+ }
+}
+
+int path_walk(const char *path, namei_t *ni) {
+ if (path == NULL) {
+ return -EINVAL;
+ }
+
+ // 先跳过最开始的 '/'
+ while (*path == '/') {
+ path++;
+ }
+
+ // 所有连续'/'之后立即就是'\0'
+ if (*path == 0) {
+ return 0;
+ }
+
+ // 拿到当前目录的 inode
+ inode_t *inode = ni->dentry->d_inode;
+
+ while (1) {
+ qstr_t this;
+ this.name = path;
+
+ do {
+ path++;
+ } while (*path && (*path != '/'));
+
+ this.len = path - this.name;
+
+ // 看是不是路径的最后一个文件名
+ if (*path == 0) {
+ //
+ }
+
+ // 跳过所有连续的 '/'
+ while (*path == '/') {
+ path++;
+ }
+
+ // 看是不是路径其实是以'/'结尾的
+ if (*path == 0) {
+ //
+ }
+
+ // 开始解析name(到这里这个name后跟着的所有的'/'都已经跳过了)
+ if (this.name[0] == '.') {
+ if (this.len == 1) {
+ // 目录无变化,继续下一轮解析
+ continue;
+ } else if (this.len == 2 && this.name[1] == '.') {
+ follow_dotdot(ni);
+ inode = ni->dentry->d_inode;
+ continue;
+ }
+ }
+
+ //
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * ------------------------------------------------------------------------
+ * File Name: ramfs.c
+ * Author: Zhao Yanbai
+ * 2024-04-13 23:43:49 Saturday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#include "ramfs.h"
+
+#include "fs.h"
+#include "mm.h"
+#include "string.h"
+#include "system.h"
+#include "vfs.h"
+
+superblock_t *ramfs_read_super(superblock_t *sb, void *data);
+fs_type_t ramfs_type = {
+ .name = "ramfs",
+ .read_super = ramfs_read_super,
+ .next = 0,
+};
+
+typedef struct ramfs_superblock {
+ //
+} ramfs_superblock_t;
+
+typedef struct ramfs_dentry {
+ // d
+
+} ramfs_dentry_t;
+
+typedef struct ramfs_inode {
+ // d
+} ramfs_inode_t;
+
+void ramfs_init() { vfs_register_filesystem(&ramfs_type); }
+
+superblock_t *ramfs_read_super(superblock_t *sb, void *data) { return sb; }
--- /dev/null
+/*
+ * ------------------------------------------------------------------------
+ * File Name: ramfs.h
+ * Author: Zhao Yanbai
+ * 2024-04-13 23:43:53 Saturday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#pragma once
*/
#include <string.h>
+#include <system.h>
#include <vfs.h>
// 要访问一个文件就必需先访问一个目录,才能根据文件名从目录中找到该文件的目录项,进而找到其inode
add->next = fs;
fs->next = 0;
}
+
+fs_type_t *vfs_find_filesystem(const char *name) {
+ for (fs_type_t *fs = &file_systems; fs != 0; fs = fs->next) {
+ if (strcmp(fs->name, name) == 0) {
+ return fs;
+ }
+ }
+
+ return NULL;
+}
+
+void ramfs_init();
+void vfs_init() {
+ ramfs_init();
+ fs_type_t *fs = vfs_find_filesystem("ramfs");
+ if (NULL == fs) {
+ panic("no ramfs");
+ }
+
+ superblock_t *sb = fs->read_super(NULL, NULL);
+}
#pragma once
#include <list.h>
+#include <types.h>
typedef struct dentry dentry_t;
// super block
typedef struct superblock {
- //
+ // 该超级起的根目录的 dentry
dentry_t *sb_root;
+ //
void *sb_private;
+ //
sb_operations_t *sb_ops;
} superblock_t;
// 缓存的pages
list_head_t i_pages;
+
+ dev_t i_dev; // inode存储在该设备上
+ dev_t i_rdev; // inode所代表的设备号
+
+ loff_t i_size;
} inode_t;
struct dentry {
// 但多个dentry可以指向同一个inode(不实现)
inode_t *d_inode;
+ // 需要一个标记自己已经成为挂载点的标志?
+ // uint32_t d_flags;
+ // 也可以用一个指向vfsmount的指针,非0表示挂载?
+ // 貌似应该搞个链表,因为一个点可以重复挂N次,N个文件系统
+ list_head_t d_vfsmnt; // 所有挂载到这个目录的挂载点
+
//
dentry_operations_t *d_ops;
};
struct sb_operations {
- //
+ // read_inode
};
-struct file_operations {
- // open
- // close
- // read
- // write
- // lseek
- // ioctl
-};
+// struct file_operations {
+// // open
+// // close
+// // read
+// // write
+// // lseek
+// // ioctl
+
+// };
struct inode_operations {
//
};
//
// hash
// compare
+ // d_release 关闭文件
+ // d_delete 删除文件
+ //
};
// 每当将一个存储设备安装到现有文件系统中的某个节点时,内核就要为之建立一个vfsmount结构
// 这个结构中即包含着该设备的有关信息,也包含了安装点的信息
// 系统中的每个文件系统,包括根设备的根文件系统,都要经过安装
+//
+// 在安装文件系统时内核主要做如下的事情
+// 创建一个vfsmount
+// 为被安装的设备创建一个superblock,并由该设备对应的文件系统来设置这个superblock
+// 为被安装的设备的根目录创建一个dentry
+// 为被安装的设备的根目录创建一个inode,由sb->sb_ops->read_inode来实现
+// 将superblock与被安装设备根目录的dentry关联
+// 将vfsmount与被安装设备的根目录dentry关联
typedef struct vfsmount {
+ dentry_t *mount_point; // 挂载点 dentry
+ dentry_t *root; // 设备根目录 dentry
+ superblock_t *sb; // 被安装的设备的superblock
+ struct vfsmount *parent;
+ // sb->sb_ops->read_inode得到被安装设备根目录的inode
+
+ list_head_t list; // vfsmount 链表
+
+ // 先简单实现:不支持一个设备挂载多次,或一个目录被挂载多次
} vfsmount_t;
typedef struct fs_type {
const char *name;
superblock_t *(*read_super)(superblock_t *, void *);
struct fs_type *next;
+ list_head_t sbs; // 同属于这个文件系统的所有超级块链表
} fs_type_t;
extern superblock_t *root_sb;
#include <page.h>
#include <types.h>
+#include <vfs.h>
/* 分区表开始的位置 */
#define PARTS_POS 0x1BE
#define DEV_MINOR_MASK ((1UL << DEV_MAJOR_BITS) - 1)
#define MAKE_DEV(major, minor) ((major) << DEV_MAJOR_BITS | minor)
-#define MAKE_DISK_DEV(drv_no, part_no) MAKE_DEV(DEV_MAJOR_DISK, (((drv_no)&0x03) << 8) | (((part_no)&0xFF) << 0))
+#define MAKE_DISK_DEV(drv_no, part_no) MAKE_DEV(DEV_MAJOR_DISK, (((drv_no) & 0x03) << 8) | (((part_no) & 0xFF) << 0))
#define DEV_MAJOR(dev) ((unsigned int)((dev) >> DEV_MAJOR_BITS))
-#define DEV_MINOR(dev) ((unsigned int)((dev)&DEV_MINOR_MASK))
+#define DEV_MINOR(dev) ((unsigned int)((dev) & DEV_MINOR_MASK))
// #define MAX_SUPT_FILE_SIZE (1)
#define NR_FILES (1)
extern chrdev_t *chrdev[];
-typedef struct {
-} file_t;
+typedef struct file file_t;
+
+typedef struct file_operations {
+ int (*open)(inode_t *, file_t *);
+ ssize_t (*read)(file_t *, char *, size_t, loff_t *);
+} file_operations_t;
+
+struct file {
+ // 多个打开的文件可能是同一个文件
+ dentry_t *f_dentry;
+ file_operations_t *f_ops;
+};
+
+typedef struct namei {
+ vfsmount_t *mnt;
+ dentry_t *dentry;
+} namei_t;
+
+typedef struct qstr {
+ const char *name;
+ unsigned int len;
+} qstr_t;
#if 0
#define NR_FILES (PAGE_SIZE / sizeof(File))
}
#endif
-typedef uint32_t dev_t;
-
#endif //_FS_H
#include <processor.h>
#include <system.h>
#include <types.h>
+#include <vfs.h>
// #include <wait.h>
enum {
#define TASK_MAGIC 0xAABBCCDD11223344
+#define NR_TASK_OPEN_CNT 32
+typedef struct task_files {
+ // 暂时先不用bitmap,直接线性搜索
+ file_t *fds[NR_TASK_OPEN_CNT];
+} task_files_t;
+
typedef union task_union {
struct {
uint32_t esp0; /* kernel stack */
char name[TASK_NAME_SIZE];
+ task_files_t files;
+
+ dentry_t *dentry_root;
+ dentry_t *dentry_pwd;
+
+ vfsmount_t *mnt_root;
+ vfsmount_t *mnt_pwd;
+
list_head_t list; // 所有进程串成一个链表
list_head_t pend; // 某些条件串成一个链表
typedef unsigned long long uint64_t;
typedef long long int64_t;
+typedef uint64_t loff_t;
+
+typedef uint32_t dev_t;
+
typedef unsigned long pid_t;
typedef unsigned long mode_t;
assert(irq_disabled());
reenter++;
+ // TODO 判断打断的是否是内核态代码
+
// 屏蔽当前中断
p->chip->disable(irq);
wrmsr(MSR_SYSENTER_ESP, root_task.esp0, 0);
#endif
+ for (i = 0; i < NR_TASK_OPEN_CNT; i++) {
+ root_task.files.fds[i] = NULL;
+ }
+
printk("init_root_task tss.esp0 %08x\n", tss.esp0);
}