From: Minep Date: Fri, 29 Jul 2022 16:04:02 +0000 (+0100) Subject: feat: lseek(2), read(2), write(2) implementation X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/6fefc6f5af83f316e18b0cb9dbbde1cea0b98add?hp=77e7b21f117eecd04bb31257ee68dfc1f425a47e feat: lseek(2), read(2), write(2) implementation feat: unified block device manipulation using vfs. chore: bug fix & code formatting. --- diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index e892858..53981a0 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -175,6 +176,8 @@ ahci_init() if (!ahci_init_device(port)) { kprintf(KERROR "fail to init device"); } + + block_mount_disk(port->device); } } diff --git a/lunaix-os/includes/lunaix/block.h b/lunaix-os/includes/lunaix/block.h index db8ae5c..94e8775 100644 --- a/lunaix-os/includes/lunaix/block.h +++ b/lunaix-os/includes/lunaix/block.h @@ -5,12 +5,14 @@ #define LPT_SIG 0x414e554c #define PARTITION_NAME_SIZE 48 +#define DEV_ID_SIZE 32 typedef uint64_t partition_t; typedef uint32_t bdev_t; struct block_dev { + char bdev_id[DEV_ID_SIZE]; char name[PARTITION_NAME_SIZE]; struct hba_device* hd_dev; uint64_t base_lba; @@ -34,4 +36,10 @@ struct lpt_header uint32_t table_len; } __attribute__((packed)); +void +block_init(); + +int +block_mount_disk(struct hba_device* hd_dev); + #endif /* __LUNAIX_BLOCK_H */ diff --git a/lunaix-os/includes/lunaix/fctrl.h b/lunaix-os/includes/lunaix/fctrl.h index 978553e..e76ae7b 100644 --- a/lunaix-os/includes/lunaix/fctrl.h +++ b/lunaix-os/includes/lunaix/fctrl.h @@ -12,4 +12,10 @@ __LXSYSCALL1(int, mkdir, const char*, path); __LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent); +__LXSYSCALL3(int, lseek, int, fd, int, offset, int, options); + +__LXSYSCALL3(int, read, int, fd, void*, buf, unsigned int, count); + +__LXSYSCALL3(int, write, int, fd, void*, buf, unsigned int, count); + #endif /* __LUNAIX_FCTRL_H */ diff --git a/lunaix-os/includes/lunaix/foptions.h b/lunaix-os/includes/lunaix/foptions.h index 6d6d2d3..00f3486 100644 --- a/lunaix-os/includes/lunaix/foptions.h +++ b/lunaix-os/includes/lunaix/foptions.h @@ -4,4 +4,8 @@ #define FO_CREATE 0x1 #define FO_APPEND 0x2 +#define FSEEK_SET 0x1 +#define FSEEK_CUR 0x2 +#define FSEEK_END 0x3 + #endif /* __LUNAIX_FOPTIONS_H */ diff --git a/lunaix-os/includes/lunaix/fs/twifs.h b/lunaix-os/includes/lunaix/fs/twifs.h index 8df3ddc..b83b1a4 100644 --- a/lunaix-os/includes/lunaix/fs/twifs.h +++ b/lunaix-os/includes/lunaix/fs/twifs.h @@ -7,6 +7,7 @@ struct twifs_node { struct v_inode* inode; struct hstr name; + void* data; uint32_t itype; struct llist_header children; struct llist_header siblings; diff --git a/lunaix-os/includes/lunaix/proc.h b/lunaix-os/includes/lunaix/proc.h index eafae4f..f4de8cf 100644 --- a/lunaix-os/includes/lunaix/proc.h +++ b/lunaix-os/includes/lunaix/proc.h @@ -10,4 +10,6 @@ __LXSYSCALL1(pid_t, wait, int*, status); __LXSYSCALL3(pid_t, waitpid, pid_t, pid, int*, status, int, options); +__LXSYSCALL(int, geterrno); + #endif /* __LUNAIX_SYS_H */ diff --git a/lunaix-os/includes/lunaix/status.h b/lunaix-os/includes/lunaix/status.h index dd353fe..2c3ff96 100644 --- a/lunaix-os/includes/lunaix/status.h +++ b/lunaix-os/includes/lunaix/status.h @@ -17,5 +17,6 @@ #define EEXIST -12 #define EBADF -13 #define ENOTSUP -14 +#define ENXIO -15 #endif /* __LUNAIX_CODE_H */ diff --git a/lunaix-os/includes/lunaix/syscall.h b/lunaix-os/includes/lunaix/syscall.h index 42bc85b..88aa026 100644 --- a/lunaix-os/includes/lunaix/syscall.h +++ b/lunaix-os/includes/lunaix/syscall.h @@ -28,6 +28,8 @@ #define __SYSCALL_write 22 #define __SYSCALL_readdir 23 #define __SYSCALL_mkdir 24 +#define __SYSCALL_lseek 25 +#define __SYSCALL_geterrno 26 #define __SYSCALL_MAX 0x100 diff --git a/lunaix-os/kernel/asm/x86/syscall.S b/lunaix-os/kernel/asm/x86/syscall.S index 2816bae..6a8b432 100644 --- a/lunaix-os/kernel/asm/x86/syscall.S +++ b/lunaix-os/kernel/asm/x86/syscall.S @@ -27,11 +27,13 @@ .long __lxsys_sigpending .long __lxsys_sigsuspend .long __lxsys_open - .long __lxsys_close + .long __lxsys_close /* 20 */ .long __lxsys_read .long __lxsys_write .long __lxsys_readdir .long __lxsys_mkdir + .long __lxsys_lseek /* 25 */ + .long __lxsys_geterrno 2: .rept __SYSCALL_MAX - (2b - 1b)/4 .long 0 diff --git a/lunaix-os/kernel/block.c b/lunaix-os/kernel/block.c index 0e28f66..23b9374 100644 --- a/lunaix-os/kernel/block.c +++ b/lunaix-os/kernel/block.c @@ -1,11 +1,15 @@ #include +#include #include #include #include +#include #include #include #include +#include + #define BLOCK_EREAD 1 #define BLOCK_ESIG 2 #define BLOCK_ECRC 3 @@ -31,6 +35,106 @@ block_init() { lbd_pile = cake_new_pile("block_dev", sizeof(struct block_dev), 1, 0); dev_registry = vcalloc(sizeof(struct block_dev*), MAX_DEV); + free_slot = 0; +} + +int +__block_read(struct v_file* file, void* buffer, size_t len); + +int +__block_write(struct v_file* file, void* buffer, size_t len); + +void +block_twifs_create() +{ + struct twifs_node* dev = twifs_toplevel_node("dev", 3); + struct twifs_node* dev_block = twifs_dir_node(dev, "block", 5); + + if (!dev_block) { + kprintf(KERROR "fail to create twifs node"); + return; + } + + struct block_dev* bdev; + struct twifs_node* bdev_node; + for (size_t i = 0; i < MAX_DEV; i++) { + if (!(bdev = dev_registry[i])) { + continue; + } + + bdev_node = + twifs_dir_node(dev_block, bdev->bdev_id, strlen(bdev->bdev_id)); + bdev_node->fops.read = __block_read; + bdev_node->fops.write = __block_write; + bdev_node->data = i; + bdev_node->inode->fsize = bdev->hd_dev->max_lba; + } +} + +int +__block_read(struct v_file* file, void* buffer, size_t len) +{ + int index = (int)((struct twifs_node*)file->inode->data)->data; + int errno; + struct block_dev* bdev; + if (index < 0 || index >= MAX_DEV || !(bdev = dev_registry[index])) { + return ENXIO; + } + size_t acc_size = 0, rd_size = 0, bsize = bdev->hd_dev->block_size, + rd_block = 0; + void* block = valloc(bsize); + + while (acc_size < len) { + if (!bdev->hd_dev->ops.read_buffer( + bdev->hd_dev, file->f_pos + rd_block, block, bsize)) { + errno = ENXIO; + goto error; + } + rd_size = MIN(len - acc_size, bsize); + memcpy(buffer + acc_size, block, rd_size); + acc_size += rd_size; + rd_block++; + } + + vfree(block); + return rd_block; + +error: + vfree(block); + return errno; +} + +int +__block_write(struct v_file* file, void* buffer, size_t len) +{ + int index = (int)((struct twifs_node*)file->inode->data)->data; + int errno; + struct block_dev* bdev; + if (index < 0 || index >= MAX_DEV || !(bdev = dev_registry[index])) { + return ENXIO; + } + size_t acc_size = 0, wr_size = 0, bsize = bdev->hd_dev->block_size, + wr_block = 0; + void* block = valloc(bsize); + + while (acc_size < len) { + wr_size = MIN(len - acc_size, bsize); + memcpy(block, buffer + acc_size, wr_size); + if (!bdev->hd_dev->ops.write_buffer( + bdev->hd_dev, file->f_pos + wr_block, block, bsize)) { + errno = ENXIO; + break; + } + acc_size += wr_size; + wr_block++; + } + + vfree(block); + return wr_block; + +error: + vfree(block); + return errno; } int @@ -47,17 +151,16 @@ block_mount_disk(struct hba_device* hd_dev) goto error; } - if ((errno = __block_mount_partitions(hd_dev))) { - goto error; - } + return errno; error: - kprintf(KERROR "Fail to mount hd: %s[%s] (%x)", + kprintf(KERROR "Fail to mount hd: %s[%s] (%x)\n", hd_dev->model, hd_dev->serial_num, -errno); } +// FIXME make it more general, manipulate the device through vfs mapping int __block_mount_partitions(struct hba_device* hd_dev) { @@ -113,7 +216,7 @@ __block_register(struct block_dev* dev) if (free_slot >= MAX_DEV) { return 0; } - + snprintf(dev->bdev_id, DEV_ID_SIZE, "bd%x", free_slot); dev_registry[free_slot++] = dev; return 1; } \ No newline at end of file diff --git a/lunaix-os/kernel/demos/dir_read.c b/lunaix-os/kernel/demos/dir_read.c index 8c4a344..7a63ba9 100644 --- a/lunaix-os/kernel/demos/dir_read.c +++ b/lunaix-os/kernel/demos/dir_read.c @@ -7,7 +7,7 @@ LOG_MODULE("RDDIR") void _readdir_main() { - int fd = open("/bus/../..", 0); + int fd = open("/dev/block", 0); if (fd == -1) { kprintf(KERROR "fail to open\n"); return; diff --git a/lunaix-os/kernel/demos/iotest.c b/lunaix-os/kernel/demos/iotest.c new file mode 100644 index 0000000..3fc8914 --- /dev/null +++ b/lunaix-os/kernel/demos/iotest.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +LOG_MODULE("IOTEST") + +void +_iotest_main() +{ + char test_sequence[] = "Once upon a time, in a magical land of Equestria. " + "There were two regal sisters who ruled together " + "and created harmony for all the land."; + int fd = open("/dev/block/bd0", 0); + + if (fd < 0) { + kprintf(KERROR "fail to open (%d)\n", geterrno()); + return; + } + + lseek(fd, 1, FSEEK_SET); + write(fd, test_sequence, sizeof(test_sequence)); + + lseek(fd, -1, FSEEK_CUR); + char read_out[256]; + read(fd, read_out, sizeof(read_out)); + + kprintf("%s", read_out); +} \ No newline at end of file diff --git a/lunaix-os/kernel/fs/twifs.c b/lunaix-os/kernel/fs/twifs.c index a50a657..ad226ca 100644 --- a/lunaix-os/kernel/fs/twifs.c +++ b/lunaix-os/kernel/fs/twifs.c @@ -59,18 +59,11 @@ twifs_init() struct twifs_node* __twifs_new_node(struct twifs_node* parent, const char* name, int name_len) { - struct hstr hname = HSTR(name, name_len); - hstr_rehash(&hname, HSTR_FULL_HASH); - - struct twifs_node* node = __twifs_get_node(parent, &hname); - if (node) { - return node; - } - - node = cake_grab(twi_pile); + struct twifs_node* node = cake_grab(twi_pile); memset(node, 0, sizeof(*node)); - node->name = hname; + node->name = HSTR(name, name_len); + hstr_rehash(&node->name, HSTR_FULL_HASH); llist_init_head(&node->children); if (parent) { @@ -95,6 +88,13 @@ twifs_file_node(struct twifs_node* parent, const char* name, int name_len) struct twifs_node* twifs_dir_node(struct twifs_node* parent, const char* name, int name_len) { + struct hstr hname = HSTR(name, name_len); + hstr_rehash(&hname, HSTR_FULL_HASH); + struct twifs_node* node = __twifs_get_node(parent, &hname); + if (node) { + return node; + } + struct twifs_node* twi_node = __twifs_new_node(parent, name, name_len); twi_node->itype = VFS_INODE_TYPE_DIR; twi_node->fops.readdir = __twifs_iterate_dir; diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index 51ef5c9..09668f5 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -204,6 +204,7 @@ vfs_walk(struct v_dnode* start, error: vfree(dnode->name.value); vfs_d_free(dnode); + *dentry = NULL; return errno; } @@ -403,18 +404,21 @@ __DEFINE_LXSYSCALL2(int, open, const char*, path, int, options) if (!errno && !(errno = vfs_alloc_fdslot(&fd))) { struct v_fd* fd_s = vzalloc(sizeof(*fd_s)); fd_s->file = opened_file; - fd_s->pos = file->inode->fsize & -((options & FO_APPEND) == 0); + fd_s->pos = file->inode->fsize & -((options & FO_APPEND) != 0); __current->fdtable->fds[fd] = fd_s; } return SYSCALL_ESTATUS(errno); } +#define GET_FD(fd, fd_s) \ + (fd >= 0 && fd < VFS_MAX_FD && (fd_s = __current->fdtable->fds[fd])) + __DEFINE_LXSYSCALL1(int, close, int, fd) { struct v_fd* fd_s; int errno; - if (fd < 0 || fd >= VFS_MAX_FD || !(fd_s = __current->fdtable->fds[fd])) { + if (!GET_FD(fd, fd_s)) { errno = EBADF; } else if (!(errno = vfs_close(fd_s->file))) { vfree(fd_s); @@ -442,7 +446,7 @@ __DEFINE_LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent) { struct v_fd* fd_s; int errno; - if (fd < 0 || fd >= VFS_MAX_FD || !(fd_s = __current->fdtable->fds[fd])) { + if (!GET_FD(fd, fd_s)) { errno = EBADF; } else if (!(fd_s->file->inode->itype & VFS_INODE_TYPE_DIR)) { errno = ENOTDIR; @@ -490,12 +494,67 @@ done: return SYSCALL_ESTATUS(errno); } -__DEFINE_LXSYSCALL3(size_t, read, int, fd, void*, buf, size_t, count) +__DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count) { - // TODO + int errno = 0; + struct v_fd* fd_s; + if (!GET_FD(fd, fd_s)) { + errno = EBADF; + } else { + struct v_file* file = fd_s->file; + file->f_pos = fd_s->pos; + if ((errno = file->ops.read(file, buf, count)) >= 0) { + fd_s->pos += errno; + } + } + + __current->k_status = errno; + return SYSCALL_ESTATUS(errno); } -__DEFINE_LXSYSCALL3(size_t, write, int, fd, void*, buf, size_t, count) +__DEFINE_LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count) { - // TODO + int errno = 0; + struct v_fd* fd_s; + if (!GET_FD(fd, fd_s)) { + errno = EBADF; + } else { + struct v_file* file = fd_s->file; + file->f_pos = fd_s->pos; + if ((errno = file->ops.write(file, buf, count)) >= 0) { + fd_s->pos += errno; + } + } + + __current->k_status = errno; + return SYSCALL_ESTATUS(errno); +} + +__DEFINE_LXSYSCALL3(int, lseek, int, fd, int, offset, int, options) +{ + int errno = 0; + struct v_fd* fd_s; + if (!GET_FD(fd, fd_s)) { + errno = EBADF; + } else { + size_t fpos = fd_s->file->f_pos; + switch (options) { + case FSEEK_CUR: + fpos = (size_t)((int)fd_s->file->f_pos + offset); + break; + case FSEEK_END: + fpos = (size_t)((int)fd_s->file->inode->fsize + offset); + break; + case FSEEK_SET: + fpos = offset; + break; + + default: + break; + } + fd_s->pos = fpos; + } + + __current->k_status = errno; + return SYSCALL_ESTATUS(errno); } \ No newline at end of file diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c index 4cf0c82..3ad6476 100644 --- a/lunaix-os/kernel/proc0.c +++ b/lunaix-os/kernel/proc0.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -42,7 +43,8 @@ __do_reserved_memory(int unlock); #define USE_DEMO // #define DEMO_SIGNAL -#define DEMO_READDIR +// #define DEMO_READDIR +#define DEMO_IOTEST extern void _pconsole_main(); @@ -56,6 +58,9 @@ _lxinit_main(); extern void _readdir_main(); +extern void +_iotest_main(); + void __USER__ __proc0_usr() { @@ -71,6 +76,8 @@ __proc0_usr() _signal_demo_main(); #elif defined DEMO_READDIR _readdir_main(); +#elif defined DEMO_IOTEST + _iotest_main(); #else _lxinit_main(); #endif @@ -119,39 +126,8 @@ extern uint8_t __kernel_end; /* link/linker.ld */ extern uint8_t __init_hhk_end; /* link/linker.ld */ extern multiboot_info_t* _k_init_mb_info; /* k_init.c */ -char test_sequence[] = "Once upon a time, in a magical land of Equestria. " - "There were two regal sisters who ruled together " - "and created harmony for all the land."; - -void -__test_disk_io() -{ - struct hba_port* port = ahci_get_port(0); - struct hba_device* dev = port->device; - char* buffer = vzalloc_dma(port->device->block_size); - strcpy(buffer, test_sequence); - kprintf("WRITE: %s\n", buffer); - int result; - - // 写入第一扇区 (LBA=0) - result = dev->ops.write_buffer(dev, 0, buffer, dev->block_size); - if (!result) { - kprintf(KWARN "fail to write: %x\n", dev->last_error); - } - - memset(buffer, 0, dev->block_size); - - // 读出我们刚刚写的内容! - result = dev->ops.read_buffer(dev, 0, buffer, dev->block_size); - kprintf(KDEBUG "%x, %x\n", port->regs[HBA_RPxIS], port->regs[HBA_RPxTFD]); - if (!result) { - kprintf(KWARN "fail to read: %x\n", dev->last_error); - } else { - kprint_hex(buffer, 256); - } - - vfree_dma(buffer); -} +extern void +block_twifs_create(); void init_platform() @@ -168,6 +144,7 @@ init_platform() clock_init(); ps2_kbd_init(); pci_init(); + block_init(); ahci_init(); // ahci_list_device(); @@ -175,6 +152,8 @@ init_platform() vfs_init(); twifs_init(); + block_twifs_create(); + vfs_mount("/", "twifs", -1); //__test_disk_io(); diff --git a/lunaix-os/kernel/sched.c b/lunaix-os/kernel/sched.c index ee596b1..d1ee39d 100644 --- a/lunaix-os/kernel/sched.c +++ b/lunaix-os/kernel/sched.c @@ -203,6 +203,11 @@ __DEFINE_LXSYSCALL3(pid_t, waitpid, pid_t, pid, int*, status, int, options) return _wait(pid, status, options); } +__DEFINE_LXSYSCALL(int, geterrno) +{ + return __current->k_status; +} + pid_t _wait(pid_t wpid, int* status, int options) {