diff options
-rw-r--r-- | block/iscsi.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/block/iscsi.c b/block/iscsi.c index 259192f535..249778986d 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -48,6 +48,7 @@ typedef struct IscsiLun { int block_size; uint64_t num_blocks; int events; + QEMUTimer *nop_timer; } IscsiLun; typedef struct IscsiAIOCB { @@ -66,6 +67,9 @@ typedef struct IscsiAIOCB { #endif } IscsiAIOCB; +#define NOP_INTERVAL 5000 +#define MAX_NOP_FAILURES 3 + static void iscsi_bh_cb(void *p) { @@ -768,6 +772,26 @@ static char *parse_initiator_name(const char *target) } } +#if defined(LIBISCSI_FEATURE_NOP_COUNTER) +static void iscsi_nop_timed_event(void *opaque) +{ + IscsiLun *iscsilun = opaque; + + if (iscsi_get_nops_in_flight(iscsilun->iscsi) > MAX_NOP_FAILURES) { + error_report("iSCSI: NOP timeout. Reconnecting..."); + iscsi_reconnect(iscsilun->iscsi); + } + + if (iscsi_nop_out_async(iscsilun->iscsi, NULL, NULL, 0, NULL) != 0) { + error_report("iSCSI: failed to sent NOP-Out. Disabling NOP messages."); + return; + } + + qemu_mod_timer(iscsilun->nop_timer, qemu_get_clock_ms(rt_clock) + NOP_INTERVAL); + iscsi_set_events(iscsilun); +} +#endif + /* * We support iscsi url's on the form * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun> @@ -928,6 +952,12 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags) ret = 0; +#if defined(LIBISCSI_FEATURE_NOP_COUNTER) + /* Set up a timer for sending out iSCSI NOPs */ + iscsilun->nop_timer = qemu_new_timer_ms(rt_clock, iscsi_nop_timed_event, iscsilun); + qemu_mod_timer(iscsilun->nop_timer, qemu_get_clock_ms(rt_clock) + NOP_INTERVAL); +#endif + out: if (initiator_name != NULL) { g_free(initiator_name); @@ -953,6 +983,10 @@ static void iscsi_close(BlockDriverState *bs) IscsiLun *iscsilun = bs->opaque; struct iscsi_context *iscsi = iscsilun->iscsi; + if (iscsilun->nop_timer) { + qemu_del_timer(iscsilun->nop_timer); + qemu_free_timer(iscsilun->nop_timer); + } qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL, NULL); iscsi_destroy_context(iscsi); memset(iscsilun, 0, sizeof(IscsiLun)); @@ -987,6 +1021,10 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options) if (ret != 0) { goto out; } + if (iscsilun->nop_timer) { + qemu_del_timer(iscsilun->nop_timer); + qemu_free_timer(iscsilun->nop_timer); + } if (iscsilun->type != TYPE_DISK) { ret = -ENODEV; goto out; |