]> Zhao Yanbai Git Server - kernel.git/commitdiff
初步支持ramfs文件读
authoracevest <zhaoyanbai@126.com>
Tue, 8 Oct 2024 15:22:47 +0000 (23:22 +0800)
committeracevest <zhaoyanbai@126.com>
Tue, 8 Oct 2024 15:22:47 +0000 (23:22 +0800)
fs/file.c
fs/fslib.c [deleted file]
fs/fssysc.c
fs/inode.c
fs/path.c
fs/ramfs.c
fs/read.c
fs/vfs.h
fs/write.c
kernel/task_init.c
lib/vsprintf.c

index f10c7dd3b15dda11e5c3d9cec2557a4e645d066b..a034ac765dbc95e405a34b53efebc6eafc0332c6 100644 (file)
--- 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 (file)
index 3b149c9..0000000
+++ /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 = {
-
-};
index 22435b732c7a835c9e9cc7604d70c1f057765c5c..aac8de042055791265cdb248497e3c2712dc5b49 100644 (file)
@@ -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);
index 26fd847777fe15db5c68658a67ada0945745d747..00b83044d532e658337e4f9f4be15da498a0b1a4 100644 (file)
@@ -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;
 }
 
index 48d2caaa87e31f3d84192260f7ea84aabed2d485..f47d10cf3eadab3399306c6e20489cd5507746ea 100644 (file)
--- 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;
index ef1ca1193b45b67f8711469aa2920192a7a3d37f..557fa9b9714ba01f92393368bae2f6fafeba5ec4 100644 (file)
@@ -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");
index 3c2467827748b263e31653025a090edbad742d08..743be3fb4f83efaa59ecf3cc65f4ee7b0dbc736d 100644 (file)
--- a/fs/read.c
+++ b/fs/read.c
 #include <sched.h>
 #include <types.h>
 
-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;
 }
index d215530d6d75f3fd52096b5e279cd44354273288..712820f29c3a584977fbbd9fcd98c79330f2fc8f 100644 (file)
--- 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);
index 5ac4ca7da671342bcd716de174479a18e01baa82..d29ca9a6516250c34faaadcbdc2219b94dff0e46 100644 (file)
 #include <errno.h>
 #include <fcntl.h>
 #include <fs.h>
+#include <page.h>
+#include <printk.h>
+#include <string.h>
 #include <types.h>
+
+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 检查文件是否有写权限
index 4cab5145ef810354ed1d4f96ac8b6475341d1eb0..a212ee68bc11e45620166f470940b864b80a3f1e 100644 (file)
@@ -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
 
index c7f87370af576d63c6483ca0f303c863622f5dbc..5c53fd5785661c5db850d6b2a15b77e27966bd81 100644 (file)
@@ -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 <assert.h>
 #include <types.h>
 
 #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);
+}