From: acevest Date: Mon, 23 Sep 2024 06:57:10 +0000 (+0800) Subject: vfs_create相关修改,部分sysc_write逻辑 X-Git-Url: http://zhaoyanbai.com/repos/icons/debian/static/%22http:/valid-xhtml10.png?a=commitdiff_plain;h=4383e27d94ca77b4d3329c547ca35c1bc85025c0;p=kernel.git vfs_create相关修改,部分sysc_write逻辑 --- diff --git a/.gitignore b/.gitignore index e603669..7e9c83e 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ *.IMG *.img +*.vdi *build* *.BIN *.ELF diff --git a/fs/file.c b/fs/file.c new file mode 100644 index 0000000..f10c7dd --- /dev/null +++ b/fs/file.c @@ -0,0 +1,105 @@ +/* + * ------------------------------------------------------------------------ + * File Name: file.c + * Author: Zhao Yanbai + * 2024-09-18 12:14:26 Wednesday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +#include +#include +#include + +file_t *get_file(int fd) { + assert(fd >= 0); + assert(fd < NR_TASK_OPEN_CNT); + + file_t *fp = current->files.fds[fd]; + + // TOOD 添加对fp的引用记数 + + return fp; +} + +////////// +const uint32_t PAGE_HASH_BITS = 10; +const uint32_t PAGE_HASH_SIZE = 1 << PAGE_HASH_BITS; +page_t **page_hash_table = NULL; + +static uint32_t page_hash_func(address_space_t *mapping, uint32_t index) { + uint32_t i = (((uint32_t)mapping) / (sizeof(inode_t) & ~(sizeof(inode_t) - 1))); +#define s(x) ((x) + (x) >> PAGE_HASH_BITS) + return s(i + index) & (PAGE_HASH_SIZE - 1); +#undef s +} + +page_t *page_hash(address_space_t *mapping, uint32_t index) { + uint32_t hash = page_hash_func(mapping, index); + assert(hash < PAGE_HASH_SIZE); + + return page_hash_table[hash]; +} + +page_t *find_hash_page(address_space_t *mapping, uint32_t index) { + page_t *page = NULL; + + uint32_t hash = page_hash_func(mapping, index); + assert(hash < PAGE_HASH_SIZE); + + ENTER_CRITICAL_ZONE(EFLAGS); + + page_t *p = page_hash_table[hash]; + + while (p != NULL) { + if (p->mapping != mapping) { + continue; + } + if (p->index == index) { + page = p; + break; + } + } + + EXIT_CRITICAL_ZONE(EFLAGS); + + return page; +} + +void add_page_to_hash(page_t *page, address_space_t *mapping, uint32_t index) { + uint32_t hash = page_hash_func(mapping, index); + assert(hash < PAGE_HASH_SIZE); + + ENTER_CRITICAL_ZONE(EFLAGS); + page_t *p = 0; + p = page_hash_table[hash]; + page->hash_next = p; + page_hash_table[hash] = page; + EXIT_CRITICAL_ZONE(EFLAGS); +} + +page_t *get_cached_page(address_space_t *mapping, uint32_t index) { + page_t *page = NULL; + page = find_hash_page(mapping, index); + + if (NULL == page) { + page = alloc_one_page(0); + assert(page != NULL); + + page->index = index; + + add_page_to_hash(page, mapping, index); + + ENTER_CRITICAL_ZONE(EFLAGS); + list_add(&page->list, &mapping->pages); + EXIT_CRITICAL_ZONE(EFLAGS); + } + + return page; +} + +void vfs_page_cache_init() { + page_hash_table = (page_t **)page2va(alloc_one_page(0)); + assert(page_hash_table != NULL); + memset(page_hash_table, 0, PAGE_SIZE); +} diff --git a/fs/fs.c b/fs/fs.c index cd800ad..9125c99 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -42,6 +42,9 @@ dentry_t rootfs_root_dentry; void setup_fs() { // ext2_setup_fs(); + void vfs_page_cache_init(); + vfs_page_cache_init(); + void inode_cache_init(); inode_cache_init(); diff --git a/fs/fssysc.c b/fs/fssysc.c index f528d9e..255b964 100644 --- a/fs/fssysc.c +++ b/fs/fssysc.c @@ -12,24 +12,6 @@ #include "system.h" ////// -int vfs_mkdir(inode_t *dir, dentry_t *dentry, int mode) { - int ret = 0; - - // TODO REMOVE - assert(dir->i_ops->mkdir != NULL); - - if (dir->i_ops->mkdir == NULL) { - return -EPERM; - } - - ret = dir->i_ops->mkdir(dir, dentry, mode); - - if (0 != ret) { - printk("%s ret %d\n", __func__, ret); - } - - return ret; -} __attribute__((regparm(0))) long sysc_mkdir(const char *path, int mode) { int ret = 0; diff --git a/fs/path.c b/fs/path.c index 98f5ec1..25dfb3a 100644 --- a/fs/path.c +++ b/fs/path.c @@ -380,7 +380,7 @@ int path_open_namei(const char *path, int flags, int mode, namei_t *ni) { dentry_t *dir = NULL; inode_t *inode = NULL; - if (flags % O_CREAT == 0) { + if ((flags & O_CREAT) == 0) { path_init(path, flags, ni); ret = path_walk(path, ni); if (0 != ret) { @@ -415,11 +415,24 @@ int path_open_namei(const char *path, int flags, int mode, namei_t *ni) { if (NULL == dentry->d_inode) { // vfs_create(); + + ret = vfs_create(dir->d_inode, dentry, mode, ni); + up(&dir->d_inode->i_sem); dentry_put(ni->path.dentry); + if (0 != ret) { + goto end; + } goto ok; } + // 上述是文件不存在的逻辑 + // 此处是文件存在的情况下的处理逻辑 + + if ((flags & O_EXCL) == 0) { + panic("unsupport O_EXCL") + } + ok: inode = dentry->d_inode; if (NULL == inode) { diff --git a/fs/ramfs.c b/fs/ramfs.c index 93a225e..ef1ca11 100644 --- a/fs/ramfs.c +++ b/fs/ramfs.c @@ -42,6 +42,7 @@ inode_t *ramfs_get_inode(superblock_t *sb, umode_t mode, dev_t dev); static const file_operations_t ramfs_file_operations = { .read = 0, + .write = 0, }; static const inode_operations_t ramfs_file_inode_operations = { diff --git a/fs/vfs.c b/fs/vfs.c index e7ceae4..836a285 100644 --- a/fs/vfs.c +++ b/fs/vfs.c @@ -85,3 +85,33 @@ void vfsmnt_put(vfsmount_t *m) { // panic("todo"); } + +int vfs_create(inode_t *dir, dentry_t *dentry, int mode, namei_t *ni) { + int ret = 0; + + assert(dir->i_ops != NULL); + assert(dir->i_ops->create != NULL); + + ret = dir->i_ops->create(dir, dentry, mode, ni); + + return ret; +} + +int vfs_mkdir(inode_t *dir, dentry_t *dentry, int mode) { + int ret = 0; + + // TODO REMOVE + assert(dir->i_ops->mkdir != NULL); + + if (dir->i_ops->mkdir == NULL) { + return -EPERM; + } + + ret = dir->i_ops->mkdir(dir, dentry, mode); + + if (0 != ret) { + printk("%s ret %d\n", __func__, ret); + } + + return ret; +} diff --git a/fs/vfs.h b/fs/vfs.h index 40f60ff..9902063 100644 --- a/fs/vfs.h +++ b/fs/vfs.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -29,6 +30,9 @@ typedef struct dentry_operations dentry_operations_t; typedef struct vfsmount vfsmount_t; typedef struct path path_t; +typedef struct address_space_operations address_space_operations_t; +typedef struct address_space address_space_t; + struct path { dentry_t *dentry; vfsmount_t *mnt; @@ -66,6 +70,9 @@ struct file { // 多个打开的文件可能是同一个文件 dentry_t *f_dentry; file_operations_t *f_ops; + + loff_t f_pos; + uint32_t f_flags; }; // super block @@ -86,6 +93,18 @@ typedef struct superblock { dev_t sb_dev; } superblock_t; +struct address_space_operations { + int (*write_page)(page_t *); + int (*read_page)(page_t *, file_t *file); +}; + +struct address_space { + list_head_t pages; + uint32_t total_pages; + inode_t *a_inode; + address_space_operations_t *a_ops; +}; + // dentry和inode为什么不合二为一? // 每一个文件除了有一个索引节点inode(里面记录着文件在存储介质上的位置和分布信息)外还有一个目录项dentry // 同时dentry还有个指针指向inode结构 @@ -116,6 +135,8 @@ struct inode { loff_t i_size; umode_t i_mode; // FILE DIR CHR BLK FIFO SOCK + + address_space_t i_mapping; }; // d_flags @@ -256,6 +277,10 @@ int vfs_register_filesystem(fs_type_t *fs); fs_type_t *vfs_find_filesystem(const char *name); ///// +int vfs_create(inode_t *dir, dentry_t *dentry, int mode, namei_t *ni); +int vfs_mkdir(inode_t *dir, dentry_t *dentry, int mode); +//// + inode_t *alloc_inode(superblock_t *sb); void init_special_inode(inode_t *inode, umode_t mode, dev_t rdev); //// diff --git a/fs/write.c b/fs/write.c index 82d9af7..5ac4ca7 100644 --- a/fs/write.c +++ b/fs/write.c @@ -15,19 +15,82 @@ */ #include +#include +#include +#include +#include +ssize_t vfs_generic_file_write(file_t *file, const char *buf, size_t size, loff_t *p_pos) { + ssize_t ret = 0; -extern void vga_puts(unsigned int nr, const char *buf, unsigned char color); -int sysc_write(int fd, const char *buf, unsigned long size) { - if (size < 0) return -1; - - switch (fd) { - case 0: - assert(0); - // vga_puts(0, buf, 0xF); - break; - default: - return -1; + loff_t pos = *p_pos; + if (buf == NULL || size < 0 || pos < 0) { + return -EINVAL; } - return size; + assert(file->f_dentry->d_inode != NULL); + assert((file->f_flags & O_APPEND) == O_APPEND); // 目前只支持这个 + + inode_t *inode = file->f_dentry->d_inode; + + down(&inode->i_sem); + + while (size > 0) { + uint32_t index = pos >> PAGE_SHIFT; + uint32_t offset = pos & (PAGE_SIZE - 1); + uint32_t bytes = PAGE_SIZE - offset; + if (size < bytes) { + bytes = size; + } + + // + } + +end: + up(&inode->i_sem); + + return ret; } + +ssize_t sysc_write(int fd, const char *buf, size_t size) { + ssize_t ret = 0; + + file_t *file = get_file(fd); + if (NULL == file) { + return -EBADF; + } + + // TODO 检查文件是否有写权限 + + inode_t *inode = file->f_dentry->d_inode; + + assert(file->f_ops != 0); + assert(file->f_ops->write != 0); + assert(inode->i_fops != 0); + assert(inode->i_fops->write != 0); + assert(file->f_ops->write == inode->i_fops->write); + + ssize_t (*write)(file_t *, const char *, size_t, loff_t *); + write = file->f_ops->write; + + ret = write(file, buf, size, &file->f_pos); + + // TODO 释放file的引用计数 + + return ret; +} + +// extern void vga_puts(unsigned int nr, const char *buf, unsigned char color); +// int sysc_write(int fd, const char *buf, unsigned long size) { +// if (size < 0) return -1; + +// switch (fd) { +// case 0: +// assert(0); +// // vga_puts(0, buf, 0xF); +// break; +// default: +// return -1; +// } + +// return size; +// } diff --git a/include/fs.h b/include/fs.h index be93260..b96b7ee 100644 --- a/include/fs.h +++ b/include/fs.h @@ -65,4 +65,6 @@ superblock_t *sget(fs_type_t *type, // void *data // ); +file_t *get_file(int fd); + #endif //_FS_H diff --git a/include/page.h b/include/page.h index bbe407d..ad11224 100644 --- a/include/page.h +++ b/include/page.h @@ -134,18 +134,25 @@ struct kmem_cache; typedef struct kmem_cache kmem_cache_t; struct blk_buffer; +struct address_space; typedef struct page { unsigned long count; unsigned long flags; unsigned long private; - unsigned long index; + list_head_t lru; + list_head_t list; + struct page *head_page; // buddy system unsigned int order; void **freelist; // for slub + unsigned long index; + struct page *hash_next; + struct address_space *mapping; + kmem_cache_t *cache; unsigned long inuse; diff --git a/include/types.h b/include/types.h index 30fb457..308f8c9 100644 --- a/include/types.h +++ b/include/types.h @@ -50,7 +50,7 @@ typedef long int32_t; typedef unsigned long long uint64_t; typedef long long int64_t; -typedef uint64_t loff_t; +typedef int64_t loff_t; typedef uint32_t dev_t; typedef uint32_t umode_t; diff --git a/mm/buddy.c b/mm/buddy.c index 7463ebd..c8d4f99 100644 --- a/mm/buddy.c +++ b/mm/buddy.c @@ -7,6 +7,7 @@ * ------------------------------------------------------------------------ */ #include +#include #include #include #include @@ -95,6 +96,18 @@ found: } page->count = 0; + page->buffers = NULL; + page->cache = NULL; + page->count = 0; + page->flags = 0; + page->hash_next = NULL; + page->index = 0; + page->inuse = 0; + page->freelist = NULL; + INIT_LIST_HEAD(&page->lru); + INIT_LIST_HEAD(&page->list); + page->mapping = NULL; + // page->private = 0; return page; }