|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH v2 1/6] lib/ramfs: initial import from OSv
Reviewed-by: Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
> On 8. Feb 2019, at 15:31, Yuri Volchkov <yuri.volchkov@xxxxxxxxx> wrote:
>
> git tag: v0.52.0
> commit: 00299190414e4c7c5b0f2d74cd11763dac34e5b9
>
> Signed-off-by: Yuri Volchkov <yuri.volchkov@xxxxxxxxx>
> ---
> lib/ramfs/ramfs.h | 68 ++++
> lib/ramfs/ramfs_vfsops.c | 90 ++++++
> lib/ramfs/ramfs_vnops.c | 669 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 827 insertions(+)
> create mode 100644 lib/ramfs/ramfs.h
> create mode 100644 lib/ramfs/ramfs_vfsops.c
> create mode 100644 lib/ramfs/ramfs_vnops.c
>
> diff --git a/lib/ramfs/ramfs.h b/lib/ramfs/ramfs.h
> new file mode 100644
> index 00000000..88ccbe72
> --- /dev/null
> +++ b/lib/ramfs/ramfs.h
> @@ -0,0 +1,68 @@
> +/*
> + * Copyright (c) 2006-2007, Kohsuke Ohtani
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of the author nor the names of any co-contributors
> + * may be used to endorse or promote products derived from this software
> + * without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#ifndef _RAMFS_H
> +#define _RAMFS_H
> +
> +#include <osv/prex.h>
> +
> +/* #define DEBUG_RAMFS 1 */
> +
> +#ifdef DEBUG_RAMFS
> +#define DPRINTF(a) dprintf a
> +#else
> +#define DPRINTF(a) do {} while (0)
> +#endif
> +
> +#define ASSERT(e) assert(e)
> +
> +/*
> + * File/directory node for RAMFS
> + */
> +struct ramfs_node {
> + struct ramfs_node *rn_next; /* next node in the same directory */
> + struct ramfs_node *rn_child; /* first child node */
> + int rn_type; /* file or directory */
> + char *rn_name; /* name (null-terminated) */
> + size_t rn_namelen; /* length of name not including terminator */
> + size_t rn_size; /* file size */
> + char *rn_buf; /* buffer to the file data */
> + size_t rn_bufsize; /* allocated buffer size */
> + struct timespec rn_ctime;
> + struct timespec rn_atime;
> + struct timespec rn_mtime;
> + int rn_mode;
> + bool rn_owns_buf;
> +};
> +
> +struct ramfs_node *ramfs_allocate_node(const char *name, int type);
> +
> +void ramfs_free_node(struct ramfs_node *node);
> +
> +#endif /* !_RAMFS_H */
> diff --git a/lib/ramfs/ramfs_vfsops.c b/lib/ramfs/ramfs_vfsops.c
> new file mode 100644
> index 00000000..72fe7edb
> --- /dev/null
> +++ b/lib/ramfs/ramfs_vfsops.c
> @@ -0,0 +1,90 @@
> +/*
> + * Copyright (c) 2006-2007, Kohsuke Ohtani
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of the author nor the names of any co-contributors
> + * may be used to endorse or promote products derived from this software
> + * without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <errno.h>
> +
> +#include <osv/vnode.h>
> +#include <osv/mount.h>
> +#include <osv/dentry.h>
> +
> +#include "ramfs.h"
> +
> +extern struct vnops ramfs_vnops;
> +
> +static int ramfs_mount(struct mount *mp, const char *dev, int flags, const
> void *data);
> +
> +static int ramfs_unmount(struct mount *mp, int flags);
> +
> +#define ramfs_sync ((vfsop_sync_t)vfs_nullop)
> +#define ramfs_vget ((vfsop_vget_t)vfs_nullop)
> +#define ramfs_statfs ((vfsop_statfs_t)vfs_nullop)
> +
> +/*
> + * File system operations
> + */
> +struct vfsops ramfs_vfsops = {
> + ramfs_mount, /* mount */
> + ramfs_unmount, /* unmount */
> + ramfs_sync, /* sync */
> + ramfs_vget, /* vget */
> + ramfs_statfs, /* statfs */
> + &ramfs_vnops, /* vnops */
> +};
> +
> +/*
> + * Mount a file system.
> + */
> +static int
> +ramfs_mount(struct mount *mp, const char *dev, int flags, const void *data)
> +{
> + struct ramfs_node *np;
> +
> + DPRINTF(("ramfs_mount: dev=%s\n", dev));
> +
> + /* Create a root node */
> + np = ramfs_allocate_node("/", VDIR);
> + if (np == NULL)
> + return ENOMEM;
> + mp->m_root->d_vnode->v_data = np;
> + return 0;
> +}
> +
> +/*
> + * Unmount a file system.
> + *
> + * NOTE: Currently, we don't support unmounting of the RAMFS. This is
> + * because we have to deallocate all nodes included in all sub
> + * directories, and it requires more work...
> + */
> +static int
> +ramfs_unmount(struct mount *mp, int flags)
> +{
> + release_mp_dentries(mp);
> + return 0;
> +}
> diff --git a/lib/ramfs/ramfs_vnops.c b/lib/ramfs/ramfs_vnops.c
> new file mode 100644
> index 00000000..9291a4ec
> --- /dev/null
> +++ b/lib/ramfs/ramfs_vnops.c
> @@ -0,0 +1,669 @@
> +/*
> + * Copyright (c) 2006-2007, Kohsuke Ohtani
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of the author nor the names of any co-contributors
> + * may be used to endorse or promote products derived from this software
> + * without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +/*
> + * rmafs_vnops.c - vnode operations for RAM file system.
> + */
> +
> +#include <sys/stat.h>
> +#include <dirent.h>
> +#include <sys/param.h>
> +
> +#include <errno.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +
> +#include <osv/prex.h>
> +#include <osv/vnode.h>
> +#include <osv/file.h>
> +#include <osv/mount.h>
> +#include <osv/vnode_attr.h>
> +
> +#include "ramfs.h"
> +
> +static mutex_t ramfs_lock = MUTEX_INITIALIZER;
> +static uint64_t inode_count = 1; /* inode 0 is reserved to root */
> +
> +static void
> +set_times_to_now(struct timespec *time1, struct timespec *time2 = nullptr,
> struct timespec *time3 = nullptr)
> +{
> + struct timespec now;
> + clock_gettime(CLOCK_REALTIME, &now);
> + if (time1) {
> + memcpy(time1, &now, sizeof(struct timespec));
> + }
> + if (time2) {
> + memcpy(time2, &now, sizeof(struct timespec));
> + }
> + if (time3) {
> + memcpy(time3, &now, sizeof(struct timespec));
> + }
> +}
> +
> +struct ramfs_node *
> +ramfs_allocate_node(const char *name, int type)
> +{
> + struct ramfs_node *np;
> +
> + np = (ramfs_node *) malloc(sizeof(struct ramfs_node));
> + if (np == NULL)
> + return NULL;
> + memset(np, 0, sizeof(struct ramfs_node));
> +
> + np->rn_namelen = strlen(name);
> + np->rn_name = (char *) malloc(np->rn_namelen + 1);
> + if (np->rn_name == NULL) {
> + free(np);
> + return NULL;
> + }
> + strlcpy(np->rn_name, name, np->rn_namelen + 1);
> + np->rn_type = type;
> +
> + if (type == VDIR)
> + np->rn_mode = S_IFDIR|0777;
> + else if (type == VLNK)
> + np->rn_mode = S_IFLNK|0777;
> + else
> + np->rn_mode = S_IFREG|0777;
> +
> + set_times_to_now(&(np->rn_ctime), &(np->rn_atime), &(np->rn_mtime));
> + np->rn_owns_buf = true;
> +
> + return np;
> +}
> +
> +void
> +ramfs_free_node(struct ramfs_node *np)
> +{
> + if (np->rn_buf != NULL && np->rn_owns_buf)
> + free(np->rn_buf);
> +
> + free(np->rn_name);
> + free(np);
> +}
> +
> +static struct ramfs_node *
> +ramfs_add_node(struct ramfs_node *dnp, char *name, int type)
> +{
> + struct ramfs_node *np, *prev;
> +
> + np = ramfs_allocate_node(name, type);
> + if (np == NULL)
> + return NULL;
> +
> + mutex_lock(&ramfs_lock);
> +
> + /* Link to the directory list */
> + if (dnp->rn_child == NULL) {
> + dnp->rn_child = np;
> + } else {
> + prev = dnp->rn_child;
> + while (prev->rn_next != NULL)
> + prev = prev->rn_next;
> + prev->rn_next = np;
> + }
> +
> + set_times_to_now(&(dnp->rn_mtime), &(dnp->rn_ctime));
> +
> + mutex_unlock(&ramfs_lock);
> + return np;
> +}
> +
> +static int
> +ramfs_remove_node(struct ramfs_node *dnp, struct ramfs_node *np)
> +{
> + struct ramfs_node *prev;
> +
> + if (dnp->rn_child == NULL)
> + return EBUSY;
> +
> + mutex_lock(&ramfs_lock);
> +
> + /* Unlink from the directory list */
> + if (dnp->rn_child == np) {
> + dnp->rn_child = np->rn_next;
> + } else {
> + for (prev = dnp->rn_child; prev->rn_next != np;
> + prev = prev->rn_next) {
> + if (prev->rn_next == NULL) {
> + mutex_unlock(&ramfs_lock);
> + return ENOENT;
> + }
> + }
> + prev->rn_next = np->rn_next;
> + }
> + ramfs_free_node(np);
> +
> + set_times_to_now(&(dnp->rn_mtime), &(dnp->rn_ctime));
> +
> + mutex_unlock(&ramfs_lock);
> + return 0;
> +}
> +
> +static int
> +ramfs_rename_node(struct ramfs_node *np, char *name)
> +{
> + size_t len;
> + char *tmp;
> +
> + len = strlen(name);
> + if (len > NAME_MAX) {
> + return ENAMETOOLONG;
> + }
> + if (len <= np->rn_namelen) {
> + /* Reuse current name buffer */
> + strlcpy(np->rn_name, name, np->rn_namelen + 1);
> + } else {
> + /* Expand name buffer */
> + tmp = (char *) malloc(len + 1);
> + if (tmp == NULL)
> + return ENOMEM;
> + strlcpy(tmp, name, len + 1);
> + free(np->rn_name);
> + np->rn_name = tmp;
> + }
> + np->rn_namelen = len;
> + set_times_to_now(&(np->rn_ctime));
> + return 0;
> +}
> +
> +static int
> +ramfs_lookup(struct vnode *dvp, char *name, struct vnode **vpp)
> +{
> + struct ramfs_node *np, *dnp;
> + struct vnode *vp;
> + size_t len;
> + int found;
> +
> + *vpp = NULL;
> +
> + if (*name == '\0')
> + return ENOENT;
> +
> + mutex_lock(&ramfs_lock);
> +
> + len = strlen(name);
> + dnp = (ramfs_node *) dvp->v_data;
> + found = 0;
> + for (np = dnp->rn_child; np != NULL; np = np->rn_next) {
> + if (np->rn_namelen == len &&
> + memcmp(name, np->rn_name, len) == 0) {
> + found = 1;
> + break;
> + }
> + }
> + if (found == 0) {
> + mutex_unlock(&ramfs_lock);
> + return ENOENT;
> + }
> + if (vget(dvp->v_mount, inode_count++, &vp)) {
> + /* found in cache */
> + *vpp = vp;
> + mutex_unlock(&ramfs_lock);
> + return 0;
> + }
> + if (!vp) {
> + mutex_unlock(&ramfs_lock);
> + return ENOMEM;
> + }
> + vp->v_data = np;
> + vp->v_mode = ALLPERMS;
> + vp->v_type = np->rn_type;
> + vp->v_size = np->rn_size;
> +
> + mutex_unlock(&ramfs_lock);
> +
> + *vpp = vp;
> +
> + return 0;
> +}
> +
> +static int
> +ramfs_mkdir(struct vnode *dvp, char *name, mode_t mode)
> +{
> + struct ramfs_node *np;
> +
> + DPRINTF(("mkdir %s\n", name));
> + if (strlen(name) > NAME_MAX) {
> + return ENAMETOOLONG;
> + }
> +
> + if (!S_ISDIR(mode))
> + return EINVAL;
> +
> + np = (ramfs_node *) ramfs_add_node((ramfs_node *) dvp->v_data, name,
> VDIR);
> + if (np == NULL)
> + return ENOMEM;
> + np->rn_size = 0;
> +
> + return 0;
> +}
> +
> +static int
> +ramfs_symlink(struct vnode *dvp, char *name, char *link)
> +{
> + if (strlen(name) > NAME_MAX) {
> + return ENAMETOOLONG;
> + }
> + auto np = ramfs_add_node((ramfs_node *) dvp->v_data, name, VLNK);
> + if (np == NULL)
> + return ENOMEM;
> + // Save the link target without the final null, as readlink() wants it.
> + size_t len = strlen(link);
> + np->rn_buf = strndup(link, len);
> + np->rn_bufsize = np->rn_size = len;
> +
> + return 0;
> +}
> +
> +static int
> +ramfs_readlink(struct vnode *vp, struct uio *uio)
> +{
> + struct ramfs_node *np = (ramfs_node *) vp->v_data;
> + size_t len;
> +
> + if (vp->v_type != VLNK) {
> + return EINVAL;
> + }
> + if (uio->uio_offset < 0) {
> + return EINVAL;
> + }
> + if (uio->uio_resid == 0) {
> + return 0;
> + }
> + if (uio->uio_offset >= (off_t) vp->v_size)
> + return 0;
> + if (vp->v_size - uio->uio_offset < uio->uio_resid)
> + len = vp->v_size - uio->uio_offset;
> + else
> + len = uio->uio_resid;
> +
> + set_times_to_now( &(np->rn_atime));
> + return uiomove(np->rn_buf + uio->uio_offset, len, uio);
> +}
> +
> +/* Remove a directory */
> +static int
> +ramfs_rmdir(struct vnode *dvp, struct vnode *vp, char *name)
> +{
> + return ramfs_remove_node((ramfs_node *) dvp->v_data, (ramfs_node *)
> vp->v_data);
> +}
> +
> +/* Remove a file */
> +static int
> +ramfs_remove(struct vnode *dvp, struct vnode *vp, char *name)
> +{
> + DPRINTF(("remove %s in %s\n", name, dvp->v_path));
> + return ramfs_remove_node((ramfs_node *) dvp->v_data, (ramfs_node *)
> vp->v_data);
> +}
> +
> +/* Truncate file */
> +static int
> +ramfs_truncate(struct vnode *vp, off_t length)
> +{
> + struct ramfs_node *np;
> + void *new_buf;
> + size_t new_size;
> +
> + DPRINTF(("truncate %s length=%d\n", vp->v_path, length));
> + np = (ramfs_node *) vp->v_data;
> +
> + if (length == 0) {
> + if (np->rn_buf != NULL) {
> + if(np->rn_owns_buf)
> + free(np->rn_buf);
> + np->rn_buf = NULL;
> + np->rn_bufsize = 0;
> + }
> + } else if (size_t(length) > np->rn_bufsize) {
> + // XXX: this could use a page level allocator
> + new_size = round_page(length);
> + new_buf = malloc(new_size);
> + if (!new_buf)
> + return EIO;
> + if (np->rn_size != 0) {
> + memcpy(new_buf, np->rn_buf, vp->v_size);
> + if(np->rn_owns_buf)
> + free(np->rn_buf);
> + }
> + np->rn_buf = (char *) new_buf;
> + np->rn_bufsize = new_size;
> + np->rn_owns_buf = true;
> + }
> + np->rn_size = length;
> + vp->v_size = length;
> + set_times_to_now(&(np->rn_mtime), &(np->rn_ctime));
> + return 0;
> +}
> +
> +/*
> + * Create empty file.
> + */
> +static int
> +ramfs_create(struct vnode *dvp, char *name, mode_t mode)
> +{
> + struct ramfs_node *np;
> +
> + if (strlen(name) > NAME_MAX) {
> + return ENAMETOOLONG;
> + }
> +
> + DPRINTF(("create %s in %s\n", name, dvp->v_path));
> + if (!S_ISREG(mode))
> + return EINVAL;
> +
> + np = ramfs_add_node((ramfs_node *) dvp->v_data, name, VREG);
> + if (np == NULL)
> + return ENOMEM;
> + return 0;
> +}
> +
> +static int
> +ramfs_read(struct vnode *vp, struct file *fp, struct uio *uio, int ioflag)
> +{
> + struct ramfs_node *np = (ramfs_node *) vp->v_data;
> + size_t len;
> +
> + if (vp->v_type == VDIR) {
> + return EISDIR;
> + }
> + if (vp->v_type != VREG) {
> + return EINVAL;
> + }
> + if (uio->uio_offset < 0) {
> + return EINVAL;
> + }
> + if (uio->uio_resid == 0) {
> + return 0;
> + }
> +
> + if (uio->uio_offset >= (off_t) vp->v_size)
> + return 0;
> +
> + if (vp->v_size - uio->uio_offset < uio->uio_resid)
> + len = vp->v_size - uio->uio_offset;
> + else
> + len = uio->uio_resid;
> +
> + set_times_to_now(&(np->rn_atime));
> +
> + return uiomove(np->rn_buf + uio->uio_offset, len, uio);
> +}
> +
> +int
> +ramfs_set_file_data(struct vnode *vp, const void *data, size_t size)
> +{
> + struct ramfs_node *np = (ramfs_node *) vp->v_data;
> +
> + if (vp->v_type == VDIR) {
> + return EISDIR;
> + }
> + if (vp->v_type != VREG) {
> + return EINVAL;
> + }
> + if (np->rn_buf) {
> + return EINVAL;
> + }
> +
> + np->rn_buf = (char *) data;
> + np->rn_bufsize = size;
> + np->rn_size = size;
> + vp->v_size = size;
> + np->rn_owns_buf = false;
> +
> + return 0;
> +}
> +
> +static int
> +ramfs_write(struct vnode *vp, struct uio *uio, int ioflag)
> +{
> + struct ramfs_node *np = (ramfs_node *) vp->v_data;
> +
> + if (vp->v_type == VDIR) {
> + return EISDIR;
> + }
> + if (vp->v_type != VREG) {
> + return EINVAL;
> + }
> + if (uio->uio_offset < 0) {
> + return EINVAL;
> + }
> + if (uio->uio_offset >= LONG_MAX) {
> + return EFBIG;
> + }
> + if (uio->uio_resid == 0) {
> + return 0;
> + }
> +
> + if (ioflag & IO_APPEND)
> + uio->uio_offset = np->rn_size;
> +
> + if (size_t(uio->uio_offset + uio->uio_resid) > (size_t) vp->v_size) {
> + /* Expand the file size before writing to it */
> + off_t end_pos = uio->uio_offset + uio->uio_resid;
> + if (end_pos > (off_t) np->rn_bufsize) {
> + // XXX: this could use a page level allocator
> + size_t new_size = round_page(end_pos);
> + void *new_buf = malloc(new_size);
> + if (!new_buf)
> + return EIO;
> + if (np->rn_size != 0) {
> + memcpy(new_buf, np->rn_buf, vp->v_size);
> + if(np->rn_owns_buf)
> + free(np->rn_buf);
> + }
> + np->rn_buf = (char *) new_buf;
> + np->rn_bufsize = new_size;
> + }
> + np->rn_size = end_pos;
> + vp->v_size = end_pos;
> + np->rn_owns_buf = true;
> + }
> +
> + set_times_to_now(&(np->rn_mtime), &(np->rn_ctime));
> + return uiomove(np->rn_buf + uio->uio_offset, uio->uio_resid, uio);
> +}
> +
> +static int
> +ramfs_rename(struct vnode *dvp1, struct vnode *vp1, char *name1,
> + struct vnode *dvp2, struct vnode *vp2, char *name2)
> +{
> + struct ramfs_node *np, *old_np;
> + int error;
> +
> + if (vp2) {
> + /* Remove destination file, first */
> + error = ramfs_remove_node((ramfs_node *) dvp2->v_data, (ramfs_node
> *) vp2->v_data);
> + if (error)
> + return error;
> + }
> + /* Same directory ? */
> + if (dvp1 == dvp2) {
> + /* Change the name of existing file */
> + error = ramfs_rename_node((ramfs_node *) vp1->v_data, name2);
> + if (error)
> + return error;
> + } else {
> + /* Create new file or directory */
> + old_np = (ramfs_node *) vp1->v_data;
> + np = ramfs_add_node((ramfs_node *) dvp2->v_data, name2,
> old_np->rn_type);
> + if (np == NULL)
> + return ENOMEM;
> +
> + if (old_np->rn_buf) {
> + /* Copy file data */
> + np->rn_buf = old_np->rn_buf;
> + np->rn_size = old_np->rn_size;
> + np->rn_bufsize = old_np->rn_bufsize;
> + old_np->rn_buf = NULL;
> + }
> + /* Remove source file */
> + ramfs_remove_node((ramfs_node *) dvp1->v_data, (ramfs_node *)
> vp1->v_data);
> + }
> + return 0;
> +}
> +
> +/*
> + * @vp: vnode of the directory.
> + */
> +static int
> +ramfs_readdir(struct vnode *vp, struct file *fp, struct dirent *dir)
> +{
> + struct ramfs_node *np, *dnp;
> + int i;
> +
> + mutex_lock(&ramfs_lock);
> +
> + set_times_to_now(&(((ramfs_node *) vp->v_data)->rn_atime));
> +
> + if (fp->f_offset == 0) {
> + dir->d_type = DT_DIR;
> + strlcpy((char *) &dir->d_name, ".", sizeof(dir->d_name));
> + } else if (fp->f_offset == 1) {
> + dir->d_type = DT_DIR;
> + strlcpy((char *) &dir->d_name, "..", sizeof(dir->d_name));
> + } else {
> + dnp = (ramfs_node *) vp->v_data;
> + np = dnp->rn_child;
> + if (np == NULL) {
> + mutex_unlock(&ramfs_lock);
> + return ENOENT;
> + }
> +
> + for (i = 0; i != (fp->f_offset - 2); i++) {
> + np = np->rn_next;
> + if (np == NULL) {
> + mutex_unlock(&ramfs_lock);
> + return ENOENT;
> + }
> + }
> + if (np->rn_type == VDIR)
> + dir->d_type = DT_DIR;
> + else if (np->rn_type == VLNK)
> + dir->d_type = DT_LNK;
> + else
> + dir->d_type = DT_REG;
> + strlcpy((char *) &dir->d_name, np->rn_name,
> + sizeof(dir->d_name));
> + }
> + dir->d_fileno = fp->f_offset;
> +// dir->d_namelen = strlen(dir->d_name);
> +
> + fp->f_offset++;
> +
> + mutex_unlock(&ramfs_lock);
> + return 0;
> +}
> +
> +int
> +ramfs_init(void)
> +{
> + return 0;
> +}
> +
> +static int
> +ramfs_getattr(struct vnode *vnode, struct vattr *attr)
> +{
> + attr->va_nodeid = vnode->v_ino;
> + attr->va_size = vnode->v_size;
> +
> + struct ramfs_node *np = (ramfs_node *) vnode->v_data;
> + attr->va_type = (vtype) np->rn_type;
> +
> + memcpy(&(attr->va_atime), &(np->rn_atime), sizeof(struct timespec));
> + memcpy(&(attr->va_ctime), &(np->rn_ctime), sizeof(struct timespec));
> + memcpy(&(attr->va_mtime), &(np->rn_mtime), sizeof(struct timespec));
> +
> + attr->va_mode = np->rn_mode;
> +
> + return 0;
> +}
> +
> +static int
> +ramfs_setattr(struct vnode *vnode, struct vattr *attr) {
> + struct ramfs_node *np = (ramfs_node *) vnode->v_data;
> +
> + if (attr->va_mask & AT_ATIME) {
> + memcpy(&(np->rn_atime), &(attr->va_atime), sizeof(struct timespec));
> + }
> +
> + if (attr->va_mask & AT_CTIME) {
> + memcpy(&(np->rn_ctime), &(attr->va_ctime), sizeof(struct timespec));
> + }
> +
> + if (attr->va_mask & AT_MTIME) {
> + memcpy(&(np->rn_mtime), &(attr->va_mtime), sizeof(struct timespec));
> + }
> +
> + if (attr->va_mask & AT_MODE) {
> + np->rn_mode = attr->va_mode;
> + }
> +
> + return 0;
> +}
> +
> +#define ramfs_open ((vnop_open_t)vop_nullop)
> +#define ramfs_close ((vnop_close_t)vop_nullop)
> +#define ramfs_seek ((vnop_seek_t)vop_nullop)
> +#define ramfs_ioctl ((vnop_ioctl_t)vop_einval)
> +#define ramfs_fsync ((vnop_fsync_t)vop_nullop)
> +#define ramfs_inactive ((vnop_inactive_t)vop_nullop)
> +#define ramfs_link ((vnop_link_t)vop_eperm)
> +#define ramfs_fallocate ((vnop_fallocate_t)vop_nullop)
> +
> +/*
> + * vnode operations
> + */
> +struct vnops ramfs_vnops = {
> + ramfs_open, /* open */
> + ramfs_close, /* close */
> + ramfs_read, /* read */
> + ramfs_write, /* write */
> + ramfs_seek, /* seek */
> + ramfs_ioctl, /* ioctl */
> + ramfs_fsync, /* fsync */
> + ramfs_readdir, /* readdir */
> + ramfs_lookup, /* lookup */
> + ramfs_create, /* create */
> + ramfs_remove, /* remove */
> + ramfs_rename, /* remame */
> + ramfs_mkdir, /* mkdir */
> + ramfs_rmdir, /* rmdir */
> + ramfs_getattr, /* getattr */
> + ramfs_setattr, /* setattr */
> + ramfs_inactive, /* inactive */
> + ramfs_truncate, /* truncate */
> + ramfs_link, /* link */
> + (vnop_cache_t) nullptr, /* arc */
> + ramfs_fallocate, /* fallocate */
> + ramfs_readlink, /* read link */
> + ramfs_symlink, /* symbolic link */
> +};
> +
> --
> 2.19.2
>
>
> _______________________________________________
> Minios-devel mailing list
> Minios-devel@xxxxxxxxxxxxxxxxxxxx
> https://lists.xenproject.org/mailman/listinfo/minios-devel
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |