diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 658dc98..c74390c 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -126,6 +126,7 @@ struct iscsi_context { int no_auto_reconnect; int reconnect_deferred; int reconnect_max_retries; + int pending_reconnect; int log_level; iscsi_log_fn log_fn; @@ -189,8 +190,9 @@ enum iscsi_opcode { ISCSI_PDU_DATA_IN = 0x25, ISCSI_PDU_LOGOUT_RESPONSE = 0x26, ISCSI_PDU_R2T = 0x31, + ISCSI_PDU_ASYNC_MSG = 0x32, ISCSI_PDU_REJECT = 0x3f, - ISCSI_PDU_NO_PDU = 0xff + ISCSI_PDU_NO_PDU = 0xff }; struct iscsi_scsi_cbdata { diff --git a/lib/pdu.c b/lib/pdu.c index 89b15c2..0b0ce1f 100644 --- a/lib/pdu.c +++ b/lib/pdu.c @@ -359,6 +359,17 @@ int iscsi_process_reject(struct iscsi_context *iscsi, } +static void iscsi_reconnect_after_logout(struct iscsi_context *iscsi, int status, + void *command_data _U_, void *opaque _U_) +{ + if (status) { + ISCSI_LOG(iscsi, 1, "logout failed: %s", iscsi_get_error(iscsi)); + } else { + ISCSI_LOG(iscsi, 2, "logout was successful"); + } + iscsi->pending_reconnect = 1; +} + int iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in) { @@ -376,6 +387,22 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in) return -1; } + if (opcode == ISCSI_PDU_ASYNC_MSG) { + uint8_t event = in->hdr[36]; + uint16_t param1 = scsi_get_uint16(&in->hdr[38]); + uint16_t param2 = scsi_get_uint16(&in->hdr[40]); + uint16_t param3 = scsi_get_uint16(&in->hdr[42]); + switch (event) { + case 0x1: + ISCSI_LOG(iscsi, 2, "target requests logout within %u seconds", param3); + iscsi_logout_async_internal(iscsi, iscsi_reconnect_after_logout, NULL, ISCSI_PDU_DROP_ON_RECONNECT|ISCSI_PDU_URGENT_DELIVERY); + return 0; + default: + ISCSI_LOG(iscsi, 1, "unhandled async event %u: param1 %u param2 %u param3 %u", event, param1, param2, param3); + return -1; + } + } + if (opcode == ISCSI_PDU_REJECT) { iscsi_set_error(iscsi, "Request was rejected with reason: 0x%02x (%s)", in->hdr[2], iscsi_reject_reason_str(in->hdr[2])); diff --git a/lib/socket.c b/lib/socket.c index 2a79538..9844084 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -735,6 +735,10 @@ iscsi_service(struct iscsi_context *iscsi, int revents) return 0; } + if (iscsi->pending_reconnect) { + iscsi_reconnect(iscsi); + } + if (revents & POLLERR) { int err = 0; socklen_t err_size = sizeof(err);