[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Minios-devel] [UNIKRAFT PATCH v3] lib/vfscore: Add anonymous pipe
- To: Costin Lupu <costin.lupu@xxxxxxxxx>, "minios-devel@xxxxxxxxxxxxx" <minios-devel@xxxxxxxxxxxxx>
- From: Vlad-Andrei BĂDOIU (78692) <vlad_andrei.badoiu@xxxxxxxxxxxxxxx>
- Date: Fri, 20 Sep 2019 11:56:28 +0000
- Accept-language: en-US
- Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=stud.acs.upb.ro; dmarc=pass action=none header.from=stud.acs.upb.ro; dkim=pass header.d=stud.acs.upb.ro; arc=none
- Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=x8Mjrr7dTFUTJkshn8sO4dd/Q+0yY07ijrQBIGP9Kkc=; b=Yf9FVjJkw1JTfSpFaeE7FqXWGadej2KDLPBcjax4tnAqpAzTQRLqb23kXuAWnbM1sGjWli66mGcocViE2WAb9qzjdwz8eRasylvqH+R9E0TsZbmU9Onl7Iqm5xiL2N5cESf5pSao3exHQVPJvdxVmKUP22+j6n6ManSkCy+cMeXcw9NH8SE7HiBSJFZ7HhRsb3y/Xv8iMgKNNbT6noRSjSQ8X5svvr3KjdW2BmMIZGlzpPFHb62H0jYBi7WJtPl0xJRXi1QcfQdIWp9DpYj82WEyO4d5vrX//dcYXBj1ZGV5cax4/AFqheQ7/2dy2eLHkUHHKM9VP3QhMkjtqfXUXw==
- Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ILSJyH6ZJ1mNBNASziGOmf8DL4PFpxb+0vbt7vZ5NnIjKPoaZjXplRWJwgQb+uYiy1iYzTZjadGdfsOJkVP1Sg527FnB2cTSFNAplnzdJP/80CoHElqcX/0Yiwk5HtmYcl/veIwZeTdNhvhpZGlPo0Lp4yqNUdVYrcCI2J2bRVNVDoeGp0iIRvDEmfQGemmlvpdJ1GrbwLGlfo0E/UgroLNEpTWkXEFZwK7xRlC2IZy5WLgSSpGc46A39UvgcbyFklxDb0jjGPg24te58hhGLl1I2WnWe/jqU49OlMLdUajaB9SnLYreDlwkSBuFo2QjWShXCvH+7pvwyujV50qWvw==
- Authentication-results: spf=none (sender IP is ) smtp.mailfrom=vlad_andrei.badoiu@xxxxxxxxxxxxxxx;
- Cc: Bogdan Lascu <lascu.bogdan96@xxxxxxxxx>
- Delivery-date: Fri, 20 Sep 2019 11:56:40 +0000
- List-id: Mini-os development list <minios-devel.lists.xenproject.org>
- Thread-index: AQHVbtuf+quN3AWHRkOCLOZ+JreH+6c0dyUA
- Thread-topic: [UNIKRAFT PATCH v3] lib/vfscore: Add anonymous pipe
Hey Costin,
Thanks for the patch. I have left two comments inline that may be useful for future revision of the pipe code.
Reviewed-by: Vlad-Andrei Badoiu <vlad_andrei.badoiu@xxxxxxxxxxxxxxx>
Vlad
PS: Before upstreaming this patch, we need another patch to remove the pipe stub from newlib.
On 19.09.2019 14:15, 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/Config.uk | 12 +-
lib/vfscore/Makefile.uk | 2 +
lib/vfscore/exportsyms.uk | 1 +
lib/vfscore/pipe.c | 573 ++++++++++++++++++++++++++++++++++++++
4 files changed, 587 insertions(+), 1 deletion(-)
create mode 100644 lib/vfscore/pipe.c
diff --git a/lib/vfscore/Config.uk b/lib/vfscore/Config.uk
index 6cf6c63a..5deb7d04 100644
--- a/lib/vfscore/Config.uk
+++ b/lib/vfscore/Config.uk
@@ -1,6 +1,16 @@
-config LIBVFSCORE
+menuconfig LIBVFSCORE
bool "vfscore: VFS Core Interface"
default n
select LIBNOLIBC if !HAVE_LIBC
select LIBUKDEBUG
select LIBUKLOCK
+
+if LIBVFSCORE
+
+config LIBVFSCORE_PIPE_SIZE_ORDER
+ int "Pipe size order"
+ default 16
+ help
+ The size of the internal buffer for anonymous pipes is 2^order.
+
+endif
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 46156098..70392721 100644
--- a/lib/vfscore/exportsyms.uk
+++ b/lib/vfscore/exportsyms.uk
@@ -109,3 +109,4 @@ vn_settimes
vn_stat
vn_unlock
vfs_busy
+pipe
diff --git a/lib/vfscore/pipe.c b/lib/vfscore/pipe.c
new file mode 100644
index 00000000..4c561304
--- /dev/null
+++ b/lib/vfscore/pipe.c
@@ -0,0 +1,573 @@
+/* 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 <uk/config.h>
+#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 << CONFIG_LIBVFSCORE_PIPE_SIZE_ORDER)
+
+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) ((n) & ((buf)->capacity - 1))
+#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 = malloc(sizeof(*pipe_buf));
+ if (!pipe_buf)
+ return NULL;
+
+ pipe_buf->data = ""
+ if (!pipe_buf->data) {
+ free(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)
+{
+ free(pipe_buf->data);
+ free(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 = malloc(sizeof(*pipe_file));
+ if (!pipe_file)
+ return NULL;
+
+ pipe_file->buf = pipe_buf_alloc(capacity);
+ if (!pipe_file->buf) {
+ free(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);
+ free(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 */
In this case even though we support non-blocking we always have the value set to false.
+ 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--;
Shouldn't we have a lock on pipe_file in order to avoid race conditions?
+
+ 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 = calloc(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:
+ free(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
|