diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-07-10 11:24:56 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-07-10 11:24:56 +0800 |
| commit | 1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (patch) | |
| tree | 0f5e01cd7c7a05abb6b1c7472d7f00f49caf02cc /na/fs/file_table.cc | |
| parent | 63dc025705f6533b91fb1a7d26e6ed864efd9900 (diff) | |
| download | lume-1767d390fbf3d0c65389de46caf0b6d43ef3b6ad.tar.gz lume-1767d390fbf3d0c65389de46caf0b6d43ef3b6ad.tar.xz | |
feat: establish bootable new architecture checkpoint
Replace the compressed boot path with a relocatable higher-half RISC-V entry, expand memory and SMP support, and add the driver, TTY, VFS, exec, signal, syscall, initramfs, and self-test infrastructure needed for a bootable kernel checkpoint.
Diffstat (limited to 'na/fs/file_table.cc')
| -rw-r--r-- | na/fs/file_table.cc | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/na/fs/file_table.cc b/na/fs/file_table.cc new file mode 100644 index 0000000..06095c1 --- /dev/null +++ b/na/fs/file_table.cc @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (C) 2026 Richard Qin */ + +/* + * file_table.cc — Open file allocation and reference counting + */ + +#include <lume/file.h> +#include <lume/fs.h> +#include <lume/dcache.h> +#include <lume/slab.h> +#include <lume/errno.h> + +/* ================================================================== */ +/* alloc_empty_file */ +/* ================================================================== */ + +file* alloc_empty_file(int flags) +{ + auto* fp = new file{}; + if (!fp) return nullptr; + + fp->f_count.store(1); + fp->f_flags = flags; + fp->f_mode = 0; + fp->f_op = nullptr; + fp->f_mapping = nullptr; + fp->f_inode = nullptr; + fp->f_pos = 0; + fp->private_data = nullptr; + fp->f_path.mnt = nullptr; + fp->f_path.de = nullptr; + + /* Derive f_mode from O_* flags */ + int acc = flags & O_ACCMODE; + if (acc == O_RDONLY) + fp->f_mode = FMODE_READ | FMODE_CAN_READ; + else if (acc == O_WRONLY) + fp->f_mode = FMODE_WRITE | FMODE_CAN_WRITE; + else if (acc == O_RDWR) + fp->f_mode = FMODE_READ | FMODE_WRITE | FMODE_CAN_READ | FMODE_CAN_WRITE; + + fp->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE; + + return fp; +} + +/* ================================================================== */ +/* get_file / fput */ +/* ================================================================== */ + +file* get_file(file* f) +{ + f->f_count.fetch_add(1); + return f; +} + +void fput(file* fp) +{ + if (!fp) return; + + int old = fp->f_count.fetch_sub(1); + if (old > 1) return; + + /* Last reference — release */ + if (fp->f_op && fp->f_op->release) + fp->f_op->release(fp->f_inode, fp); + + if (fp->f_path.de) + dput(fp->f_path.de); + + /* Future: mntput(fp->f_path.mnt) */ + + delete fp; +} + +/* ================================================================== */ +/* vfs_read / vfs_write / vfs_llseek / vfs_fstat */ +/* ================================================================== */ + +int64 vfs_read(file* fp, char* buf, uint64 count, int64* pos) +{ + if (!(fp->f_mode & FMODE_CAN_READ)) + return -EBADF; + if (!fp->f_op || !fp->f_op->read) + return -EINVAL; + + return fp->f_op->read(fp, buf, count, pos); +} + +int64 vfs_write(file* fp, const char* buf, uint64 count, int64* pos) +{ + if (!(fp->f_mode & FMODE_CAN_WRITE)) + return -EBADF; + if (!fp->f_op || !fp->f_op->write) + return -EINVAL; + + return fp->f_op->write(fp, buf, count, pos); +} + +int64 vfs_llseek(file* fp, int64 offset, int whence) +{ + if (fp->f_op && fp->f_op->llseek) + return fp->f_op->llseek(fp, offset, whence); + return generic_file_llseek(fp, offset, whence); +} + +int64 generic_file_llseek(file* fp, int64 offset, int whence) +{ + int64 new_pos; + switch (whence) { + case SEEK_SET: + new_pos = offset; + break; + case SEEK_CUR: + new_pos = fp->f_pos + offset; + break; + case SEEK_END: + new_pos = fp->f_inode->i_size + offset; + break; + default: + return -EINVAL; + } + + if (new_pos < 0) return -EINVAL; + fp->f_pos = new_pos; + return new_pos; +} + +int vfs_fstat(file* fp, kstat* stat) +{ + inode* ip = file_inode(fp); + if (!ip) return -EBADF; + + if (ip->i_op && ip->i_op->getattr) { + return ip->i_op->getattr(&fp->f_path, stat, 0, 0); + } + + generic_fillattr(ip, stat); + return 0; +} + +/* ================================================================== */ +/* path_get / path_put (simplified) */ +/* ================================================================== */ + +void path_get(const path* p) +{ + if (p->de) dget(p->de); + /* Future: mntget(p->mnt) */ +} + +void path_put(const path* p) +{ + if (p->de) dput(p->de); + /* Future: mntput(p->mnt) */ +} + +/* ================================================================== */ +/* mntget / mntput (stubs for Phase 1) */ +/* ================================================================== */ + +vfsmount* mntget(vfsmount* mnt) { return mnt; } +void mntput(vfsmount*) {} |
