#include <hal/acpi/acpi.h>
-#include <lunaix/mm/kalloc.h>
+#include <lunaix/mm/valloc.h>
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
acpi_rsdt_t* rsdt = rsdp->rsdt;
- ctx = lxcalloc(1, sizeof(acpi_context));
+ ctx = vzalloc(sizeof(acpi_context));
assert_msg(ctx, "Fail to create ACPI context");
strncpy(ctx->oem_id, rsdt->header.oem_id, 6);
#include "parser.h"
-#include <lunaix/mm/kalloc.h>
+#include <lunaix/mm/valloc.h>
void
madt_parse(acpi_madt_t* madt, acpi_context* toc)
// Cosidering only one IOAPIC present (max 24 pins)
// FIXME: use hash table instead
- toc->madt.irq_exception =
- (acpi_intso_t*)lxcalloc(24, sizeof(acpi_intso_t*));
+ toc->madt.irq_exception = (acpi_intso_t*)vcalloc(24, sizeof(acpi_intso_t*));
size_t so_idx = 0;
while (ics_start < ics_end) {
#include "lunaix/syslog.h"
#include "parser.h"
-#include <lunaix/mm/kalloc.h>
+#include <lunaix/mm/valloc.h>
LOG_MODULE("MCFG")
(struct acpi_mcfg_alloc*)((uintptr_t)mcfg + (sizeof(acpi_sdthdr_t) + 8));
toc->mcfg.alloc_num = alloc_num;
- toc->mcfg.allocations =
- lxmalloc(sizeof(struct mcfg_alloc_info) * alloc_num);
+ toc->mcfg.allocations = valloc(sizeof(struct mcfg_alloc_info) * alloc_num);
for (size_t i = 0; i < alloc_num; i++) {
toc->mcfg.allocations[i] = (struct mcfg_alloc_info){
#include <hal/acpi/acpi.h>
#include <hal/apic.h>
#include <hal/pci.h>
-#include <lunaix/mm/kalloc.h>
+#include <lunaix/mm/valloc.h>
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
pci_reg_t intr = pci_read_cspace(base, 0x3c);
pci_reg_t class = pci_read_cspace(base, 0x8);
- struct pci_device* device = lxmalloc(sizeof(struct pci_device));
+ struct pci_device* device = valloc(sizeof(struct pci_device));
*device = (struct pci_device){ .cspace_base = base,
.class_info = class,
.device_info = reg1,
--- /dev/null
+#ifndef __LUNAIX_SPARSE_H
+#define __LUNAIX_SPARSE_H
+
+#include <lunaix/ds/llist.h>
+#include <lunaix/types.h>
+
+#define BTRIE_BITS 4
+
+struct btrie
+{
+ struct btrie_node* btrie_root;
+ int truncated;
+};
+
+struct btrie_node
+{
+ struct llist_header children;
+ struct llist_header siblings;
+ struct llist_header nodes;
+ struct btrie_node* parent;
+ uint32_t index;
+ void* data;
+};
+
+void
+btrie_init(struct btrie* btrie, uint32_t trunc_bits);
+
+void*
+btrie_get(struct btrie* root, uint32_t index);
+
+void
+btrie_set(struct btrie* root, uint32_t index, void* data);
+
+void*
+btrie_remove(struct btrie* root, uint32_t index);
+
+void
+btrie_release(struct btrie* tree);
+
+#endif /* __LUNAIX_SPARSE_H */
#define FO_CREATE 0x1
#define FO_APPEND 0x2
+#define FO_DIRECT 0x4
#define FSEEK_SET 0x1
#define FSEEK_CUR 0x2
#include <hal/ahci/hba.h>
#include <lunaix/block.h>
+#include <lunaix/ds/btrie.h>
#include <lunaix/ds/hashtable.h>
#include <lunaix/ds/hstr.h>
#include <lunaix/ds/llist.h>
#define VFS_INODE_TYPE_DEVICE 0x4
#define VFS_INODE_TYPE_SYMLINK 0x8
-#define VFS_ENOFS -2
-#define VFS_EBADMNT -3
-
-#define VFS_EENDOFDIR -5
-
-#define VFS_EINVLD -8
-#define VFS_EEOF -9
-
#define VFS_WALK_MKPARENT 0x1
#define VFS_WALK_FSRELATIVE 0x2
#define VFS_WALK_PARENT 0x4
#define VFS_WALK_NOFOLLOW 0x4
-#define VFS_IOBUF_FDIRTY 0x1
-
#define FSTYPE_ROFS 0x1
#define VFS_VALID_CHAR(chr) \
extern struct hstr vfs_dot;
struct v_dnode;
+struct pcache;
struct filesystem
{
struct v_file_ops
{
- int (*write)(struct v_file* file, void* buffer, size_t len);
- int (*read)(struct v_file* file, void* buffer, size_t len);
+ int (*write)(struct v_file* file, void* buffer, size_t len, size_t fpos);
+ int (*read)(struct v_file* file, void* buffer, size_t len, size_t fpos);
int (*readdir)(struct v_file* file, struct dir_context* dctx);
int (*seek)(struct v_file* file, size_t offset);
int (*rename)(struct v_file* file, char* new_name);
struct v_dnode* dnode;
struct llist_header* f_list;
uint32_t f_pos;
+ uint32_t ref_count;
void* data; // 允许底层FS绑定他的一些专有数据
struct v_file_ops ops;
};
struct v_fd
{
struct v_file* file;
- int pos;
int flags;
};
uint32_t link_count;
uint32_t lb_usage;
uint32_t fsize;
+ struct pcache* pg_cache;
void* data; // 允许底层FS绑定他的一些专有数据
struct
{
- int (*create)(struct v_inode* this, struct v_file* file);
+ int (*create)(struct v_inode* this);
int (*open)(struct v_inode* this, struct v_file* file);
int (*sync)(struct v_inode* this);
int (*mkdir)(struct v_inode* this, struct v_dnode* dnode);
struct v_fd* fds[VFS_MAX_FD];
};
+struct pcache_pg
+{
+ struct llist_header pg_list;
+ struct llist_header dirty_list;
+ void* pg;
+ uint32_t flags;
+ uint32_t fpos;
+};
+
+struct pcache
+{
+ struct btrie tree;
+ struct llist_header pages;
+ struct llist_header dirty;
+ uint32_t n_dirty;
+ uint32_t n_pages;
+};
+
/* --- file system manager --- */
void
fsm_init();
void
vfs_i_free(struct v_inode* inode);
+
+void
+pcache_init(struct pcache* pcache);
+
+void
+pcache_release_page(struct pcache* pcache, struct pcache_pg* page);
+
+struct pcache_pg*
+pcache_new_page(struct pcache* pcache, uint32_t index);
+
+void
+pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg);
+
+struct pcache_pg*
+pcache_get_page(struct pcache* pcache,
+ uint32_t index,
+ uint32_t* offset,
+ struct pcache_pg** page);
+
+int
+pcache_write(struct v_file* file, void* data, uint32_t len);
+
+int
+pcache_read(struct v_file* file, void* data, uint32_t len);
+
+void
+pcache_release(struct pcache* pcache);
+
+int
+pcache_commit(struct v_file* file, struct pcache_pg* page);
+
+void
+pcache_invalidate(struct v_file* file, struct pcache_pg* page);
+
+void
+pcache_commit_all(struct v_file* file);
#endif /* __LUNAIX_VFS_H */
#define EBUSY -20
#define EXDEV -21
#define ELOOP -22
+#define ENODEV -23
#endif /* __LUNAIX_CODE_H */
int errno;
struct block_dev* bdev = (struct block_dev*)dev->underlay;
size_t acc_size = 0, rd_size = 0, bsize = bdev->hd_dev->block_size,
- rd_block = 0;
- void* block = valloc(bsize);
+ rd_block = offset / bsize, r = offset % bsize;
+ void* block = vzalloc(bsize);
while (acc_size < len) {
if (!bdev->hd_dev->ops.read_buffer(
- bdev->hd_dev, offset + rd_block, block, bsize)) {
+ bdev->hd_dev, rd_block, block, bsize)) {
errno = ENXIO;
goto error;
}
- rd_size = MIN(len - acc_size, bsize);
- memcpy(buf + acc_size, block, rd_size);
+ rd_size = MIN(len - acc_size, bsize - r);
+ memcpy(buf + acc_size, block + r, rd_size);
acc_size += rd_size;
+ r = 0;
rd_block++;
}
int errno;
struct block_dev* bdev = (struct block_dev*)dev->underlay;
size_t acc_size = 0, wr_size = 0, bsize = bdev->hd_dev->block_size,
- wr_block = 0;
- void* block = valloc(bsize);
+ wr_block = offset / bsize, r = offset % bsize;
+ void* block = vzalloc(bsize);
while (acc_size < len) {
- wr_size = MIN(len - acc_size, bsize);
- memcpy(block, buf + acc_size, wr_size);
+ wr_size = MIN(len - acc_size, bsize - r);
+ memcpy(block + r, buf + acc_size, wr_size);
if (!bdev->hd_dev->ops.write_buffer(
- bdev->hd_dev, offset + wr_block, block, bsize)) {
+ bdev->hd_dev, wr_block, block, bsize)) {
errno = ENXIO;
break;
}
acc_size += wr_size;
+ r = 0;
wr_block++;
}
"There were two regal sisters who ruled together "
"and created harmony for all the land.";
- int fd = open("/dev/sda", 0); // bd0 设备 - 硬盘
- int tty = open("/dev/tty", 0); // tty 设备 - 控制台
+ int fd = open("/dev/sda", 0); // sda 设备 - 硬盘
+
+ // tty 设备 - 控制台,使用O_DIRECT打开,即所有IO绕过Lunaix内核的缓存机制
+ int tty = open("/dev/tty", FO_DIRECT);
if (fd < 0 || tty < 0) {
kprintf(KERROR "fail to open (%d)\n", geterrno());
return;
}
- // 移动指针至第二个逻辑扇区(LBA=1),并写入
- lseek(fd, 1, FSEEK_SET);
+ // 移动指针至512字节,在大多数情况下,这是第二个逻辑扇区的起始处
+ lseek(fd, 512, FSEEK_SET);
+ write(fd, test_sequence, sizeof(test_sequence));
+ lseek(fd, 521, FSEEK_SET);
write(fd, test_sequence, sizeof(test_sequence));
// 读出我们写的内容
char read_out[256];
- lseek(fd, -1, FSEEK_CUR);
+ lseek(fd, 512, FSEEK_SET);
read(fd, read_out, sizeof(read_out));
+ // 将读出的内容直接写入tty设备
write(tty, read_out, sizeof(read_out));
+ write(tty, "\n", 1);
close(fd);
close(tty);
static struct twifs_node* dev_root;
int
-__dev_read(struct v_file* file, void* buffer, size_t len);
+__dev_read(struct v_file* file, void* buffer, size_t len, size_t fpos);
int
-__dev_write(struct v_file* file, void* buffer, size_t len);
+__dev_write(struct v_file* file, void* buffer, size_t len, size_t fpos);
void
device_init()
}
int
-__dev_read(struct v_file* file, void* buffer, size_t len)
+__dev_read(struct v_file* file, void* buffer, size_t len, size_t fpos)
{
struct twifs_node* dev_node = (struct twifs_node*)file->inode->data;
struct device* dev = (struct device*)dev_node->data;
if (!dev->read) {
return ENOTSUP;
}
- return dev->read(dev, buffer, file->f_pos, len);
+ return dev->read(dev, buffer, fpos, len);
}
int
-__dev_write(struct v_file* file, void* buffer, size_t len)
+__dev_write(struct v_file* file, void* buffer, size_t len, size_t fpos)
{
struct twifs_node* dev_node = (struct twifs_node*)file->inode->data;
struct device* dev = (struct device*)dev_node->data;
if (!dev->write) {
return ENOTSUP;
}
- return dev->write(dev, buffer, file->f_pos, len);
+ return dev->write(dev, buffer, fpos, len);
}
void
--- /dev/null
+/**
+ * @file btrie.c
+ * @author Lunaixsky
+ * @brief Bitwise trie tree implementation for sparse array.
+ * @version 0.1
+ * @date 2022-08-01
+ *
+ * @copyright Copyright (c) 2022
+ *
+ */
+
+#include <lunaix/ds/btrie.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+
+#define BTRIE_INSERT 1
+
+struct btrie_node*
+__btrie_traversal(struct btrie* root, uint32_t index, int options)
+{
+ index = index >> root->truncated;
+ uint32_t lz = index ? ROUNDDOWN(31 - __builtin_clz(index), BTRIE_BITS) : 0;
+ uint32_t bitmask = ((1 << BTRIE_BITS) - 1) << lz;
+ uint32_t i = 0;
+ struct btrie_node* tree = root->btrie_root;
+
+ // Time complexity: O(log_2(log_2(N))) where N is the index to lookup
+ while (lz && tree) {
+ i = (index & bitmask) >> lz;
+ struct btrie_node *subtree = 0, *pos, *n;
+
+ llist_for_each(pos, n, &tree->children, siblings)
+ {
+ if (pos->index == i) {
+ subtree = pos;
+ break;
+ }
+ }
+
+ if (!subtree && (options & BTRIE_INSERT)) {
+ struct btrie_node* new_tree = vzalloc(sizeof(struct btrie_node));
+ new_tree->index = i;
+ new_tree->parent = tree;
+ llist_init_head(&new_tree->children);
+
+ llist_append(&tree->children, &new_tree->siblings);
+ llist_append(&root->btrie_root->nodes, &new_tree->nodes);
+ tree = new_tree;
+ } else {
+ tree = subtree;
+ }
+ bitmask = bitmask >> BTRIE_BITS;
+ lz -= BTRIE_BITS;
+ }
+
+ return tree;
+}
+
+void
+btrie_init(struct btrie* btrie, uint32_t trunc_bits)
+{
+ btrie->btrie_root = vzalloc(sizeof(struct btrie_node));
+ llist_init_head(&btrie->btrie_root->nodes);
+ btrie->truncated = trunc_bits;
+}
+
+void*
+btrie_get(struct btrie* root, uint32_t index)
+{
+ struct btrie_node* node = __btrie_traversal(root, index, 0);
+ if (!node) {
+ return NULL;
+ }
+ return node->data;
+}
+
+void
+btrie_set(struct btrie* root, uint32_t index, void* data)
+{
+ struct btrie_node* node = __btrie_traversal(root, index, BTRIE_INSERT);
+ node->data = data;
+}
+
+void
+__btrie_remove(struct btrie_node* node)
+{
+ struct btrie_node* parent = node->parent;
+ if (parent) {
+ llist_delete(&node->siblings);
+ llist_delete(&node->nodes);
+ vfree(node);
+ if (llist_empty(&parent->children)) {
+ __btrie_remove(parent);
+ }
+ }
+}
+
+void*
+btrie_remove(struct btrie* root, uint32_t index)
+{
+ struct btrie_node* node = __btrie_traversal(root, index, 0);
+ if (!node) {
+ return 0;
+ }
+ void* data = node->data;
+ __btrie_remove(node);
+ return data;
+}
+
+void
+btrie_release(struct btrie* tree)
+{
+ struct btrie_node *pos, *n;
+ llist_for_each(pos, n, &tree->btrie_root->nodes, nodes)
+ {
+ vfree(pos);
+ }
+
+ vfree(tree->btrie_root);
+}
\ No newline at end of file
--- /dev/null
+#include <klibc/string.h>
+#include <lunaix/ds/btrie.h>
+#include <lunaix/fs.h>
+#include <lunaix/mm/page.h>
+#include <lunaix/mm/pmm.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/spike.h>
+
+#define PCACHE_DIRTY 0x1
+
+void
+pcache_init(struct pcache* pcache)
+{
+ btrie_init(&pcache->tree, PG_SIZE_BITS);
+ llist_init_head(&pcache->dirty);
+ llist_init_head(&pcache->pages);
+}
+
+void
+pcache_release_page(struct pcache* pcache, struct pcache_pg* page)
+{
+ pmm_free_page(KERNEL_PID, page->pg);
+ vmm_del_mapping(PD_REFERENCED, page->pg);
+
+ llist_delete(&page->pg_list);
+
+ vfree(page);
+
+ pcache->n_pages--;
+}
+
+struct pcache_pg*
+pcache_new_page(struct pcache* pcache, uint32_t index)
+{
+ void* pg = pmm_alloc_page(KERNEL_PID, 0);
+ void* pg_v = vmm_vmap(pg, PG_SIZE, PG_PREM_URW);
+ struct pcache_pg* ppg = valloc(sizeof(struct pcache_pg));
+ ppg->pg = pg_v;
+
+ llist_append(&pcache->pages, &ppg->pg_list);
+ btrie_set(&pcache->tree, index, ppg);
+
+ return ppg;
+}
+
+void
+pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg)
+{
+ if (!(pg->flags & PCACHE_DIRTY)) {
+ pg->flags |= PCACHE_DIRTY;
+ pcache->n_dirty++;
+ llist_append(&pcache->dirty, &pg->dirty_list);
+ }
+}
+
+struct pcache_pg*
+pcache_get_page(struct pcache* pcache,
+ uint32_t index,
+ uint32_t* offset,
+ struct pcache_pg** page)
+{
+ struct pcache_pg* pg = btrie_get(&pcache->tree, index);
+ int is_new = 0;
+ *offset = index & ((1 << pcache->tree.truncated) - 1);
+ if (!pg) {
+ pg = pcache_new_page(pcache, index);
+ pg->fpos = index - *offset;
+ pcache->n_pages++;
+ is_new = 1;
+ }
+ *page = pg;
+ return is_new;
+}
+
+int
+pcache_write(struct v_file* file, void* data, uint32_t len)
+{
+ uint32_t pg_off, buf_off = 0, fpos = file->f_pos;
+ struct pcache* pcache = file->inode->pg_cache;
+ struct pcache_pg* pg;
+
+ while (buf_off < len) {
+ pcache_get_page(pcache, fpos, &pg_off, &pg);
+ uint32_t wr_bytes = MIN(PG_SIZE - pg_off, len - buf_off);
+ memcpy(pg->pg + pg_off, (data + buf_off), wr_bytes);
+
+ pcache_set_dirty(pcache, pg);
+
+ buf_off += wr_bytes;
+ fpos += wr_bytes;
+ }
+
+ return buf_off;
+}
+
+int
+pcache_read(struct v_file* file, void* data, uint32_t len)
+{
+ uint32_t pg_off, buf_off = 0, new_pg = 0, fpos = file->f_pos;
+ int errno = 0;
+ struct pcache* pcache = file->inode->pg_cache;
+ struct pcache_pg* pg;
+
+ while (buf_off < len) {
+ if (pcache_get_page(pcache, fpos, &pg_off, &pg)) {
+ // Filling up the page
+ errno = file->ops.read(file, pg->pg, PG_SIZE, pg->fpos);
+ if (errno > 0 && errno < PG_SIZE) {
+ // EOF
+ len = buf_off + errno;
+ } else if (errno < 0) {
+ break;
+ }
+ }
+ uint32_t rd_bytes = MIN(PG_SIZE - pg_off, len - buf_off);
+ memcpy((data + buf_off), pg->pg + pg_off, rd_bytes);
+
+ buf_off += rd_bytes;
+ fpos += rd_bytes;
+ }
+
+ return errno < 0 ? errno : buf_off;
+}
+
+void
+pcache_release(struct pcache* pcache)
+{
+ struct pcache_pg *pos, *n;
+ llist_for_each(pos, n, &pcache->pages, pg_list)
+ {
+ vfree(pos);
+ }
+
+ btrie_release(&pcache->tree);
+}
+
+int
+pcache_commit(struct v_file* file, struct pcache_pg* page)
+{
+ if (!(page->flags & PCACHE_DIRTY)) {
+ return;
+ }
+
+ int errno = file->ops.write(file, page->pg, PG_SIZE, page->fpos);
+
+ if (!errno) {
+ page->flags &= ~PCACHE_DIRTY;
+ llist_delete(&page->dirty_list);
+ file->inode->pg_cache->n_dirty--;
+ }
+
+ return errno;
+}
+
+void
+pcache_commit_all(struct v_file* file)
+{
+ struct pcache* cache = file->inode->pg_cache;
+ struct pcache_pg *pos, *n;
+ llist_for_each(pos, n, &cache->dirty, dirty_list)
+ {
+ pcache_commit(file, pos);
+ }
+}
+
+void
+pcache_invalidate(struct v_file* file, struct pcache_pg* page)
+{
+ pcache_commit(file, page);
+ pcache_release_page(&file->inode->pg_cache, page);
+}
\ No newline at end of file
return ENAMETOOLONG;
}
if (!VFS_VALID_CHAR(current)) {
- return VFS_EINVLD;
+ return EINVAL;
}
name_content[j++] = current;
if (lookahead) {
} else {
break;
}
- errno =
- __vfs_walk_internal(start, pathname, &interim, component, options);
+ errno = __vfs_walk(start, pathname, &interim, component, options);
counter++;
}
{
struct filesystem* fs = fsm_get(fs_name);
if (!fs)
- return VFS_ENOFS;
+ return ENODEV;
struct v_superblock* sb = vfs_sb_alloc();
sb->dev = device;
sb->fs_id = fs_id++;
int errno = 0;
struct v_superblock* sb = mnt_point->super_block;
if (!sb) {
- return VFS_EBADMNT;
+ return EINVAL;
}
if (!(errno = sb->fs->unmount(sb))) {
struct v_dnode* fs_root = sb->root;
vfile->dnode = dnode;
vfile->inode = dnode->inode;
+ vfile->ref_count = 1;
dnode->inode->open_count++;
+ if ((dnode->inode->itype & VFS_INODE_TYPE_FILE) &&
+ !dnode->inode->pg_cache) {
+ struct pcache* pcache = vzalloc(sizeof(struct pcache));
+ pcache_init(pcache);
+ dnode->inode->pg_cache = pcache;
+ }
+
int errno = dnode->inode->ops.open(dnode->inode, vfile);
if (errno) {
cake_release(file_pile, vfile);
int
vfs_close(struct v_file* file)
{
- if (!file->ops.close) {
- return ENOTSUP;
- }
-
- int errno = file->ops.close(file);
- if (!errno) {
+ int errno = 0;
+ if (!file->ops.close || !(errno = file->ops.close(file))) {
if (file->inode->open_count) {
file->inode->open_count--;
}
+ pcache_commit_all(file);
cake_release(file_pile, file);
}
return errno;
{
struct v_inode* inode = cake_grab(inode_pile);
memset(inode, 0, sizeof(*inode));
-
return inode;
}
char name_str[VFS_NAME_MAXLEN];
struct hstr name = HSTR(name_str, 0);
int errno;
- if (!(errno = vfs_walk(NULL, path, fdir, &name, VFS_WALK_PARENT))) {
- errno = vfs_walk(*fdir, name.value, file, NULL, 0);
- if (errno == ENOENT && (options & FLOCATE_CREATE_EMPTY)) {
- struct v_dnode* file_new;
- file_new = vfs_d_alloc();
- file_new->name =
- HHSTR(valloc(VFS_NAME_MAXLEN), name.len, name.hash);
- strcpy(file_new->name.value, name_str);
- *file = file_new;
-
- llist_append(&(*fdir)->children, &file_new->siblings);
- }
+ if ((errno = vfs_walk(NULL, path, fdir, &name, VFS_WALK_PARENT))) {
+ return errno;
+ }
+
+ errno = vfs_walk(*fdir, name.value, file, NULL, 0);
+ if (errno != ENOENT || !(options & FLOCATE_CREATE_EMPTY)) {
+ return errno;
+ }
+
+ if (!(errno = (*fdir)->inode->ops.create((*fdir)->inode))) {
+ struct v_dnode* file_new;
+ file_new = vfs_d_alloc();
+ file_new->name = HHSTR(valloc(VFS_NAME_MAXLEN), name.len, name.hash);
+ strcpy(file_new->name.value, name_str);
+ *file = file_new;
+
+ llist_append(&(*fdir)->children, &file_new->siblings);
}
return errno;
errno = __vfs_try_locate_file(path, &dentry, &file, 0);
if (errno != ENOENT && (options & FO_CREATE)) {
- errno = dentry->inode->ops.create(dentry->inode, opened_file);
- } else if (!errno) {
+ errno = dentry->inode->ops.create(dentry->inode);
+ }
+
+ if (!errno) {
errno = vfs_open(file, &opened_file);
}
if (!errno && !(errno = vfs_alloc_fdslot(&fd))) {
struct v_fd* fd_s = vzalloc(sizeof(*fd_s));
+ opened_file->f_pos =
+ opened_file->inode->fsize & -((options & FO_APPEND) != 0);
fd_s->file = opened_file;
- fd_s->pos = opened_file->inode->fsize & -((options & FO_APPEND) != 0);
+ fd_s->flags = options;
__current->fdtable->fds[fd] = fd_s;
return fd;
}
__DEFINE_LXSYSCALL1(int, close, int, fd)
{
struct v_fd* fd_s;
- int errno;
+ int errno = 0;
if (!GET_FD(fd, fd_s)) {
errno = EBADF;
- } else if (!(errno = vfs_close(fd_s->file))) {
- vfree(fd_s);
- __current->fdtable->fds[fd] = 0;
+ goto done_err;
}
+ if (fd_s->file->ref_count > 1) {
+ fd_s->file->ref_count--;
+ } else if ((errno = vfs_close(fd_s->file))) {
+ goto done_err;
+ }
+
+ vfree(fd_s);
+ __current->fdtable->fds[fd] = 0;
+
+done_err:
return DO_STATUS(errno);
}
struct v_fd* fd_s;
if (!GET_FD(fd, fd_s)) {
errno = EBADF;
+ goto done;
+ }
+
+ struct v_file* file = fd_s->file;
+ if ((file->inode->itype & VFS_INODE_TYPE_DIR)) {
+ errno = EISDIR;
+ goto done;
+ }
+
+ if ((fd_s->flags & FO_DIRECT)) {
+ errno = file->ops.read(file, buf, count, file->f_pos);
} 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;
- }
+ errno = pcache_read(file, buf, count);
+ }
+
+ if (errno > 0) {
+ file->f_pos += errno;
+ return errno;
}
+done:
return DO_STATUS(errno);
}
struct v_fd* fd_s;
if (!GET_FD(fd, fd_s)) {
errno = EBADF;
+ goto done;
+ }
+
+ struct v_file* file = fd_s->file;
+ if ((file->inode->itype & VFS_INODE_TYPE_DIR)) {
+ errno = EISDIR;
+ goto done;
+ }
+
+ if ((fd_s->flags & FO_DIRECT)) {
+ errno = file->ops.write(file, buf, count, file->f_pos);
} 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;
- }
+ errno = pcache_write(file, buf, count);
+ }
+
+ if (errno > 0) {
+ file->f_pos += errno;
+ return errno;
}
+done:
return DO_STATUS(errno);
}
if (!GET_FD(fd, fd_s)) {
errno = EBADF;
} else {
- size_t fpos = fd_s->file->f_pos;
+ struct v_file* file = fd_s->file;
+ size_t fpos = file->f_pos;
switch (options) {
case FSEEK_CUR:
- fpos = (size_t)((int)fd_s->file->f_pos + offset);
+ fpos = (size_t)((int)file->f_pos + offset);
break;
case FSEEK_END:
- fpos = (size_t)((int)fd_s->file->inode->fsize + offset);
+ fpos = (size_t)((int)file->inode->fsize + offset);
break;
case FSEEK_SET:
fpos = offset;
break;
-
- default:
- break;
}
- fd_s->pos = fpos;
+ if (!file->ops.seek || !(errno = file->ops.seek(file, fpos))) {
+ file->f_pos = fpos;
+ }
}
return DO_STATUS(errno);
__vfs_dup_fd(struct v_fd* old, struct v_fd** new)
{
int errno = 0;
- struct v_file* newopened;
- if (!(errno = vfs_open(old->file->dnode, &newopened))) {
- *new = cake_grab(fd_pile);
- **new = (struct v_fd){ .file = newopened,
- .pos = old->pos,
- .flags = old->flags };
- }
+ struct v_fd* copied = cake_grab(fd_pile);
+
+ memcpy(copied, old, sizeof(struct v_fd));
+ old->file->ref_count++;
return errno;
}
-#include <lunaix/mm/kalloc.h>
#include <lunaix/mm/region.h>
+#include <lunaix/mm/valloc.h>
void
region_add(struct mm_region* regions,
unsigned long end,
unsigned int attr)
{
- struct mm_region* region = lxmalloc(sizeof(struct mm_region));
+ struct mm_region* region = valloc(sizeof(struct mm_region));
*region = (struct mm_region){ .attr = attr, .end = end, .start = start };
#define USE_DEMO
// #define DEMO_SIGNAL
-#define DEMO_READDIR
-//#define DEMO_IOTEST
+// #define DEMO_READDIR
+#define DEMO_IOTEST
extern void
_pconsole_main();