On 03/15/2011 05:38 AM, Arun R Bharadwaj wrote:
* Arun R Bharadwaj<a...@linux.vnet.ibm.com> [2011-03-15 16:04:53]:
Author: Arun R Bharadwaj<a...@linux.vnet.ibm.com>
Date: Thu Mar 10 15:11:49 2011 +0530
Helper routines to use GLib threadpool infrastructure in 9pfs.
This patch creates helper routines to make use of the
threadpool infrastructure provided by GLib. This is based
on the prototype patch by Anthony which does a similar thing
for posix-aio-compat.c
An example use case is provided in the next patch where one
of the syscalls in 9pfs is converted into the threaded model
using these helper routines.
Signed-off-by: Arun R Bharadwaj<a...@linux.vnet.ibm.com>
Reviewed-by: Aneesh Kumar K.V<aneesh.ku...@linux.vnet.ibm.com>
Why even bothering signaling for completion with the virtio-9p threadpool?
There's no sane guest that's going to poll on virtio-9p completion with
interrupts disabled and no timer. Once we enable the I/O thread by
default, it won't even be necessary for the paio layer.
Regards,
Anthony Liguori
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index dceefd5..cf61345 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -18,6 +18,8 @@
#include "fsdev/qemu-fsdev.h"
#include "virtio-9p-debug.h"
#include "virtio-9p-xattr.h"
+#include "signal.h"
+#include "qemu-thread.h"
int debug_9p_pdu;
static void v9fs_reclaim_fd(V9fsState *s);
@@ -36,6 +38,89 @@ enum {
Oappend = 0x80,
};
+typedef struct V9fsPool {
+ GThreadPool *pool;
+ GList *requests;
+ int rfd;
+ int wfd;
+} V9fsPool;
+
+static V9fsPool v9fs_pool;
+
+static void v9fs_qemu_submit_request(V9fsRequest *req)
+{
+ V9fsPool *p =&v9fs_pool;
+
+ p->requests = g_list_append(p->requests, req);
+ g_thread_pool_push(v9fs_pool.pool, req, NULL);
+}
+
+static void die2(int err, const char *what)
+{
+ fprintf(stderr, "%s failed: %s\n", what, strerror(err));
+ abort();
+}
+
+static void die(const char *what)
+{
+ die2(errno, what);
+}
+
+static void v9fs_qemu_process_post_ops(void *arg)
+{
+ struct V9fsPool *p =&v9fs_pool;
+ struct V9fsPostOp *post_op;
+ char byte;
+ ssize_t len;
+ GList *cur_req, *next_req;
+
+ do {
+ len = read(p->rfd,&byte, sizeof(byte));
+ } while (len == -1&& errno == EINTR);
+
+ for (cur_req = p->requests; cur_req != NULL; cur_req = next_req) {
+ V9fsRequest *req = cur_req->data;
+ next_req = g_list_next(cur_req);
+
+ if (!req->done) {
+ continue;
+ }
+
+ post_op =&req->post_op;
+ post_op->func(post_op->arg);
+ p->requests = g_list_remove_link(p->requests, cur_req);
+ g_list_free(p->requests);
+ }
+}
+
+static inline void v9fs_thread_signal(void)
+{
+ struct V9fsPool *p =&v9fs_pool;
+ char byte = 0;
+ ssize_t ret;
+
+ do {
+ ret = write(p->wfd,&byte, sizeof(byte));
+ } while (ret == -1&& errno == EINTR);
+
+ if (ret< 0&& errno != EAGAIN) {
+ die("write() in v9fs");
+ }
+
+ if (kill(getpid(), SIGUSR2)) {
+ die("kill failed");
+ }
+}
+
+static void v9fs_thread_routine(gpointer data, gpointer user_data)
+{
+ V9fsRequest *req = data;
+
+ req->func(req);
+ v9fs_thread_signal();
+ req->done = 1;
+}
+
static int omode_to_uflags(int8_t mode)
{
int ret = 0;
@@ -3850,7 +3935,8 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf
*conf)
int i, len;
struct stat stat;
FsTypeEntry *fse;
-
+ int fds[2];
+ V9fsPool *p =&v9fs_pool;
s = (V9fsState *)virtio_common_init("virtio-9p",
VIRTIO_ID_9P,
@@ -3939,5 +4025,21 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf
*conf)
s->tag_len;
s->vdev.get_config = virtio_9p_get_config;
+ if (qemu_pipe(fds) == -1) {
+ fprintf(stderr, "failed to create fd's for virtio-9p\n");
+ exit(1);
+ }
+
+ p->pool = g_thread_pool_new(v9fs_thread_routine, p, 8, FALSE, NULL);
+ p->rfd = fds[0];
+ p->wfd = fds[1];
+
+ fcntl(p->rfd, F_SETFL, O_NONBLOCK);
+ fcntl(p->wfd, F_SETFL, O_NONBLOCK);
+
+ qemu_set_fd_handler(p->rfd, v9fs_qemu_process_post_ops, NULL, NULL);
+
+ (void) v9fs_qemu_submit_request;
+
return&s->vdev;
}
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 10809ba..e7d2326 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -124,6 +124,20 @@ struct V9fsPDU
QLIST_ENTRY(V9fsPDU) next;
};
+typedef struct V9fsPostOp {
+ /* Post Operation routine to execute after executing syscall */
+ void (*func)(void *arg);
+ void *arg;
+} V9fsPostOp;
+
+typedef struct V9fsRequest {
+ void (*func)(struct V9fsRequest *req);
+
+ /* Flag to indicate that request is satisfied, ready for post-processing */
+ int done;
+
+ V9fsPostOp post_op;
+} V9fsRequest;
/* FIXME
* 1) change user needs to set groups and stuff