socsvn commit: r254753 - soc2013/zcore/head/usr.sbin/bhyve
zcore at FreeBSD.org
zcore at FreeBSD.org
Sat Jul 13 12:56:06 UTC 2013
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 at 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, §sz)) {
+ 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 at 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_ */
More information about the svn-soc-all
mailing list