[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Minios-devel] [UNIKRAFT PATCH v2] lib/vfscore: Add anonymous pipe



On 9/19/19 12:51 PM, Vlad-Andrei BĂDOIU (78692) wrote:
> Hey Costin,
> 
> I have tested the implementation with a program that writes 3 different
> value to a pipe and then
> 
> reads 3 times from the pipe. For each read we only get the last value.
> Also, the patch does not apply
> 
> over staging without conflicts.
> 

Yeah, I was wrongly calculating the index, it should be:

-#define PIPE_BUF_IDX(buf, n)    ((buf)->capacity & (n))
+#define PIPE_BUF_IDX(buf, n)    (((buf)->capacity - 1) & (n))
> 
> Please see the rest of the comments inline.
> 
> Thanks,
> 
> Vlad
> 
> On 13.09.2019 11:55, Costin Lupu wrote:
>> From: Bogdan Lascu <lascu.bogdan96@xxxxxxxxx>
>>
>> This patch adds support for anonymous pipes. The underlying buffer is a ring
>> buffer whose size must be a power of 2. The creating of its file descriptors
>> follows closely the implementation for sockets in lwip glue code.
>>
>> Signed-off-by: Bogdan Lascu <lascu.bogdan96@xxxxxxxxx>
>> Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx>
>> ---
>>  lib/vfscore/Makefile.uk   |   2 +
>>  lib/vfscore/exportsyms.uk |   1 +
>>  lib/vfscore/pipe.c        | 572 ++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 575 insertions(+)
>>  create mode 100644 lib/vfscore/pipe.c
>>
>> diff --git a/lib/vfscore/Makefile.uk b/lib/vfscore/Makefile.uk
>> index 79878f26..e36c9217 100644
>> --- a/lib/vfscore/Makefile.uk
>> +++ b/lib/vfscore/Makefile.uk
>> @@ -14,6 +14,8 @@ LIBVFSCORE_SRCS-y += $(LIBVFSCORE_BASE)/task.c
>>  LIBVFSCORE_SRCS-y += $(LIBVFSCORE_BASE)/lookup.c
>>  LIBVFSCORE_SRCS-y += $(LIBVFSCORE_BASE)/fops.c
>>  LIBVFSCORE_SRCS-y += $(LIBVFSCORE_BASE)/subr_uio.c
>> +LIBVFSCORE_SRCS-y += $(LIBVFSCORE_BASE)/pipe.c
>> +LIBVFSCORE_PIPE_FLAGS-y += -Wno-cast-function-type
>>  LIBVFSCORE_SRCS-y += $(LIBVFSCORE_BASE)/extra.ld
>>  
>>  
>> diff --git a/lib/vfscore/exportsyms.uk b/lib/vfscore/exportsyms.uk
>> index e3d6723a..7f02c667 100644
>> --- a/lib/vfscore/exportsyms.uk
>> +++ b/lib/vfscore/exportsyms.uk
>> @@ -79,3 +79,4 @@ dentry_alloc
>>  drele
>>  vrele
>>  fcntl
>> +pipe
>> diff --git a/lib/vfscore/pipe.c b/lib/vfscore/pipe.c
>> new file mode 100644
>> index 00000000..252e65f7
>> --- /dev/null
>> +++ b/lib/vfscore/pipe.c
>> @@ -0,0 +1,572 @@
>> +/* SPDX-License-Identifier: BSD-3-Clause */
>> +/*
>> + * Authors: Bogdan-George Lascu <lascu.bogdan96@xxxxxxxxx>
>> + *          Costin Lupu <costin.lupu@xxxxxxxxx>
>> + *
>> + * Copyright (c) 2019, University Politehnica of Bucharest. 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 copyright holder nor the names of its
>> + *    contributors may be used to endorse or promote products derived from
>> + *    this software without specific prior written permission.
>> + *
>> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
>> + *
>> + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
>> + */
>> +
>> +#include <stdio.h>
>> +#include <string.h>
>> +#include <vfscore/file.h>
>> +#include <vfscore/fs.h>
>> +#include <vfscore/mount.h>
>> +#include <vfscore/vnode.h>
>> +#include <uk/wait.h>
>> +#include <sys/ioctl.h>
>> +
>> +/* We use the default size in Linux kernel */
>> +#define PIPE_MAX_SIZE       (1 << 16)
> 
> I think that we should provide a config option for this value because
> allocating 64KB for each pipe
> 
> call is quite a lot of memory for a unikernel.
> 

Will do.

>> +
>> +struct pipe_buf {
>> +    /* The buffer */
>> +    char *data;
>> +    /* The buffer capacity, always a power of 2 */
>> +    unsigned long capacity;
>> +    /* Producer index */
>> +    unsigned long prod;
>> +    /* Consumer index */
>> +    unsigned long cons;
>> +
>> +    /* Read lock */
>> +    struct uk_mutex rdlock;
>> +    /* Write lock */
>> +    struct uk_mutex wrlock;
>> +
>> +    /* Readers queue */
>> +    struct uk_waitq rdwq;
>> +    /* Writers queue */
>> +    struct uk_waitq wrwq;
>> +};
>> +
>> +#define PIPE_BUF_IDX(buf, n)    ((buf)->capacity & (n))
>> +#define PIPE_BUF_PROD_IDX(buf)  PIPE_BUF_IDX((buf), (buf)->prod)
>> +#define PIPE_BUF_CONS_IDX(buf)  PIPE_BUF_IDX((buf), (buf)->cons)
>> +
>> +struct pipe_file {
>> +    /* Pipe buffer */
>> +    struct pipe_buf *buf;
>> +    /* Write reference count */
>> +    int w_refcount;
>> +    /* Read reference count */
>> +    int r_refcount;
>> +    /* Flags */
>> +    int flags;
>> +};
>> +
>> +
>> +static struct pipe_buf *pipe_buf_alloc(int capacity)
>> +{
>> +    struct pipe_buf *pipe_buf;
>> +
>> +    UK_ASSERT(POWER_OF_2(capacity));
>> +
>> +    pipe_buf = uk_malloc(uk_alloc_get_default(), sizeof(*pipe_buf));
>> +    if (!pipe_buf)
>> +            return NULL;
>> +
>> +    pipe_buf->data = uk_malloc(uk_alloc_get_default(), capacity);
>> +    if (!pipe_buf->data) {
>> +            uk_free(uk_alloc_get_default(), pipe_buf);
>> +            return NULL;
>> +    }
>> +
>> +    pipe_buf->capacity = capacity;
>> +    pipe_buf->cons = 0;
>> +    pipe_buf->prod = 0;
>> +    uk_mutex_init(&pipe_buf->rdlock);
>> +    uk_mutex_init(&pipe_buf->wrlock);
>> +    uk_waitq_init(&pipe_buf->rdwq);
>> +    uk_waitq_init(&pipe_buf->wrwq);
>> +
>> +    return pipe_buf;
>> +}
>> +
>> +void pipe_buf_free(struct pipe_buf *pipe_buf)
>> +{
>> +    uk_free(uk_alloc_get_default(), pipe_buf->data);
> 
> vfscore does not use uk_free directly but through the free call. Perhaps
> we should follow the same approach.
> 
> The same comment applies for uk_malloc.
> 

Ack.

>> +    uk_free(uk_alloc_get_default(), pipe_buf);
>> +}
>> +
>> +static unsigned long pipe_buf_get_available(const struct pipe_buf *pipe_buf)
>> +{
>> +    return pipe_buf->prod - pipe_buf->cons;
>> +}
>> +
>> +static unsigned long pipe_buf_get_free_space(struct pipe_buf *pipe_buf)
>> +{
>> +    return pipe_buf->capacity - pipe_buf_get_available(pipe_buf);
>> +}
>> +
>> +static int pipe_buf_can_write(struct pipe_buf *pipe_buf)
>> +{
>> +    return pipe_buf_get_free_space(pipe_buf) > 0;
>> +}
>> +
>> +static int pipe_buf_can_read(struct pipe_buf *pipe_buf)
>> +{
>> +    return pipe_buf_get_available(pipe_buf) > 0;
>> +}
>> +
>> +static unsigned long pipe_buf_write(struct pipe_buf *pipe_buf,
>> +            struct iovec *iovec, size_t iovec_off)
>> +{
>> +    unsigned long prod_idx, to_write;
>> +    void *iovec_data = iovec->iov_base + iovec_off;
>> +    size_t iov_len = iovec->iov_len - iovec_off;
>> +
>> +    prod_idx = PIPE_BUF_PROD_IDX(pipe_buf);
>> +    to_write = MIN(pipe_buf_get_free_space(pipe_buf), iov_len);
>> +    if (to_write == 0)
>> +            goto out;
>> +
>> +    /* Copy in one piece */
>> +    if (prod_idx + to_write <= pipe_buf->capacity)
>> +            memcpy(pipe_buf->data + prod_idx, iovec_data, to_write);
>> +
>> +    else {
>> +            int first_copy_bytes, second_copy_bytes;
>> +
>> +            /* Copy the first part */
>> +            first_copy_bytes = pipe_buf->capacity - prod_idx;
>> +            memcpy(pipe_buf->data + prod_idx,
>> +                            iovec_data,
>> +                            first_copy_bytes);
>> +
>> +            /* Copy the second part */
>> +            second_copy_bytes = prod_idx + to_write - pipe_buf->capacity;
>> +            memcpy(pipe_buf->data,
>> +                            iovec_data + first_copy_bytes,
>> +                            second_copy_bytes);
>> +    }
>> +
>> +    /* Update producer */
>> +    pipe_buf->prod += to_write;
>> +
>> +out:
>> +    return to_write;
>> +}
>> +
>> +static unsigned long pipe_buf_read(struct pipe_buf *pipe_buf,
>> +            struct iovec *iovec, size_t iovec_off)
>> +{
>> +    unsigned long cons_idx, to_read;
>> +    void *iovec_data = iovec->iov_base + iovec_off;
>> +    size_t iov_len = iovec->iov_len - iovec_off;
>> +
>> +    cons_idx = PIPE_BUF_CONS_IDX(pipe_buf);
>> +    to_read = MIN(pipe_buf_get_available(pipe_buf), iov_len);
>> +    if (to_read == 0)
>> +            goto out;
>> +
>> +    /* Copy in one piece */
>> +    if (cons_idx + to_read <= pipe_buf->capacity)
>> +            memcpy(iovec_data, pipe_buf->data + cons_idx, to_read);
>> +
>> +    else {
>> +            int first_copy_bytes;
>> +            int second_copy_bytes;
>> +
>> +            /* Copy the first part */
>> +            first_copy_bytes = pipe_buf->capacity - pipe_buf->cons;
>> +            memcpy(iovec_data,
>> +                            pipe_buf->data + cons_idx,
>> +                            first_copy_bytes);
>> +
>> +            /* Copy the second part */
>> +            second_copy_bytes = cons_idx + to_read - pipe_buf->capacity;
>> +            memcpy(iovec_data + first_copy_bytes,
>> +                            pipe_buf->data,
>> +                            second_copy_bytes);
>> +    }
>> +
>> +    /* Update consumer */
>> +    pipe_buf->cons += to_read;
>> +
>> +out:
>> +    return to_read;
>> +}
>> +
>> +struct pipe_file *pipe_file_alloc(int capacity, int flags)
>> +{
>> +    struct pipe_file *pipe_file;
>> +
>> +    pipe_file = uk_malloc(uk_alloc_get_default(), sizeof(*pipe_file));
>> +    if (!pipe_file)
>> +            return NULL;
>> +
>> +    pipe_file->buf = pipe_buf_alloc(capacity);
>> +    if (!pipe_file->buf) {
>> +            uk_free(uk_alloc_get_default(), pipe_file);
>> +            return NULL;
>> +    }
>> +
>> +    pipe_file->w_refcount = 1;
>> +    pipe_file->r_refcount = 1;
>> +    pipe_file->flags = flags;
>> +
>> +    return pipe_file;
>> +}
>> +
>> +void pipe_file_free(struct pipe_file *pipe_file)
>> +{
>> +    pipe_buf_free(pipe_file->buf);
>> +    uk_free(uk_alloc_get_default(), pipe_file);
>> +}
>> +
>> +static int pipe_write(struct vnode *vnode,
>> +            struct uio *buf, int ioflag __unused)
>> +{
>> +    struct pipe_file *pipe_file = vnode->v_data;
>> +    struct pipe_buf *pipe_buf = pipe_file->buf;
>> +    bool nonblocking = false; /* TODO handle nonblocking */
>> +    bool data_available = true;
>> +    int uio_idx = 0;
>> +
>> +    if (!pipe_file->r_refcount) {
>> +            /* TODO before returning the error, send a SIGPIPE signal */
>> +            return -EPIPE;
>> +    }
>> +
>> +    uk_mutex_lock(&pipe_buf->wrlock);
>> +    while (data_available && uio_idx < buf->uio_iovcnt) {
>> +            struct iovec *iovec = &buf->uio_iov[uio_idx];
>> +            unsigned long off = 0;
>> +
>> +            while (off < iovec->iov_len) {
>> +                    unsigned long written_bytes;
>> +
>> +                    written_bytes = pipe_buf_write(pipe_buf, iovec, off);
>> +                    if (written_bytes == 0) {
>> +                            /* No data */
>> +                            if (nonblocking) {
>> +                                    data_available = false;
>> +                                    break;
>> +
>> +                            } else {
>> +                                    /* Wait until data available */
>> +                                    while (!pipe_buf_can_write(pipe_buf)) {
>> +                                            
>> uk_mutex_unlock(&pipe_buf->wrlock);
>> +                                            
>> uk_waitq_wait_event(&pipe_buf->wrwq,
>> +                                                    
>> pipe_buf_can_write(pipe_buf));
>> +                                            
>> uk_mutex_lock(&pipe_buf->wrlock);
>> +                                    }
>> +                            }
>> +
>> +                    } else {
>> +                            /* Update bytes written_bytes. */
>> +                            buf->uio_resid -= written_bytes;
>> +
>> +                            off += written_bytes;
>> +
>> +                            /* wake some readers */
>> +                            uk_waitq_wake_up(&pipe_buf->rdwq);
>> +                    }
>> +            }
>> +
>> +            uio_idx++;
>> +    }
>> +    uk_mutex_unlock(&pipe_buf->wrlock);
>> +
>> +    return 0;
>> +}
>> +
>> +static int pipe_read(struct vnode *vnode,
>> +            struct vfscore_file *vfscore_file,
>> +            struct uio *buf, int ioflag __unused)
>> +{
>> +    struct pipe_file *pipe_file = vnode->v_data;
>> +    struct pipe_buf *pipe_buf = pipe_file->buf;
>> +    bool nonblocking = (vfscore_file->f_flags & O_NONBLOCK);
>> +    bool data_available = true;
>> +    int uio_idx = 0;
>> +
>> +    uk_mutex_lock(&pipe_buf->rdlock);
>> +    if (nonblocking && !pipe_buf_can_read(pipe_buf)) {
>> +            uk_mutex_unlock(&pipe_buf->rdlock);
>> +            return EAGAIN;
>> +    }
>> +
>> +    while (data_available && uio_idx < buf->uio_iovcnt) {
>> +            struct iovec *iovec = &buf->uio_iov[uio_idx];
>> +            unsigned long off = 0;
>> +
>> +            while (off < iovec->iov_len) {
>> +                    unsigned long read_bytes;
>> +
>> +                    read_bytes = pipe_buf_read(pipe_buf, iovec, off);
>> +                    if (read_bytes == 0) {
>> +                            /* No data */
>> +                            if (nonblocking) {
>> +                                    data_available = false;
>> +                                    break;
>> +
>> +                            } else {
>> +                                    /* Wait until data available */
>> +                                    while (!pipe_buf_can_read(pipe_buf)) {
>> +                                            
>> uk_mutex_unlock(&pipe_buf->rdlock);
>> +                                            
>> uk_waitq_wait_event(&pipe_buf->rdwq,
>> +                                                    
>> pipe_buf_can_read(pipe_buf));
>> +                                            
>> uk_mutex_lock(&pipe_buf->rdlock);
>> +                                    }
>> +                            }
>> +
>> +                    } else {
>> +                            /* Update bytes read */
>> +                            buf->uio_resid -= read_bytes;
>> +
>> +                            off += read_bytes;
>> +
>> +                            /* wake some writers */
>> +                            uk_waitq_wake_up(&pipe_buf->wrwq);
>> +                    }
>> +            }
>> +
>> +            uio_idx++;
>> +    }
>> +    uk_mutex_unlock(&pipe_buf->rdlock);
>> +
>> +    return 0;
>> +}
>> +
>> +static int pipe_close(struct vnode *vnode,
>> +            struct vfscore_file *vfscore_file)
>> +{
>> +    struct pipe_file *pipe_file = vnode->v_data;
>> +
>> +    UK_ASSERT(vfscore_file->f_dentry->d_vnode == vnode);
>> +    UK_ASSERT(vnode->v_refcnt == 1);
>> +
>> +    if (vfscore_file->f_flags & UK_FREAD)
>> +            pipe_file->r_refcount--;
>> +
>> +    if (vfscore_file->f_flags & UK_FWRITE)
>> +            pipe_file->w_refcount--;
>> +
>> +    if (!pipe_file->r_refcount && !pipe_file->w_refcount)
>> +            pipe_file_free(pipe_file);
>> +
>> +    return 0;
>> +}
>> +
>> +static int pipe_seek(struct vnode *vnode __unused,
>> +                    struct vfscore_file *vfscore_file __unused,
>> +                    off_t off1 __unused, off_t off2 __unused)
>> +{
>> +    errno = ESPIPE;
>> +    return -1;
>> +}
>> +
>> +static int pipe_ioctl(struct vnode *vnode,
>> +            struct vfscore_file *vfscore_file __unused,
>> +            unsigned long com, void *data)
>> +{
>> +    struct pipe_file *pipe_file = vnode->v_data;
>> +    struct pipe_buf *pipe_buf = pipe_file->buf;
>> +
>> +    switch (com) {
>> +    case FIONREAD:
>> +            uk_mutex_lock(&pipe_buf->rdlock);
>> +            *((int *) data) = pipe_buf_get_available(pipe_buf);
>> +            uk_mutex_unlock(&pipe_buf->rdlock);
>> +            return 0;
>> +    default:
>> +            return -EINVAL;
>> +    }
>> +}
>> +
>> +#define pipe_open        ((vnop_open_t) vfscore_vop_einval)
>> +#define pipe_fsync       ((vnop_fsync_t) vfscore_vop_nullop)
>> +#define pipe_readdir     ((vnop_readdir_t) vfscore_vop_einval)
>> +#define pipe_lookup      ((vnop_lookup_t) vfscore_vop_einval)
>> +#define pipe_create      ((vnop_create_t) vfscore_vop_einval)
>> +#define pipe_remove      ((vnop_remove_t) vfscore_vop_einval)
>> +#define pipe_rename      ((vnop_rename_t) vfscore_vop_einval)
>> +#define pipe_mkdir       ((vnop_mkdir_t) vfscore_vop_einval)
>> +#define pipe_rmdir       ((vnop_rmdir_t) vfscore_vop_einval)
>> +#define pipe_getattr     ((vnop_getattr_t) vfscore_vop_einval)
>> +#define pipe_setattr     ((vnop_setattr_t) vfscore_vop_nullop)
>> +#define pipe_inactive    ((vnop_inactive_t) vfscore_vop_einval)
>> +#define pipe_truncate    ((vnop_truncate_t) vfscore_vop_nullop)
>> +#define pipe_link        ((vnop_link_t) vfscore_vop_eperm)
>> +#define pipe_cache       ((vnop_cache_t) NULL)
>> +#define pipe_readlink    ((vnop_readlink_t) vfscore_vop_einval)
>> +#define pipe_symlink     ((vnop_symlink_t) vfscore_vop_eperm)
>> +#define pipe_fallocate   ((vnop_fallocate_t) vfscore_vop_nullop)
>> +
>> +static struct vnops pipe_vnops = {
>> +    .vop_open      = pipe_open,
>> +    .vop_close     = pipe_close,
>> +    .vop_read      = pipe_read,
>> +    .vop_write     = pipe_write,
>> +    .vop_seek      = pipe_seek,
>> +    .vop_ioctl     = pipe_ioctl,
>> +    .vop_fsync     = pipe_fsync,
>> +    .vop_readdir   = pipe_readdir,
>> +    .vop_lookup    = pipe_lookup,
>> +    .vop_create    = pipe_create,
>> +    .vop_remove    = pipe_remove,
>> +    .vop_rename    = pipe_rename,
>> +    .vop_mkdir     = pipe_mkdir,
>> +    .vop_rmdir     = pipe_rmdir,
>> +    .vop_getattr   = pipe_getattr,
>> +    .vop_setattr   = pipe_setattr,
>> +    .vop_inactive  = pipe_inactive,
>> +    .vop_truncate  = pipe_truncate,
>> +    .vop_link      = pipe_link,
>> +    .vop_cache     = pipe_cache,
>> +    .vop_fallocate = pipe_fallocate,
>> +    .vop_readlink  = pipe_readlink,
>> +    .vop_symlink   = pipe_symlink
>> +};
>> +
>> +#define pipe_vget  ((vfsop_vget_t) vfscore_vop_nullop)
>> +
>> +static struct vfsops pipe_vfsops = {
>> +    .vfs_vget = pipe_vget,
>> +    .vfs_vnops = &pipe_vnops
>> +};
>> +
>> +static uint64_t p_inode;
>> +
>> +/*
>> + * Bogus mount point used by all sockets
>> + */
>> +static struct mount p_mount = {
>> +    .m_op = &pipe_vfsops
>> +};
>> +
>> +static int pipe_fd_alloc(struct pipe_file *pipe_file, int flags)
>> +{
>> +    int ret = 0;
>> +    int vfs_fd;
>> +    struct vfscore_file *vfs_file = NULL;
>> +    struct dentry *p_dentry;
>> +    struct vnode *p_vnode;
>> +
>> +    /* Reserve file descriptor number */
>> +    vfs_fd = vfscore_alloc_fd();
>> +    if (vfs_fd < 0) {
>> +            ret = -ENFILE;
>> +            goto ERR_EXIT;
>> +    }
>> +
>> +    /* Allocate file, dentry, and vnode */
>> +    vfs_file = uk_calloc(uk_alloc_get_default(), 1, sizeof(*vfs_file));
>> +    if (!vfs_file) {
>> +            ret = -ENOMEM;
>> +            goto ERR_MALLOC_VFS_FILE;
>> +    }
>> +
>> +    ret = vfscore_vget(&p_mount, p_inode++, &p_vnode);
>> +    UK_ASSERT(ret == 0); /* we should not find it in cache */
>> +
>> +    if (!p_vnode) {
>> +            ret = -ENOMEM;
>> +            goto ERR_ALLOC_VNODE;
>> +    }
>> +
>> +    uk_mutex_unlock(&p_vnode->v_lock);
>> +
>> +    p_dentry = dentry_alloc(NULL, p_vnode, "/");
>> +    if (!p_dentry) {
>> +            ret = -ENOMEM;
>> +            goto ERR_ALLOC_DENTRY;
>> +    }
>> +
>> +    /* Fill out necessary fields. */
>> +    vfs_file->fd = vfs_fd;
>> +    vfs_file->f_flags = flags;
>> +    vfs_file->f_count = 1;
>> +    vfs_file->f_data = pipe_file;
>> +    vfs_file->f_dentry = p_dentry;
>> +    vfs_file->f_vfs_flags = UK_VFSCORE_NOPOS;
>> +
>> +    p_vnode->v_data = pipe_file;
>> +    p_vnode->v_type = VFIFO;
>> +
>> +    /* Assign the file descriptors to the corresponding vfs_file. */
>> +    ret = vfscore_install_fd(vfs_fd, vfs_file);
>> +    if (ret)
>> +            goto ERR_VFS_INSTALL;
>> +
>> +    /* Only the dentry should hold a reference; release ours */
>> +    vrele(p_vnode);
>> +
>> +    return vfs_fd;
>> +
>> +ERR_VFS_INSTALL:
>> +    drele(p_dentry);
>> +ERR_ALLOC_DENTRY:
>> +    vrele(p_vnode);
>> +ERR_ALLOC_VNODE:
>> +    uk_free(uk_alloc_get_default(), vfs_file);
>> +ERR_MALLOC_VFS_FILE:
>> +    vfscore_put_fd(vfs_fd);
>> +ERR_EXIT:
>> +    UK_ASSERT(ret < 0);
>> +    return ret;
>> +}
>> +
>> +int pipe(int pipefd[2])
>> +{
>> +    int ret = 0;
>> +    int r_fd, w_fd;
>> +    struct pipe_file *pipe_file;
>> +
>> +    /* Allocate pipe internal structure. */
>> +    pipe_file = pipe_file_alloc(PIPE_MAX_SIZE, 0);
>> +    if (!pipe_file) {
>> +            ret = -ENOMEM;
>> +            goto ERR_EXIT;
>> +    }
>> +
>> +    r_fd = pipe_fd_alloc(pipe_file, UK_FREAD);
>> +    if (r_fd < 0)
>> +            goto ERR_VFS_INSTALL;
>> +
>> +    w_fd = pipe_fd_alloc(pipe_file, UK_FWRITE);
>> +    if (w_fd < 0)
>> +            goto ERR_W_FD;
>> +
>> +    /* Fill pipefd fields. */
>> +    pipefd[0] = r_fd;
>> +    pipefd[1] = w_fd;
>> +
>> +    return ret;
>> +
>> +ERR_W_FD:
>> +    vfscore_put_fd(r_fd);
>> +ERR_VFS_INSTALL:
>> +    pipe_file_free(pipe_file);
>> +ERR_EXIT:
>> +    UK_ASSERT(ret < 0);
>> +    return ret;
>> +}
> 
> _______________________________________________
> 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®.