*.IMG
*.img
+*.vdi
*build*
*.BIN
*.ELF
--- /dev/null
+/*
+ * ------------------------------------------------------------------------
+ * 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);
+}
void setup_fs() {
// ext2_setup_fs();
+ void vfs_page_cache_init();
+ vfs_page_cache_init();
+
void inode_cache_init();
inode_cache_init();
#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;
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) {
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) {
static const file_operations_t ramfs_file_operations = {
.read = 0,
+ .write = 0,
};
static const inode_operations_t ramfs_file_inode_operations = {
//
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;
+}
#include <atomic.h>
#include <list.h>
+#include <page.h>
#include <semaphore.h>
#include <types.h>
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;
// 多个打开的文件可能是同一个文件
dentry_t *f_dentry;
file_operations_t *f_ops;
+
+ loff_t f_pos;
+ uint32_t f_flags;
};
// super block
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结构
loff_t i_size;
umode_t i_mode; // FILE DIR CHR BLK FIFO SOCK
+
+ address_space_t i_mapping;
};
// d_flags
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);
////
*/
#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;
+// }
void *data //
);
+file_t *get_file(int fd);
+
#endif //_FS_H
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;
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;
* ------------------------------------------------------------------------
*/
#include <irq.h>
+#include <list.h>
#include <mm.h>
#include <string.h>
#include <sysctl.h>
}
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;
}