Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 13 Jul 2013 12:56:05 GMT
From:      zcore@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r254753 - soc2013/zcore/head/usr.sbin/bhyve
Message-ID:  <201307131256.r6DCu53x024994@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: zcore
Date: Sat Jul 13 12:56:05 2013
New Revision: 254753
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=254753

Log:
  import block_if from Peter Grehan

Added:
  soc2013/zcore/head/usr.sbin/bhyve/block_if.c
  soc2013/zcore/head/usr.sbin/bhyve/block_if.h
Modified:
  soc2013/zcore/head/usr.sbin/bhyve/Makefile

Modified: soc2013/zcore/head/usr.sbin/bhyve/Makefile
==============================================================================
--- soc2013/zcore/head/usr.sbin/bhyve/Makefile	Sat Jul 13 12:55:37 2013	(r254752)
+++ soc2013/zcore/head/usr.sbin/bhyve/Makefile	Sat Jul 13 12:56:05 2013	(r254753)
@@ -6,8 +6,8 @@
 
 DEBUG_FLAGS= -g -O0 
 
-SRCS=	acpi.c atpic.c bhyverun.c consport.c dbgport.c elcr.c inout.c 
-SRCS+=  ioapic.c mem.c mevent.c mptbl.c
+SRCS=	acpi.c atpic.c bhyverun.c block_if.c consport.c dbgport.c elcr.c
+SRCS+=  inout.c ioapic.c mem.c mevent.c mptbl.c
 SRCS+=	pci_emul.c pci_hostbridge.c pci_passthru.c pci_virtio_block.c
 SRCS+=	pci_virtio_net.c pci_uart.c pit_8254.c pmtmr.c post.c rtc.c
 SRCS+=	xmsr.c spinup_ap.c pci_ahci.c

Added: soc2013/zcore/head/usr.sbin/bhyve/block_if.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2013/zcore/head/usr.sbin/bhyve/block_if.c	Sat Jul 13 12:56:05 2013	(r254753)
@@ -0,0 +1,371 @@
+/*-
+ * Copyright (c) 2013  Peter Grehan <grehan@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``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 NETAPP, INC 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/disk.h>
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <pthread_np.h>
+#include <unistd.h>
+
+#include "bhyverun.h"
+#include "block_if.h"
+
+#define BLOCKIF_SIG	0xb109b109
+
+#define BLOCKIF_MAXREQ	8
+
+enum blockop {
+	BOP_READ,
+	BOP_WRITE,
+	BOP_CANCEL
+};
+
+struct blockif_elem {
+	struct blockif_req  *be_req;
+	enum blockop	     be_op;
+};
+
+struct blockif_ctxt {
+	int			bc_magic;
+	int			bc_fd;
+	int			bc_rdonly;
+	off_t			bc_size;
+	int			bc_sectsz;
+	pthread_t		bc_btid;
+        pthread_mutex_t		bc_mtx;
+        pthread_cond_t		bc_cond;
+	int			bc_closing;
+
+	/* Circular request queue */
+	int			bc_req_next;
+	u_int			bc_req_count;
+	struct blockif_elem	bc_reqs[BLOCKIF_MAXREQ];
+};
+
+static int
+blockif_enqueue(struct blockif_ctxt *bc, struct blockif_req *breq,
+		enum blockop op)
+{
+
+	assert(bc->bc_req_count < BLOCKIF_MAXREQ);
+
+	bc->bc_reqs[bc->bc_req_next].be_req = breq;
+	bc->bc_reqs[bc->bc_req_next].be_op = op;
+	bc->bc_req_next = (bc->bc_req_next + 1) % BLOCKIF_MAXREQ;
+	bc->bc_req_count++;
+
+	return (0);
+}
+
+static int
+blockif_dequeue(struct blockif_ctxt *bc, struct blockif_elem *el)
+{
+	int tail;
+
+	if (bc->bc_req_count == 0)
+		return (ENOENT);
+
+	tail = (bc->bc_req_next - bc->bc_req_count + BLOCKIF_MAXREQ) %
+	    BLOCKIF_MAXREQ;
+	*el = bc->bc_reqs[tail];
+	bc->bc_req_count--;
+
+	return (0);
+}
+
+static void
+blockif_proc(struct blockif_ctxt *bc, struct blockif_elem *be)
+{
+	struct blockif_req *br;
+	int err;
+
+	br = be->be_req;
+	err = 0;
+
+	switch (be->be_op) {
+	case BOP_READ:
+		if (preadv(bc->bc_fd, br->br_iov, br->br_iovcnt,
+			   br->br_offset) < 0)
+			err = errno;
+		break;
+	case BOP_WRITE:
+		if (bc->bc_rdonly)
+			err = EROFS;
+		else if (pwritev(bc->bc_fd, br->br_iov, br->br_iovcnt,
+			     br->br_offset) < 0)
+			err = errno;
+		break;
+	case BOP_CANCEL:
+		err = EINTR;
+		break;
+	default:
+		err = EINVAL;
+		break;
+	}
+
+	(*br->br_callback)(br, err);
+}
+
+static void *
+blockif_thr(void *arg)
+{
+	struct blockif_ctxt *bc;
+	struct blockif_elem req;
+
+	bc = arg;
+
+	for (;;) {
+		pthread_mutex_lock(&bc->bc_mtx);
+		while (!blockif_dequeue(bc, &req)) {
+			pthread_mutex_unlock(&bc->bc_mtx);
+			blockif_proc(bc, &req);
+			pthread_mutex_lock(&bc->bc_mtx);
+		}
+		pthread_cond_wait(&bc->bc_cond, &bc->bc_mtx);
+
+		/*
+		 * Check ctxt status here to see if exit requested
+		 */
+		if (bc->bc_closing) {
+			pthread_mutex_unlock(&bc->bc_mtx);
+			pthread_exit(NULL);
+		}
+	}
+
+	/* Not reached */
+	return (NULL);
+}
+
+struct blockif_ctxt *
+blockif_open(const char *optstr, const char *ident)
+{
+	char tname[MAXCOMLEN + 1];
+	struct blockif_ctxt *bc;
+	struct stat sbuf;
+	off_t size;
+	int extra, fd, ro, sectsz;
+
+	ro = 0;
+
+	/*
+	 * XXX test option. cache/nocache/default behaviour should be
+	 * implemented in the optstr
+	 */
+	extra = 0;
+	if (getenv("BHYVE_BLOCKIF_NOCACHE"))
+		extra = O_DIRECT;
+	else if (getenv("BHYVE_BLOCKIF_SYNC"))
+		extra = O_SYNC;
+
+	fd = open(optstr, O_RDWR | extra);
+	if (fd < 0) {
+		/*
+		 * Try again as read-only
+		 */
+		fd = open(optstr, O_RDONLY | extra);
+		if (fd < 0) {
+			perror("Could not open backing file");
+			return (NULL);
+		}
+		ro = 1;
+	}
+
+        if (fstat(fd, &sbuf) < 0) {
+                perror("Could not stat backing file");
+                close(fd);
+                return (NULL);
+        }
+
+        /*
+	 * Deal with raw devices
+	 */
+        size = sbuf.st_size;
+	sectsz = DEV_BSIZE;
+	if (S_ISCHR(sbuf.st_mode)) {
+		if (ioctl(fd, DIOCGMEDIASIZE, &size) < 0 ||
+		    ioctl(fd, DIOCGSECTORSIZE, &sectsz)) {
+			perror("Could not fetch dev blk/sector size");
+			close(fd);
+			return (NULL);
+		}
+		assert(size != 0);
+		assert(sectsz != 0);
+	}
+
+	bc = malloc(sizeof(struct blockif_ctxt));
+	if (bc == NULL) {
+		close(fd);
+		return (NULL);
+	}
+
+	memset(bc, 0, sizeof(*bc));
+	bc->bc_magic = BLOCKIF_SIG;
+	bc->bc_fd = fd;
+	bc->bc_size = size;
+	bc->bc_sectsz = sectsz;
+	pthread_mutex_init(&bc->bc_mtx, NULL);
+	pthread_cond_init(&bc->bc_cond, NULL);
+	bc->bc_req_next = 0;
+	bc->bc_req_count = 0;
+
+	pthread_create(&bc->bc_btid, NULL, blockif_thr, bc);
+
+        snprintf(tname, sizeof(tname), "%s blk-%s", vmname, ident);
+	pthread_set_name_np(bc->bc_btid, tname);
+
+	return (bc);
+}
+
+static int
+blockif_request(struct blockif_ctxt *bc, struct blockif_req *breq,
+		enum blockop op)
+{
+	int err;
+
+	err = 0;
+
+	pthread_mutex_lock(&bc->bc_mtx);
+	if (bc->bc_req_count < BLOCKIF_MAXREQ) {
+		/*
+		 * Enqueue and inform the block i/o thread
+		 * that there is work available
+		 */
+		blockif_enqueue(bc, breq, op);
+		pthread_cond_signal(&bc->bc_cond);
+	} else {
+		/*
+		 * Callers are not allowed to enqueue more than
+		 * the specified blockif queue limit. Return an
+		 * error to indicate that the queue length has been
+		 * exceeded.
+		 */
+		err = E2BIG;
+	}
+	pthread_mutex_unlock(&bc->bc_mtx);
+
+	return (err);
+}
+
+int
+blockif_read(struct blockif_ctxt *bc, struct blockif_req *breq)
+{
+
+	assert(bc->bc_magic == BLOCKIF_SIG);
+	return (blockif_request(bc, breq, BOP_READ));
+}
+
+int
+blockif_write(struct blockif_ctxt *bc, struct blockif_req *breq)
+{
+
+	assert(bc->bc_magic == BLOCKIF_SIG);
+	return (blockif_request(bc, breq, BOP_WRITE));
+}
+
+int
+blockif_cancel(struct blockif_ctxt *bc, struct blockif_req *breq)
+{
+
+	assert(bc->bc_magic == BLOCKIF_SIG);
+	return (blockif_request(bc, breq, BOP_CANCEL));
+}
+
+int
+blockif_close(struct blockif_ctxt *bc)
+{
+	void *jval;
+	int err;
+
+	err = 0;
+
+	assert(bc->bc_magic == BLOCKIF_SIG);
+
+	/*
+	 * Stop the block i/o thread
+	 */
+	bc->bc_closing = 1;
+	pthread_join(bc->bc_btid, &jval);
+
+	/* XXX Cancel queued i/o's ??? */
+
+	/*
+	 * Release resources
+	 */
+	bc->bc_magic = 0;
+	close(bc->bc_fd);
+	free(bc);
+
+	return (0);
+}
+
+/*
+ * Accessors
+ */
+off_t
+blockif_size(struct blockif_ctxt *bc)
+{
+
+	assert(bc->bc_magic == BLOCKIF_SIG);
+	return (bc->bc_size);
+}
+
+int
+blockif_sectsz(struct blockif_ctxt *bc)
+{
+
+	assert(bc->bc_magic == BLOCKIF_SIG);
+	return (bc->bc_sectsz);
+}
+
+int
+blockif_queuesz(struct blockif_ctxt *bc)
+{
+
+	assert(bc->bc_magic == BLOCKIF_SIG);
+	return (BLOCKIF_MAXREQ);
+}
+
+int
+blockif_is_ro(struct blockif_ctxt *bc)
+{
+
+	assert(bc->bc_magic == BLOCKIF_SIG);
+	return (bc->bc_rdonly);
+}

Added: soc2013/zcore/head/usr.sbin/bhyve/block_if.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2013/zcore/head/usr.sbin/bhyve/block_if.h	Sat Jul 13 12:56:05 2013	(r254753)
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2013  Peter Grehan <grehan@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``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 NETAPP, INC 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _BLOCK_IF_H_
+#define _BLOCK_IF_H_
+
+#include <sys/uio.h>
+#include <sys/unistd.h>
+
+#define BLOCKIF_IOV_MAX		32	/* XXX */
+
+struct blockif_req {
+	struct iovec	br_iov[BLOCKIF_IOV_MAX];
+	int		br_iovcnt;
+	off_t		br_offset;
+	void		(*br_callback)(struct blockif_req *req, int err);
+	void		*br_param;
+};
+
+struct blockif_ctxt;
+struct blockif_ctxt *blockif_open(const char *optstr, const char *ident);
+off_t	 blockif_size(struct blockif_ctxt *bc);
+int	 blockif_sectsz(struct blockif_ctxt *bc);
+int	 blockif_queuesz(struct blockif_ctxt *bc);
+int	 blockif_is_ro(struct blockif_ctxt *bc);
+int	 blockif_read(struct blockif_ctxt *bc, struct blockif_req *breq);
+int	 blockif_write(struct blockif_ctxt *bc, struct blockif_req *breq);
+int	 blockif_cancel(struct blockif_ctxt *bc, struct blockif_req *breq);
+int	 blockif_close(struct blockif_ctxt *bc);
+
+#endif /* _BLOCK_IF_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201307131256.r6DCu53x024994>