From: acevest Date: Tue, 8 Oct 2024 15:22:47 +0000 (+0800) Subject: 初步支持ramfs文件读 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zlib_tech.html?a=commitdiff_plain;h=365ea12f2cc4e3c15809454998063510d25050d2;p=kernel.git 初步支持ramfs文件读 --- diff --git a/fs/file.c b/fs/file.c index f10c7dd..a034ac7 100644 --- a/fs/file.c +++ b/fs/file.c @@ -70,6 +70,8 @@ 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); + assert(page->mapping == mapping); + ENTER_CRITICAL_ZONE(EFLAGS); page_t *p = 0; p = page_hash_table[hash]; @@ -78,17 +80,28 @@ void add_page_to_hash(page_t *page, address_space_t *mapping, uint32_t index) { EXIT_CRITICAL_ZONE(EFLAGS); } +void add_page_to_inode(address_space_t *mapping, page_t *page) { + assert(mapping != NULL); + assert(page != NULL); + assert(page->mapping == mapping); + + ENTER_CRITICAL_ZONE(EFLAGS); + list_add(&page->list, &mapping->pages); + 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; + page->mapping = mapping; add_page_to_hash(page, mapping, index); + add_page_to_inode(mapping, page); ENTER_CRITICAL_ZONE(EFLAGS); list_add(&page->list, &mapping->pages); diff --git a/fs/fslib.c b/fs/fslib.c deleted file mode 100644 index 3b149c9..0000000 --- a/fs/fslib.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * ------------------------------------------------------------------------ - * File Name: fslib.c - * Author: Zhao Yanbai - * 2024-08-31 21:12:58 Saturday CST - * Description: none - * ------------------------------------------------------------------------ - */ - -#include "fs.h" - -const file_operations_t simple_dir_operations = { - -}; diff --git a/fs/fssysc.c b/fs/fssysc.c index 22435b7..aac8de0 100644 --- a/fs/fssysc.c +++ b/fs/fssysc.c @@ -28,12 +28,12 @@ __attribute__((regparm(0))) long sysc_mkdir(const char *path, int mode) { dentry_t *dentry = NULL; ret = path_lookup_create(&ni, &dentry); - if (0 != ret) { - assert(dentry == NULL); + if (0 == ret && dentry != NULL) { + assert(dentry != NULL); ret = vfs_mkdir(ni.path.dentry->d_inode, dentry, mode); dentry_put(dentry); } else { - assert(dentry != NULL); + assert(dentry == NULL); } up(&ni.path.dentry->d_inode->i_sem); diff --git a/fs/inode.c b/fs/inode.c index 26fd847..00b8304 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -38,6 +38,11 @@ inode_t *alloc_inode(superblock_t *sb) { inode->i_fops = &empty_fops; inode->i_ops = &empty_iops; inode->i_size = 0; + inode->i_mapping = &inode->i_as; + inode->i_mapping->a_inode = inode; + inode->i_mapping->pages; + INIT_LIST_HEAD(&inode->i_mapping->pages); + inode->i_mapping->a_ops = 0; return inode; } diff --git a/fs/path.c b/fs/path.c index 48d2caa..f47d10c 100644 --- a/fs/path.c +++ b/fs/path.c @@ -221,7 +221,6 @@ int path_walk(const char *path, namei_t *ni) { // 不是挂载点 或已经处理完了挂载点 ret = -ENOENT; inode = dentry->d_inode; - if (inode == NULL) { goto out_dput_entry; } @@ -324,6 +323,7 @@ int path_walk(const char *path, namei_t *ni) { ok: return 0; } + out_dput_entry: dentry_put(dentry); end: @@ -353,7 +353,7 @@ int path_lookup_hash(dentry_t *base, qstr_t *name, dentry_t **dentry) { dentry_put(dentry_new); } - return 0; + return ret; } int path_lookup_create(namei_t *ni, dentry_t **dentry) { @@ -404,7 +404,6 @@ int path_open_namei(const char *path, int flags, int mode, namei_t *ni) { dir = ni->path.dentry; assert(NULL != dir); - down(&dir->d_inode->i_sem); ret = path_lookup_hash(dir, &ni->last, &dentry); @@ -413,13 +412,12 @@ int path_open_namei(const char *path, int flags, int mode, namei_t *ni) { goto end; } + assert(dentry != NULL); 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); + ni->path.dentry = dentry; if (0 != ret) { goto end; } @@ -428,18 +426,28 @@ int path_open_namei(const char *path, int flags, int mode, namei_t *ni) { // 上述是文件不存在的逻辑 // 此处是文件存在的情况下的处理逻辑 + up(&dir->d_inode->i_sem); if ((flags & O_EXCL) == 0) { - panic("unsupport O_EXCL") + panic("unsupport O_EXCL"); } ok: inode = dentry->d_inode; if (NULL == inode) { - ret = -ENOENT; + ret = ENOENT; + goto end; + } + + if (S_ISDIR(inode->i_mode)) { + ret = EISDIR; goto end; } + if ((flags & O_TRUNC) != 0) { + panic("unsupport O_TRUNC"); + } + end: return ret; diff --git a/fs/ramfs.c b/fs/ramfs.c index ef1ca11..557fa9b 100644 --- a/fs/ramfs.c +++ b/fs/ramfs.c @@ -42,7 +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, + .write = vfs_generic_file_write, }; static const inode_operations_t ramfs_file_inode_operations = { @@ -53,6 +53,13 @@ static const file_operations_t ramfs_dir_operations = { }; +static const address_space_operations_t ramfs_address_space_operations = { + .read_page = NULL, + .write_page = NULL, + .write_begin = NULL, + .write_end = NULL, +}; + static int ramfs_mknod(inode_t *dir, dentry_t *dentry, umode_t mode) { int ret = 0; @@ -63,6 +70,8 @@ static int ramfs_mknod(inode_t *dir, dentry_t *dentry, umode_t mode) { return -ENOSPC; } + assert(inode != NULL); + dentry_attach_inode(dentry, inode); dentry_get(dentry); @@ -93,6 +102,11 @@ static const inode_operations_t ramfs_dir_inode_operations = { .mkdir = ramfs_mkdir, }; +void ramfs_debug_set_f_ops(file_t *filp) { + // + filp->f_ops = &ramfs_file_operations; +} + inode_t *ramfs_get_inode(superblock_t *sb, umode_t mode, dev_t dev) { inode_t *inode = alloc_inode(sb); @@ -107,11 +121,13 @@ inode_t *ramfs_get_inode(superblock_t *sb, umode_t mode, dev_t dev) { // panic("S_IFREG: not implement"); inode->i_fops = &ramfs_file_operations; inode->i_ops = &ramfs_file_inode_operations; + inode->i_mapping->a_ops = &ramfs_address_space_operations; break; case S_IFDIR: // panic("S_IFDIR: not implement"); inode->i_fops = &ramfs_dir_operations; inode->i_ops = &ramfs_dir_inode_operations; + inode->i_mapping->a_ops = &ramfs_address_space_operations; break; case S_IFLNK: panic("S_IFLNK: not implement"); diff --git a/fs/read.c b/fs/read.c index 3c24678..743be3f 100644 --- a/fs/read.c +++ b/fs/read.c @@ -15,12 +15,110 @@ #include #include -int sysc_read(int fd, void *buf, size_t count) { - if (fd < 0 || fd >= NR_OPENS) return -EBADF; - - // only support char device - // only support read from console. - // ignore fd - chrdev_t *p = chrdev[CHRDEV_CNSL]; - return p->read(buf, count); +ssize_t vfs_generic_file_read(file_t *file, char *buf, size_t size, loff_t *p_pos) { + ssize_t ret = 0; + + loff_t pos = *p_pos; + + inode_t *inode = file->f_dentry->d_inode; + address_space_t *mapping = inode->i_mapping; + + assert(S_ISREG(inode->i_mode)); + + uint32_t index = pos >> PAGE_SHIFT; + uint32_t offset = pos & (PAGE_SIZE - 1); + size_t left = size; + + while (true) { + page_t *page = NULL; + uint32_t end_index = inode->i_size >> PAGE_SHIFT; + if (index > end_index) { + break; + } + + uint32_t bytes = PAGE_SIZE; + if (index == end_index) { + bytes = inode->i_size & (PAGE_SIZE - 1); + if (bytes <= offset) { + break; + } + } + + bytes = bytes - offset; + + // 在hash里找page + page_t *find_hash_page(address_space_t * mapping, uint32_t index); + page = find_hash_page(mapping, index); + if (NULL == page) { + goto no_cached_page_in_hash; + } + + // 在hash里找到了page + // TODO 增加page引用计数 + + // copy data + void *addr = page2va(page); + memcpy(buf, addr, bytes); + + offset += bytes; + index += offset >> PAGE_SHIFT; + offset &= (PAGE_SIZE - 1); + + // TODO 减少page引用计数 + + left -= bytes; + if (bytes != 0 && left != 0) { + continue; + } else { + break; + } + + no_cached_page_in_hash: + page = alloc_one_page(0); + if (page == NULL) { + return ENOMEM; + } + + // TODO:可能已经有其它进程已经把数据读入内存了 + // + + // read page + assert(mapping->a_ops != NULL); + assert(mapping->a_ops->read_page != NULL); + ret = mapping->a_ops->read_page(file, page); + if (0 != ret) { + return EIO; + } + + // + void add_page_to_hash(page_t * page, address_space_t * mapping, uint32_t index); + add_page_to_hash(page, mapping, index); + } + + return ret; +} + +ssize_t sysc_read(int fd, void *buf, size_t count) { + ssize_t ret = 0; + + file_t *file = get_file(fd); + if (NULL == file) { + return EBADF; + } + + inode_t *inode = file->f_dentry->d_inode; + + assert(file->f_ops != 0); + assert(file->f_ops->read != 0); + assert(inode->i_fops != 0); + assert(inode->i_fops->read != 0); + assert(file->f_ops->read == inode->i_fops->read); + + ssize_t (*read)(file_t *, char *, size_t, loff_t *); + read = file->f_ops->read; + + loff_t pos = file->f_pos; + ret = read(file, buf, count, &pos); + + return ret; } diff --git a/fs/vfs.h b/fs/vfs.h index d215530..712820f 100644 --- a/fs/vfs.h +++ b/fs/vfs.h @@ -69,7 +69,7 @@ typedef struct file_operations { struct file { // 多个打开的文件可能是同一个文件 dentry_t *f_dentry; - file_operations_t *f_ops; + const file_operations_t *f_ops; loff_t f_pos; uint32_t f_flags; @@ -95,14 +95,16 @@ typedef struct superblock { struct address_space_operations { int (*write_page)(page_t *); - int (*read_page)(page_t *, file_t *file); + int (*read_page)(file_t *file, page_t *); + int (*write_begin)(file_t *file, page_t *, loff_t pos, int len); + int (*write_end)(file_t *file, page_t *, loff_t pos, int len); }; struct address_space { list_head_t pages; uint32_t total_pages; inode_t *a_inode; - address_space_operations_t *a_ops; + const address_space_operations_t *a_ops; }; // dentry和inode为什么不合二为一? @@ -136,7 +138,8 @@ struct inode { umode_t i_mode; // FILE DIR CHR BLK FIFO SOCK - address_space_t i_mapping; + address_space_t *i_mapping; + address_space_t i_as; }; // d_flags @@ -308,12 +311,15 @@ void dentry_get_locked(dentry_t *dentry); void dentry_put(dentry_t *dentry); -///// -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); int path_lookup_create(namei_t *ni, // dentry_t **dentry // OUT ); + +int path_open_namei(const char *path, int flags, int mode, namei_t *ni); + +// +ssize_t vfs_generic_file_read(file_t *file, char *buf, size_t size, loff_t *p_pos); +ssize_t vfs_generic_file_write(file_t *file, const char *buf, size_t size, loff_t *p_pos); diff --git a/fs/write.c b/fs/write.c index 5ac4ca7..d29ca9a 100644 --- a/fs/write.c +++ b/fs/write.c @@ -18,7 +18,13 @@ #include #include #include +#include +#include +#include #include + +page_t *get_cached_page(address_space_t *mapping, uint32_t index); + ssize_t vfs_generic_file_write(file_t *file, const char *buf, size_t size, loff_t *p_pos) { ssize_t ret = 0; @@ -31,22 +37,53 @@ ssize_t vfs_generic_file_write(file_t *file, const char *buf, size_t size, loff_ assert((file->f_flags & O_APPEND) == O_APPEND); // 目前只支持这个 inode_t *inode = file->f_dentry->d_inode; + assert(inode != NULL); + + address_space_t *mapping = inode->i_mapping; + assert(mapping->a_inode == inode); + assert(mapping->a_ops != NULL); + // assert(mapping->a_ops->read_page != NULL); + // assert(mapping->a_ops->write_page != NULL); 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; + uint32_t index = pos >> PAGE_SHIFT; // 所在页号索引 + uint32_t offset = pos & (PAGE_SIZE - 1); // 所在页内偏移 + uint32_t bytes = PAGE_SIZE - offset; // 要在这一页写的字节数 if (size < bytes) { bytes = size; } + // 找出page + // 若找不出,则分配一个,并加到cache里 + page_t *page = get_cached_page(mapping, index); + assert(page != NULL); + assert(page->index == index); + assert(page->mapping == mapping); + + void *addr = page2va(page); + + // TODO + // ... + + // 写入page + memcpy(addr, buf, bytes); + + // TODO + // ... + // + size -= bytes; + pos += bytes; } end: up(&inode->i_sem); + *p_pos = pos; + + // + inode->i_size = pos; return ret; } @@ -56,7 +93,7 @@ ssize_t sysc_write(int fd, const char *buf, size_t size) { file_t *file = get_file(fd); if (NULL == file) { - return -EBADF; + return EBADF; } // TODO 检查文件是否有写权限 diff --git a/kernel/task_init.c b/kernel/task_init.c index 4cab514..a212ee6 100644 --- a/kernel/task_init.c +++ b/kernel/task_init.c @@ -140,13 +140,40 @@ void init_task_entry() { #if 1 extern __attribute__((regparm(0))) long sysc_mkdir(const char *path, int mode); sysc_mkdir("/root", 0777); - sysc_mkdir("/root/aaa", 0777); + sysc_mkdir("/root/sbin/", 0777); { namei_t ni; - const char *path = "/root"; - path_init(path, 0, &ni); + const char *path = "/root/sbin/init.elf"; + path_init(path, PATH_LOOKUP_PARENT, &ni); path_walk(path, &ni); + + printk("FLAGS %08x\n", ni.flags); + ni.flags = O_CREAT | O_APPEND; + path_open_namei(path, ni.flags, S_IFREG, &ni); + ni.flags = O_CREAT | O_APPEND; + printk("FLAGS %08x\n", ni.flags); + void ramfs_debug_set_f_ops(file_t * filp); + loff_t pos = 0; + file_t file; + file.f_dentry = ni.path.dentry; + file.f_flags = ni.flags; + printk("FLAGS %08x\n", ni.flags); + printk("FLAGS %08x\n", file.f_flags); + file.f_ops = 0; + file.f_pos = 0; + ramfs_debug_set_f_ops(&file); + vfs_generic_file_write(&file, "aaa1234567", 10, &file.f_pos); + file.f_pos = 0; + char buf[128] = { + 'b', + 'u', + 'f', + }; + vfs_generic_file_read(&file, buf, 4, &file.f_pos); + for (int i = 0; i < 16; i++) { + printk("%c\n", buf[i]); + } } #endif diff --git a/lib/vsprintf.c b/lib/vsprintf.c index c7f8737..5c53fd5 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -3,15 +3,19 @@ // wed, 30 Jul 2008 14:47 +0800 // Add %012d %012x %12d %12x Support Mon, 20 Jul 2009 19:30:34 // Add %u Support Sun, 06 Jul 2014 12:07:54 +// Add %o Support Tue, 08 Oct 2024 22:54:36 // ======================================================================== +#include #include #include "string.h" char *itoa(char *s, int n); char *itou(char *s, unsigned int n); +char *itoo(char *s, unsigned int n); char *itox(char *s, unsigned int n, int upper); -char *i64tou(char *s, int64_t n); +char *i64tou(char *s, uint64_t n); +char *i64too(char *s, uint64_t n); char *i64tox(char *s, uint64_t n, int upper); enum { ALIGN_RIGHT, ALIGN_LEFT }; @@ -87,6 +91,10 @@ int vsprintf(char *buf, const char *fmt, char *args) { i64tou(tmp, *((int64_t *)args)); p += write_buf(p, tmp, char_fill, char_cnt, align); args += 4; + } else if (*fmt == 'o') { + i64too(tmp, *((uint64_t *)args)); + p += write_buf(p, tmp, char_fill, char_cnt, align); + args += 4; } else if (*fmt == 'x' || *fmt == 'X') { // i64tox(tmp, *((uint64_t *)args), *fmt == 'X' ? 1 : 0); i64tox(tmp, *((uint64_t *)args), 1); // x X都强制为大写 @@ -107,6 +115,10 @@ int vsprintf(char *buf, const char *fmt, char *args) { itox(tmp, *((unsigned int *)args), 1); // x X都强制为大写 p += write_buf(p, tmp, char_fill, char_cnt, align); break; + case 'o': + itoo(tmp, *((unsigned *)args)); + p += write_buf(p, tmp, char_fill, char_cnt, align); + break; default: break; } @@ -150,7 +162,7 @@ char *itoa(char *s, int n) { } } -char *i64tou(char *s, int64_t n) { +char *i64tou(char *s, uint64_t n) { itou(s, n >> 32); int i = 0; if ((n >> 32) > 0) { @@ -177,41 +189,55 @@ char *itou(char *s, unsigned int n) { } } -char *itox(char *s, unsigned int n, int upper) { +char *_itoo(char *s, uint64_t n, int bgn) { char *p = s; char ch; int i; bool flag = false; - for (i = 28; i >= 0; i -= 4) { - ch = (n >> i) & 0x0F; + for (i = bgn; i >= 0; i -= 3) { + ch = (n >> i) & 0x07; - if (ch >= 0 && ch <= 9) { - ch += '0'; - } else { - ch -= 10; - ch += upper == 1 ? 'A' : 'a'; - } + assert(ch >= 0); + assert(ch <= 7); - if (ch != '0') flag = true; + ch += '0'; - if (flag || ch != '0') *p++ = ch; + if (ch != '0') { + flag = true; + } + + if (flag || ch != '0') { + *p++ = ch; + } } - if (s == p) *p++ = '0'; + if (s == p) { + *p++ = '0'; + } *p = 0; return s; } -char *i64tox(char *s, uint64_t n, int upper) { +char *itoo(char *s, unsigned int n) { + // + return _itoo(s, n, 30); +} + +char *i64too(char *s, uint64_t n) { + // + return _itoo(s, n, 63); +} + +char *_itox(char *s, uint64_t n, int upper, int bgn) { char *p = s; char ch; int i; bool flag = false; - for (i = 60; i >= 0; i -= 4) { + for (i = bgn; i >= 0; i -= 4) { ch = (n >> i) & 0x0F; if (ch >= 0 && ch <= 9) { @@ -221,14 +247,30 @@ char *i64tox(char *s, uint64_t n, int upper) { ch += upper == 1 ? 'A' : 'a'; } - if (ch != '0') flag = true; + if (ch != '0') { + flag = true; + } - if (flag || ch != '0') *p++ = ch; + if (flag || ch != '0') { + *p++ = ch; + } } - if (s == p) *p++ = '0'; + if (s == p) { + *p++ = '0'; + } *p = 0; return s; } + +char *itox(char *s, unsigned int n, int upper) { + // + return _itox(s, n, upper, 28); +} + +char *i64tox(char *s, uint64_t n, int upper) { + // + return _itox(s, n, upper, 60); +}