#include <vfs.h>
#define DENTRY_HASH_TABLE_SIZE 233
-static kmem_cache_t *dentry_kmem_cache = NULL;
+static kmem_cache_t *g_dentry_kmem_cache = NULL;
typedef struct {
list_head_t list;
mutex_t mutex;
assert(s->len > 0);
assert(s->len < DENTRY_INLINE_NAME_LEN - 1);
- dentry = kmem_cache_zalloc(dentry_kmem_cache, 0);
+ dentry = kmem_cache_zalloc(g_dentry_kmem_cache, 0);
if (dentry == NULL) {
panic("no mem for dentry");
return dentry;
mutex_unlock(&dhe->mutex);
- return dentry;
+ return NULL;
}
int dentry_real_lookup(dentry_t *parent, qstr_t *s, dentry_t **dentry) {
*dentry = NULL;
int ret = 0;
- down(&parent->d_inode->i_sem);
+ assert(parent->d_inode != NULL);
+ inode_t *dir = parent->d_inode;
+
+ down(&dir->i_sem);
// 在获得信号量后,需要再上cache中查找一遍
// 因为这个过程中当前进程可能会睡眠,当被唤醒后,其它进程已经在内存准备好了
*dentry = dentry_cached_lookup(parent, s);
if (NULL != *dentry) {
- up(&parent->d_inode->i_sem);
+ up(&dir->i_sem);
return ret;
}
if (new_dentry == NULL) {
ret = -ENOMEM;
} else {
- *dentry = parent->d_inode->i_ops->lookup(parent->d_inode, new_dentry);
-
- // 如果找到了,刚分配的,就不用了
- if (*dentry != NULL) {
+ *dentry = dir->i_ops->lookup(dir, new_dentry);
+ // 返回 lookup 没有再分配一个dentry
+ // 否则就释放dentry_new使用lookup返回的dentry
+ if (dentry == NULL) {
+ *dentry = new_dentry;
+ } else {
dentry_put(new_dentry);
}
+ // if (ret == 0) { // 返回0才代表成功
+ // *dentry = new_dentry;
+ // } else {
+ // dentry_put(new_dentry);
+ // }
}
- up(&parent->d_inode->i_sem);
+ up(&dir->i_sem);
return ret;
}
void dentry_cache_init() {
- kmem_cache_t *dentry_kmem_cache = kmem_cache_create("dentry_cache", sizeof(dentry_t), 4);
- if (NULL == dentry_kmem_cache) {
+ g_dentry_kmem_cache = kmem_cache_create("dentry_cache", sizeof(dentry_t), 4);
+ if (NULL == g_dentry_kmem_cache) {
panic("create dentry cache faild");
}
void dentry_cache_init();
dentry_cache_init();
+ void ramfs_init();
+ ramfs_init();
+
void init_mount();
init_mount();
}
--- /dev/null
+/*
+ * ------------------------------------------------------------------------
+ * File Name: fssysc.c
+ * Author: Zhao Yanbai
+ * 2024-09-01 21:41:00 Sunday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#include "fs.h"
+#include "system.h"
+
+//////
+int vfs_mkdir() {
+ int ret = 0;
+
+ return ret;
+}
+
+__attribute__((regparm(0))) long sysc_mkdir(const char *path, int mode) {
+ int ret = 0;
+
+ // TODO 检查参数
+
+ namei_t ni;
+ if (path_init(path, PATH_LOOKUP_PARENT, &ni)) {
+ ret = path_walk(path, &ni);
+ if (0 != ret) {
+ return ret;
+ }
+ }
+
+ dentry_t *dentry;
+ dentry = path_lookup_create(&ni);
+ ret = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ ret = vfs_mkdir(ni.path.dentry, dentry, mode);
+ dentry_put(dentry);
+ }
+
+ up(&ni.path.dentry->d_inode->i_sem);
+
+ return ret;
+}
static file_operations_t empty_fops;
static inode_operations_t empty_iops;
inode->i_sb = sb;
- // inode->i_sem;
+ semaphore_init(&inode->i_sem, 1);
inode->i_fops = &empty_fops;
inode->i_ops = &empty_iops;
inode->i_size = 0;
#include "mm.h"
#include "string.h"
#include "system.h"
+#include "task.h"
kmem_cache_t *vfsmount_kmem_cache = 0;
}
assert(bit1_cnt == 1);
}
+
+void mount_root() {
+ fs_type_t *type = vfs_find_filesystem("ramfs");
+ assert(type != NULL);
+
+ vfsmount_t *mnt = vfs_kernel_mount(type, 0, "ramfs", NULL);
+ assert(mnt != NULL);
+
+ assert(mnt->mnt_root != NULL);
+
+ current->root.mnt = mnt;
+ current->root.dentry = mnt->mnt_root;
+ current->pwd.mnt = mnt;
+ current->pwd.dentry = mnt->mnt_root;
+}
}
if (*path == '/') {
- ni->mnt = current->mnt_root;
- ni->dentry = current->dentry_root;
+ // ni->path.mnt = current->mnt_root;
+ // ni->path.dentry = current->dentry_root;
+ ni->path = current->root;
return true;
}
- ni->mnt = current->mnt_pwd;
- ni->dentry = current->dentry_pwd;
+ // ni->path.mnt = current->mnt_pwd;
+ // ni->path.dentry = current->dentry_pwd;
+ ni->path = current->pwd;
return true;
}
void follow_dotdot(namei_t *ni) {
+#if 1
+ panic("not supported");
+#else
while (1) {
dentry_t *dentry = NULL;
vfsmount_t *parent = NULL;
// 分别产生 vfsmnt_a vfsmnt_b
// 这两个vfsmnt都会挂载到dentry->d_vfsmnt链表上
}
+#endif
}
uint64_t compute_qstr_hash(qstr_t *q) {
}
// 拿到当前目录的 inode
- inode_t *inode = ni->dentry->d_inode;
+ inode_t *inode = ni->path.dentry->d_inode;
+
+ uint32_t path_lookup_flags = ni->flags;
while (true) {
qstr_t this;
do {
path++;
- } while (*path && (*path != '/'));
+ } while (*path != 0 && (*path != '/'));
this.len = path - this.name;
// 看是不是路径的最后一个文件名
if (*path == 0) {
- // 当前是最后一个文件名,且文件名结尾没有带上 '/'
+ goto last_file_name;
}
// 继续解析路径,此时this.name肯定带上了 '/',现在就是要确定它是不是最后一个文件名
// 若路径是以'/'结尾的,则肯定是最后一个文件名
// 但这种情况下,最后这个文件名必需是文件夹名
if (*path == 0) {
+ goto last_file_name_with_slash;
}
// 若除了'/'又遇到了其它字符,则代表当前不是最后一个文件名
} else if (this.len == 2 && this.name[1] == '.') {
// 跳到父目录
follow_dotdot(ni);
- inode = ni->dentry->d_inode;
+ inode = ni->path.dentry->d_inode;
continue;
}
}
compute_qstr_hash(&this);
// 根据该名字,先上dentry cache里找
- dentry = dentry_cached_lookup(ni->dentry, &this);
+ dentry = dentry_cached_lookup(ni->path.dentry, &this);
// 如果找不到就上实际存储设备中去找
if (NULL == dentry) {
- ret = dentry_real_lookup(ni->dentry, &this, &dentry);
+ ret = dentry_real_lookup(ni->path.dentry, &this, &dentry);
if (0 != ret) {
break;
}
}
- // 找到了,先看看它是不是一个挂载点
- while (!list_empty(&dentry->d_vfsmnt)) {
- // 如果是一个挂载点,则更进一步
+ // 找到了,先看其是不是一个挂载点
+ // TODO
+ if (dentry->d_flags & DENTRY_FLAGS_MOUNTED) {
+ panic("not supported");
+ }
+
+ // 不是挂载点 或已经处理完了挂载点
+ ret = -ENOENT;
+ inode = dentry->d_inode;
- // 这种解决的是先将/a 挂载到 /b
- // 再将/b挂载到/c
- // 读/c时,直接读到/a的dentry
+ if (inode == NULL) {
+ goto out_dput_entry;
+ }
+
+ ret = -ENOTDIR;
+ if (!S_ISDIR(inode->i_mode)) {
+ goto out_dput_entry;
+ }
+ if (inode->i_ops == NULL) {
+ goto out_dput_entry;
+ }
+
+ // TODO 判断 symlink
+ // ...
+
+ dentry_put(ni->path.dentry);
+ ni->path.dentry = dentry;
+ assert(inode->i_ops->lookup != NULL);
+
+ // 进入下轮解析
+ continue;
+
+ // ---------------- 以下处理其它逻辑 ----------------
+
+ last_file_name_with_slash:
+ path_lookup_flags |= PATH_LOOKUP_DIRECTORY;
+ last_file_name:
+ if (path_lookup_flags & PATH_LOOKUP_PARENT) {
+ ni->last = this;
+ ni->last_type = LAST_NORMAL;
+ if (this.len == 1 && this.name[0] == '.') {
+ ni->last_type = LAST_DOT;
+ }
+ if (this.len == 2 && this.name[0] == '.' && this.name[1] == '.') {
+ ni->last_type = LAST_DOTDOT;
+ }
+ goto ok;
+ }
+
+ // 最后一个文件名可能是 '.' 或 '..'
+ if (this.len == 1 && this.name[0] == '.') {
+ goto ok;
+ }
+
+ if (this.len == 2 && this.name[0] == '.' && this.name[1] == '.') {
+ follow_dotdot(ni);
+ inode = ni->path.dentry->d_inode;
+ goto ok;
+ }
+
+ // 计算当前文件名的hash
+ compute_qstr_hash(&this);
+
+ // 根据该名字,先上dentry cache里找
+ dentry = dentry_cached_lookup(ni->path.dentry, &this);
+
+ // 如果找不到就上实际存储设备中去找
+ if (NULL == dentry) {
+ ret = dentry_real_lookup(ni->path.dentry, &this, &dentry);
+ if (0 != ret) {
+ break;
+ }
}
- }
+ // 找到了,先看其是不是一个挂载点
+ // TODO
+ if (dentry->d_flags & DENTRY_FLAGS_MOUNTED) {
+ panic("not supported");
+ }
+
+ inode = dentry->d_inode;
+ // TODO 判断 symlink
+ // ...
+
+ dentry_put(dentry);
+ ni->path.dentry = dentry;
+
+ ret = -ENOENT;
+ if (inode == NULL) {
+ if (path_lookup_flags & (PATH_LOOKUP_DIRECTORY | PATH_LOOKUP_MUST_HAVE_INODE)) {
+ goto end;
+ }
+
+ goto ok;
+ }
+
+ if (path_lookup_flags & PATH_LOOKUP_MUST_HAVE_INODE) {
+ ret = -ENOTDIR;
+ if (inode->i_ops == NULL || inode->i_ops->lookup == NULL) {
+ goto end;
+ }
+ }
+ ok:
+ return 0;
+ }
+out_dput_entry:
+ dentry_put(dentry);
+end:
return ret;
}
+
+dentry_t *path_lookup_hash(dentry_t *base, qstr_t *name) {
+ dentry_t *dentry = NULL;
+
+ inode_t *inode = base->d_inode;
+
+ dentry = dentry_cached_lookup(base, name);
+ if (dentry != NULL) {
+ return dentry;
+ }
+
+ dentry_t *dentry_new = dentry_alloc(base, name);
+ if (dentry_new == NULL) {
+ dentry = ERR_PTR(-ENOMEM);
+ return dentry;
+ }
+
+ dentry = inode->i_ops->lookup(inode, dentry_new);
+
+ if (dentry == NULL) { // 返回 lookup 没有再分配一个dentry
+ dentry = dentry_new;
+ } else { // 否则就释放dentry_new使用lookup返回的dentry
+ dentry_put(dentry_new);
+ }
+
+ return dentry;
+}
+
+dentry_t *path_lookup_create(namei_t *ni) {
+ dentry_t *dentry = NULL;
+
+ // 在调用完path_lookup_create后调用 up 操作
+ down(&ni->path.dentry->d_inode->i_sem);
+
+ dentry = ERR_PTR(-EEXIST);
+ if (ni->last_type != LAST_NORMAL) {
+ return dentry;
+ }
+
+ dentry = path_lookup_hash(ni->path.dentry, &ni->last);
+ if (IS_ERR(dentry)) {
+ return dentry;
+ }
+
+ return dentry;
+}
};
-static const inode_operations_t ramfs_dir_inode_operations = {
+static const file_operations_t ramfs_dir_operations = {
+
+};
+
+int ramfs_mkdir(inode_t *, dentry_t *, int) {
+ int ret = 0;
+ return ret;
+}
+
+static const inode_operations_t ramfs_dir_inode_operations = {
+ .mkdir = ramfs_mkdir,
};
inode_t *ramfs_get_inode(superblock_t *sb, umode_t mode, dev_t dev) {
inode->i_ops = &ramfs_file_inode_operations;
break;
case S_IFDIR:
- panic("S_IFDIR: not implement");
- inode->i_fops = &simple_dir_operations;
+ // panic("S_IFDIR: not implement");
+ inode->i_fops = &ramfs_dir_operations;
inode->i_ops = &ramfs_dir_inode_operations;
break;
case S_IFLNK:
break;
}
- return NULL;
+ return inode;
}
static sb_operations_t ramfs_ops = {
return s;
}
+static uint32_t __minor = 0;
+int set_anonymous_super(superblock_t *s, void *data) {
+ s->sb_dev = MAKE_DEV(0, ++__minor);
+ return 0;
+}
+
int read_super_for_nodev(fs_type_t *type, int flags, void *data, fill_super_cb_t fill_super, vfsmount_t *mnt) {
int ret = 0;
superblock_t *s = 0;
// 分配superblock
+ s = sget(type, NULL, set_anonymous_super, NULL);
+
+ assert(s != NULL);
//
s->sb_flags = flags;
ret = fill_super(s, data);
if (0 != ret) {
+ panic("ret: %d", ret);
}
+ mnt->mnt_sb = s;
+ mnt->mnt_root = dentry_get(s->sb_root);
+
return ret;
}
return NULL;
}
-void ramfs_init();
-void vfs_init() {
- ramfs_init();
- fs_type_t *fs = vfs_find_filesystem("ramfs");
- if (NULL == fs) {
- panic("no ramfs");
- }
+// 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);
-}
+// // superblock_t *sb = fs->read_super(NULL, NULL);
+// }
/////////
vfsmount_t *vfsmnt_get(vfsmount_t *m) {
typedef struct vfsmount vfsmount_t;
typedef struct path path_t;
+struct path {
+ dentry_t *dentry;
+ vfsmount_t *mnt;
+};
+
+#define PATH_LOOKUP_PARENT /* */ 0x00000001
+#define PATH_LOOKUP_DIRECTORY /* */ 0x00000002
+#define PATH_LOOKUP_MUST_HAVE_INODE 0x00000004
+
+enum {
+ LAST_FORGET_INIT = 0,
+ LAST_NORMAL = 1,
+ LAST_ROOT,
+ LAST_DOT,
+ LAST_DOTDOT,
+};
+
+typedef struct namei {
+ path_t path;
+ qstr_t last;
+ uint32_t last_type;
+ uint32_t flags;
+} namei_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;
+};
+
// super block
typedef struct superblock {
// 该超级起的根目录的 dentry
list_head_t sb_list;
list_head_t sb_instance;
+
+ dev_t sb_dev;
} superblock_t;
// dentry和inode为什么不合二为一?
umode_t i_mode; // FILE DIR CHR BLK FIFO SOCK
};
+// d_flags
+#define DENTRY_FLAGS_MOUNTED 0x01
+
+// d_inline_name
#define DENTRY_INLINE_NAME_LEN 16
+
struct dentry {
// char *d_name;
uint32_t d_flags;
// };
struct inode_operations {
- //
- dentry_t *(*lookup)(inode_t *i, dentry_t *d);
+ // 用于在inode下找一个dentry->d_small_name的目录项
+ dentry_t *(*lookup)(inode_t *, dentry_t *);
+
+ // 在inode下创建一个dentry->d_small_name的文件
+ int (*create)(inode_t *, dentry_t *, int, namei_t *);
+
+ // 创建文件夹
+ int (*mkdir)(inode_t *, dentry_t *, int);
+
+ // link
+ // unlink
+ // symlink
+ // link 是普通连接 symlink是符号连接
+ // 连接是指一个节点(文件或目录项)直接指向另一个节点,成为为该节点的一个代表
+ // link必需处于同一个设备上,必需连接到一个真实的文件上
+ // symlink可以处于不同的设备上,可以悬空,也就是没有连接到真实的文件上
};
struct dentry_operations {
//
};
-struct path {
- dentry_t *dentry;
- vfsmount_t *mount;
-};
-
// 每当将一个存储设备安装到现有文件系统中的某个节点时,内核就要为之建立一个vfsmount结构
// 这个结构中即包含着该设备的有关信息,也包含了安装点的信息
// 系统中的每个文件系统,包括根设备的根文件系统,都要经过安装
extern superblock_t *root_sb;
int vfs_register_filesystem(fs_type_t *fs);
-
+fs_type_t *vfs_find_filesystem(const char *name);
/////
inode_t *alloc_inode(superblock_t *sb);
dentry_t *dentry_cached_lookup(dentry_t *parent, qstr_t *s);
int dentry_real_lookup(dentry_t *parent, qstr_t *s, dentry_t **dentry);
dentry_t *dentry_alloc_root(inode_t *root_inode);
+dentry_t *dentry_alloc(dentry_t *parent, const qstr_t *s);
vfsmount_t *vfsmnt_get(vfsmount_t *m);
void vfsmnt_put(vfsmount_t *m);
/////
extern const file_operations_t simple_dir_operations;
+
+//
+bool path_init(const char *path, unsigned int flags, namei_t *ni);
+int path_walk(const char *path, namei_t *ni);
+dentry_t *path_lookup_create(namei_t *ni);
#break *0x100000
-b block.c:63
+#b block.c:63
#b task_disk.c:94
#handle SIGINT nostop noprint
+b root_task_entry
+
target remote localhost:1234
extern chrdev_t *chrdev[];
-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))
-#define NR_INODES (2 * NR_FILES)
-#define NR_OPENS (2) /* 一个进程同时打开文件的限制数 */
-extern File file_table[NR_FILES];
-extern Inode inode_table[NR_INODES];
-
-
-typedef struct
-{
- int count;
- int ino_nr;
- pInode inode;
-} File, *pFile;
-
-
-static inline int get_inode_nr(const char *path)
-{
- return ext2_get_file_inode_nr(path);
-}
-
-static inline int get_inode(unsigned int n, pInode inode)
-{
- return ext2_read_inode(n, inode);
-}
-
-static inline int read_file(const pInode inode, void *buf, size_t count)
-{
- return ext2_read_file(inode, buf, count);
-}
-
-/* 在多进程下这样肯定不行
- * 管不了这么多了,先这样写吧
- */
-static inline pInode find_empty_inode()
-{
- int i;
- pInode p = inode_table;
- for(i=0; i<NR_FILES; i++, p++)
- {
- if(p->i_size == 0)
- {
- p->i_size = 1;
- return p;
- }
- }
-
- return NULL;
-}
-#endif
-
typedef int (*fill_super_cb_t)(superblock_t *sb, void *data);
int read_super_for_nodev(fs_type_t *type, int flags, void *data, fill_super_cb_t fill_super, vfsmount_t *mnt);
task_files_t files;
- dentry_t *dentry_root;
- dentry_t *dentry_pwd;
-
- vfsmount_t *mnt_root;
- vfsmount_t *mnt_pwd;
+ path_t root;
+ path_t pwd;
list_head_t list; // 所有进程串成一个链表
init_buffer();
+ void init_mount();
+ init_mount();
+
// printk("kernel: %08x - %08x\n", system.kernel_begin, system.kernel_end);
boot_delay(DEFAULT_BOOT_DELAY_TICKS);
const char *title = "KERNEL MONITOR";
printlxy(MPL_TITLE, (80 - strlen(title)) / 2, title);
+ setup_fs();
+
setup_tasks();
boot_delay(DEFAULT_BOOT_DELAY_TICKS);
+ void mount_root();
+ mount_root();
+
setup_pci();
boot_delay(DEFAULT_BOOT_DELAY_TICKS);
qemu-system-i386 \
-boot d \
+ -m 128 \
-serial tcp::6666,server,nowait \
-drive file=HD.IMG,format=raw,index=0,media=disk \
-drive file=kernel.iso,index=1,media=cdrom \