[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.