diff --git a/kernel/include/fs/vfs.h b/kernel/include/fs/vfs.h index a7749d5..02f1186 100644 --- a/kernel/include/fs/vfs.h +++ b/kernel/include/fs/vfs.h @@ -72,6 +72,8 @@ typedef struct } vfs_dirent_t; +int vfs_destroy(vnode_t *vn); + /** * @brief Increment vnode reference count. * @@ -98,7 +100,7 @@ static inline bool vnode_unref(vnode_t *vn) { if (atomic_fetch_sub_explicit(&vn->refcount, 1, memory_order_acq_rel) == 1) { - // TODO: run vnode destructor + vfs_destroy(vn); return true; } return false; @@ -106,6 +108,9 @@ static inline bool vnode_unref(vnode_t *vn) struct vnode_ops { + int (*open) (vnode_t *vn, int flags, void *cred); + int (*close) (vnode_t *vp, int flags, void *cred); + int (*destroy)(vnode_t *vn, int flags); int (*read) (vnode_t *vn, void *buffer, uint64_t offset, uint64_t count, uint64_t *out_bytes_read); int (*write) (vnode_t *vn, const void *buffer, uint64_t offset, uint64_t count, uint64_t *out_bytes_written); int (*lookup) (vnode_t *vn, const char *name, vnode_t **out_vn); @@ -123,6 +128,8 @@ struct vnode_ops [[nodiscard]] int vfs_read(vnode_t *vn, void *buffer, uint64_t offset, uint64_t count, uint64_t *out_bytes_read); [[nodiscard]] int vfs_write(vnode_t *vn, void *buffer, uint64_t offset, uint64_t count, uint64_t *out_bytes_written); +[[nodiscard]] int vfs_open(vnode_t *vn, int flags, void *cred); +[[nodiscard]] int vfs_close(vnode_t *vn, int flags, void *cred); [[nodiscard]] int vfs_lookup(const char *path, vnode_t **out_vn); [[nodiscard]] int vfs_create(const char *path, vnode_type_t type, vnode_t **out_vn); [[nodiscard]] int vfs_remove(const char *path); diff --git a/kernel/include/mm/vm.h b/kernel/include/mm/vm.h index e4b1c11..e758299 100644 --- a/kernel/include/mm/vm.h +++ b/kernel/include/mm/vm.h @@ -26,7 +26,6 @@ typedef struct { uintptr_t start; size_t length; - int prot; int prot; int flags; diff --git a/kernel/source/fs/ramfs.c b/kernel/source/fs/ramfs.c index caed6ec..16ee71f 100644 --- a/kernel/source/fs/ramfs.c +++ b/kernel/source/fs/ramfs.c @@ -39,12 +39,18 @@ vfs_ops_t ramfs_ops = { static int read (vnode_t *self, void *buf, uint64_t offset, uint64_t count, uint64_t *out); static int write (vnode_t *self, const void *buf, uint64_t offset, uint64_t count, uint64_t *out); +static int open (vnode_t *self, int flags, void *cred); +static int close (vnode_t *self, int flags, void *cred); +static int destroy(vnode_t *self, int flags); static int lookup(vnode_t *self, const char *name, vnode_t **out); static int create(vnode_t *self, const char *name, vnode_type_t t, vnode_t **out); static int remove(vnode_t *self, const char *name); static int readdir(vnode_t *self, vfs_dirent_t **out_entries, size_t *out_count); vnode_ops_t ramfs_node_ops = { + .open = open, + .close = close, + .destroy = destroy, .read = read, .write = write, .lookup = lookup, @@ -60,6 +66,30 @@ static vnode_t *ramfs_get_root(vfs_t *self) return (vnode_t *)self->private_data; } +static int open(vnode_t *self, int flags, void *cred) +{ + if (!self) + return EINVAL; + + ramfs_node_t *node = (ramfs_node_t *)self; + + // TODO: implement proper credential checking) + // TODO: Can't open directory for writing + + node->vn.atime = arch_clock_get_unix_time(); + + return EOK; +} + +static int close(vnode_t *self, int flags, void *cred) +{ + if (!self) + return EINVAL; + + return EOK; +} + + // Node Operations static int read(vnode_t *self, void *buf, uint64_t offset, uint64_t count, uint64_t *out) @@ -115,6 +145,7 @@ static int write(vnode_t *self, const void *buf, uint64_t offset, uint64_t count { page = (void*)(pm_alloc(0)->addr + HHDM); xa_insert(&node->pages, page_idx, page); + node->page_count = page_idx + 1; } memcpy((uint8_t *)page + page_off, src + written, to_copy); @@ -200,6 +231,9 @@ static int remove(vnode_t *self, const char *name) ramfs_node_t *child = LIST_GET_CONTAINER(n, ramfs_node_t, list_node); if (strcmp(child->vn.name, name) == 0) { + if (atomic_load(&child->vn.refcount) > 1) + return EBUSY; + list_remove(¤t->children, &child->list_node); FOREACH(c, child->children) { diff --git a/kernel/source/fs/vfs.c b/kernel/source/fs/vfs.c index 7e06121..08fb838 100644 --- a/kernel/source/fs/vfs.c +++ b/kernel/source/fs/vfs.c @@ -102,6 +102,7 @@ int vfs_lookup(const char *path, vnode_t **out_vn) { vnode_t *curr; path = vfs_get_mountpoint(path, &curr); + const char *comp; size_t comp_len; @@ -111,9 +112,11 @@ int vfs_lookup(const char *path, vnode_t **out_vn) memcpy(name_buf, comp, comp_len); name_buf[comp_len] = '\0'; - if (curr->ops->lookup(curr, name_buf, &curr) != EOK) + vnode_t *next; + if (curr->ops->lookup(curr, name_buf, &next) != EOK) return ENOENT; - + + curr = next; path = comp + comp_len; } @@ -172,6 +175,41 @@ int vfs_ioctl(vnode_t *vn, uint64_t cmd, void *arg) return vn->ops->ioctl(vn, cmd, arg); } +int vfs_open(vnode_t *vn, int flags, void *cred) +{ + if (!vn) + return EINVAL; + + // TODO: permission checks + + if (vn->ops->open) + return vn->ops->open(vn, flags, cred); + + return ENOTSUP; +} + +int vfs_close(vnode_t *vn, int flags, void *cred) +{ + if (!vn) + return EINVAL; + + // TODO: permission checks + + if (vn->ops->close) + return vn->ops->close(vn, flags, cred); + + return ENOTSUP; +} +int vfs_destroy(vnode_t *vn) +{ + if (!vn) + return EINVAL; + + if (vn->ops && vn->ops->destroy) + return vn->ops->destroy(vn, 0); + + return ENOTSUP; +} void vfs_init() { vfs_t *ramfs = ramfs_create();