Orion
Barry Importing existing Orion kernel d41a53c (2 years, 4 months ago)diff --git a/vfs/inode.c b/vfs/inode.c new file mode 100644 index 0000000..34b5c65 --- /dev/null +++ b/vfs/inode.c @@ -0,0 +1,204 @@ +/* + * This file deals with inode operations. Most of the functions here are just + * wrappers for the inode operations. They generally check if the operation + * exists and use it if it does. If it doesn't they may implement a generic + * action, or just simply return. They also perform the necessary validation to + * ensure the operation can be called on the particular inode. + */ + +#include <string.h> +#include <errno.h> +#include "vfs.h" +#include "cache.h" +#include "inode.h" +#include "super.h" +#include "../mem/heap.h" +#include "../screen.h" + +/* Get an Inode */ +Inode * +inode_get(Inode *inode) +{ + /* Add the inode to the Inode List */ + if (!inode->usage && inode->super) { + if (!inode->super->inodes) { + inode->super->inodes = inode; + } else { + inode->lnext = inode->super->inodes; + inode->super->inodes = inode; + } + inode->super->cachedInodes++; + } + + inode->usage++; + return inode; +} + +/* Put an Inode */ +void +inode_put(Inode *inode) +{ + ASSERT(inode->usage); + if (--inode->usage) + return; + + /* Remove the inode from the Inode List */ + Inode *search, *prev = NULL; + if (inode->super) { + for (search = inode->super->inodes; search; + prev = search, search = search->lnext) + if (search == inode) + break; + if (search) { + if (prev) + prev->lnext = search->lnext; + else + inode->super->inodes = search->lnext; + } + } + + /* Clean up */ + if (S_ISDIR(inode->mode)) + entry_clean(inode); + else + page_clean(inode); + + kfree(inode); +} + +/* Create an inode */ +int +inode_create(Inode *inode, DirEntry *entry, mode_t mode) +{ + if (!inode->ops) + return -EINVAL; + if (!inode->ops->create) + return -EINVAL; + acquire(&inode->lock); + int err = inode->ops->create(inode, entry, mode); + if (!err) { + entry_add(inode, entry); + entry->inode = super_alloc_inode(inode->super); + entry->inode->mode = mode | S_IFREG; + } + release(&inode->lock); + return err; +} + +/* Find a child inode in a directory inode */ +DirEntry * +inode_lookup(Inode *inode, const char *name) +{ + if (!S_ISDIR(inode->mode)) + return NULL; + + acquire(&inode->lock); + + /* Check cache first */ + DirEntry *de = entry_find(inode, name); + if (de) { + entry_get(de); + if (de->inode) { + release(&inode->lock); + return de; + } + } + /* Try file system lookup */ + if (!inode->ops) { + release(&inode->lock); + return NULL; + } + if (!inode->ops->lookup) { + release(&inode->lock); + return NULL; + } + Inode *child = inode->ops->lookup(inode, name); + + /* The file doesn't exist */ + if (!child) { + if (de) + entry_remove(inode, name); + release(&inode->lock); + return NULL; + } + + /* Fill in DirEntry */ + if (!de) { + de = kmalloc(sizeof(DirEntry)); + strncpy(de->name, name, NAME_MAX); + de->super = inode->super; + entry_add(inode, de); + } + de->inode = inode_get(child); + de->mnt = NULL; + release(&inode->lock); + + return entry_get(de); +} + +/* Make a directory */ +int +inode_mkdir(Inode *inode, DirEntry *entry, mode_t mode) +{ + if (!inode->ops) + return -EINVAL; + if (!inode->ops->mkdir) + return -EINVAL; + acquire(&inode->lock); + int err = inode->ops->mkdir(inode, entry, mode); + if (!err) { + entry_add(inode, entry); + entry->inode = super_alloc_inode(inode->super); + entry->inode->mode = mode | S_IFDIR; + } + release(&inode->lock); + return err; +} + +/* Remove a directory */ +int +inode_rmdir(Inode *inode, DirEntry *entry) +{ + if (!inode->ops) + return -EINVAL; + if (!inode->ops->rmdir) + return -EINVAL; + acquire(&inode->lock); + int err = inode->ops->rmdir(inode, entry); + if (!err) + entry_remove(inode, entry->name); + release(&inode->lock); + return err; +} + +/* Make a node */ +int +inode_mknod(Inode *inode, DirEntry *entry, mode_t mode, dev_t dev) +{ + if (!inode->ops) + return -EINVAL; + if (!inode->ops->mknod) + return -EINVAL; + acquire(&inode->lock); + + int err = inode->ops->mknod(inode, entry, mode, dev); + if (!err) { + entry_add(inode, entry); + entry->inode = super_alloc_inode(inode->super); + entry->inode->mode = mode; /* FIXME */ + entry->inode->dev = dev; + } + release(&inode->lock); + return err; +} + +/* Rename/mode a directory entry */ +int +inode_rename(Inode *si, DirEntry *sde, Inode *di, DirEntry *dde) +{ + if (!si->ops) + return -EINVAL; + if (!si->ops->rename) + return -EINVAL; + return 0; +}