[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

 


Rackspace

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