From: Paolo Bonzini <pbonzini@redhat.com>
To: Stefan Hajnoczi <stefanha@gmail.com>
Cc: Kevin Wolf <kwolf@redhat.com>,
Luiz Capitulino <lcapitulino@redhat.com>,
Marcelo Tosatti <mtosatti@redhat.com>,
Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>,
qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v4 01/15] coroutine: add co_sleep_ns() coroutine sleep function
Date: Thu, 12 Jan 2012 12:07:54 +0100 [thread overview]
Message-ID: <4F0EBF0A.602@redhat.com> (raw)
In-Reply-To: <CAJSP0QWp3p6vkRBV2k64EYYtvF_ns52XqdvYwkAwj6ARv_knbw@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 848 bytes --]
On 01/12/2012 11:58 AM, Stefan Hajnoczi wrote:
> This is something I'm looking at right now and will probably want to
> discuss with Paolo.
>
> In a coroutine we're probably using a main loop and timers should be
> available there. In general, the problem we're starting to see is
> that some block layer features are using timers (I/O throttling, QED
> deferred dirty bit clearing, image streaming). The question is do we
> isolate this functionality so it is unavailable from a qemu-tool world
> when there's no main loop, or do we move everything into a main loop?
Yes, I would move things into a main loop just like qemu-nbd does. I
even had some prototype patches for it. The qemu-img part is broken
because it uses callbacks that haven't been made asynchronous yet; the
one for qemu-io should be okay modulo some more testing.
Paolo
[-- Attachment #2: tools-co.patch --]
[-- Type: text/x-patch, Size: 8122 bytes --]
>From 9b67defc5eacb9254a8140a4daa52949f0fe60e2 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Mon, 26 Sep 2011 10:59:46 +0200
Subject: [PATCH 1/2] qemu-io: use main_loop_wait
This will let timers run during aio_read and aio_write commands,
though not during synchronous commands.
Not-tested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cmd.c | 10 +++++-----
qemu-io.c | 8 +++++---
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/cmd.c b/cmd.c
index 0806e18..7ffbb71 100644
--- a/cmd.c
+++ b/cmd.c
@@ -25,6 +25,7 @@
#include "cmd.h"
#include "qemu-aio.h"
+#include "main-loop.h"
#define _(x) x /* not gettext support yet */
@@ -146,7 +147,7 @@ static void prep_fetchline(void *opaque)
{
int *fetchable = opaque;
- qemu_aio_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL, NULL, NULL);
+ qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
*fetchable= 1;
}
@@ -193,12 +194,11 @@ void command_loop(void)
if (!prompted) {
printf("%s", get_prompt());
fflush(stdout);
- qemu_aio_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, NULL,
- NULL, &fetchable);
+ qemu_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, &fetchable);
prompted = 1;
}
- qemu_aio_wait();
+ main_loop_wait(false);
if (!fetchable) {
continue;
@@ -221,7 +221,7 @@ void command_loop(void)
prompted = 0;
fetchable = 0;
}
- qemu_aio_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL, NULL, NULL);
+ qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
}
/* from libxcmd/input.c */
diff --git a/qemu-io.c b/qemu-io.c
index ffa62fb..6e1bee3 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -15,6 +15,7 @@
#include <libgen.h>
#include "qemu-common.h"
+#include "main-loop.h"
#include "block_int.h"
#include "cmd.h"
@@ -249,7 +250,7 @@ static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
aio_rw_done, &async_ret);
while (async_ret == NOT_DONE) {
- qemu_aio_wait();
+ main_loop_wait(false);
}
*total = qiov->size;
@@ -263,7 +264,7 @@ static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
aio_rw_done, &async_ret);
while (async_ret == NOT_DONE) {
- qemu_aio_wait();
+ main_loop_wait(false);
}
*total = qiov->size;
@@ -306,7 +307,7 @@ static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total)
}
while (async_ret.num_done < num_reqs) {
- qemu_aio_wait();
+ main_loop_wait(false);
}
return async_ret.error < 0 ? async_ret.error : 1;
@@ -1793,6 +1794,7 @@ int main(int argc, char **argv)
exit(1);
}
+ qemu_init_main_loop();
bdrv_init();
/* initialize commands */
--
1.7.7.1
>From ac2958b0992dcd155ab76885cac044a9fec5cc06 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 18 Oct 2011 12:20:44 +0200
Subject: [PATCH 2/2] qemu-img: run commands in coroutine context
The new function qemu_coroutine_schedule is in qemu-coroutine-lock.c
since it's where the other dependencies on the main loop reside.
Not-tested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
main-loop.h | 20 ++++++--------------
qemu-coroutine-lock.c | 24 ++++++++++++++++++++++++
qemu-coroutine.h | 8 ++++++++
qemu-img.c | 40 ++++++++++++++++++++++++++++++++--------
4 files changed, 70 insertions(+), 22 deletions(-)
diff --git a/main-loop.h b/main-loop.h
index f971013..4e99485 100644
--- a/main-loop.h
+++ b/main-loop.h
@@ -59,24 +59,16 @@ int qemu_init_main_loop(void);
* It is sometimes useful to put a whole program in a coroutine. In this
* case, the coroutine actually should be started from within the main loop,
* so that the main loop can run whenever the coroutine yields. To do this,
- * you can use a bottom half to enter the coroutine as soon as the main loop
- * starts:
+ * you can use qemu_coroutine_schedule.
*
- * void enter_co_bh(void *opaque) {
- * QEMUCoroutine *co = opaque;
- * qemu_coroutine_enter(co, NULL);
- * }
- *
- * ...
- * QEMUCoroutine *co = qemu_coroutine_create(coroutine_entry);
- * QEMUBH *start_bh = qemu_bh_new(enter_co_bh, co);
- * qemu_bh_schedule(start_bh);
- * while (...) {
+ * int ret = -1;
+ * Coroutine *co = qemu_coroutine_create(coroutine_entry);
+ * qemu_init_main_loop();
+ * qemu_coroutine_schedule(co, &ret);
+ * while (ret == -1) {
* main_loop_wait(false);
* }
*
- * (In the future we may provide a wrapper for this).
- *
* @nonblocking: Whether the caller should block until an event occurs.
*/
int main_loop_wait(int nonblocking);
diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c
index 26ad76b..45a2fc2 100644
--- a/qemu-coroutine-lock.c
+++ b/qemu-coroutine-lock.c
@@ -169,3 +169,27 @@ void qemu_co_rwlock_wrlock(CoRwlock *lock)
}
lock->writer = true;
}
+
+typedef struct {
+ QEMUBH *bh;
+ Coroutine *co;
+ void *opaque;
+} CoroutineBHArgs;
+
+static void qemu_coroutine_schedule_bh(void *opaque)
+{
+ CoroutineBHArgs args = *(CoroutineBHArgs *)opaque;
+ g_free(opaque);
+ qemu_bh_delete(args.bh);
+ qemu_coroutine_enter(args.co, args.opaque);
+}
+
+void qemu_coroutine_schedule(Coroutine *co, void *opaque)
+{
+ CoroutineBHArgs *args = g_malloc(sizeof(CoroutineBHArgs));
+ args->bh = qemu_bh_new(qemu_coroutine_schedule_bh, args);
+ args->co = co;
+ args->opaque = opaque;
+ qemu_bh_schedule(args->bh);
+}
+
diff --git a/qemu-coroutine.h b/qemu-coroutine.h
index 8a55fe1..8cdef58 100644
--- a/qemu-coroutine.h
+++ b/qemu-coroutine.h
@@ -199,4 +199,12 @@ void qemu_co_rwlock_wrlock(CoRwlock *lock);
*/
void qemu_co_rwlock_unlock(CoRwlock *lock);
+/**
+ * Transfer control to a coroutine from a bottom half
+ *
+ * The opaque argument is passed as the argument to the entry point when
+ * entering the coroutine for the first time. It is subsequently ignored.
+ */
+void qemu_coroutine_schedule(Coroutine *coroutine, void *opaque);
+
#endif /* QEMU_COROUTINE_H */
diff --git a/qemu-img.c b/qemu-img.c
index 01cc0d3..2123476 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -24,6 +24,8 @@
#include "qemu-common.h"
#include "qemu-option.h"
#include "qemu-error.h"
+#include "qemu-coroutine.h"
+#include "main-loop.h"
#include "osdep.h"
#include "sysemu.h"
#include "block_int.h"
@@ -1674,27 +1676,49 @@ static const img_cmd_t img_cmds[] = {
{ NULL, NULL, },
};
-int main(int argc, char **argv)
+typedef struct {
+ int argc;
+ char **argv;
+ int ret;
+} MainArgs;
+
+static void main_co_entry(void *opaque)
{
+ MainArgs *args = opaque;
const img_cmd_t *cmd;
const char *cmdname;
- error_set_progname(argv[0]);
-
- bdrv_init();
- if (argc < 2)
+ if (args->argc < 2)
help();
- cmdname = argv[1];
- argc--; argv++;
+ cmdname = args->argv[1];
+ args->argc--; args->argv++;
/* find the command */
for(cmd = img_cmds; cmd->name != NULL; cmd++) {
if (!strcmp(cmdname, cmd->name)) {
- return cmd->handler(argc, argv);
+ args->ret = cmd->handler(args->argc, args->argv);
+ return;
}
}
/* not found */
help();
+ args->ret = 0;
+}
+
+#define NOT_DONE 0x7fffffff
+
+int main(int argc, char **argv)
+{
+ error_set_progname(argv[0]);
+ MainArgs args = { .argc = argc, .argv = argv, .ret = NOT_DONE };
+ Coroutine *co = qemu_coroutine_create(main_co_entry);
+
+ qemu_init_main_loop();
+ bdrv_init();
+ qemu_coroutine_schedule(co, &args);
+ while (args.ret == NOT_DONE) {
+ main_loop_wait(false);
+ }
return 0;
}
--
1.7.7.1
next prev parent reply other threads:[~2012-01-12 11:08 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-06 14:01 [Qemu-devel] [PATCH v4 00/15] block: generic image streaming Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 01/15] coroutine: add co_sleep_ns() coroutine sleep function Stefan Hajnoczi
2012-01-12 10:13 ` Kevin Wolf
2012-01-12 10:58 ` Stefan Hajnoczi
2012-01-12 11:07 ` Paolo Bonzini [this message]
2012-01-12 13:11 ` Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 02/15] block: check bdrv_in_use() before blockdev operations Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 03/15] block: add BlockJob interface for long-running operations Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 04/15] block: add image streaming block job Stefan Hajnoczi
2012-01-11 17:18 ` Luiz Capitulino
2012-01-12 9:11 ` Stefan Hajnoczi
2012-01-12 10:59 ` Kevin Wolf
2012-01-12 11:39 ` Stefan Hajnoczi
2012-01-12 12:53 ` Kevin Wolf
2012-01-12 13:05 ` Stefan Hajnoczi
2012-01-12 13:17 ` Kevin Wolf
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 05/15] block: rate-limit streaming operations Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 06/15] qmp: add block_stream command Stefan Hajnoczi
2012-01-11 17:23 ` Luiz Capitulino
2012-01-12 9:25 ` Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 07/15] qmp: add block_job_set_speed command Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 08/15] qmp: add block_job_cancel command Stefan Hajnoczi
2012-01-20 0:02 ` Eric Blake
2012-01-20 8:30 ` Kevin Wolf
2012-01-20 12:08 ` Luiz Capitulino
2012-01-20 19:55 ` Eric Blake
2012-02-07 15:44 ` Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 09/15] qmp: add query-block-jobs Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 10/15] blockdev: make image streaming safe across hotplug Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 11/15] block: add bdrv_find_backing_image Stefan Hajnoczi
2012-01-12 12:17 ` Kevin Wolf
2012-01-12 13:01 ` Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 12/15] add QERR_BASE_ID_NOT_FOUND Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 13/15] block stream: add support for partial streaming Stefan Hajnoczi
2012-01-12 12:42 ` Kevin Wolf
2012-01-12 16:14 ` Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 14/15] add doc to describe live block operations Stefan Hajnoczi
2012-01-06 14:01 ` [Qemu-devel] [PATCH v4 15/15] test: add image streaming test cases Stefan Hajnoczi
2012-01-11 17:58 ` [Qemu-devel] [PATCH v4 00/15] block: generic image streaming Luiz Capitulino
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F0EBF0A.602@redhat.com \
--to=pbonzini@redhat.com \
--cc=kwolf@redhat.com \
--cc=lcapitulino@redhat.com \
--cc=mtosatti@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@gmail.com \
--cc=stefanha@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.