]> Zhao Yanbai Git Server - kernel.git/commitdiff
vfs_create相关修改,部分sysc_write逻辑 dev/202408/vfs
authoracevest <zhaoyanbai@126.com>
Mon, 23 Sep 2024 06:57:10 +0000 (14:57 +0800)
committeracevest <zhaoyanbai@126.com>
Mon, 23 Sep 2024 06:57:10 +0000 (14:57 +0800)
13 files changed:
.gitignore
fs/file.c [new file with mode: 0644]
fs/fs.c
fs/fssysc.c
fs/path.c
fs/ramfs.c
fs/vfs.c
fs/vfs.h
fs/write.c
include/fs.h
include/page.h
include/types.h
mm/buddy.c

index e60366917b6801a175dad436b8a4f5ce8fcd3f85..7e9c83eb9612f030b68ef107a28f1011c8e165aa 100644 (file)
@@ -19,6 +19,7 @@
 
 *.IMG
 *.img
+*.vdi
 *build*
 *.BIN
 *.ELF
diff --git a/fs/file.c b/fs/file.c
new file mode 100644 (file)
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 <fs.h>
+#include <irq.h>
+#include <task.h>
+
+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 cd800ad05ea4c3f4612b34c21760713a98638764..9125c99a69fbe3af85dd698c771869b39d574094 100644 (file)
--- 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();
 
index f528d9ea1d0d80133dd3bab89db81a332ecd0115..255b9649809c448e8deffd57e731eb4d4f78ecab 100644 (file)
 #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;
index 98f5ec11e6a2fd29c35f3ffef7b5a3e98054bdb3..25dfb3ad933df43fc7ef7e626e959cd355733fd6 100644 (file)
--- 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) {
index 93a225e69a84383f8e9ba6cd69ca88779ed9dab4..ef1ca1193b45b67f8711469aa2920192a7a3d37f 100644 (file)
@@ -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 = {
index e7ceae429a9e35536e18b484888ab11299c23edd..836a28540fc035bbaed651ff496bd3a54a084fc4 100644 (file)
--- 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;
+}
index 40f60ffbe32175df0b6913139b06e4831d962d45..99020632aac9334f4b9187ce9a6ee290cee9348d 100644 (file)
--- a/fs/vfs.h
+++ b/fs/vfs.h
@@ -11,6 +11,7 @@
 
 #include <atomic.h>
 #include <list.h>
+#include <page.h>
 #include <semaphore.h>
 #include <types.h>
 
@@ -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);
 ////
index 82d9af7069885f1109c6a6f6aee8aeb5e45a534a..5ac4ca7da671342bcd716de174479a18e01baa82 100644 (file)
  */
 
 #include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fs.h>
+#include <types.h>
+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;
+// }
index be93260074846567f94a039e2fe0c64b2cb8cc7a..b96b7eee3f3fe8cd02b05f24740e72bdfaca48e8 100644 (file)
@@ -65,4 +65,6 @@ superblock_t *sget(fs_type_t *type,                      //
                    void *data                            //
 );
 
+file_t *get_file(int fd);
+
 #endif  //_FS_H
index bbe407dfa043edd351597a83cd7571285532ea67..ad11224a9869bb466cf384962a2d676dff9c947d 100644 (file)
@@ -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;
index 30fb45772e47291914a8cf96fceda96e426e916a..308f8c90bf70fa341f2d8d39e6a68e868d5435d1 100644 (file)
@@ -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;
index 7463ebdb3cd2c977a418353fe76b8e58f1ea43cd..c8d4f99c3c4202a6b80b7e6d08c6a1a16f3782dd 100644 (file)
@@ -7,6 +7,7 @@
  * ------------------------------------------------------------------------
  */
 #include <irq.h>
+#include <list.h>
 #include <mm.h>
 #include <string.h>
 #include <sysctl.h>
@@ -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;
 }