]> Zhao Yanbai Git Server - kernel.git/commitdiff
vfs 初步代码
authoracevest <zhaoyanbai@126.com>
Fri, 7 Jun 2024 15:10:10 +0000 (23:10 +0800)
committeracevest <zhaoyanbai@126.com>
Fri, 23 Aug 2024 11:20:06 +0000 (19:20 +0800)
18 files changed:
fs/dentry.c [new file with mode: 0644]
fs/ext2.c
fs/ext2.h
fs/fs.c
fs/inode.c [new file with mode: 0644]
fs/open.c
fs/path.c [new file with mode: 0644]
fs/ramfs.c [new file with mode: 0644]
fs/ramfs.h [new file with mode: 0644]
fs/vfs.c
fs/vfs.h
include/fs.h
include/semaphore.h
include/task.h
include/types.h
kernel/irq.c
kernel/sched.c
kernel/semaphore.c

diff --git a/fs/dentry.c b/fs/dentry.c
new file mode 100644 (file)
index 0000000..ff51992
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: dentry.c
+ *      Author: Zhao Yanbai
+ *              2024-05-15 20:32:49 Wednesday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#include <errno.h>
+#include <mm.h>
+#include <semaphore.h>
+#include <string.h>
+#include <system.h>
+#include <vfs.h>
+#define DENTRY_HASH_TABLE_SIZE 233
+
+typedef struct {
+    list_head_t list;
+    mutex_t mutex;
+} dentry_hash_entry_t;
+
+dentry_hash_entry_t dentry_hash_table[DENTRY_HASH_TABLE_SIZE] = {
+    0,
+};
+
+uint32_t mod64(uint64_t x, uint32_t y) {
+    uint32_t mod;
+
+    asm("div %3;" : "=d"(mod) : "a"((uint32_t)x), "d"((uint32_t)(x >> 32)), "r"(y) : "cc");
+
+    return mod;
+}
+
+dentry_t *dentry_alloc(dentry_t *parent, qstr_t *s) {
+    dentry_t *dentry = NULL;
+    atomic_set(&dentry->d_count, 1);
+    panic("to do");
+    return dentry;
+}
+
+dentry_t *dentry_cached_lookup(dentry_t *parent, qstr_t *s) {
+    int index = mod64(s->hash, DENTRY_HASH_TABLE_SIZE);
+    assert(index < DENTRY_HASH_TABLE_SIZE);
+
+    dentry_hash_entry_t *dhe = dentry_hash_table + index;
+
+    dentry_t *dentry = NULL;
+
+    mutex_lock(&dhe->mutex);
+
+    list_head_t *p;
+    list_for_each(p, &dhe->list) {
+        dentry = list_entry(p, dentry_t, d_hash);
+        assert(dentry != NULL);
+
+        if (dentry->d_name.hash != s->hash) {
+            continue;
+        }
+
+        if (dentry->d_name.len != s->len) {
+            continue;
+        }
+
+        if (dentry->d_parent != parent) {
+            continue;
+        }
+
+        if (memcmp(dentry->d_name.name, s->name, s->len) != 0) {
+            continue;
+        }
+
+        dentry_get_locked(dentry);
+
+        break;
+    }
+
+    mutex_unlock(&dhe->mutex);
+
+    return dentry;
+}
+int dentry_real_lookup(dentry_t *parent, qstr_t *s, dentry_t **dentry) {
+    *dentry = NULL;
+    int ret = 0;
+
+    down(&parent->d_inode->i_sem);
+
+    // 在获得信号量后,需要再上cache中查找一遍
+    // 因为这个过程中当前进程可能会睡眠,当被唤醒后,其它进程已经在内存准备好了
+    *dentry = dentry_cached_lookup(parent, s);
+
+    if (NULL != *dentry) {
+        up(&parent->d_inode->i_sem);
+        return ret;
+    }
+
+    dentry_t *new_dentry = dentry_alloc(parent, s);
+    if (new_dentry == NULL) {
+        ret = -ENOMEM;
+    } else {
+        *dentry = parent->d_inode->i_ops->lookup(parent->d_inode, new_dentry);
+
+        // 如果找到了,刚分配的,就不用了
+        if (*dentry != NULL) {
+            dentry_put(new_dentry);
+        }
+    }
+
+    up(&parent->d_inode->i_sem);
+
+    return ret;
+}
+
+kmem_cache_t *dentry_kmem_cache = NULL;
+
+void dentry_cache_init() {
+    kmem_cache_t *dentry_kmem_cache = kmem_cache_create("dentry_cache", sizeof(dentry_t), 4);
+    if (NULL == dentry_kmem_cache) {
+        panic("create dentry cache faild");
+    }
+
+    for (int i = 0; i < DENTRY_HASH_TABLE_SIZE; i++) {
+        dentry_hash_entry_t *dhe = dentry_hash_table + i;
+        list_init(&dhe->list);
+        mutex_init(&dhe->mutex);
+    }
+}
+
+dentry_t *dentry_get(dentry_t *dentry) {
+    assert(dentry != NULL);
+    atomic_inc(&dentry->d_count);
+    return dentry;
+}
+
+void dentry_get_locked(dentry_t *dentry) {}
+
+void dentry_put(dentry_t *dentry) { panic("todo"); }
+
+// static __inline__ struct dentry * dget(struct dentry *dentry)
+// {
+//     if (dentry) {
+//             if (!atomic_read(&dentry->d_count))
+//                     BUG();
+//             atomic_inc(&dentry->d_count);
+//     }
+//     return dentry;
+// }
+
+// static inline struct dentry * __dget_locked(struct dentry *dentry)
+// {
+//     atomic_inc(&dentry->d_count);
+//     if (atomic_read(&dentry->d_count) == 1) {
+//             dentry_stat.nr_unused--;
+//             list_del(&dentry->d_lru);
+//             INIT_LIST_HEAD(&dentry->d_lru);         /* make "list_empty()" work */
+//     }
+//     return dentry;
+// }
+
+// struct dentry * dget_locked(struct dentry *dentry)
+// {
+//     return __dget_locked(dentry);
+// }
index 36345ce11090659a2871b8fe46fc56e64fe3d651..ffa6e1b551037798660ceade2f1d0a40cee30fe8 100644 (file)
--- a/fs/ext2.c
+++ b/fs/ext2.c
 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;
@@ -30,9 +33,9 @@ struct {
 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;
@@ -213,7 +216,9 @@ void ext2_setup_fs() {
     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
 
index b5e88a603c99eb1e00fb76407fb22de49e977cf0..b76eb2168da21956b3d98f57bc8d9bc4dbc832b4 100644 (file)
--- a/fs/ext2.h
+++ b/fs/ext2.h
@@ -179,13 +179,6 @@ typedef struct ext2_inode {
 } ext2_inode_t;
 
 #define EXT2_NAME_LEN 255
-typedef struct ext2_dir_ent {
-    u32 inode;
-    u16 rec_len;
-    u8 name_len;
-    u8 file_type;
-    char name[EXT2_NAME_LEN];
-} ext2_dirent_t;
 
 /*
  * Ext2 目录类型.
@@ -202,6 +195,13 @@ enum {
     EXT2_FT_SYMLINK,
     EXT2_FT_MAX
 };
+typedef struct ext2_dir_ent {
+    u32 inode;
+    u16 rec_len;
+    u8 name_len;
+    u8 file_type;
+    char name[EXT2_NAME_LEN];
+} ext2_dirent_t;
 
 #define EXT2_DIR_PAD 4
 #define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
diff --git a/fs/fs.c b/fs/fs.c
index 008818910ceb1e2c7d5dabf35741c23cf6392862..cde27a894501c9de547fa4eaf4475adad7183e82 100644 (file)
--- a/fs/fs.c
+++ b/fs/fs.c
 #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); }
diff --git a/fs/inode.c b/fs/inode.c
new file mode 100644 (file)
index 0000000..142839d
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: inode.c
+ *      Author: Zhao Yanbai
+ *              2024-05-15 20:32:55 Wednesday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
index 46ff07e4ce755c05927d983c816325394176cf69..54c57b365900952c33dc56ec20ea413442f86f1e 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
 #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;
+}
diff --git a/fs/path.c b/fs/path.c
new file mode 100644 (file)
index 0000000..c3f33a3
--- /dev/null
+++ b/fs/path.c
@@ -0,0 +1,210 @@
+/*
+ * ------------------------------------------------------------------------
+ *   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;
+        return true;
+    }
+
+    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->mnt_root) {
+            dentry = ni->dentry->d_parent;
+            ni->dentry = dentry;
+            return;
+        }
+
+        // 当前目录是挂载的根目录,这就需要找到挂载点的上一层目录
+        // 所以先找到挂载点的父挂载点vfsmount
+        parent = ni->mnt->mnt_parent;
+
+        // 如果当前挂载点已经是最开始的挂载点vfsmount了
+        if (ni->mnt == parent) {
+            return;
+        }
+
+        // 如果当前挂载点有父挂载点
+        // 就记录当前挂载点的dentry和它所在的挂载vfsmount
+        dentry = ni->mnt->mnt_point;
+        ni->dentry = dentry;
+        ni->mnt = parent;
+
+        // 此时有两种情况
+        // 1. dentry 是根目录,就需要继续往上找
+        // 2. dentry 不是根目录,也需要再往上找一层dentry
+
+        // 关于这个循环可能处理的情况举例如下:
+
+        // case1
+        // 以 /root/aa/.. 为例 代表的是 /root
+        // 如果 挂载一个目录到 /root/aa/
+        // 这时 dentry 指向的是 aa
+        // 还需要再往上走一层
+
+        // case2
+        // 假设 /mnt/a 挂载到 /mnt/b 后, /mnt/b 再挂载到 /mnt/c
+        // 分别产生vfsmnt_a vfsmnt_b
+        // 对于路径/mnt/c/..当读到c时,对于它的dentry,会最终读到a的dentry
+        // 对于..
+        // 第一次循环 dentry为b的dentry,mnt为 vfsmnt_b
+        // 第二次循环 dentry为c的dentry, mnt为 vfsmnt_a
+        // 第三次循环,dentry为mnt的dentry,mnt为mnt_root
+
+        // case3
+        // 假设 /mnt/a 挂载到 /mnt/c 后, /mnt/b 再挂载到 /mnt/c
+        // 分别产生 vfsmnt_a vfsmnt_b
+        // 这两个vfsmnt都会挂载到dentry->d_vfsmnt链表上
+    }
+}
+
+uint64_t compute_qstr_hash(qstr_t *q) {
+    q->hash = 0;
+    for (int i = 0; i < q->len; i++) {
+        uint64_t x = (uint64_t)(q->name[i]);
+        q->hash = (x << 4) | (x >> (8 * sizeof(q->hash) - 4));
+    }
+
+    q->hash += q->hash >> (4 * sizeof(q->hash));
+
+    return q->hash;
+}
+
+int follow_down(dentry_t **dentry, vfsmount_t **vfsmnt) {
+    assert(*dentry != NULL);
+    assert(*vfsmnt != NULL);
+
+    list_head_t *pos;
+    list_for_each(pos, &((*dentry)->d_vfsmnt)) {
+        vfsmount_t *tmp_mnt = list_entry(pos, vfsmount_t, mnt_clash);
+        if (*vfsmnt == tmp_mnt->mnt_parent) {
+            *vfsmnt = vfsmnt_get(tmp_mnt);
+            vfsmnt_put(tmp_mnt->mnt_parent);
+
+            dentry_put(*dentry);
+            *dentry = dentry_get(tmp_mnt->mnt_root);
+        }
+    }
+}
+
+int path_walk(const char *path, namei_t *ni) {
+    dentry_t *dentry;
+    int ret = 0;
+    if (path == NULL) {
+        return -EINVAL;
+    }
+
+    // 先跳过最开始的 '/'
+    while (*path == '/') {
+        path++;
+    }
+
+    // 所有连续'/'之后立即就是'\0'就当作 '/'处理
+    if (*path == 0) {
+        return 0;
+    }
+
+    // 拿到当前目录的 inode
+    inode_t *inode = ni->dentry->d_inode;
+
+    while (true) {
+        qstr_t this;
+        this.name = path;
+
+        do {
+            path++;
+        } while (*path && (*path != '/'));
+
+        this.len = path - this.name;
+
+        // 看是不是路径的最后一个文件名
+        if (*path == 0) {
+            // 当前是最后一个文件名,且文件名结尾没有带上 '/'
+        }
+
+        // 继续解析路径,此时this.name肯定带上了 '/',现在就是要确定它是不是最后一个文件名
+        // 首先,跳过所有连续的 '/'
+        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;
+            }
+        }
+
+        // 计算当前文件名的hash
+        compute_qstr_hash(&this);
+
+        // 根据该名字,先上dentry cache里找
+        dentry = dentry_cached_lookup(ni->dentry, &this);
+
+        // 如果找不到就上实际存储设备中去找
+        if (NULL == dentry) {
+            ret = dentry_real_lookup(ni->dentry, &this, &dentry);
+            if (0 != ret) {
+                break;
+            }
+        }
+
+        // 找到了,先看看它是不是一个挂载点
+        while (!list_empty(&dentry->d_vfsmnt)) {
+            // 如果是一个挂载点,则更进一步
+
+            // 这种解决的是先将/a 挂载到 /b
+            // 再将/b挂载到/c
+            // 读/c时,直接读到/a的dentry
+        }
+    }
+
+    return ret;
+}
diff --git a/fs/ramfs.c b/fs/ramfs.c
new file mode 100644 (file)
index 0000000..e1caf28
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * ------------------------------------------------------------------------
+ *   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; }
diff --git a/fs/ramfs.h b/fs/ramfs.h
new file mode 100644 (file)
index 0000000..4fd1d9a
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: ramfs.h
+ *      Author: Zhao Yanbai
+ *              2024-04-13 23:43:53 Saturday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#pragma once
index d1ab375a0341752edc4bc06ad42a555ee36bdc18..525dce5ddb9631fd8096e743d70842df74584e6f 100644 (file)
--- a/fs/vfs.c
+++ b/fs/vfs.c
@@ -8,6 +8,7 @@
  */
 
 #include <string.h>
+#include <system.h>
 #include <vfs.h>
 
 // 要访问一个文件就必需先访问一个目录,才能根据文件名从目录中找到该文件的目录项,进而找到其inode
@@ -42,3 +43,34 @@ void vfs_register_filesystem(fs_type_t *fs) {
     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);
+}
+
+/////////
+vfsmount_t *vfsmnt_get(vfsmount_t *m) {
+    panic("todo");
+    return NULL;
+}
+void vfsmnt_put(vfsmount_t *m) {
+    //
+    panic("todo");
+}
index af9dee58de5404c5df9164dfcb7821e7831a5cfb..6a9e75ebba96badf86d0a2103fe37c3514b750c8 100644 (file)
--- a/fs/vfs.h
+++ b/fs/vfs.h
@@ -9,7 +9,16 @@
 
 #pragma once
 
+#include <atomic.h>
 #include <list.h>
+#include <semaphore.h>
+#include <types.h>
+
+typedef struct qstr {
+    const char *name;
+    unsigned int len;
+    uint64_t hash;
+} qstr_t;
 
 typedef struct dentry dentry_t;
 
@@ -20,9 +29,11 @@ typedef struct dentry_operations dentry_operations_t;
 
 // super block
 typedef struct superblock {
-    //
+    // 该超级起的根目录的 dentry
     dentry_t *sb_root;
+    //
     void *sb_private;
+    //
     sb_operations_t *sb_ops;
 } superblock_t;
 
@@ -39,6 +50,8 @@ typedef struct inode {
 
     void *i_private;
 
+    semaphore_t i_sem;
+
     // fops - file ops 的副本
     file_operations_t *i_fops;
 
@@ -47,10 +60,20 @@ typedef struct inode {
 
     // 缓存的pages
     list_head_t i_pages;
+
+    dev_t i_dev;   // inode存储在该设备上
+    dev_t i_rdev;  // inode所代表的设备号
+
+    loff_t i_size;
 } inode_t;
 
+#define DENTRY_INLINE_NAME_LEN 16
 struct dentry {
-    char *d_name;
+    // char *d_name;
+    qstr_t d_name;
+    char d_inline_name[DENTRY_INLINE_NAME_LEN];
+
+    atomic_t d_count;
 
     //
     dentry_t *d_parent;
@@ -60,6 +83,8 @@ struct dentry {
     list_head_t d_child;
     list_head_t d_subdirs;
 
+    list_head_t d_hash;
+
     //
     superblock_t *d_sb;
 
@@ -67,6 +92,12 @@ 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;
 
@@ -75,39 +106,79 @@ struct dentry {
 };
 
 struct sb_operations {
-    //
+    // alloc inode
+    inode_t *alloc_inode(superblock_t *sb);
+    // read_inode
 };
 
-struct file_operations {
-    // open
-    // close
-    // read
-    // write
-    // lseek
-    // ioctl
-};
+// struct file_operations {
+//     // open
+//     // close
+//     // read
+//     // write
+//     // lseek
+//     // ioctl
+
+// };
 struct inode_operations {
     //
+    dentry_t *(*lookup)(inode_t *i, dentry_t *d);
 };
 
 struct dentry_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 *mnt_point;   // 挂载点 dentry
+    dentry_t *mnt_root;    // 设备根目录 dentry
+    superblock_t *mnt_sb;  // 被安装的设备的superblock
+    struct vfsmount *mnt_parent;  // 如果多个设备挂载到同一个目录,则每个vfsmount的parent都指向同一个vfsmount
+    // sb->sb_ops->read_inode得到被安装设备根目录的inode
+
+    list_head_t mnt_list;  // vfsmount 链表
+
+    list_head_t mnt_clash;
+
+    // 先简单实现:不支持一个设备挂载多次,或一个目录被挂载多次
 } 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;
 
 void vfs_register_filesystem(fs_type_t *fs);
+
+/////
+
+dentry_t *dentry_cached_lookup(dentry_t *parent, qstr_t *s);
+int dentry_real_lookup(dentry_t *parent, qstr_t *s, dentry_t **dentry);
+
+vfsmount_t *vfsmnt_get(vfsmount_t *m);
+void vfsmnt_put(vfsmount_t *m);
+
+dentry_t *dentry_get(dentry_t *dentry);
+void dentry_get_locked(dentry_t *dentry);
+
+void dentry_put(dentry_t *dentry);
index 7750690b24dacde030d4e649d3b007b6ab8a9db3..12b8deccce6d1ae4a4ee653dc05e0a8716994ca8 100644 (file)
@@ -15,6 +15,7 @@
 
 #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)
@@ -53,8 +54,25 @@ enum { CHRDEV_CNSL, CHRDEV_SIZE };
 
 extern chrdev_t *chrdev[];
 
-typedef struct {
-} file_t;
+typedef struct file file_t;
+
+typedef struct file_operations {
+    int (*open)(inode_t *, file_t *);
+    int (*release)(inode_t *, file_t *);
+    ssize_t (*read)(file_t *, char *, size_t, loff_t *);
+    ssize_t (*write)(file_t *, const 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;
 
 #if 0
 #define NR_FILES (PAGE_SIZE / sizeof(File))
@@ -107,6 +125,4 @@ static inline pInode find_empty_inode()
 }
 #endif
 
-typedef uint32_t dev_t;
-
 #endif  //_FS_H
index 207341cb428e48770733035c4a9fa3ff125215d0..cd826def333fd56f9d3100ad58f882e4aa4b9e52 100644 (file)
@@ -9,9 +9,7 @@
 
 #pragma once
 
-#include <irq.h>
 #include <list.h>
-#include <task.h>
 
 typedef struct semaphore {
     volatile unsigned int cnt;
@@ -44,5 +42,6 @@ typedef semaphore_t mutex_t;
         (ptr)->cnt = 1;                      \
         INIT_LIST_HEAD(&((ptr)->wait_list)); \
     } while (0)
+void mutex_init(mutex_t *);
 void mutex_lock(mutex_t *);
 void mutex_unlock(mutex_t *);
index eebbf8d4ac7bed5ecf042e8ddb5a01b946a7f02c..f91562f41e1ccc51136a383da2e17e8626cddbb5 100644 (file)
@@ -22,6 +22,7 @@
 #include <processor.h>
 #include <system.h>
 #include <types.h>
+#include <vfs.h>
 // #include <wait.h>
 
 enum {
@@ -40,6 +41,12 @@ 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 */
@@ -68,6 +75,14 @@ typedef union task_union {
 
         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;  // 某些条件串成一个链表
index 04a3aaad23da66ce14ab253c022971ab31aa4ee8..62c2b65dd00b56cad16460fb967e0529b0d77929 100644 (file)
@@ -50,6 +50,10 @@ typedef long int32_t;
 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;
 
index 36f1b615affb05357ec65b42cf3d0fc53314aec7..770f4581a68e6a3c5121a1d32c2c31bf3b7fa84b 100644 (file)
@@ -96,6 +96,8 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) {
     assert(reenter >= 0);
     assert(reenter <= 1);
 
+    // TODO 判断打断的是否是内核态代码
+
     // 屏蔽当前中断
     p->chip->disable(irq);
 
index cace86f77ba4648ed2c74e21f8dc54c87b146bc2..08a98e6626efa0f0f07e9880c9b550b14f55c22b 100644 (file)
@@ -83,6 +83,10 @@ void init_root_task() {
     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);
 }
 
index 23763a5cb8219eb9855576327fc240d2590a4de3..7207a3ec743a74766c021cc4831eb2ed598d517b 100644 (file)
@@ -9,6 +9,7 @@
 #include <irq.h>
 #include <sched.h>
 #include <semaphore.h>
+#include <task.h>
 
 typedef struct semaphore_waiter {
     list_head_t list;
@@ -77,5 +78,6 @@ volatile void up(semaphore_t *s) {
     }
 }
 
+void mutex_init(mutex_t *s) { INIT_MUTEX(s); }
 void mutex_lock(semaphore_t *s) { down(s); }
 void mutex_unlock(semaphore_t *s) { up(s); }