aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/iscsi.c38
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;