[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 06/22] curl: implement .bdrv_detach/attach_aio_conte
From: |
Stefan Hajnoczi |
Subject: |
[Qemu-devel] [PATCH 06/22] curl: implement .bdrv_detach/attach_aio_context() |
Date: |
Thu, 1 May 2014 16:54:30 +0200 |
The curl block driver uses fd handlers, timers, and BHs. The fd
handlers and timers are managed on behalf of libcurl, which controls
them using callback functions that the block driver implements.
The simplest way to implement .bdrv_detach/attach_aio_context() is to
clean up libcurl in the old event loop and initialize it again in the
new event loop. We do not need to keep track of anything since there
are no pending requests when the AioContext is changed.
Also make sure to use aio_set_fd_handler() instead of
qemu_aio_set_fd_handler() and aio_bh_new() instead of qemu_bh_new() so
the current AioContext is passed in.
Cc: Alexander Graf <address@hidden>
Cc: Fam Zheng <address@hidden>
Signed-off-by: Stefan Hajnoczi <address@hidden>
---
block/curl.c | 194 +++++++++++++++++++++++++++++++++++------------------------
1 file changed, 116 insertions(+), 78 deletions(-)
diff --git a/block/curl.c b/block/curl.c
index 6731d28..88638ec 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -88,6 +88,7 @@ typedef struct BDRVCURLState {
char *url;
size_t readahead_size;
bool accept_range;
+ AioContext *aio_context;
} BDRVCURLState;
static void curl_clean_state(CURLState *s);
@@ -111,21 +112,24 @@ static int curl_timer_cb(CURLM *multi, long timeout_ms,
void *opaque)
#endif
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
- void *s, void *sp)
+ void *userp, void *sp)
{
+ BDRVCURLState *s = userp;
+
DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd);
switch (action) {
case CURL_POLL_IN:
- qemu_aio_set_fd_handler(fd, curl_multi_do, NULL, s);
+ aio_set_fd_handler(s->aio_context, fd, curl_multi_do, NULL, s);
break;
case CURL_POLL_OUT:
- qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, s);
+ aio_set_fd_handler(s->aio_context, fd, NULL, curl_multi_do, s);
break;
case CURL_POLL_INOUT:
- qemu_aio_set_fd_handler(fd, curl_multi_do, curl_multi_do, s);
+ aio_set_fd_handler(s->aio_context, fd, curl_multi_do,
+ curl_multi_do, s);
break;
case CURL_POLL_REMOVE:
- qemu_aio_set_fd_handler(fd, NULL, NULL, NULL);
+ aio_set_fd_handler(s->aio_context, fd, NULL, NULL, NULL);
break;
}
@@ -430,6 +434,55 @@ static void curl_parse_filename(const char *filename,
QDict *options,
g_free(file);
}
+static void curl_detach_aio_context(BlockDriverState *bs)
+{
+ BDRVCURLState *s = bs->opaque;
+ int i;
+
+ for (i = 0; i < CURL_NUM_STATES; i++) {
+ if (s->states[i].in_use) {
+ curl_clean_state(&s->states[i]);
+ }
+ if (s->states[i].curl) {
+ curl_easy_cleanup(s->states[i].curl);
+ s->states[i].curl = NULL;
+ }
+ if (s->states[i].orig_buf) {
+ g_free(s->states[i].orig_buf);
+ s->states[i].orig_buf = NULL;
+ }
+ }
+ if (s->multi) {
+ curl_multi_cleanup(s->multi);
+ s->multi = NULL;
+ }
+
+ timer_del(&s->timer);
+}
+
+static void curl_attach_aio_context(BlockDriverState *bs,
+ AioContext *new_context)
+{
+ BDRVCURLState *s = bs->opaque;
+
+ aio_timer_init(new_context, &s->timer,
+ QEMU_CLOCK_REALTIME, SCALE_NS,
+ curl_multi_timeout_do, s);
+
+ // Now we know the file exists and its size, so let's
+ // initialize the multi interface!
+
+ s->multi = curl_multi_init();
+ s->aio_context = new_context;
+ curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s);
+ curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
+#ifdef NEED_CURL_TIMER_CALLBACK
+ curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
+ curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
+#endif
+ curl_multi_do(s);
+}
+
static QemuOptsList runtime_opts = {
.name = "curl",
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
@@ -523,21 +576,7 @@ static int curl_open(BlockDriverState *bs, QDict *options,
int flags,
curl_easy_cleanup(state->curl);
state->curl = NULL;
- aio_timer_init(bdrv_get_aio_context(bs), &s->timer,
- QEMU_CLOCK_REALTIME, SCALE_NS,
- curl_multi_timeout_do, s);
-
- // Now we know the file exists and its size, so let's
- // initialize the multi interface!
-
- s->multi = curl_multi_init();
- curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s);
- curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
-#ifdef NEED_CURL_TIMER_CALLBACK
- curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
- curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
-#endif
- curl_multi_do(s);
+ curl_attach_aio_context(bs, bdrv_get_aio_context(bs));
qemu_opts_del(opts);
return 0;
@@ -630,7 +669,7 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState
*bs,
acb->sector_num = sector_num;
acb->nb_sectors = nb_sectors;
- acb->bh = qemu_bh_new(curl_readv_bh_cb, acb);
+ acb->bh = aio_bh_new(bdrv_get_aio_context(bs), curl_readv_bh_cb, acb);
qemu_bh_schedule(acb->bh);
return &acb->common;
}
@@ -638,25 +677,9 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState
*bs,
static void curl_close(BlockDriverState *bs)
{
BDRVCURLState *s = bs->opaque;
- int i;
DPRINTF("CURL: Close\n");
- for (i=0; i<CURL_NUM_STATES; i++) {
- if (s->states[i].in_use)
- curl_clean_state(&s->states[i]);
- if (s->states[i].curl) {
- curl_easy_cleanup(s->states[i].curl);
- s->states[i].curl = NULL;
- }
- if (s->states[i].orig_buf) {
- g_free(s->states[i].orig_buf);
- s->states[i].orig_buf = NULL;
- }
- }
- if (s->multi)
- curl_multi_cleanup(s->multi);
-
- timer_del(&s->timer);
+ curl_detach_aio_context(bs);
g_free(s->url);
}
@@ -668,68 +691,83 @@ static int64_t curl_getlength(BlockDriverState *bs)
}
static BlockDriver bdrv_http = {
- .format_name = "http",
- .protocol_name = "http",
+ .format_name = "http",
+ .protocol_name = "http",
+
+ .instance_size = sizeof(BDRVCURLState),
+ .bdrv_parse_filename = curl_parse_filename,
+ .bdrv_file_open = curl_open,
+ .bdrv_close = curl_close,
+ .bdrv_getlength = curl_getlength,
- .instance_size = sizeof(BDRVCURLState),
- .bdrv_parse_filename = curl_parse_filename,
- .bdrv_file_open = curl_open,
- .bdrv_close = curl_close,
- .bdrv_getlength = curl_getlength,
+ .bdrv_aio_readv = curl_aio_readv,
- .bdrv_aio_readv = curl_aio_readv,
+ .bdrv_detach_aio_context = curl_detach_aio_context,
+ .bdrv_attach_aio_context = curl_attach_aio_context,
};
static BlockDriver bdrv_https = {
- .format_name = "https",
- .protocol_name = "https",
+ .format_name = "https",
+ .protocol_name = "https",
- .instance_size = sizeof(BDRVCURLState),
- .bdrv_parse_filename = curl_parse_filename,
- .bdrv_file_open = curl_open,
- .bdrv_close = curl_close,
- .bdrv_getlength = curl_getlength,
+ .instance_size = sizeof(BDRVCURLState),
+ .bdrv_parse_filename = curl_parse_filename,
+ .bdrv_file_open = curl_open,
+ .bdrv_close = curl_close,
+ .bdrv_getlength = curl_getlength,
- .bdrv_aio_readv = curl_aio_readv,
+ .bdrv_aio_readv = curl_aio_readv,
+
+ .bdrv_detach_aio_context = curl_detach_aio_context,
+ .bdrv_attach_aio_context = curl_attach_aio_context,
};
static BlockDriver bdrv_ftp = {
- .format_name = "ftp",
- .protocol_name = "ftp",
+ .format_name = "ftp",
+ .protocol_name = "ftp",
+
+ .instance_size = sizeof(BDRVCURLState),
+ .bdrv_parse_filename = curl_parse_filename,
+ .bdrv_file_open = curl_open,
+ .bdrv_close = curl_close,
+ .bdrv_getlength = curl_getlength,
- .instance_size = sizeof(BDRVCURLState),
- .bdrv_parse_filename = curl_parse_filename,
- .bdrv_file_open = curl_open,
- .bdrv_close = curl_close,
- .bdrv_getlength = curl_getlength,
+ .bdrv_aio_readv = curl_aio_readv,
- .bdrv_aio_readv = curl_aio_readv,
+ .bdrv_detach_aio_context = curl_detach_aio_context,
+ .bdrv_attach_aio_context = curl_attach_aio_context,
};
static BlockDriver bdrv_ftps = {
- .format_name = "ftps",
- .protocol_name = "ftps",
+ .format_name = "ftps",
+ .protocol_name = "ftps",
- .instance_size = sizeof(BDRVCURLState),
- .bdrv_parse_filename = curl_parse_filename,
- .bdrv_file_open = curl_open,
- .bdrv_close = curl_close,
- .bdrv_getlength = curl_getlength,
+ .instance_size = sizeof(BDRVCURLState),
+ .bdrv_parse_filename = curl_parse_filename,
+ .bdrv_file_open = curl_open,
+ .bdrv_close = curl_close,
+ .bdrv_getlength = curl_getlength,
- .bdrv_aio_readv = curl_aio_readv,
+ .bdrv_aio_readv = curl_aio_readv,
+
+ .bdrv_detach_aio_context = curl_detach_aio_context,
+ .bdrv_attach_aio_context = curl_attach_aio_context,
};
static BlockDriver bdrv_tftp = {
- .format_name = "tftp",
- .protocol_name = "tftp",
+ .format_name = "tftp",
+ .protocol_name = "tftp",
+
+ .instance_size = sizeof(BDRVCURLState),
+ .bdrv_parse_filename = curl_parse_filename,
+ .bdrv_file_open = curl_open,
+ .bdrv_close = curl_close,
+ .bdrv_getlength = curl_getlength,
- .instance_size = sizeof(BDRVCURLState),
- .bdrv_parse_filename = curl_parse_filename,
- .bdrv_file_open = curl_open,
- .bdrv_close = curl_close,
- .bdrv_getlength = curl_getlength,
+ .bdrv_aio_readv = curl_aio_readv,
- .bdrv_aio_readv = curl_aio_readv,
+ .bdrv_detach_aio_context = curl_detach_aio_context,
+ .bdrv_attach_aio_context = curl_attach_aio_context,
};
static void curl_block_init(void)
--
1.9.0
- [Qemu-devel] [PATCH 00/22] dataplane: use QEMU block layer, Stefan Hajnoczi, 2014/05/01
- [Qemu-devel] [PATCH 01/22] block: use BlockDriverState AioContext, Stefan Hajnoczi, 2014/05/01
- [Qemu-devel] [PATCH 02/22] block: acquire AioContext in bdrv_close_all(), Stefan Hajnoczi, 2014/05/01
- [Qemu-devel] [PATCH 03/22] block: add bdrv_set_aio_context(), Stefan Hajnoczi, 2014/05/01
- [Qemu-devel] [PATCH 04/22] blkdebug: use BlockDriverState's AioContext, Stefan Hajnoczi, 2014/05/01
- [Qemu-devel] [PATCH 06/22] curl: implement .bdrv_detach/attach_aio_context(),
Stefan Hajnoczi <=
- [Qemu-devel] [PATCH 07/22] gluster: use BlockDriverState's AioContext, Stefan Hajnoczi, 2014/05/01
- [Qemu-devel] [PATCH 05/22] blkverify: implement .bdrv_detach/attach_aio_context(), Stefan Hajnoczi, 2014/05/01
- [Qemu-devel] [PATCH 09/22] nbd: implement .bdrv_detach/attach_aio_context(), Stefan Hajnoczi, 2014/05/01
- [Qemu-devel] [PATCH 11/22] qed: use BlockDriverState's AioContext, Stefan Hajnoczi, 2014/05/01
- [Qemu-devel] [PATCH 12/22] quorum: implement .bdrv_detach/attach_aio_context(), Stefan Hajnoczi, 2014/05/01