diff options
Diffstat (limited to 'src/VBox/Storage/ISCSI.cpp')
| -rw-r--r-- | src/VBox/Storage/ISCSI.cpp | 62 |
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; |
