diff options
author | Peter Lieven <pl@kamp.de> | 2015-04-07 22:08:15 +0200 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2015-04-09 10:31:45 +0100 |
commit | 05b685fbabb7fdcab72cb42b27db916fd74b2265 (patch) | |
tree | f2446f518d780be7921321c30c6ad4d787a7e5ef /block/iscsi.c | |
parent | e8d3b1a25f284cdf9705b7cf0412281cc9ee3a36 (diff) |
block/iscsi: handle zero events from iscsi_which_events
newer libiscsi versions may return zero events from iscsi_which_events.
In this case iscsi_service will return immediately without any progress.
To avoid busy waiting for iscsi_which_events to change we deregister all
read and write handlers in this case and schedule a timer to periodically
check iscsi_which_events for changed events.
Next libiscsi version will introduce async reconnects and zero events
are returned while libiscsi is waiting for a reconnect retry.
Signed-off-by: Peter Lieven <pl@kamp.de>
Message-id: 1428437295-29577-1-git-send-email-pl@kamp.de
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/iscsi.c')
-rw-r--r-- | block/iscsi.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/block/iscsi.c b/block/iscsi.c index 3e34b1f3a2..ba33290000 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -56,6 +56,7 @@ typedef struct IscsiLun { uint64_t num_blocks; int events; QEMUTimer *nop_timer; + QEMUTimer *event_timer; uint8_t lbpme; uint8_t lbprz; uint8_t has_write_same; @@ -95,6 +96,7 @@ typedef struct IscsiAIOCB { #endif } IscsiAIOCB; +#define EVENT_INTERVAL 250 #define NOP_INTERVAL 5000 #define MAX_NOP_FAILURES 3 #define ISCSI_CMD_RETRIES ARRAY_SIZE(iscsi_retry_times) @@ -256,21 +258,30 @@ static void iscsi_set_events(IscsiLun *iscsilun) { struct iscsi_context *iscsi = iscsilun->iscsi; - int ev; + int ev = iscsi_which_events(iscsi); - /* We always register a read handler. */ - ev = POLLIN; - ev |= iscsi_which_events(iscsi); if (ev != iscsilun->events) { aio_set_fd_handler(iscsilun->aio_context, iscsi_get_fd(iscsi), - iscsi_process_read, + (ev & POLLIN) ? iscsi_process_read : NULL, (ev & POLLOUT) ? iscsi_process_write : NULL, iscsilun); + iscsilun->events = ev; + } + /* newer versions of libiscsi may return zero events. In this + * case start a timer to ensure we are able to return to service + * once this situation changes. */ + if (!ev) { + timer_mod(iscsilun->event_timer, + qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + EVENT_INTERVAL); } +} - iscsilun->events = ev; +static void iscsi_timed_set_events(void *opaque) +{ + IscsiLun *iscsilun = opaque; + iscsi_set_events(iscsilun); } static void @@ -1214,6 +1225,11 @@ static void iscsi_detach_aio_context(BlockDriverState *bs) timer_free(iscsilun->nop_timer); iscsilun->nop_timer = NULL; } + if (iscsilun->event_timer) { + timer_del(iscsilun->event_timer); + timer_free(iscsilun->event_timer); + iscsilun->event_timer = NULL; + } } static void iscsi_attach_aio_context(BlockDriverState *bs, @@ -1230,6 +1246,11 @@ static void iscsi_attach_aio_context(BlockDriverState *bs, iscsi_nop_timed_event, iscsilun); timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL); + + /* Prepare a timer for a delayed call to iscsi_set_events */ + iscsilun->event_timer = aio_timer_new(iscsilun->aio_context, + QEMU_CLOCK_REALTIME, SCALE_MS, + iscsi_timed_set_events, iscsilun); } static bool iscsi_is_write_protected(IscsiLun *iscsilun) |