Module Name: src
Committed By: pooka
Date: Mon Apr 29 12:56:04 UTC 2013
Modified Files:
src/lib/librumpuser: Makefile rumpuser.c rumpuser_int.h rumpuser_pth.c
src/sys/rump/include/rump: rumpuser.h
src/sys/rump/librump/rumpvfs: rump_vfs.c rumpblk.c
Added Files:
src/lib/librumpuser: rumpuser_bio.c
Log Message:
Rework how the bio hypercalls work, part 1/n:
Reduce the set of hypercalls to one: "do block i/o". This not only
eliminates a lot of pseudo-duplicate code, it also gives the
hypervisor a lot more freedom on how to optimize the i/o.
To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 src/lib/librumpuser/Makefile
cvs rdiff -u -r1.37 -r1.38 src/lib/librumpuser/rumpuser.c
cvs rdiff -u -r0 -r1.1 src/lib/librumpuser/rumpuser_bio.c
cvs rdiff -u -r1.5 -r1.6 src/lib/librumpuser/rumpuser_int.h
cvs rdiff -u -r1.16 -r1.17 src/lib/librumpuser/rumpuser_pth.c
cvs rdiff -u -r1.88 -r1.89 src/sys/rump/include/rump/rumpuser.h
cvs rdiff -u -r1.73 -r1.74 src/sys/rump/librump/rumpvfs/rump_vfs.c
cvs rdiff -u -r1.48 -r1.49 src/sys/rump/librump/rumpvfs/rumpblk.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/librumpuser/Makefile
diff -u src/lib/librumpuser/Makefile:1.9 src/lib/librumpuser/Makefile:1.10
--- src/lib/librumpuser/Makefile:1.9 Mon Mar 18 13:14:10 2013
+++ src/lib/librumpuser/Makefile Mon Apr 29 12:56:04 2013
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.9 2013/03/18 13:14:10 pooka Exp $
+# $NetBSD: Makefile,v 1.10 2013/04/29 12:56:04 pooka Exp $
#
WARNS?= 5
@@ -13,7 +13,7 @@ CPPFLAGS+= -DLIBRUMPUSER
SRCS= rumpuser.c
SRCS+= rumpuser_pth.c
-SRCS+= rumpuser_dl.c rumpuser_sp.c rumpuser_daemonize.c
+SRCS+= rumpuser_dl.c rumpuser_sp.c rumpuser_daemonize.c rumpuser_bio.c
SRCS+= rumpuser_component.c
INCSDIR= /usr/include/rump
Index: src/lib/librumpuser/rumpuser.c
diff -u src/lib/librumpuser/rumpuser.c:1.37 src/lib/librumpuser/rumpuser.c:1.38
--- src/lib/librumpuser/rumpuser.c:1.37 Sun Apr 28 13:39:13 2013
+++ src/lib/librumpuser/rumpuser.c Mon Apr 29 12:56:04 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpuser.c,v 1.37 2013/04/28 13:39:13 pooka Exp $ */
+/* $NetBSD: rumpuser.c,v 1.38 2013/04/29 12:56:04 pooka Exp $ */
/*
* Copyright (c) 2007-2010 Antti Kantee. All Rights Reserved.
@@ -28,7 +28,7 @@
#include "rumpuser_port.h"
#if !defined(lint)
-__RCSID("$NetBSD: rumpuser.c,v 1.37 2013/04/28 13:39:13 pooka Exp $");
+__RCSID("$NetBSD: rumpuser.c,v 1.38 2013/04/29 12:56:04 pooka Exp $");
#endif /* !lint */
#include <sys/ioctl.h>
@@ -403,22 +403,6 @@ rumpuser_pread(int fd, void *data, size_
return rv;
}
-void
-rumpuser_read_bio(int fd, void *data, size_t size, off_t offset,
- rump_biodone_fn biodone, void *biodonecookie)
-{
- ssize_t rv;
- int error = 0;
-
- rv = rumpuser_pread(fd, data, size, offset, &error);
- /* check against <0 instead of ==-1 to get typing below right */
- if (rv < 0)
- rv = 0;
-
- /* LINTED: see above */
- biodone(biodonecookie, rv, error);
-}
-
ssize_t
rumpuser_write(int fd, const void *data, size_t size, int *error)
{
@@ -443,22 +427,6 @@ rumpuser_pwrite(int fd, const void *data
return rv;
}
-void
-rumpuser_write_bio(int fd, const void *data, size_t size, off_t offset,
- rump_biodone_fn biodone, void *biodonecookie)
-{
- ssize_t rv;
- int error = 0;
-
- rv = rumpuser_pwrite(fd, data, size, offset, &error);
- /* check against <0 instead of ==-1 to get typing below right */
- if (rv < 0)
- rv = 0;
-
- /* LINTED: see above */
- biodone(biodonecookie, rv, error);
-}
-
ssize_t
rumpuser_readv(int fd, const struct rumpuser_iovec *riov, int iovcnt,
int *error)
Index: src/lib/librumpuser/rumpuser_int.h
diff -u src/lib/librumpuser/rumpuser_int.h:1.5 src/lib/librumpuser/rumpuser_int.h:1.6
--- src/lib/librumpuser/rumpuser_int.h:1.5 Sat Apr 27 14:59:08 2013
+++ src/lib/librumpuser/rumpuser_int.h Mon Apr 29 12:56:04 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpuser_int.h,v 1.5 2013/04/27 14:59:08 pooka Exp $ */
+/* $NetBSD: rumpuser_int.h,v 1.6 2013/04/29 12:56:04 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. All Rights Reserved.
@@ -68,3 +68,15 @@ do { \
}
void rumpuser__thrinit(void);
+
+#define NOFAIL(a) do {if (!(a)) abort();} while (/*CONSTCOND*/0)
+
+#define NOFAIL_ERRNO(a) \
+do { \
+ int fail_rv = (a); \
+ if (fail_rv) { \
+ printf("panic: rumpuser fatal failure %d (%s)\n", \
+ fail_rv, strerror(fail_rv)); \
+ abort(); \
+ } \
+} while (/*CONSTCOND*/0)
Index: src/lib/librumpuser/rumpuser_pth.c
diff -u src/lib/librumpuser/rumpuser_pth.c:1.16 src/lib/librumpuser/rumpuser_pth.c:1.17
--- src/lib/librumpuser/rumpuser_pth.c:1.16 Sun Apr 28 13:37:51 2013
+++ src/lib/librumpuser/rumpuser_pth.c Mon Apr 29 12:56:04 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpuser_pth.c,v 1.16 2013/04/28 13:37:51 pooka Exp $ */
+/* $NetBSD: rumpuser_pth.c,v 1.17 2013/04/29 12:56:04 pooka Exp $ */
/*
* Copyright (c) 2007-2010 Antti Kantee. All Rights Reserved.
@@ -28,7 +28,7 @@
#include "rumpuser_port.h"
#if !defined(lint)
-__RCSID("$NetBSD: rumpuser_pth.c,v 1.16 2013/04/28 13:37:51 pooka Exp $");
+__RCSID("$NetBSD: rumpuser_pth.c,v 1.17 2013/04/29 12:56:04 pooka Exp $");
#endif /* !lint */
#include <assert.h>
@@ -47,17 +47,6 @@ __RCSID("$NetBSD: rumpuser_pth.c,v 1.16
static pthread_key_t curlwpkey;
-#define NOFAIL(a) do {if (!(a)) abort();} while (/*CONSTCOND*/0)
-#define NOFAIL_ERRNO(a) \
-do { \
- int fail_rv = (a); \
- if (fail_rv) { \
- printf("panic: rumpuser fatal failure %d (%s)\n", \
- fail_rv, strerror(fail_rv)); \
- abort(); \
- } \
-} while (/*CONSTCOND*/0)
-
struct rumpuser_mtx {
pthread_mutex_t pthmtx;
struct lwp *owner;
@@ -106,84 +95,13 @@ struct rumpuser_cv {
int nwaiters;
};
-struct rumpuser_mtx rumpuser_aio_mtx;
-struct rumpuser_cv rumpuser_aio_cv;
-int rumpuser_aio_head, rumpuser_aio_tail;
-struct rumpuser_aio rumpuser_aios[N_AIOS];
-
void
rumpuser__thrinit(void)
{
- pthread_mutex_init(&rumpuser_aio_mtx.pthmtx, NULL);
- pthread_cond_init(&rumpuser_aio_cv.pthcv, NULL);
pthread_key_create(&curlwpkey, NULL);
}
-void
-/*ARGSUSED*/
-rumpuser_biothread(void *arg)
-{
- struct rumpuser_aio *rua;
- rump_biodone_fn biodone = arg;
- ssize_t rv;
- int error, dummy;
-
- /* unschedule from CPU. we reschedule before running the interrupt */
- rumpuser__unschedule(0, &dummy, NULL);
- assert(dummy == 0);
-
- NOFAIL_ERRNO(pthread_mutex_lock(&rumpuser_aio_mtx.pthmtx));
- for (;;) {
- while (rumpuser_aio_head == rumpuser_aio_tail) {
- NOFAIL_ERRNO(pthread_cond_wait(&rumpuser_aio_cv.pthcv,
- &rumpuser_aio_mtx.pthmtx));
- }
-
- rua = &rumpuser_aios[rumpuser_aio_tail];
- assert(rua->rua_bp != NULL);
- pthread_mutex_unlock(&rumpuser_aio_mtx.pthmtx);
-
- if (rua->rua_op & RUA_OP_READ) {
- error = 0;
- rv = pread(rua->rua_fd, rua->rua_data,
- rua->rua_dlen, rua->rua_off);
- if (rv < 0) {
- rv = 0;
- error = errno;
- }
- } else {
- error = 0;
- rv = pwrite(rua->rua_fd, rua->rua_data,
- rua->rua_dlen, rua->rua_off);
- if (rv < 0) {
- rv = 0;
- error = errno;
- } else if (rua->rua_op & RUA_OP_SYNC) {
-#ifdef __NetBSD__
- fsync_range(rua->rua_fd, FDATASYNC,
- rua->rua_off, rua->rua_dlen);
-#else
- fsync(rua->rua_fd);
-#endif
- }
- }
- rumpuser__reschedule(0, NULL);
- biodone(rua->rua_bp, (size_t)rv, error);
- rumpuser__unschedule(0, &dummy, NULL);
-
- rua->rua_bp = NULL;
-
- NOFAIL_ERRNO(pthread_mutex_lock(&rumpuser_aio_mtx.pthmtx));
- rumpuser_aio_tail = (rumpuser_aio_tail+1) % N_AIOS;
- pthread_cond_signal(&rumpuser_aio_cv.pthcv);
- }
-
- /*NOTREACHED*/
- fprintf(stderr, "error: rumpuser_biothread reached unreachable\n");
- abort();
-}
-
int
rumpuser_thread_create(void *(*f)(void *), void *arg, const char *thrname,
int joinable, void **ptcookie)
Index: src/sys/rump/include/rump/rumpuser.h
diff -u src/sys/rump/include/rump/rumpuser.h:1.88 src/sys/rump/include/rump/rumpuser.h:1.89
--- src/sys/rump/include/rump/rumpuser.h:1.88 Sun Apr 28 13:17:24 2013
+++ src/sys/rump/include/rump/rumpuser.h Mon Apr 29 12:56:03 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpuser.h,v 1.88 2013/04/28 13:17:24 pooka Exp $ */
+/* $NetBSD: rumpuser.h,v 1.89 2013/04/29 12:56:03 pooka Exp $ */
/*
* Copyright (c) 2007-2013 Antti Kantee. All Rights Reserved.
@@ -65,31 +65,29 @@ void *rumpuser_filemmap(int fd, off_t, s
void rumpuser_unmap(void *, size_t);
int rumpuser_memsync(void *, size_t, int *);
-/*
- * Open modes. these "accidentally" happen to match the respective
- * NetBSD bit representations to preserve NetBSD binary compat for
- * current users. If you need to add new ones, just pick any numbers.
- */
-#define RUMPUSER_OPEN_RDONLY 0x000000
-#define RUMPUSER_OPEN_WRONLY 0x000001
-#define RUMPUSER_OPEN_RDWR 0x000002
-#define RUMPUSER_OPEN_ACCMODE 0x000003 /* "yay" */
-#define RUMPUSER_OPEN_CREATE 0x000200
-#define RUMPUSER_OPEN_EXCL 0x000800
-#define RUMPUSER_OPEN_DIRECT 0x080000
+#define RUMPUSER_OPEN_RDONLY 0x0000
+#define RUMPUSER_OPEN_WRONLY 0x0001
+#define RUMPUSER_OPEN_RDWR 0x0002
+#define RUMPUSER_OPEN_ACCMODE 0x0003 /* "yay" */
+#define RUMPUSER_OPEN_CREATE 0x0004 /* create file if it doesn't exist */
+#define RUMPUSER_OPEN_EXCL 0x0008 /* exclusive open */
+#define RUMPUSER_OPEN_DIRECT 0x0010 /* use direct i/o */
+#define RUMPUSER_OPEN_BIO 0x0020 /* open device for block i/o */
int rumpuser_open(const char *, int, int *);
int rumpuser_close(int, int *);
int rumpuser_fsync(int, int *);
+#define RUMPUSER_BIO_READ 0x01
+#define RUMPUSER_BIO_WRITE 0x02
+#define RUMPUSER_BIO_SYNC 0x04
typedef void (*rump_biodone_fn)(void *, size_t, int);
+void rumpuser_bio(int, int, void *, size_t, off_t, rump_biodone_fn, void *);
ssize_t rumpuser_read(int, void *, size_t, int *);
ssize_t rumpuser_pread(int, void *, size_t, off_t, int *);
ssize_t rumpuser_write(int, const void *, size_t, int *);
ssize_t rumpuser_pwrite(int, const void *, size_t, off_t, int *);
-void rumpuser_read_bio(int, void *, size_t, off_t, rump_biodone_fn, void *);
-void rumpuser_write_bio(int, const void *, size_t, off_t,rump_biodone_fn,void*);
struct rumpuser_iovec {
void *iov_base;
@@ -124,8 +122,6 @@ int rumpuser_getnhostcpu(void);
#define RUMPUSER_RANDOM_NOWAIT 0x02
size_t rumpuser_getrandom(void *, size_t, int);
-__dead void rumpuser_biothread(void *);
-
int rumpuser_thread_create(void *(*f)(void *), void *, const char *, int,
void **);
void rumpuser_thread_exit(void) __dead;
@@ -167,25 +163,6 @@ void rumpuser_cv_signal(struct rumpuser_
void rumpuser_cv_broadcast(struct rumpuser_cv *);
int rumpuser_cv_has_waiters(struct rumpuser_cv *);
-/* "aio" stuff for being able to fire of a B_ASYNC I/O and continue */
-struct rumpuser_aio {
- int rua_fd;
- uint8_t *rua_data;
- size_t rua_dlen;
- off_t rua_off;
- void *rua_bp;
- int rua_op;
-};
-#define RUA_OP_READ 0x01
-#define RUA_OP_WRITE 0x02
-#define RUA_OP_SYNC 0x04
-
-#define N_AIOS 1024
-extern struct rumpuser_mtx rumpuser_aio_mtx;
-extern struct rumpuser_cv rumpuser_aio_cv;
-extern struct rumpuser_aio rumpuser_aios[N_AIOS];
-extern int rumpuser_aio_head, rumpuser_aio_tail;
-
/* rumpuser dynloader */
struct modinfo;
Index: src/sys/rump/librump/rumpvfs/rump_vfs.c
diff -u src/sys/rump/librump/rumpvfs/rump_vfs.c:1.73 src/sys/rump/librump/rumpvfs/rump_vfs.c:1.74
--- src/sys/rump/librump/rumpvfs/rump_vfs.c:1.73 Thu Apr 4 11:21:37 2013
+++ src/sys/rump/librump/rumpvfs/rump_vfs.c Mon Apr 29 12:56:03 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: rump_vfs.c,v 1.73 2013/04/04 11:21:37 pooka Exp $ */
+/* $NetBSD: rump_vfs.c,v 1.74 2013/04/29 12:56:03 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. All Rights Reserved.
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rump_vfs.c,v 1.73 2013/04/04 11:21:37 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rump_vfs.c,v 1.74 2013/04/29 12:56:03 pooka Exp $");
#include <sys/param.h>
#include <sys/buf.h>
@@ -126,12 +126,6 @@ RUMP_COMPONENT(RUMP__FACTION_VFS)
spec_init();
fstrans_init();
- if (rump_threads) {
- if ((rv = kthread_create(PRI_BIO, KTHREAD_MPSAFE, NULL,
- rumpuser_biothread, rump_biodone, NULL, "rmpabio")) != 0)
- panic("syncer thread create failed: %d", rv);
- }
-
root_device = &rump_rootdev;
/* bootstrap cwdi (rest done in vfs_mountroot() */
Index: src/sys/rump/librump/rumpvfs/rumpblk.c
diff -u src/sys/rump/librump/rumpvfs/rumpblk.c:1.48 src/sys/rump/librump/rumpvfs/rumpblk.c:1.49
--- src/sys/rump/librump/rumpvfs/rumpblk.c:1.48 Fri Sep 14 16:29:21 2012
+++ src/sys/rump/librump/rumpvfs/rumpblk.c Mon Apr 29 12:56:03 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpblk.c,v 1.48 2012/09/14 16:29:21 pooka Exp $ */
+/* $NetBSD: rumpblk.c,v 1.49 2013/04/29 12:56:03 pooka Exp $ */
/*
* Copyright (c) 2009 Antti Kantee. All Rights Reserved.
@@ -52,7 +52,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rumpblk.c,v 1.48 2012/09/14 16:29:21 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rumpblk.c,v 1.49 2013/04/29 12:56:03 pooka Exp $");
#include <sys/param.h>
#include <sys/buf.h>
@@ -504,9 +504,11 @@ backend_open(struct rblkdev *rblk, const
int error, fd;
KASSERT(rblk->rblk_fd == -1);
- fd = rumpuser_open(path, RUMPUSER_OPEN_RDWR, &error);
+ fd = rumpuser_open(path,
+ RUMPUSER_OPEN_RDWR | RUMPUSER_OPEN_BIO, &error);
if (error) {
- fd = rumpuser_open(path, RUMPUSER_OPEN_RDONLY, &error);
+ fd = rumpuser_open(path,
+ RUMPUSER_OPEN_RDONLY | RUMPUSER_OPEN_BIO, &error);
if (error)
return error;
rblk->rblk_mode = FREAD;
@@ -689,7 +691,7 @@ dostrategy(struct buf *bp)
struct rblkdev *rblk = &minors[minor(bp->b_dev)];
off_t off;
int async = bp->b_flags & B_ASYNC;
- int error;
+ int error, op;
if (bp->b_bcount % (1<<sectshift) != 0) {
rump_biodone(bp, 0, EINVAL);
@@ -780,73 +782,13 @@ dostrategy(struct buf *bp)
}
rump_biodone(bp, bp->b_bcount, 0);
- return;
- }
-
- /*
- * Do I/O. We have different paths for async and sync I/O.
- * Async I/O is done by passing a request to rumpuser where
- * it is executed. The rumpuser routine then calls
- * biodone() to signal any waiters in the kernel. I/O's are
- * executed in series. Technically executing them in parallel
- * would produce better results, but then we'd need either
- * more threads or posix aio. Maybe worth investigating
- * this later.
- *
- * Using bufq here might be a good idea.
- */
-
- if (rump_threads) {
- struct rumpuser_aio *rua;
- int op, fd;
-
- fd = rblk->rblk_fd;
- if (BUF_ISREAD(bp)) {
- op = RUA_OP_READ;
- } else {
- op = RUA_OP_WRITE;
- if (!async) {
- /* O_DIRECT not fully automatic yet */
-#ifdef HAS_ODIRECT
- if ((off & ((1<<sectshift)-1)) == 0
- && ((intptr_t)bp->b_data
- & ((1<<sectshift)-1)) == 0
- && (bp->b_bcount & ((1<<sectshift)-1)) == 0)
- fd = rblk->rblk_dfd;
- else
-#endif
- op |= RUA_OP_SYNC;
- }
- }
-
- rumpuser_mutex_enter(&rumpuser_aio_mtx);
- while ((rumpuser_aio_head+1) % N_AIOS == rumpuser_aio_tail) {
- rumpuser_cv_wait(&rumpuser_aio_cv, &rumpuser_aio_mtx);
- }
-
- rua = &rumpuser_aios[rumpuser_aio_head];
- KASSERT(rua->rua_bp == NULL);
- rua->rua_fd = fd;
- rua->rua_data = bp->b_data;
- rua->rua_dlen = bp->b_bcount;
- rua->rua_off = off;
- rua->rua_bp = bp;
- rua->rua_op = op;
-
- /* insert into queue & signal */
- rumpuser_aio_head = (rumpuser_aio_head+1) % N_AIOS;
- rumpuser_cv_signal(&rumpuser_aio_cv);
- rumpuser_mutex_exit(&rumpuser_aio_mtx);
} else {
- if (BUF_ISREAD(bp)) {
- rumpuser_read_bio(rblk->rblk_fd, bp->b_data,
- bp->b_bcount, off, rump_biodone, bp);
- } else {
- rumpuser_write_bio(rblk->rblk_fd, bp->b_data,
- bp->b_bcount, off, rump_biodone, bp);
- }
+ op = BUF_ISREAD(bp) ? RUMPUSER_BIO_READ : RUMPUSER_BIO_WRITE;
if (BUF_ISWRITE(bp) && !async)
- rumpuser_fsync(rblk->rblk_fd, &error);
+ op |= RUMPUSER_BIO_SYNC;
+
+ rumpuser_bio(rblk->rblk_fd, op, bp->b_data, bp->b_bcount, off,
+ rump_biodone, bp);
}
}
Added files:
Index: src/lib/librumpuser/rumpuser_bio.c
diff -u /dev/null src/lib/librumpuser/rumpuser_bio.c:1.1
--- /dev/null Mon Apr 29 12:56:04 2013
+++ src/lib/librumpuser/rumpuser_bio.c Mon Apr 29 12:56:04 2013
@@ -0,0 +1,173 @@
+/* $NetBSD: rumpuser_bio.c,v 1.1 2013/04/29 12:56:04 pooka Exp $ */
+
+/*-
+ * Copyright (c) 2013 Antti Kantee. 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 THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#include "rumpuser_port.h"
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rump/rumpuser.h>
+
+#include "rumpuser_int.h"
+
+struct rumpuser_bio {
+ int bio_fd;
+ int bio_op;
+ void *bio_data;
+ size_t bio_dlen;
+ off_t bio_off;
+
+ rump_biodone_fn bio_done;
+ void *bio_donearg;
+};
+
+#define N_BIOS 128
+static pthread_mutex_t biomtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t biocv = PTHREAD_COND_INITIALIZER;
+static int bio_head, bio_tail;
+static struct rumpuser_bio bios[N_BIOS];
+
+static void
+dobio(struct rumpuser_bio *biop)
+{
+ ssize_t rv;
+ int error, dummy;
+
+ assert(biop->bio_donearg != NULL);
+ if (biop->bio_op & RUMPUSER_BIO_READ) {
+ error = 0;
+ rv = pread(biop->bio_fd, biop->bio_data,
+ biop->bio_dlen, biop->bio_off);
+ if (rv < 0) {
+ rv = 0;
+ error = errno;
+ }
+ } else {
+ error = 0;
+ rv = pwrite(biop->bio_fd, biop->bio_data,
+ biop->bio_dlen, biop->bio_off);
+ if (rv < 0) {
+ rv = 0;
+ error = errno;
+ } else if (biop->bio_op & RUMPUSER_BIO_SYNC) {
+#ifdef __NetBSD__
+ fsync_range(biop->bio_fd, FDATASYNC,
+ biop->bio_off, biop->bio_dlen);
+#else
+ fsync(biop->bio_fd);
+#endif
+ }
+ }
+ rumpuser__reschedule(0, NULL);
+ biop->bio_done(biop->bio_donearg, (size_t)rv, error);
+ rumpuser__unschedule(0, &dummy, NULL);
+
+ /* paranoia */
+ biop->bio_donearg = NULL;
+}
+
+static void *
+biothread(void *arg)
+{
+ struct rumpuser_bio *biop;
+
+ NOFAIL_ERRNO(pthread_mutex_lock(&biomtx));
+ for (;;) {
+ while (bio_head == bio_tail)
+ NOFAIL_ERRNO(pthread_cond_wait(&biocv, &biomtx));
+
+ biop = &bios[bio_tail];
+ pthread_mutex_unlock(&biomtx);
+
+ dobio(biop);
+
+ NOFAIL_ERRNO(pthread_mutex_lock(&biomtx));
+ bio_tail = (bio_tail+1) % N_BIOS;
+ pthread_cond_signal(&biocv);
+ }
+
+ /* unreachable */
+ abort();
+}
+
+void
+rumpuser_bio(int fd, int op, void *data, size_t dlen, off_t doff,
+ rump_biodone_fn biodone, void *bioarg)
+{
+ struct rumpuser_bio bio;
+ static int inited = 0;
+ static int usethread = 0;
+
+ if (!inited) {
+ pthread_mutex_lock(&biomtx);
+ if (!inited) {
+ char buf[16];
+ pthread_t pt;
+
+ /*
+ * duplicates policy of rump kernel. maybe a bit
+ * questionable, but since the setting is not
+ * used in normal circumstances, let's not care
+ */
+ if (getenv_r("RUMP_THREADS", buf, sizeof(buf)) == 0)
+ usethread = *buf != '0';
+
+ pthread_create(&pt, NULL, biothread, NULL);
+ inited = 1;
+ }
+ pthread_mutex_unlock(&biomtx);
+ assert(inited);
+ }
+
+ bio.bio_fd = fd;
+ bio.bio_op = op;
+ bio.bio_data = data;
+ bio.bio_dlen = dlen;
+ bio.bio_off = doff;
+ bio.bio_done = biodone;
+ bio.bio_donearg = bioarg;
+
+ if (!usethread) {
+ dobio(&bio);
+ } else {
+ pthread_mutex_lock(&biomtx);
+ while ((bio_head+1) % N_BIOS == bio_tail)
+ pthread_cond_wait(&biocv, &biomtx);
+
+ bios[bio_head] = bio;
+ bio_head = (bio_head+1) % N_BIOS;
+
+ pthread_cond_signal(&biocv);
+ pthread_mutex_unlock(&biomtx);
+ }
+}