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.cpp1237
1 files changed, 536 insertions, 701 deletions
diff --git a/src/VBox/Storage/ISCSI.cpp b/src/VBox/Storage/ISCSI.cpp
index 76b24444..2ed7f4f3 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 */
@@ -335,6 +335,8 @@ typedef struct ISCSIIMAGE *PISCSIIMAGE;
*/
typedef struct SCSIREQ
{
+ /** I/O context associated with this request. */
+ PVDIOCTX pIoCtx;
/** Transfer direction. */
SCSIXFER enmXfer;
/** Length of command block. */
@@ -348,10 +350,12 @@ typedef struct SCSIREQ
size_t cbSense;
/** Completion status of the command. */
uint8_t status;
- /** Pointer to command block. */
- void *pvCDB;
- /** Pointer to sense buffer. */
- void *pvSense;
+ /** The CDB. */
+ uint8_t abCDB[16];
+ /** The sense buffer. */
+ uint8_t abSense[96];
+ /** Status code to return if we got sense data. */
+ int rcSense;
/** Pointer to the Initiator2Target S/G list. */
PRTSGSEG paI2TSegs;
/** Number of entries in the I2T S/G list. */
@@ -362,38 +366,16 @@ typedef struct SCSIREQ
unsigned cT2ISegs;
/** S/G buffer for the target to initiator bits. */
RTSGBUF SgBufT2I;
-} SCSIREQ, *PSCSIREQ;
-
-/**
- * Async request structure holding all necessary data for
- * request processing.
- */
-typedef struct SCSIREQASYNC
-{
- /** I/O context associated with this request. */
- PVDIOCTX pIoCtx;
- /** Pointer to the SCSI request structure. */
- PSCSIREQ pScsiReq;
- /** The CDB. */
- uint8_t abCDB[16];
- /** The sense buffer. */
- uint8_t abSense[96];
- /** Status code to return if we got sense data. */
- int rcSense;
/** Number of retries if the command completes with sense
* data before we return with an error.
*/
unsigned cSenseRetries;
- /** The number of entries in the I2T S/G list. */
- unsigned cI2TSegs;
- /** The number of entries in the T2I S/G list. */
- unsigned cT2ISegs;
/** The S/G list - variable in size.
* This array holds both the I2T and T2I segments.
* The I2T segments are first and the T2I are second.
*/
RTSGSEG aSegs[1];
-} SCSIREQASYNC, *PSCSIREQASYNC;
+} SCSIREQ, *PSCSIREQ;
typedef enum ISCSICMDTYPE
{
@@ -451,15 +433,15 @@ typedef struct ISCSICMD
struct
{
/** The SCSI request to process. */
- PSCSIREQ pScsiReq;
+ PSCSIREQ pScsiReq;
} ScsiReq;
/** Call a function in the I/O thread. */
struct
{
/** The method to execute. */
- PFNISCSIEXEC pfnExec;
+ PFNISCSIEXEC pfnExec;
/** User data. */
- void *pvUser;
+ void *pvUser;
} Exec;
} CmdType;
} ISCSICMD, *PISCSICMD;
@@ -671,7 +653,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);
@@ -1138,7 +1120,10 @@ static int iscsiTransportOpen(PISCSIIMAGE pImage)
rc = VERR_NO_MEMORY;
else
{
- memcpy(pImage->pszHostname, pImage->pszTargetAddress, cbHostname);
+ if (pImage->pszTargetAddress[0] == '[')
+ memcpy(pImage->pszHostname, pImage->pszTargetAddress + 1, cbHostname);
+ else
+ memcpy(pImage->pszHostname, pImage->pszTargetAddress, cbHostname);
pImage->pszHostname[cbHostname] = '\0';
if (pcszPort != NULL)
{
@@ -1204,6 +1189,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 +1226,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 +1379,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 +1725,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))
@@ -1818,7 +1827,7 @@ static int iscsiCommand(PISCSIIMAGE pImage, PSCSIREQ pRequest)
aReqBHS[5] = RT_H2N_U32(cbData);
aReqBHS[6] = RT_H2N_U32(pImage->CmdSN);
aReqBHS[7] = RT_H2N_U32(pImage->ExpStatSN);
- memcpy(aReqBHS + 8, pRequest->pvCDB, pRequest->cbCDB);
+ memcpy(aReqBHS + 8, pRequest->abCDB, pRequest->cbCDB);
pImage->CmdSN++;
aISCSIReq[cnISCSIReq].pcvSeg = aReqBHS;
@@ -1877,7 +1886,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;
@@ -1910,13 +1919,13 @@ static int iscsiCommand(PISCSIIMAGE pImage, PSCSIREQ pRequest)
}
/* Truncate sense data if it doesn't fit into the buffer. */
pRequest->cbSense = RT_MIN(cbStat, pRequest->cbSense);
- memcpy(pRequest->pvSense,
+ memcpy(pRequest->abSense,
((const char *)aISCSIRes[1].pvSeg) + 2,
RT_MIN(aISCSIRes[1].cbSeg - 2, pRequest->cbSense));
if ( cnISCSIRes > 2 && aISCSIRes[2].cbSeg
&& (ssize_t)pRequest->cbSense - aISCSIRes[1].cbSeg + 2 > 0)
{
- memcpy((char *)pRequest->pvSense + aISCSIRes[1].cbSeg - 2,
+ memcpy((char *)pRequest->abSense + aISCSIRes[1].cbSeg - 2,
aISCSIRes[2].pvSeg,
pRequest->cbSense - aISCSIRes[1].cbSeg + 2);
}
@@ -2056,8 +2065,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 +2089,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
@@ -2568,6 +2581,8 @@ static int iscsiValidatePDU(PISCSIRES paRes, uint32_t cnRes)
&& (hw0 & ( ISCSI_BI_READ_RESIDUAL_OVFL_BIT | ISCSI_BI_READ_RESIDUAL_UNFL_BIT
| ISCSI_RESIDUAL_OVFL_BIT))))
return VERR_PARSE_ERROR;
+ else
+ LogFlowFunc(("good SCSI response, first word %#08x\n", RT_N2H_U32(pcrgResBHS[0])));
break;
case ISCSIOP_LOGIN_RES:
/* Login responses must not contain contradicting transit and continue bits. */
@@ -2667,10 +2682,10 @@ static int iscsiPDUTxPrepare(PISCSIIMAGE pImage, PISCSICMD pIScsiCmd)
paReqBHS[2] = RT_H2N_U32(pImage->LUN >> 32);
paReqBHS[3] = RT_H2N_U32(pImage->LUN & 0xffffffff);
paReqBHS[4] = pIScsiCmd->Itt;
- paReqBHS[5] = RT_H2N_U32(cbData);
+ paReqBHS[5] = RT_H2N_U32((uint32_t)cbData); Assert((uint32_t)cbData == cbData);
paReqBHS[6] = RT_H2N_U32(pImage->CmdSN);
paReqBHS[7] = RT_H2N_U32(pImage->ExpStatSN);
- memcpy(paReqBHS + 8, pScsiReq->pvCDB, pScsiReq->cbCDB);
+ memcpy(paReqBHS + 8, pScsiReq->abCDB, pScsiReq->cbCDB);
pIScsiPDU->CmdSN = pImage->CmdSN;
pImage->CmdSN++;
@@ -2783,7 +2798,7 @@ static int iscsiRecvPDUUpdateRequest(PISCSIIMAGE pImage, PISCSIRES paRes, uint32
{
/* Truncate sense data if it doesn't fit into the buffer. */
pScsiReq->cbSense = RT_MIN(cbStat, pScsiReq->cbSense);
- memcpy(pScsiReq->pvSense, (uint8_t *)pvSense + 2,
+ memcpy(pScsiReq->abSense, (uint8_t *)pvSense + 2,
RT_MIN(paRes[0].cbSeg - ISCSI_BHS_SIZE - 2, pScsiReq->cbSense));
}
}
@@ -3613,25 +3628,24 @@ static void iscsiCommandAsyncComplete(PISCSIIMAGE pImage, int rcReq, void *pvUse
{
bool fComplete = true;
size_t cbTransfered = 0;
- PSCSIREQASYNC pReqAsync = (PSCSIREQASYNC)pvUser;
- PSCSIREQ pScsiReq = pReqAsync->pScsiReq;
+ PSCSIREQ pScsiReq = (PSCSIREQ)pvUser;
if ( RT_SUCCESS(rcReq)
&& pScsiReq->cbSense > 0)
{
/* Try again if possible. */
- if (pReqAsync->cSenseRetries > 0)
+ if (pScsiReq->cSenseRetries > 0)
{
- pReqAsync->cSenseRetries--;
- pScsiReq->cbSense = sizeof(pReqAsync->abSense);
- int rc = iscsiCommandAsync(pImage, pScsiReq, iscsiCommandAsyncComplete, pReqAsync);
+ pScsiReq->cSenseRetries--;
+ pScsiReq->cbSense = sizeof(pScsiReq->abSense);
+ int rc = iscsiCommandAsync(pImage, pScsiReq, iscsiCommandAsyncComplete, pScsiReq);
if (RT_SUCCESS(rc))
fComplete = false;
else
- rcReq = pReqAsync->rcSense;
+ rcReq = pScsiReq->rcSense;
}
else
- rcReq = pReqAsync->rcSense;
+ rcReq = pScsiReq->rcSense;
}
if (fComplete)
@@ -3645,11 +3659,10 @@ static void iscsiCommandAsyncComplete(PISCSIIMAGE pImage, int rcReq, void *pvUse
/* Continue I/O context. */
pImage->pIfIo->pfnIoCtxCompleted(pImage->pIfIo->Core.pvUser,
- pReqAsync->pIoCtx, rcReq,
+ pScsiReq->pIoCtx, rcReq,
cbTransfered);
RTMemFree(pScsiReq);
- RTMemFree(pReqAsync);
}
}
@@ -4056,43 +4069,39 @@ static int iscsiOpenImage(PISCSIIMAGE pImage, unsigned uOpenFlags)
SCSIREQ sr;
RTSGSEG DataSeg;
- uint8_t sense[96];
uint8_t data8[8];
uint8_t data12[12];
/*
* Inquire available LUNs - purely dummy request.
*/
- uint8_t CDB_rlun[12];
uint8_t rlundata[16];
- CDB_rlun[0] = SCSI_REPORT_LUNS;
- CDB_rlun[1] = 0; /* reserved */
- CDB_rlun[2] = 0; /* reserved */
- CDB_rlun[3] = 0; /* reserved */
- CDB_rlun[4] = 0; /* reserved */
- CDB_rlun[5] = 0; /* reserved */
- CDB_rlun[6] = sizeof(rlundata) >> 24;
- CDB_rlun[7] = (sizeof(rlundata) >> 16) & 0xff;
- CDB_rlun[8] = (sizeof(rlundata) >> 8) & 0xff;
- CDB_rlun[9] = sizeof(rlundata) & 0xff;
- CDB_rlun[10] = 0; /* reserved */
- CDB_rlun[11] = 0; /* control */
+ RT_ZERO(sr.abCDB);
+ sr.abCDB[0] = SCSI_REPORT_LUNS;
+ sr.abCDB[1] = 0; /* reserved */
+ sr.abCDB[2] = 0; /* reserved */
+ sr.abCDB[3] = 0; /* reserved */
+ sr.abCDB[4] = 0; /* reserved */
+ sr.abCDB[5] = 0; /* reserved */
+ sr.abCDB[6] = sizeof(rlundata) >> 24;
+ sr.abCDB[7] = (sizeof(rlundata) >> 16) & 0xff;
+ sr.abCDB[8] = (sizeof(rlundata) >> 8) & 0xff;
+ sr.abCDB[9] = sizeof(rlundata) & 0xff;
+ sr.abCDB[10] = 0; /* reserved */
+ sr.abCDB[11] = 0; /* control */
DataSeg.pvSeg = rlundata;
DataSeg.cbSeg = sizeof(rlundata);
- sr.enmXfer = SCSIXFER_FROM_TARGET;
- sr.cbCDB = sizeof(CDB_rlun);
- sr.pvCDB = CDB_rlun;
+ sr.enmXfer = SCSIXFER_FROM_TARGET;
+ sr.cbCDB = 12;
sr.cbI2TData = 0;
sr.paI2TSegs = NULL;
sr.cI2TSegs = 0;
sr.cbT2IData = DataSeg.cbSeg;
sr.paT2ISegs = &DataSeg;
sr.cT2ISegs = 1;
- sr.cbSense = sizeof(sense);
- sr.pvSense = sense;
-
+ sr.cbSense = sizeof(sr.abSense);
rc = iscsiCommandSync(pImage, &sr, false, VERR_INVALID_STATE);
if (RT_FAILURE(rc))
{
@@ -4103,29 +4112,26 @@ static int iscsiOpenImage(PISCSIIMAGE pImage, unsigned uOpenFlags)
/*
* Inquire device characteristics - no tapes, scanners etc., please.
*/
- uint8_t CDB_inq[6];
- CDB_inq[0] = SCSI_INQUIRY;
- CDB_inq[1] = 0; /* reserved */
- CDB_inq[2] = 0; /* reserved */
- CDB_inq[3] = 0; /* reserved */
- CDB_inq[4] = sizeof(data8);
- CDB_inq[5] = 0; /* control */
+ RT_ZERO(sr.abCDB);
+ sr.abCDB[0] = SCSI_INQUIRY;
+ sr.abCDB[1] = 0; /* reserved */
+ sr.abCDB[2] = 0; /* reserved */
+ sr.abCDB[3] = 0; /* reserved */
+ sr.abCDB[4] = sizeof(data8);
+ sr.abCDB[5] = 0; /* control */
DataSeg.pvSeg = data8;
DataSeg.cbSeg = sizeof(data8);
- sr.enmXfer = SCSIXFER_FROM_TARGET;
- sr.cbCDB = sizeof(CDB_inq);
- sr.pvCDB = CDB_inq;
+ sr.enmXfer = SCSIXFER_FROM_TARGET;
+ sr.cbCDB = 6;
sr.cbI2TData = 0;
sr.paI2TSegs = NULL;
sr.cI2TSegs = 0;
sr.cbT2IData = DataSeg.cbSeg;
sr.paT2ISegs = &DataSeg;
sr.cT2ISegs = 1;
- sr.cbSense = sizeof(sense);
- sr.pvSense = sense;
-
+ sr.cbSense = sizeof(sr.abSense);
rc = iscsiCommandSync(pImage, &sr, true /* fRetry */, VERR_INVALID_STATE);
if (RT_SUCCESS(rc))
{
@@ -4162,31 +4168,27 @@ static int iscsiOpenImage(PISCSIIMAGE pImage, unsigned uOpenFlags)
* Query write disable bit in the device specific parameter entry in the
* mode parameter header. Refuse read/write opening of read only disks.
*/
-
- uint8_t CDB_ms[6];
uint8_t data4[4];
- CDB_ms[0] = SCSI_MODE_SENSE_6;
- CDB_ms[1] = 0; /* dbd=0/reserved */
- CDB_ms[2] = 0x3f; /* pc=0/page code=0x3f, ask for all pages */
- CDB_ms[3] = 0; /* subpage code=0, return everything in page_0 format */
- CDB_ms[4] = sizeof(data4); /* allocation length=4 */
- CDB_ms[5] = 0; /* control */
+ RT_ZERO(sr.abCDB);
+ sr.abCDB[0] = SCSI_MODE_SENSE_6;
+ sr.abCDB[1] = 0; /* dbd=0/reserved */
+ sr.abCDB[2] = 0x3f; /* pc=0/page code=0x3f, ask for all pages */
+ sr.abCDB[3] = 0; /* subpage code=0, return everything in page_0 format */
+ sr.abCDB[4] = sizeof(data4); /* allocation length=4 */
+ sr.abCDB[5] = 0; /* control */
DataSeg.pvSeg = data4;
DataSeg.cbSeg = sizeof(data4);
- sr.enmXfer = SCSIXFER_FROM_TARGET;
- sr.cbCDB = sizeof(CDB_ms);
- sr.pvCDB = CDB_ms;
+ sr.enmXfer = SCSIXFER_FROM_TARGET;
+ sr.cbCDB = 6;
sr.cbI2TData = 0;
sr.paI2TSegs = NULL;
sr.cI2TSegs = 0;
sr.cbT2IData = DataSeg.cbSeg;
sr.paT2ISegs = &DataSeg;
sr.cT2ISegs = 1;
- sr.cbSense = sizeof(sense);
- sr.pvSense = sense;
-
+ sr.cbSense = sizeof(sr.abSense);
rc = iscsiCommandSync(pImage, &sr, true /* fRetry */, VERR_INVALID_STATE);
if (RT_SUCCESS(rc))
{
@@ -4205,90 +4207,165 @@ static int iscsiOpenImage(PISCSIIMAGE pImage, unsigned uOpenFlags)
/*
* Determine sector size and capacity of the volume immediately.
*/
- uint8_t CDB_cap[16];
-
RT_ZERO(data12);
- RT_ZERO(CDB_cap);
- CDB_cap[0] = SCSI_SERVICE_ACTION_IN_16;
- CDB_cap[1] = SCSI_SVC_ACTION_IN_READ_CAPACITY_16; /* subcommand */
- CDB_cap[10+3] = sizeof(data12); /* allocation length (dword) */
+ RT_ZERO(sr.abCDB);
+ sr.abCDB[0] = SCSI_SERVICE_ACTION_IN_16;
+ sr.abCDB[1] = SCSI_SVC_ACTION_IN_READ_CAPACITY_16; /* subcommand */
+ sr.abCDB[10+3] = sizeof(data12); /* allocation length (dword) */
DataSeg.pvSeg = data12;
DataSeg.cbSeg = sizeof(data12);
- sr.enmXfer = SCSIXFER_FROM_TARGET;
- sr.cbCDB = sizeof(CDB_cap);
- sr.pvCDB = CDB_cap;
+ sr.enmXfer = SCSIXFER_FROM_TARGET;
+ sr.cbCDB = 16;
sr.cbI2TData = 0;
sr.paI2TSegs = NULL;
sr.cI2TSegs = 0;
sr.cbT2IData = DataSeg.cbSeg;
sr.paT2ISegs = &DataSeg;
sr.cT2ISegs = 1;
- sr.cbSense = sizeof(sense);
- sr.pvSense = sense;
+ sr.cbSense = sizeof(sr.abSense);
rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
- if ( RT_SUCCESS(rc)
- && sr.status == SCSI_STATUS_OK)
+ if (RT_SUCCESS(rc))
{
- pImage->cVolume = RT_BE2H_U64(*(uint64_t *)&data12[0]);
- pImage->cVolume++;
- pImage->cbSector = RT_BE2H_U32(*(uint32_t *)&data12[8]);
- pImage->cbSize = pImage->cVolume * pImage->cbSector;
- if (pImage->cVolume == 0 || pImage->cbSector != 512 || pImage->cbSize < pImage->cVolume)
+ bool fEnd = false;
+ uint8_t cMaxRetries = 10;
+ do
{
- rc = vdIfError(pImage->pIfError, VERR_VD_ISCSI_INVALID_TYPE,
- RT_SRC_POS, N_("iSCSI: target address %s, target name %s, SCSI LUN %lld reports media sector count=%llu sector size=%u"),
- pImage->pszTargetAddress, pImage->pszTargetName,
- pImage->LUN, pImage->cVolume, pImage->cbSector);
- }
+ switch (sr.status)
+ {
+ case SCSI_STATUS_OK:
+ {
+ pImage->cVolume = RT_BE2H_U64(*(uint64_t *)&data12[0]);
+ pImage->cVolume++;
+ pImage->cbSector = RT_BE2H_U32(*(uint32_t *)&data12[8]);
+ pImage->cbSize = pImage->cVolume * pImage->cbSector;
+ if (pImage->cVolume == 0 || pImage->cbSize < pImage->cVolume)
+ {
+ rc = vdIfError(pImage->pIfError, VERR_VD_ISCSI_INVALID_TYPE,
+ RT_SRC_POS, N_("iSCSI: target address %s, target name %s, SCSI LUN %lld reports media sector count=%llu sector size=%u"),
+ pImage->pszTargetAddress, pImage->pszTargetName,
+ pImage->LUN, pImage->cVolume, pImage->cbSector);
+ }
+ fEnd = true;
+ break;
+ }
+ case SCSI_STATUS_CHECK_CONDITION:
+ {
+ if((sr.abSense[2] & 0x0f) == SCSI_SENSE_UNIT_ATTENTION)
+ {
+ if( sr.abSense[12] == SCSI_ASC_POWER_ON_RESET_BUS_DEVICE_RESET_OCCURRED
+ && sr.abSense[13] == SCSI_ASCQ_POWER_ON_RESET_BUS_DEVICE_RESET_OCCURRED)
+ {
+/** @todo for future: prepare and send command "REQUEST SENSE" which will
+return the status of target and will clear any unit attention condition that it reports */
+ rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
+ if (RT_FAILURE(rc))
+ fEnd = true;
+ cMaxRetries--;
+ break;
+
+ }
+ }
+ break;
+ }
+ default:
+ {
+ rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
+ if (RT_FAILURE(rc))
+ fEnd = true;
+ cMaxRetries--;
+ break;
+ }
+ }
+ if (!cMaxRetries)
+ fEnd = true;
+ } while(!fEnd);
}
else
{
- uint8_t CDB_capfb[10];
-
RT_ZERO(data8);
- CDB_capfb[0] = SCSI_READ_CAPACITY;
- CDB_capfb[1] = 0; /* reserved */
- CDB_capfb[2] = 0; /* reserved */
- CDB_capfb[3] = 0; /* reserved */
- CDB_capfb[4] = 0; /* reserved */
- CDB_capfb[5] = 0; /* reserved */
- CDB_capfb[6] = 0; /* reserved */
- CDB_capfb[7] = 0; /* reserved */
- CDB_capfb[8] = 0; /* reserved */
- CDB_capfb[9] = 0; /* control */
+ sr.abCDB[0] = SCSI_READ_CAPACITY;
+ sr.abCDB[1] = 0; /* reserved */
+ sr.abCDB[2] = 0; /* reserved */
+ sr.abCDB[3] = 0; /* reserved */
+ sr.abCDB[4] = 0; /* reserved */
+ sr.abCDB[5] = 0; /* reserved */
+ sr.abCDB[6] = 0; /* reserved */
+ sr.abCDB[7] = 0; /* reserved */
+ sr.abCDB[8] = 0; /* reserved */
+ sr.abCDB[9] = 0; /* control */
DataSeg.pvSeg = data8;
DataSeg.cbSeg = sizeof(data8);
- sr.enmXfer = SCSIXFER_FROM_TARGET;
- sr.cbCDB = sizeof(CDB_capfb);
- sr.pvCDB = CDB_capfb;
+ sr.enmXfer = SCSIXFER_FROM_TARGET;
+ sr.cbCDB = 10;
sr.cbI2TData = 0;
sr.paI2TSegs = NULL;
sr.cI2TSegs = 0;
sr.cbT2IData = DataSeg.cbSeg;
sr.paT2ISegs = &DataSeg;
sr.cT2ISegs = 1;
- sr.cbSense = sizeof(sense);
- sr.pvSense = sense;
-
+ sr.cbSense = sizeof(sr.abSense);
rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
if (RT_SUCCESS(rc))
{
- pImage->cVolume = (data8[0] << 24) | (data8[1] << 16) | (data8[2] << 8) | data8[3];
- pImage->cVolume++;
- pImage->cbSector = (data8[4] << 24) | (data8[5] << 16) | (data8[6] << 8) | data8[7];
- pImage->cbSize = pImage->cVolume * pImage->cbSector;
- if (pImage->cVolume == 0 || pImage->cbSector != 512)
+ bool fEnd = false;
+ uint8_t cMaxRetries = 10;
+ do
{
- rc = vdIfError(pImage->pIfError, VERR_VD_ISCSI_INVALID_TYPE,
- RT_SRC_POS, N_("iSCSI: fallback capacity detectio for target address %s, target name %s, SCSI LUN %lld reports media sector count=%llu sector size=%u"),
- pImage->pszTargetAddress, pImage->pszTargetName,
- pImage->LUN, pImage->cVolume, pImage->cbSector);
- }
+ switch (sr.status)
+ {
+ case SCSI_STATUS_OK:
+ {
+ pImage->cVolume = (data8[0] << 24) | (data8[1] << 16) | (data8[2] << 8) | data8[3];
+ pImage->cVolume++;
+ pImage->cbSector = (data8[4] << 24) | (data8[5] << 16) | (data8[6] << 8) | data8[7];
+ pImage->cbSize = pImage->cVolume * pImage->cbSector;
+ if (pImage->cVolume == 0)
+ {
+ rc = vdIfError(pImage->pIfError, VERR_VD_ISCSI_INVALID_TYPE,
+ RT_SRC_POS, N_("iSCSI: fallback capacity detection for target address %s, target name %s, SCSI LUN %lld reports media sector count=%llu sector size=%u"),
+ pImage->pszTargetAddress, pImage->pszTargetName,
+ pImage->LUN, pImage->cVolume, pImage->cbSector);
+ }
+
+ fEnd = true;
+ break;
+ }
+ case SCSI_STATUS_CHECK_CONDITION:
+ {
+ if((sr.abSense[2] & 0x0f) == SCSI_SENSE_UNIT_ATTENTION)
+ {
+ if( sr.abSense[12] == SCSI_ASC_POWER_ON_RESET_BUS_DEVICE_RESET_OCCURRED
+ && sr.abSense[13] == SCSI_ASCQ_POWER_ON_RESET_BUS_DEVICE_RESET_OCCURRED)
+ {
+ /** @todo for future: prepare and send command "REQUEST SENSE" which will
+ return the status of target and will clear any unit attention condition that it reports */
+ rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
+ if (RT_FAILURE(rc))
+ fEnd = true;
+ cMaxRetries--;
+ break;
+
+ }
+ }
+ break;
+ }
+ default:
+ {
+ rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
+ if (RT_FAILURE(rc))
+ fEnd = true;
+ cMaxRetries--;
+ break;
+ }
+ }
+ if (!cMaxRetries)
+ fEnd = true;
+ } while(!fEnd);
}
else
{
@@ -4305,30 +4382,27 @@ static int iscsiOpenImage(PISCSIIMAGE pImage, unsigned uOpenFlags)
* to do it again.
*/
uint8_t aCachingModePage[32];
- uint8_t aCDBModeSense6[6];
memset(aCachingModePage, '\0', sizeof(aCachingModePage));
- aCDBModeSense6[0] = SCSI_MODE_SENSE_6;
- aCDBModeSense6[1] = 0;
- aCDBModeSense6[2] = (0x00 << 6) | (0x08 & 0x3f); /* Current values and caching mode page */
- aCDBModeSense6[3] = 0; /* Sub page code. */
- aCDBModeSense6[4] = sizeof(aCachingModePage) & 0xff;
- aCDBModeSense6[5] = 0;
+ sr.abCDB[0] = SCSI_MODE_SENSE_6;
+ sr.abCDB[1] = 0;
+ sr.abCDB[2] = (0x00 << 6) | (0x08 & 0x3f); /* Current values and caching mode page */
+ sr.abCDB[3] = 0; /* Sub page code. */
+ sr.abCDB[4] = sizeof(aCachingModePage) & 0xff;
+ sr.abCDB[5] = 0;
DataSeg.pvSeg = aCachingModePage;
DataSeg.cbSeg = sizeof(aCachingModePage);
- sr.enmXfer = SCSIXFER_FROM_TARGET;
- sr.cbCDB = sizeof(aCDBModeSense6);
- sr.pvCDB = aCDBModeSense6;
+ sr.enmXfer = SCSIXFER_FROM_TARGET;
+ sr.cbCDB = 6;
sr.cbI2TData = 0;
sr.paI2TSegs = NULL;
sr.cI2TSegs = 0;
sr.cbT2IData = DataSeg.cbSeg;
sr.paT2ISegs = &DataSeg;
sr.cT2ISegs = 1;
- sr.cbSense = sizeof(sense);
- sr.pvSense = sense;
+ sr.cbSense = sizeof(sr.abSense);
rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
if ( RT_SUCCESS(rc)
&& (sr.status == SCSI_STATUS_OK)
@@ -4352,29 +4426,26 @@ static int iscsiOpenImage(PISCSIIMAGE pImage, unsigned uOpenFlags)
ASMBitSet(&aCachingModePage[Offset + 2], 2);
ASMBitClear(&aCachingModePage[Offset + 2], 0);
- uint8_t aCDBCaching[6];
- aCDBCaching[0] = SCSI_MODE_SELECT_6;
- aCDBCaching[1] = 0; /* Don't write the page into NV RAM. */
- aCDBCaching[2] = 0;
- aCDBCaching[3] = 0;
- aCDBCaching[4] = sizeof(aCachingModePage) & 0xff;
- aCDBCaching[5] = 0;
+ sr.abCDB[0] = SCSI_MODE_SELECT_6;
+ sr.abCDB[1] = 0; /* Don't write the page into NV RAM. */
+ sr.abCDB[2] = 0;
+ sr.abCDB[3] = 0;
+ sr.abCDB[4] = sizeof(aCachingModePage) & 0xff;
+ sr.abCDB[5] = 0;
DataSeg.pvSeg = aCachingModePage;
DataSeg.cbSeg = sizeof(aCachingModePage);
- sr.enmXfer = SCSIXFER_TO_TARGET;
- sr.cbCDB = sizeof(aCDBCaching);
- sr.pvCDB = aCDBCaching;
+ sr.enmXfer = SCSIXFER_TO_TARGET;
+ sr.cbCDB = 6;
sr.cbI2TData = DataSeg.cbSeg;
sr.paI2TSegs = &DataSeg;
sr.cI2TSegs = 1;
sr.cbT2IData = 0;
sr.paT2ISegs = NULL;
sr.cT2ISegs = 0;
- sr.cbSense = sizeof(sense);
- sr.pvSense = sense;
- sr.status = 0;
+ sr.cbSense = sizeof(sr.abSense);
+ sr.status = 0;
rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
if ( RT_SUCCESS(rc)
&& (sr.status == SCSI_STATUS_OK))
@@ -4386,7 +4457,7 @@ static int iscsiOpenImage(PISCSIIMAGE pImage, unsigned uOpenFlags)
/* Log failures but continue. */
LogRel(("iSCSI: Could not enable read and write cache of target %s, rc=%Rrc status=%#x\n",
pImage->pszTargetName, rc, sr.status));
- LogRel(("iSCSI: Sense:\n%.*Rhxd\n", sr.cbSense, sense));
+ LogRel(("iSCSI: Sense:\n%.*Rhxd\n", sr.cbSense, sr.abSense));
rc = VINF_SUCCESS;
}
}
@@ -4394,8 +4465,8 @@ static int iscsiOpenImage(PISCSIIMAGE pImage, unsigned uOpenFlags)
else
{
/* Log errors but continue. */
- LogRel(("iSCSI: Could not check write cache of target %s, rc=%Rrc, got mode page %#x\n", pImage->pszTargetName, rc,aCachingModePage[0] & 0x3f));
- LogRel(("iSCSI: Sense:\n%.*Rhxd\n", sr.cbSense, sense));
+ LogRel(("iSCSI: Could not check write cache of target %s, rc=%Rrc, got mode page %#x\n", pImage->pszTargetName, rc, aCachingModePage[0] & 0x3f));
+ LogRel(("iSCSI: Sense:\n%.*Rhxd\n", sr.cbSense, sr.abSense));
rc = VINF_SUCCESS;
}
@@ -4515,251 +4586,312 @@ static int iscsiClose(void *pBackendData, bool fDelete)
}
/** @copydoc VBOXHDDBACKEND::pfnRead */
-static int iscsiRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
- size_t cbToRead, size_t *pcbActuallyRead)
+static int iscsiRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
+ PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
{
- /** @todo reinstate logging of the target everywhere - dropped temporarily */
- LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
- uint64_t lba;
- uint16_t tls;
- int rc;
-
- Assert(pImage);
- Assert(uOffset % 512 == 0);
- Assert(cbToRead % 512 == 0);
+ int rc = VINF_SUCCESS;
- Assert(pImage->cbSector);
- AssertPtr(pvBuf);
+ LogFlowFunc(("pBackendData=%p uOffset=%#llx pIoCtx=%#p cbToRead=%u pcbActuallyRead=%p\n",
+ pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
if ( uOffset + cbToRead > pImage->cbSize
|| cbToRead == 0)
- {
- rc = VERR_INVALID_PARAMETER;
- goto out;
- }
+ return VERR_INVALID_PARAMETER;
/*
* Clip read size to a value which is supported by the target.
*/
cbToRead = RT_MIN(cbToRead, pImage->cbRecvDataLength);
- lba = uOffset / pImage->cbSector;
- tls = (uint16_t)(cbToRead / pImage->cbSector);
- SCSIREQ sr;
- RTSGSEG T2ISeg;
- size_t cbCDB;
- uint8_t abCDB[16];
- uint8_t sense[96];
+ unsigned cT2ISegs = 0;
+ size_t cbSegs = 0;
- if (pImage->cVolume < _4G)
- {
- cbCDB = 10;
- abCDB[0] = SCSI_READ_10;
- abCDB[1] = 0; /* reserved */
- abCDB[2] = (lba >> 24) & 0xff;
- abCDB[3] = (lba >> 16) & 0xff;
- abCDB[4] = (lba >> 8) & 0xff;
- abCDB[5] = lba & 0xff;
- abCDB[6] = 0; /* reserved */
- abCDB[7] = (tls >> 8) & 0xff;
- abCDB[8] = tls & 0xff;
- abCDB[9] = 0; /* control */
- }
- else
+ /* Get the number of segments. */
+ cbSegs = pImage->pIfIo->pfnIoCtxSegArrayCreate(pImage->pIfIo->Core.pvUser, pIoCtx,
+ NULL, &cT2ISegs, cbToRead);
+ Assert(cbSegs == cbToRead);
+
+ PSCSIREQ pReq = (PSCSIREQ)RTMemAllocZ(RT_OFFSETOF(SCSIREQ, aSegs[cT2ISegs]));
+ if (RT_LIKELY(pReq))
{
- cbCDB = 16;
- abCDB[0] = SCSI_READ_16;
- abCDB[1] = 0; /* reserved */
- abCDB[2] = (lba >> 56) & 0xff;
- abCDB[3] = (lba >> 48) & 0xff;
- abCDB[4] = (lba >> 40) & 0xff;
- abCDB[5] = (lba >> 32) & 0xff;
- abCDB[6] = (lba >> 24) & 0xff;
- abCDB[7] = (lba >> 16) & 0xff;
- abCDB[8] = (lba >> 8) & 0xff;
- abCDB[9] = lba & 0xff;
- abCDB[10] = 0; /* tls unused */
- abCDB[11] = 0; /* tls unused */
- abCDB[12] = (tls >> 8) & 0xff;
- abCDB[13] = tls & 0xff;
- abCDB[14] = 0; /* reserved */
- abCDB[15] = 0; /* reserved */
- }
+ uint64_t lba;
+ uint16_t tls;
+ uint8_t *pbCDB = &pReq->abCDB[0];
+ size_t cbCDB;
- T2ISeg.pvSeg = pvBuf;
- T2ISeg.cbSeg = cbToRead;
+ lba = uOffset / pImage->cbSector;
+ tls = (uint16_t)(cbToRead / pImage->cbSector);
- sr.enmXfer = SCSIXFER_FROM_TARGET;
- sr.cbCDB = cbCDB;
- sr.pvCDB = abCDB;
- sr.cbI2TData = 0;
- sr.paI2TSegs = NULL;
- sr.cI2TSegs = 0;
- sr.cbT2IData = cbToRead;
- sr.paT2ISegs = &T2ISeg;
- sr.cT2ISegs = 1;
- sr.cbSense = sizeof(sense);
- sr.pvSense = sense;
+ cbSegs = pImage->pIfIo->pfnIoCtxSegArrayCreate(pImage->pIfIo->Core.pvUser, pIoCtx,
+ &pReq->aSegs[0],
+ &cT2ISegs, cbToRead);
+ Assert(cbSegs == cbToRead);
- rc = iscsiCommandSync(pImage, &sr, true, VERR_READ_ERROR);
- if (RT_FAILURE(rc))
- {
- LogFlow(("iscsiCommandSync(%s, %#llx) -> %Rrc\n", pImage->pszTargetName, uOffset, rc));
- *pcbActuallyRead = 0;
+ if (pImage->cVolume < _4G)
+ {
+ cbCDB = 10;
+ pbCDB[0] = SCSI_READ_10;
+ pbCDB[1] = 0; /* reserved */
+ pbCDB[2] = (lba >> 24) & 0xff;
+ pbCDB[3] = (lba >> 16) & 0xff;
+ pbCDB[4] = (lba >> 8) & 0xff;
+ pbCDB[5] = lba & 0xff;
+ pbCDB[6] = 0; /* reserved */
+ pbCDB[7] = (tls >> 8) & 0xff;
+ pbCDB[8] = tls & 0xff;
+ pbCDB[9] = 0; /* control */
+ }
+ else
+ {
+ cbCDB = 16;
+ pbCDB[0] = SCSI_READ_16;
+ pbCDB[1] = 0; /* reserved */
+ pbCDB[2] = (lba >> 56) & 0xff;
+ pbCDB[3] = (lba >> 48) & 0xff;
+ pbCDB[4] = (lba >> 40) & 0xff;
+ pbCDB[5] = (lba >> 32) & 0xff;
+ pbCDB[6] = (lba >> 24) & 0xff;
+ pbCDB[7] = (lba >> 16) & 0xff;
+ pbCDB[8] = (lba >> 8) & 0xff;
+ pbCDB[9] = lba & 0xff;
+ pbCDB[10] = 0; /* tls unused */
+ pbCDB[11] = 0; /* tls unused */
+ pbCDB[12] = (tls >> 8) & 0xff;
+ pbCDB[13] = tls & 0xff;
+ pbCDB[14] = 0; /* reserved */
+ pbCDB[15] = 0; /* reserved */
+ }
+
+ pReq->enmXfer = SCSIXFER_FROM_TARGET;
+ pReq->cbCDB = cbCDB;
+ pReq->cbI2TData = 0;
+ pReq->paI2TSegs = NULL;
+ pReq->cI2TSegs = 0;
+ pReq->cbT2IData = cbToRead;
+ pReq->paT2ISegs = &pReq->aSegs[pReq->cI2TSegs];
+ pReq->cT2ISegs = pReq->cT2ISegs;
+ pReq->cbSense = sizeof(pReq->abSense);
+ pReq->cT2ISegs = cT2ISegs;
+ pReq->pIoCtx = pIoCtx;
+ pReq->cSenseRetries = 10;
+ pReq->rcSense = VERR_READ_ERROR;
+
+ if (vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx))
+ {
+ rc = iscsiCommandSync(pImage, pReq, true, VERR_READ_ERROR);
+ if (RT_FAILURE(rc))
+ {
+ LogFlow(("iscsiCommandSync(%s, %#llx) -> %Rrc\n", pImage->pszTargetName, uOffset, rc));
+ *pcbActuallyRead = 0;
+ }
+ else
+ *pcbActuallyRead = pReq->cbT2IData;
+ }
+ else
+ {
+ rc = iscsiCommandAsync(pImage, pReq, iscsiCommandAsyncComplete, pReq);
+ if (RT_FAILURE(rc))
+ AssertMsgFailed(("iscsiCommandAsync(%s, %#llx) -> %Rrc\n", pImage->pszTargetName, uOffset, rc));
+ else
+ {
+ *pcbActuallyRead = cbToRead;
+ return VERR_VD_IOCTX_HALT; /* Halt the I/O context until further notification from the I/O thread. */
+ }
+ }
+
+ RTMemFree(pReq);
}
else
- *pcbActuallyRead = sr.cbT2IData;
+ rc = VERR_NO_MEMORY;
-out:
- LogFlowFunc(("returns %Rrc\n", rc));
+ LogFlowFunc(("returns rc=%Rrc\n", rc));
return rc;
}
/** @copydoc VBOXHDDBACKEND::pfnWrite */
-static int iscsiWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
- size_t cbToWrite, size_t *pcbWriteProcess,
- size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
+static int iscsiWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
+ PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
+ size_t *pcbPostRead, unsigned fWrite)
{
- LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
+ LogFlowFunc(("pBackendData=%p uOffset=%llu pIoCtx=%#p cbToWrite=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n",
+ pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite));
PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
- uint64_t lba;
- uint16_t tls;
- int rc;
+ int rc = VINF_SUCCESS;
- Assert(pImage);
+ AssertPtr(pImage);
Assert(uOffset % 512 == 0);
Assert(cbToWrite % 512 == 0);
- Assert(pImage->cbSector);
- Assert(pvBuf);
-
- if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
- {
- rc = VERR_VD_IMAGE_READ_ONLY;
- goto out;
- }
-
- *pcbPreRead = 0;
- *pcbPostRead = 0;
+ if (uOffset + cbToWrite > pImage->cbSize)
+ return VERR_INVALID_PARAMETER;
/*
- * Clip write size to a value which is supported by the target.
+ * Clip read size to a value which is supported by the target.
*/
cbToWrite = RT_MIN(cbToWrite, pImage->cbSendDataLength);
- lba = uOffset / pImage->cbSector;
- tls = (uint16_t)(cbToWrite / pImage->cbSector);
- SCSIREQ sr;
- RTSGSEG I2TSeg;
- size_t cbCDB;
- uint8_t abCDB[16];
- uint8_t sense[96];
+ unsigned cI2TSegs = 0;
+ size_t cbSegs = 0;
- if (pImage->cVolume < _4G)
- {
- cbCDB = 10;
- abCDB[0] = SCSI_WRITE_10;
- abCDB[1] = 0; /* reserved */
- abCDB[2] = (lba >> 24) & 0xff;
- abCDB[3] = (lba >> 16) & 0xff;
- abCDB[4] = (lba >> 8) & 0xff;
- abCDB[5] = lba & 0xff;
- abCDB[6] = 0; /* reserved */
- abCDB[7] = (tls >> 8) & 0xff;
- abCDB[8] = tls & 0xff;
- abCDB[9] = 0; /* control */
- }
- else
- {
- cbCDB = 16;
- abCDB[0] = SCSI_WRITE_16;
- abCDB[1] = 0; /* reserved */
- abCDB[2] = (lba >> 56) & 0xff;
- abCDB[3] = (lba >> 48) & 0xff;
- abCDB[4] = (lba >> 40) & 0xff;
- abCDB[5] = (lba >> 32) & 0xff;
- abCDB[6] = (lba >> 24) & 0xff;
- abCDB[7] = (lba >> 16) & 0xff;
- abCDB[8] = (lba >> 8) & 0xff;
- abCDB[9] = lba & 0xff;
- abCDB[10] = 0; /* tls unused */
- abCDB[11] = 0; /* tls unused */
- abCDB[12] = (tls >> 8) & 0xff;
- abCDB[13] = tls & 0xff;
- abCDB[14] = 0; /* reserved */
- abCDB[15] = 0; /* reserved */
- }
+ /* Get the number of segments. */
+ cbSegs = pImage->pIfIo->pfnIoCtxSegArrayCreate(pImage->pIfIo->Core.pvUser, pIoCtx,
+ NULL, &cI2TSegs, cbToWrite);
+ Assert(cbSegs == cbToWrite);
- I2TSeg.pvSeg = (void *)pvBuf;
- I2TSeg.cbSeg = cbToWrite;
-
- sr.enmXfer = SCSIXFER_TO_TARGET;
- sr.cbCDB = cbCDB;
- sr.pvCDB = abCDB;
- sr.cbI2TData = cbToWrite;
- sr.paI2TSegs = &I2TSeg;
- sr.cI2TSegs = 1;
- sr.cbT2IData = 0;
- sr.paT2ISegs = NULL;
- sr.cT2ISegs = 0;
- sr.cbSense = sizeof(sense);
- sr.pvSense = sense;
-
- rc = iscsiCommandSync(pImage, &sr, true, VERR_WRITE_ERROR);
- if (RT_FAILURE(rc))
+ PSCSIREQ pReq = (PSCSIREQ)RTMemAllocZ(RT_OFFSETOF(SCSIREQ, aSegs[cI2TSegs]));
+ if (RT_LIKELY(pReq))
{
- LogFlow(("iscsiCommandSync(%s, %#llx) -> %Rrc\n", pImage->pszTargetName, uOffset, rc));
- *pcbWriteProcess = 0;
+ uint64_t lba;
+ uint16_t tls;
+ uint8_t *pbCDB = &pReq->abCDB[0];
+ size_t cbCDB;
+
+ lba = uOffset / pImage->cbSector;
+ tls = (uint16_t)(cbToWrite / pImage->cbSector);
+
+ cbSegs = pImage->pIfIo->pfnIoCtxSegArrayCreate(pImage->pIfIo->Core.pvUser, pIoCtx,
+ &pReq->aSegs[0],
+ &cI2TSegs, cbToWrite);
+ Assert(cbSegs == cbToWrite);
+
+ if (pImage->cVolume < _4G)
+ {
+ cbCDB = 10;
+ pbCDB[0] = SCSI_WRITE_10;
+ pbCDB[1] = 0; /* reserved */
+ pbCDB[2] = (lba >> 24) & 0xff;
+ pbCDB[3] = (lba >> 16) & 0xff;
+ pbCDB[4] = (lba >> 8) & 0xff;
+ pbCDB[5] = lba & 0xff;
+ pbCDB[6] = 0; /* reserved */
+ pbCDB[7] = (tls >> 8) & 0xff;
+ pbCDB[8] = tls & 0xff;
+ pbCDB[9] = 0; /* control */
+ }
+ else
+ {
+ cbCDB = 16;
+ pbCDB[0] = SCSI_WRITE_16;
+ pbCDB[1] = 0; /* reserved */
+ pbCDB[2] = (lba >> 56) & 0xff;
+ pbCDB[3] = (lba >> 48) & 0xff;
+ pbCDB[4] = (lba >> 40) & 0xff;
+ pbCDB[5] = (lba >> 32) & 0xff;
+ pbCDB[6] = (lba >> 24) & 0xff;
+ pbCDB[7] = (lba >> 16) & 0xff;
+ pbCDB[8] = (lba >> 8) & 0xff;
+ pbCDB[9] = lba & 0xff;
+ pbCDB[10] = 0; /* tls unused */
+ pbCDB[11] = 0; /* tls unused */
+ pbCDB[12] = (tls >> 8) & 0xff;
+ pbCDB[13] = tls & 0xff;
+ pbCDB[14] = 0; /* reserved */
+ pbCDB[15] = 0; /* reserved */
+ }
+
+ pReq->enmXfer = SCSIXFER_TO_TARGET;
+ pReq->cbCDB = cbCDB;
+ pReq->cbI2TData = cbToWrite;
+ pReq->paI2TSegs = &pReq->aSegs[0];
+ pReq->cI2TSegs = cI2TSegs;
+ pReq->cbT2IData = 0;
+ pReq->paT2ISegs = NULL;
+ pReq->cT2ISegs = 0;
+ pReq->cbSense = sizeof(pReq->abSense);
+ pReq->pIoCtx = pIoCtx;
+ pReq->cSenseRetries = 10;
+ pReq->rcSense = VERR_WRITE_ERROR;
+
+ if (vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx))
+ {
+ rc = iscsiCommandSync(pImage, pReq, true, VERR_WRITE_ERROR);
+ if (RT_FAILURE(rc))
+ {
+ LogFlow(("iscsiCommandSync(%s, %#llx) -> %Rrc\n", pImage->pszTargetName, uOffset, rc));
+ *pcbWriteProcess = 0;
+ }
+ else
+ *pcbWriteProcess = cbToWrite;
+ }
+ else
+ {
+ rc = iscsiCommandAsync(pImage, pReq, iscsiCommandAsyncComplete, pReq);
+ if (RT_FAILURE(rc))
+ AssertMsgFailed(("iscsiCommandAsync(%s, %#llx) -> %Rrc\n", pImage->pszTargetName, uOffset, rc));
+ else
+ {
+ *pcbWriteProcess = cbToWrite;
+ return VERR_VD_IOCTX_HALT; /* Halt the I/O context until further notification from the I/O thread. */
+ }
+ }
+
+ RTMemFree(pReq);
}
else
- *pcbWriteProcess = cbToWrite;
+ rc = VERR_NO_MEMORY;
-out:
- LogFlowFunc(("returns %Rrc\n", rc));
+ LogFlowFunc(("returns rc=%Rrc\n", rc));
return rc;
}
/** @copydoc VBOXHDDBACKEND::pfnFlush */
-static int iscsiFlush(void *pBackendData)
+static int iscsiFlush(void *pBackendData, PVDIOCTX pIoCtx)
{
- LogFlowFunc(("pBackendData=%#p\n", pBackendData));
+ LogFlowFunc(("pBackendData=%p pIoCtx=%#p\n", pBackendData, pIoCtx));
PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
- int rc;
+ int rc = VINF_SUCCESS;
- Assert(pImage);
+ PSCSIREQ pReq = (PSCSIREQ)RTMemAllocZ(sizeof(SCSIREQ));
+ if (RT_LIKELY(pReq))
+ {
+ uint8_t *pbCDB = &pReq->abCDB[0];
+
+ pbCDB[0] = SCSI_SYNCHRONIZE_CACHE;
+ pbCDB[1] = 0; /* reserved */
+ pbCDB[2] = 0; /* reserved */
+ pbCDB[3] = 0; /* reserved */
+ pbCDB[4] = 0; /* reserved */
+ pbCDB[5] = 0; /* reserved */
+ pbCDB[6] = 0; /* reserved */
+ pbCDB[7] = 0; /* reserved */
+ pbCDB[8] = 0; /* reserved */
+ pbCDB[9] = 0; /* control */
+
+ pReq->enmXfer = SCSIXFER_NONE;
+ pReq->cbCDB = 10;
+ pReq->cbI2TData = 0;
+ pReq->paI2TSegs = NULL;
+ pReq->cI2TSegs = 0;
+ pReq->cbT2IData = 0;
+ pReq->paT2ISegs = NULL;
+ pReq->cT2ISegs = 0;
+ pReq->cbSense = sizeof(pReq->abSense);
+ pReq->pIoCtx = pIoCtx;
+ pReq->cSenseRetries = 0;
+ pReq->rcSense = VINF_SUCCESS;
+
+ if (vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx))
+ {
+ rc = iscsiCommandSync(pImage, pReq, false, VINF_SUCCESS);
+ if (RT_FAILURE(rc))
+ AssertMsgFailed(("iscsiCommand(%s) -> %Rrc\n", pImage->pszTargetName, rc));
+ }
+ else
+ {
+ rc = iscsiCommandAsync(pImage, pReq, iscsiCommandAsyncComplete, pReq);
+ if (RT_FAILURE(rc))
+ AssertMsgFailed(("iscsiCommand(%s) -> %Rrc\n", pImage->pszTargetName, rc));
+ else
+ return VERR_VD_IOCTX_HALT; /* Halt the I/O context until further notification from the I/O thread. */
+ }
- SCSIREQ sr;
- uint8_t abCDB[10];
- uint8_t sense[96];
-
- abCDB[0] = SCSI_SYNCHRONIZE_CACHE;
- abCDB[1] = 0; /* reserved */
- abCDB[2] = 0; /* LBA 0 */
- abCDB[3] = 0; /* LBA 0 */
- abCDB[4] = 0; /* LBA 0 */
- abCDB[5] = 0; /* LBA 0 */
- abCDB[6] = 0; /* reserved */
- abCDB[7] = 0; /* transfer everything to disk */
- abCDB[8] = 0; /* transfer everything to disk */
- abCDB[9] = 0; /* control */
-
- sr.enmXfer = SCSIXFER_NONE;
- sr.cbCDB = sizeof(abCDB);
- sr.pvCDB = abCDB;
- sr.cbI2TData = 0;
- sr.paI2TSegs = NULL;
- sr.cI2TSegs = 0;
- sr.cbT2IData = 0;
- sr.paT2ISegs = NULL;
- sr.cT2ISegs = 0;
- sr.cbSense = sizeof(sense);
- sr.pvSense = sense;
+ RTMemFree(pReq);
+ }
+ else
+ rc = VERR_NO_MEMORY;
- rc = iscsiCommandSync(pImage, &sr, false, VINF_SUCCESS);
- if (RT_FAILURE(rc))
- AssertMsgFailed(("iscsiCommand(%s) -> %Rrc\n", pImage->pszTargetName, rc));
- LogFlowFunc(("returns %Rrc\n", rc));
+ LogFlowFunc(("returns rc=%Rrc\n", rc));
return rc;
}
@@ -4775,6 +4907,20 @@ static unsigned iscsiGetVersion(void *pBackendData)
return 0;
}
+/** @copydoc VBOXHDDBACKEND::pfnGetSectorSize */
+static uint32_t iscsiGetSectorSize(void *pBackendData)
+{
+ LogFlowFunc(("pBackendData=%#p\n", pBackendData));
+ PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
+
+ Assert(pImage);
+
+ if (pImage)
+ return pImage->cbSector;
+ else
+ return 0;
+}
+
/** @copydoc VBOXHDDBACKEND::pfnGetSize */
static uint64_t iscsiGetSize(void *pBackendData)
{
@@ -4934,7 +5080,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;
@@ -5184,313 +5332,6 @@ static void iscsiDump(void *pBackendData)
}
}
-/** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
-static int iscsiAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
- PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
-{
- LogFlowFunc(("pBackendData=%p uOffset=%#llx pIoCtx=%#p cbToRead=%u pcbActuallyRead=%p\n",
- pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
- PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
- int rc = VINF_SUCCESS;
-
- if (uOffset + cbToRead > pImage->cbSize)
- return VERR_INVALID_PARAMETER;
-
- /*
- * Clip read size to a value which is supported by the target.
- */
- cbToRead = RT_MIN(cbToRead, pImage->cbRecvDataLength);
-
- unsigned cT2ISegs = 0;
- size_t cbSegs = 0;
-
- /* Get the number of segments. */
- cbSegs = pImage->pIfIo->pfnIoCtxSegArrayCreate(pImage->pIfIo->Core.pvUser, pIoCtx,
- NULL, &cT2ISegs, cbToRead);
- Assert(cbSegs == cbToRead);
-
- PSCSIREQASYNC pReqAsync = (PSCSIREQASYNC)RTMemAllocZ(RT_OFFSETOF(SCSIREQASYNC, aSegs[cT2ISegs]));
- if (RT_LIKELY(pReqAsync))
- {
- PSCSIREQ pReq = (PSCSIREQ)RTMemAllocZ(sizeof(SCSIREQ));
- if (pReq)
- {
- uint64_t lba;
- uint16_t tls;
- uint8_t *pbCDB = &pReqAsync->abCDB[0];
- size_t cbCDB;
-
- lba = uOffset / pImage->cbSector;
- tls = (uint16_t)(cbToRead / pImage->cbSector);
-
- cbSegs = pImage->pIfIo->pfnIoCtxSegArrayCreate(pImage->pIfIo->Core.pvUser, pIoCtx,
- &pReqAsync->aSegs[0],
- &cT2ISegs, cbToRead);
- Assert(cbSegs == cbToRead);
- pReqAsync->cT2ISegs = cT2ISegs;
- pReqAsync->pIoCtx = pIoCtx;
- pReqAsync->pScsiReq = pReq;
- pReqAsync->cSenseRetries = 10;
- pReqAsync->rcSense = VERR_READ_ERROR;
-
- if (pImage->cVolume < _4G)
- {
- cbCDB = 10;
- pbCDB[0] = SCSI_READ_10;
- pbCDB[1] = 0; /* reserved */
- pbCDB[2] = (lba >> 24) & 0xff;
- pbCDB[3] = (lba >> 16) & 0xff;
- pbCDB[4] = (lba >> 8) & 0xff;
- pbCDB[5] = lba & 0xff;
- pbCDB[6] = 0; /* reserved */
- pbCDB[7] = (tls >> 8) & 0xff;
- pbCDB[8] = tls & 0xff;
- pbCDB[9] = 0; /* control */
- }
- else
- {
- cbCDB = 16;
- pbCDB[0] = SCSI_READ_16;
- pbCDB[1] = 0; /* reserved */
- pbCDB[2] = (lba >> 56) & 0xff;
- pbCDB[3] = (lba >> 48) & 0xff;
- pbCDB[4] = (lba >> 40) & 0xff;
- pbCDB[5] = (lba >> 32) & 0xff;
- pbCDB[6] = (lba >> 24) & 0xff;
- pbCDB[7] = (lba >> 16) & 0xff;
- pbCDB[8] = (lba >> 8) & 0xff;
- pbCDB[9] = lba & 0xff;
- pbCDB[10] = 0; /* tls unused */
- pbCDB[11] = 0; /* tls unused */
- pbCDB[12] = (tls >> 8) & 0xff;
- pbCDB[13] = tls & 0xff;
- pbCDB[14] = 0; /* reserved */
- pbCDB[15] = 0; /* reserved */
- }
-
- pReq->enmXfer = SCSIXFER_FROM_TARGET;
- pReq->cbCDB = cbCDB;
- pReq->pvCDB = pReqAsync->abCDB;
- pReq->cbI2TData = 0;
- pReq->paI2TSegs = NULL;
- pReq->cI2TSegs = 0;
- pReq->cbT2IData = cbToRead;
- pReq->paT2ISegs = &pReqAsync->aSegs[pReqAsync->cI2TSegs];
- pReq->cT2ISegs = pReqAsync->cT2ISegs;
- pReq->cbSense = sizeof(pReqAsync->abSense);
- pReq->pvSense = pReqAsync->abSense;
-
- rc = iscsiCommandAsync(pImage, pReq, iscsiCommandAsyncComplete, pReqAsync);
- if (RT_FAILURE(rc))
- AssertMsgFailed(("iscsiCommand(%s, %#llx) -> %Rrc\n", pImage->pszTargetName, uOffset, rc));
- else
- {
- *pcbActuallyRead = cbToRead;
- return VERR_VD_IOCTX_HALT; /* Halt the I/O context until further notification from the I/O thread. */
- }
-
- RTMemFree(pReq);
- }
- else
- rc = VERR_NO_MEMORY;
-
- RTMemFree(pReqAsync);
- }
- else
- rc = VERR_NO_MEMORY;
-
- LogFlowFunc(("returns rc=%Rrc\n", rc));
- return rc;
-}
-
-/** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
-static int iscsiAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
- PVDIOCTX pIoCtx,
- size_t *pcbWriteProcess, size_t *pcbPreRead,
- size_t *pcbPostRead, unsigned fWrite)
-{
- LogFlowFunc(("pBackendData=%p uOffset=%llu pIoCtx=%#p cbToWrite=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n",
- pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite));
- PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
- int rc = VINF_SUCCESS;
-
- AssertPtr(pImage);
- Assert(uOffset % 512 == 0);
- Assert(cbToWrite % 512 == 0);
-
- if (uOffset + cbToWrite > pImage->cbSize)
- return VERR_INVALID_PARAMETER;
-
- /*
- * Clip read size to a value which is supported by the target.
- */
- cbToWrite = RT_MIN(cbToWrite, pImage->cbSendDataLength);
-
- unsigned cI2TSegs = 0;
- size_t cbSegs = 0;
-
- /* Get the number of segments. */
- cbSegs = pImage->pIfIo->pfnIoCtxSegArrayCreate(pImage->pIfIo->Core.pvUser, pIoCtx,
- NULL, &cI2TSegs, cbToWrite);
- Assert(cbSegs == cbToWrite);
-
- PSCSIREQASYNC pReqAsync = (PSCSIREQASYNC)RTMemAllocZ(RT_OFFSETOF(SCSIREQASYNC, aSegs[cI2TSegs]));
- if (RT_LIKELY(pReqAsync))
- {
- PSCSIREQ pReq = (PSCSIREQ)RTMemAllocZ(sizeof(SCSIREQ));
- if (pReq)
- {
- uint64_t lba;
- uint16_t tls;
- uint8_t *pbCDB = &pReqAsync->abCDB[0];
- size_t cbCDB;
-
- lba = uOffset / pImage->cbSector;
- tls = (uint16_t)(cbToWrite / pImage->cbSector);
-
- cbSegs = pImage->pIfIo->pfnIoCtxSegArrayCreate(pImage->pIfIo->Core.pvUser, pIoCtx,
- &pReqAsync->aSegs[0],
- &cI2TSegs, cbToWrite);
- Assert(cbSegs == cbToWrite);
- pReqAsync->cI2TSegs = cI2TSegs;
- pReqAsync->pIoCtx = pIoCtx;
- pReqAsync->pScsiReq = pReq;
- pReqAsync->cSenseRetries = 10;
- pReqAsync->rcSense = VERR_WRITE_ERROR;
-
- if (pImage->cVolume < _4G)
- {
- cbCDB = 10;
- pbCDB[0] = SCSI_WRITE_10;
- pbCDB[1] = 0; /* reserved */
- pbCDB[2] = (lba >> 24) & 0xff;
- pbCDB[3] = (lba >> 16) & 0xff;
- pbCDB[4] = (lba >> 8) & 0xff;
- pbCDB[5] = lba & 0xff;
- pbCDB[6] = 0; /* reserved */
- pbCDB[7] = (tls >> 8) & 0xff;
- pbCDB[8] = tls & 0xff;
- pbCDB[9] = 0; /* control */
- }
- else
- {
- cbCDB = 16;
- pbCDB[0] = SCSI_WRITE_16;
- pbCDB[1] = 0; /* reserved */
- pbCDB[2] = (lba >> 56) & 0xff;
- pbCDB[3] = (lba >> 48) & 0xff;
- pbCDB[4] = (lba >> 40) & 0xff;
- pbCDB[5] = (lba >> 32) & 0xff;
- pbCDB[6] = (lba >> 24) & 0xff;
- pbCDB[7] = (lba >> 16) & 0xff;
- pbCDB[8] = (lba >> 8) & 0xff;
- pbCDB[9] = lba & 0xff;
- pbCDB[10] = 0; /* tls unused */
- pbCDB[11] = 0; /* tls unused */
- pbCDB[12] = (tls >> 8) & 0xff;
- pbCDB[13] = tls & 0xff;
- pbCDB[14] = 0; /* reserved */
- pbCDB[15] = 0; /* reserved */
- }
-
- pReq->enmXfer = SCSIXFER_TO_TARGET;
- pReq->cbCDB = cbCDB;
- pReq->pvCDB = pReqAsync->abCDB;
- pReq->cbI2TData = cbToWrite;
- pReq->paI2TSegs = &pReqAsync->aSegs[0];
- pReq->cI2TSegs = pReqAsync->cI2TSegs;
- pReq->cbT2IData = 0;
- pReq->paT2ISegs = NULL;
- pReq->cT2ISegs = 0;
- pReq->cbSense = sizeof(pReqAsync->abSense);
- pReq->pvSense = pReqAsync->abSense;
-
- rc = iscsiCommandAsync(pImage, pReq, iscsiCommandAsyncComplete, pReqAsync);
- if (RT_FAILURE(rc))
- AssertMsgFailed(("iscsiCommand(%s, %#llx) -> %Rrc\n", pImage->pszTargetName, uOffset, rc));
- else
- {
- *pcbWriteProcess = cbToWrite;
- return VERR_VD_IOCTX_HALT; /* Halt the I/O context until further notification from the I/O thread. */
- }
-
- RTMemFree(pReq);
- }
- else
- rc = VERR_NO_MEMORY;
-
- RTMemFree(pReqAsync);
- }
- else
- rc = VERR_NO_MEMORY;
-
- LogFlowFunc(("returns rc=%Rrc\n", rc));
- return rc;
-}
-
-/** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
-static int iscsiAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
-{
- LogFlowFunc(("pBackendData=%p pIoCtx=%#p\n", pBackendData, pIoCtx));
- PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
- int rc = VINF_SUCCESS;
-
- PSCSIREQASYNC pReqAsync = (PSCSIREQASYNC)RTMemAllocZ(sizeof(SCSIREQASYNC));
- if (RT_LIKELY(pReqAsync))
- {
- PSCSIREQ pReq = (PSCSIREQ)RTMemAllocZ(sizeof(SCSIREQ));
- if (pReq)
- {
- uint8_t *pbCDB = &pReqAsync->abCDB[0];
-
- pReqAsync->pIoCtx = pIoCtx;
- pReqAsync->pScsiReq = pReq;
- pReqAsync->cSenseRetries = 0;
- pReqAsync->rcSense = VINF_SUCCESS;
-
- pbCDB[0] = SCSI_SYNCHRONIZE_CACHE;
- pbCDB[1] = 0; /* reserved */
- pbCDB[2] = 0; /* reserved */
- pbCDB[3] = 0; /* reserved */
- pbCDB[4] = 0; /* reserved */
- pbCDB[5] = 0; /* reserved */
- pbCDB[6] = 0; /* reserved */
- pbCDB[7] = 0; /* reserved */
- pbCDB[8] = 0; /* reserved */
- pbCDB[9] = 0; /* control */
-
- pReq->enmXfer = SCSIXFER_NONE;
- pReq->cbCDB = 10;
- pReq->pvCDB = pReqAsync->abCDB;
- pReq->cbI2TData = 0;
- pReq->paI2TSegs = NULL;
- pReq->cI2TSegs = 0;
- pReq->cbT2IData = 0;
- pReq->paT2ISegs = NULL;
- pReq->cT2ISegs = 0;
- pReq->cbSense = sizeof(pReqAsync->abSense);
- pReq->pvSense = pReqAsync->abSense;
-
- rc = iscsiCommandAsync(pImage, pReq, iscsiCommandAsyncComplete, pReqAsync);
- if (RT_FAILURE(rc))
- AssertMsgFailed(("iscsiCommand(%s) -> %Rrc\n", pImage->pszTargetName, rc));
- else
- return VERR_VD_IOCTX_HALT; /* Halt the I/O context until further notification from the I/O thread. */
-
- RTMemFree(pReq);
- }
- else
- rc = VERR_NO_MEMORY;
-
- RTMemFree(pReqAsync);
- }
- else
- rc = VERR_NO_MEMORY;
-
- LogFlowFunc(("returns rc=%Rrc\n", rc));
- return rc;
-}
-
/** @copydoc VBOXHDDBACKEND::pfnComposeLocation */
static int iscsiComposeLocation(PVDINTERFACE pConfig, char **pszLocation)
{
@@ -5578,8 +5419,12 @@ VBOXHDDBACKEND g_ISCSIBackend =
iscsiWrite,
/* pfnFlush */
iscsiFlush,
+ /* pfnDiscard */
+ NULL,
/* pfnGetVersion */
iscsiGetVersion,
+ /* pfnGetSectorSize */
+ iscsiGetSectorSize,
/* pfnGetSize */
iscsiGetSize,
/* pfnGetFileSize */
@@ -5630,12 +5475,6 @@ VBOXHDDBACKEND g_ISCSIBackend =
NULL,
/* pfnSetParentFilename */
NULL,
- /* pfnAsyncRead */
- iscsiAsyncRead,
- /* pfnAsyncWrite */
- iscsiAsyncWrite,
- /* pfnAsyncFlush */
- iscsiAsyncFlush,
/* pfnComposeLocation */
iscsiComposeLocation,
/* pfnComposeName */
@@ -5644,10 +5483,6 @@ VBOXHDDBACKEND g_ISCSIBackend =
NULL,
/* pfnResize */
NULL,
- /* pfnDiscard */
- NULL,
- /* pfnAsyncDiscard */
- NULL,
/* pfnRepair */
NULL
};