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];
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);
+++ /dev/null
-/*
- * ------------------------------------------------------------------------
- * 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 = {
-
-};
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);
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;
}
// 不是挂载点 或已经处理完了挂载点
ret = -ENOENT;
inode = dentry->d_inode;
-
if (inode == NULL) {
goto out_dput_entry;
}
ok:
return 0;
}
+
out_dput_entry:
dentry_put(dentry);
end:
dentry_put(dentry_new);
}
- return 0;
+ return ret;
}
int path_lookup_create(namei_t *ni, dentry_t **dentry) {
dir = ni->path.dentry;
assert(NULL != dir);
-
down(&dir->d_inode->i_sem);
ret = path_lookup_hash(dir, &ni->last, &dentry);
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;
}
// 上述是文件不存在的逻辑
// 此处是文件存在的情况下的处理逻辑
+ 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;
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 = {
};
+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;
return -ENOSPC;
}
+ assert(inode != NULL);
+
dentry_attach_inode(dentry, inode);
dentry_get(dentry);
.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);
// 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");
#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;
}
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;
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为什么不合二为一?
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
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);
#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;
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;
}
file_t *file = get_file(fd);
if (NULL == file) {
- return -EBADF;
+ return EBADF;
}
// TODO 检查文件是否有写权限
#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
// 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 };
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都强制为大写
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;
}
}
}
-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) {
}
}
-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) {
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);
+}