summaryrefslogtreecommitdiff
path: root/src/VBox/Storage/ISCSI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Storage/ISCSI.cpp')
-rw-r--r--src/VBox/Storage/ISCSI.cpp62
1 files changed, 46 insertions, 16 deletions
diff --git a/src/VBox/Storage/ISCSI.cpp b/src/VBox/Storage/ISCSI.cpp
index 76b244445..7b4e1dd86 100644
--- a/src/VBox/Storage/ISCSI.cpp
+++ b/src/VBox/Storage/ISCSI.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -256,7 +256,7 @@ typedef enum ISCSISTATE
} ISCSISTATE;
/**
- * iSCSI PDU send flags (and maybe more in the future). */
+ * iSCSI PDU send/receive flags (and maybe more in the future). */
typedef enum ISCSIPDUFLAGS
{
/** No special flags */
@@ -671,7 +671,7 @@ static const VDCONFIGINFO s_iscsiConfigInfo[] =
/* iSCSI low-level functions (only to be used from the iSCSI high-level functions). */
static uint32_t iscsiNewITT(PISCSIIMAGE pImage);
static int iscsiSendPDU(PISCSIIMAGE pImage, PISCSIREQ paReq, uint32_t cnReq, uint32_t uFlags);
-static int iscsiRecvPDU(PISCSIIMAGE pImage, uint32_t itt, PISCSIRES paRes, uint32_t cnRes);
+static int iscsiRecvPDU(PISCSIIMAGE pImage, uint32_t itt, PISCSIRES paRes, uint32_t cnRes, uint32_t fFlags);
static int iscsiRecvPDUAsync(PISCSIIMAGE pImage);
static int iscsiSendPDUAsync(PISCSIIMAGE pImage);
static int iscsiValidatePDU(PISCSIRES paRes, uint32_t cnRes);
@@ -1204,6 +1204,7 @@ static int iscsiAttach(void *pvUser)
uint32_t cnISCSIRes;
ISCSIRES aISCSIRes[2];
uint32_t aResBHS[12];
+ unsigned cRetries = 5;
char *pszNext;
PISCSIIMAGE pImage = (PISCSIIMAGE)pvUser;
@@ -1240,6 +1241,20 @@ static int iscsiAttach(void *pvUser)
iscsiTransportClose(pImage);
restart:
+ if (!cRetries)
+ {
+ /*
+ * Prevent the iSCSI initiator to go into normal state if we are here,
+ * even if there is no error code set.
+ */
+ if (RT_SUCCESS(rc))
+ {
+ AssertMsgFailed(("Success status code set while out of retries\n"));
+ rc = VERR_IPE_UNEXPECTED_STATUS;
+ }
+ goto out;
+ }
+
if (!iscsiIsClientConnected(pImage))
{
rc = iscsiTransportOpen(pImage);
@@ -1379,8 +1394,17 @@ restart:
aISCSIRes[cnISCSIRes].cbSeg = sizeof(bBuf);
cnISCSIRes++;
- rc = iscsiRecvPDU(pImage, itt, aISCSIRes, cnISCSIRes);
- if (RT_FAILURE(rc))
+ rc = iscsiRecvPDU(pImage, itt, aISCSIRes, cnISCSIRes, ISCSIPDU_NO_REATTACH);
+ if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
+ {
+ /*
+ * We lost connection to the target while receiving the answer,
+ * start from the beginning.
+ */
+ cRetries--;
+ goto restart;
+ }
+ else if (RT_FAILURE(rc))
break;
/** @todo collect partial login responses with Continue bit set. */
Assert(aISCSIRes[0].pvSeg == aResBHS);
@@ -1716,7 +1740,7 @@ static int iscsiDetach(void *pvUser)
aISCSIRes.pvSeg = aResBHS;
aISCSIRes.cbSeg = sizeof(aResBHS);
- rc = iscsiRecvPDU(pImage, itt, &aISCSIRes, 1);
+ rc = iscsiRecvPDU(pImage, itt, &aISCSIRes, 1, ISCSIPDU_NO_REATTACH);
if (RT_SUCCESS(rc))
{
if (RT_N2H_U32(aResBHS[0]) != (ISCSI_FINAL_BIT | ISCSIOP_LOGOUT_RES))
@@ -1877,7 +1901,7 @@ static int iscsiCommand(PISCSIIMAGE pImage, PSCSIREQ pRequest)
aISCSIRes[cnISCSIRes].cbSeg = sizeof(aStatus);
cnISCSIRes++;
- rc = iscsiRecvPDU(pImage, itt, aISCSIRes, cnISCSIRes);
+ rc = iscsiRecvPDU(pImage, itt, aISCSIRes, cnISCSIRes, ISCSIPDU_DEFAULT);
if (RT_FAILURE(rc))
break;
@@ -2056,8 +2080,10 @@ static int iscsiSendPDU(PISCSIIMAGE pImage, PISCSIREQ paReq, uint32_t cnReq,
* @param pImage The iSCSI connection state to be used.
* @param paRes Pointer to array of iSCSI response sections.
* @param cnRes Number of valid iSCSI response sections in the array.
+ * @param fRecvFlags PDU receive flags.
*/
-static int iscsiRecvPDU(PISCSIIMAGE pImage, uint32_t itt, PISCSIRES paRes, uint32_t cnRes)
+static int iscsiRecvPDU(PISCSIIMAGE pImage, uint32_t itt, PISCSIRES paRes, uint32_t cnRes,
+ uint32_t fRecvFlags)
{
int rc = VINF_SUCCESS;
ISCSIRES aResBuf;
@@ -2078,19 +2104,21 @@ static int iscsiRecvPDU(PISCSIIMAGE pImage, uint32_t itt, PISCSIRES paRes, uint3
* try to restart by re-sending the original request (if any).
* This also handles the connection reestablishment (login etc.). */
RTThreadSleep(500);
- if (pImage->state != ISCSISTATE_IN_LOGIN)
+ if ( pImage->state != ISCSISTATE_IN_LOGIN
+ && !(fRecvFlags & ISCSIPDU_NO_REATTACH))
{
/* Attempt to re-login when a connection fails, but only when not
* currently logging in. */
rc = iscsiAttach(pImage);
if (RT_FAILURE(rc))
break;
- }
- if (pImage->paCurrReq != NULL)
- {
- rc = iscsiSendPDU(pImage, pImage->paCurrReq, pImage->cnCurrReq, ISCSIPDU_DEFAULT);
- if (RT_FAILURE(rc))
- break;
+
+ if (pImage->paCurrReq != NULL)
+ {
+ rc = iscsiSendPDU(pImage, pImage->paCurrReq, pImage->cnCurrReq, ISCSIPDU_DEFAULT);
+ if (RT_FAILURE(rc))
+ break;
+ }
}
}
else
@@ -4934,7 +4962,9 @@ static int iscsiSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
int rc;
/* Image must be opened and the new flags must be valid. */
- if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL)))
+ if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
+ | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE
+ | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
{
rc = VERR_INVALID_PARAMETER;
goto out;