On Tue, Apr 7, 2015 at 9:08 PM, Peter Lieven <p...@kamp.de> wrote: CCing the entirety of this patch to qemu-devel@nongnu.org. It is also available in the qemu-bl...@nongnu.org mailing list archives: http://permalink.gmane.org/gmane.comp.emulators.qemu.block/460
> 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 <p...@kamp.de> > --- > block/iscsi.c | 33 +++++++++++++++++++++++++++------ > 1 file changed, 27 insertions(+), 6 deletions(-) > > diff --git a/block/iscsi.c b/block/iscsi.c > index 3e34b1f..ba33290 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) > -- > 1.7.9.5 > >