Changeset 63992 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Sep 25, 2016 5:58:56 PM (8 years ago)
- Location:
- trunk/src/VBox/Devices/Storage
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DrvSCSI.cpp
r63562 r63992 45 45 * 46 46 * @implements PDMISCSICONNECTOR 47 * @implements PDMIMEDIA ASYNCPORT47 * @implements PDMIMEDIAEXPORT 48 48 * @implements PDMIMOUNTNOTIFY 49 49 */ … … 57 57 /** Pointer to the attached driver's block interface. */ 58 58 PPDMIMEDIA pDrvMedia; 59 /** Pointer to the attached driver's async blockinterface. */60 PPDMIMEDIA ASYNC pDrvMediaAsync;59 /** Pointer to the attached driver's extended media interface. */ 60 PPDMIMEDIAEX pDrvMediaEx; 61 61 /** Pointer to the attached driver's mount interface. */ 62 62 PPDMIMOUNT pDrvMount; … … 69 69 /** The media port interface. */ 70 70 PDMIMEDIAPORT IPort; 71 /** The optional media asyncport interface. */72 PDMIMEDIA ASYNCPORT IPortAsync;71 /** The optional extended media port interface. */ 72 PDMIMEDIAEXPORT IPortEx; 73 73 /** The mount notify interface. */ 74 74 PDMIMOUNTNOTIFY IMountNotify; … … 86 86 VSCSILUNIOCALLBACKS VScsiIoCallbacks; 87 87 88 /** The dedicated I/O thread for the non async approach. */89 PPDMTHREAD pAsyncIOThread;90 /** Queue for passing the requests to the thread. */91 RTREQQUEUE hQueueRequests;92 /** Request that we've left pending on wakeup or reset. */93 PRTREQ pPendingDummyReq;94 88 /** Indicates whether PDMDrvHlpAsyncNotificationCompleted should be called by 95 89 * any of the dummy functions. */ … … 109 103 } DRVSCSI, *PDRVSCSI; 110 104 111 /** Converts a pointer to DRVSCSI::ISCSIConnector to a PDRVSCSI. */ 112 #define PDMISCSICONNECTOR_2_DRVSCSI(pInterface) ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, ISCSIConnector)) ) 113 /** Converts a pointer to DRVSCSI::IPortAsync to a PDRVSCSI. */ 114 #define PDMIMEDIAASYNCPORT_2_DRVSCSI(pInterface) ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, IPortAsync)) ) 115 /** Converts a pointer to DRVSCSI::IMountNotify to PDRVSCSI. */ 116 #define PDMIMOUNTNOTIFY_2_DRVSCSI(pInterface) ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, IMountNotify)) ) 117 /** Converts a pointer to DRVSCSI::IPort to a PDRVSCSI. */ 118 #define PDMIMEDIAPORT_2_DRVSCSI(pInterface) ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, IPort)) ) 119 120 static bool drvscsiIsRedoPossible(int rc) 105 /** Convert a VSCSI I/O request handle to the associated PDMIMEDIAEX I/O request. */ 106 #define DRVSCSI_VSCSIIOREQ_2_PDMMEDIAEXIOREQ(a_hVScsiIoReq) (*(PPDMMEDIAEXIOREQ)((uint8_t *)(a_hVScsiIoReq) - sizeof(PDMMEDIAEXIOREQ))) 107 /** Convert a PDMIMEDIAEX I/O additional request memory to a VSCSI I/O request. */ 108 #define DRVSCSI_PDMMEDIAEXIOREQ_2_VSCSIIOREQ(a_pvIoReqAlloc) ((VSCSIIOREQ)((uint8_t *)(a_pvIoReqAlloc) + sizeof(PDMMEDIAEXIOREQ))) 109 110 /** 111 * Returns whether the given status code indicates a non fatal error. 112 * 113 * @returns True if the error can be fixed by the user after the VM was suspended. 114 * False if not and the error should be reported to the guest. 115 * @param rc The status code to check. 116 */ 117 DECLINLINE(bool) drvscsiIsRedoPossible(int rc) 121 118 { 122 119 if ( rc == VERR_DISK_FULL … … 130 127 } 131 128 132 static int drvscsiProcessRequestOne(PDRVSCSI pThis, VSCSIIOREQ hVScsiIoReq) 133 { 129 /* -=-=-=-=- VScsiIoCallbacks -=-=-=-=- */ 130 131 /** 132 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunReqAllocSizeSet} 133 */ 134 static DECLCALLBACK(int) drvscsiReqAllocSizeSet(VSCSILUN hVScsiLun, void *pvScsiLunUser, size_t cbVScsiIoReqAlloc) 135 { 136 RT_NOREF(hVScsiLun); 137 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 138 139 /* We need to store the I/O request handle so we can get it when VSCSI queues an I/O request. */ 140 return pThis->pDrvMediaEx->pfnIoReqAllocSizeSet(pThis->pDrvMediaEx, cbVScsiIoReqAlloc + sizeof(PDMMEDIAEXIOREQ)); 141 } 142 143 /** 144 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunReqAlloc} 145 */ 146 static DECLCALLBACK(int) drvscsiReqAlloc(VSCSILUN hVScsiLun, void *pvScsiLunUser, 147 uint64_t u64Tag, PVSCSIIOREQ phVScsiIoReq) 148 { 149 RT_NOREF(hVScsiLun); 150 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 151 PDMMEDIAEXIOREQ hIoReq; 152 void *pvIoReqAlloc; 153 int rc = pThis->pDrvMediaEx->pfnIoReqAlloc(pThis->pDrvMediaEx, &hIoReq, &pvIoReqAlloc, u64Tag, 154 PDMIMEDIAEX_F_DEFAULT); 155 if (RT_SUCCESS(rc)) 156 { 157 PPDMMEDIAEXIOREQ phIoReq = (PPDMMEDIAEXIOREQ)pvIoReqAlloc; 158 159 *phIoReq = hIoReq; 160 *phVScsiIoReq = (VSCSIIOREQ)(phIoReq + 1); 161 } 162 163 return rc; 164 } 165 166 /** 167 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunReqFree} 168 */ 169 static DECLCALLBACK(int) drvscsiReqFree(VSCSILUN hVScsiLun, void *pvScsiLunUser, VSCSIIOREQ hVScsiIoReq) 170 { 171 RT_NOREF(hVScsiLun); 172 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 173 PDMMEDIAEXIOREQ hIoReq = DRVSCSI_VSCSIIOREQ_2_PDMMEDIAEXIOREQ(hVScsiIoReq); 174 175 return pThis->pDrvMediaEx->pfnIoReqFree(pThis->pDrvMediaEx, hIoReq); 176 } 177 178 /** 179 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunMediumGetSize} 180 */ 181 static DECLCALLBACK(int) drvscsiGetSize(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint64_t *pcbSize) 182 { 183 RT_NOREF(hVScsiLun); 184 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 185 186 *pcbSize = pThis->pDrvMedia->pfnGetSize(pThis->pDrvMedia); 187 188 return VINF_SUCCESS; 189 } 190 191 /** 192 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunMediumGetSectorSize} 193 */ 194 static DECLCALLBACK(int) drvscsiGetSectorSize(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint32_t *pcbSectorSize) 195 { 196 RT_NOREF(hVScsiLun); 197 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 198 199 *pcbSectorSize = pThis->pDrvMedia->pfnGetSectorSize(pThis->pDrvMedia); 200 201 return VINF_SUCCESS; 202 } 203 204 /** 205 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunMediumSetLock} 206 */ 207 static DECLCALLBACK(int) drvscsiSetLock(VSCSILUN hVScsiLun, void *pvScsiLunUser, bool fLocked) 208 { 209 RT_NOREF(hVScsiLun); 210 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 211 212 if (fLocked) 213 pThis->pDrvMount->pfnLock(pThis->pDrvMount); 214 else 215 pThis->pDrvMount->pfnUnlock(pThis->pDrvMount); 216 217 return VINF_SUCCESS; 218 } 219 220 /** 221 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunReqTransferEnqueue} 222 */ 223 static DECLCALLBACK(int) drvscsiReqTransferEnqueue(VSCSILUN hVScsiLun, void *pvScsiLunUser, VSCSIIOREQ hVScsiIoReq) 224 { 225 RT_NOREF(hVScsiLun); 134 226 int rc = VINF_SUCCESS; 135 VSCSIIOREQTXDIR enmTxDir; 136 137 enmTxDir = VSCSIIoReqTxDirGet(hVScsiIoReq); 138 227 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 228 PDMMEDIAEXIOREQ hIoReq = DRVSCSI_VSCSIIOREQ_2_PDMMEDIAEXIOREQ(hVScsiIoReq); 229 230 LogFlowFunc(("Enqueuing hVScsiIoReq=%#p\n", hVScsiIoReq)); 231 232 VSCSIIOREQTXDIR enmTxDir = VSCSIIoReqTxDirGet(hVScsiIoReq); 139 233 switch (enmTxDir) 140 234 { 141 235 case VSCSIIOREQTXDIR_FLUSH: 142 236 { 143 rc = pThis->pDrvMedia ->pfnFlush(pThis->pDrvMedia);237 rc = pThis->pDrvMediaEx->pfnIoReqFlush(pThis->pDrvMediaEx, hIoReq); 144 238 if ( RT_FAILURE(rc) 145 239 && pThis->cErrors++ < MAX_LOG_REL_ERRORS) 146 240 LogRel(("SCSI#%u: Flush returned rc=%Rrc\n", 241 pThis->pDrvIns->iInstance, rc)); 242 break; 243 } 244 case VSCSIIOREQTXDIR_UNMAP: 245 { 246 PCRTRANGE paRanges; 247 unsigned cRanges; 248 249 rc = VSCSIIoReqUnmapParamsGet(hVScsiIoReq, &paRanges, &cRanges); 250 AssertRC(rc); 251 252 pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1; 253 rc = pThis->pDrvMediaEx->pfnIoReqDiscard(pThis->pDrvMediaEx, hIoReq, paRanges, cRanges); 254 if ( RT_FAILURE(rc) 255 && pThis->cErrors++ < MAX_LOG_REL_ERRORS) 256 LogRel(("SCSI#%u: Discard returned rc=%Rrc\n", 147 257 pThis->pDrvIns->iInstance, rc)); 148 258 break; … … 157 267 unsigned cSeg = 0; 158 268 159 rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer, &cSeg, &cbSeg,160 & paSeg);269 rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer, 270 &cSeg, &cbSeg, &paSeg); 161 271 AssertRC(rc); 162 272 163 while (cbTransfer && cSeg)273 if (enmTxDir == VSCSIIOREQTXDIR_READ) 164 274 { 165 size_t cbProcess = (cbTransfer < paSeg->cbSeg) ? cbTransfer : paSeg->cbSeg; 166 167 Log(("%s: uOffset=%llu cbProcess=%u\n", __FUNCTION__, uOffset, cbProcess)); 168 169 if (enmTxDir == VSCSIIOREQTXDIR_READ) 170 { 171 pThis->pLed->Asserted.s.fReading = pThis->pLed->Actual.s.fReading = 1; 172 rc = pThis->pDrvMedia->pfnRead(pThis->pDrvMedia, uOffset, 173 paSeg->pvSeg, cbProcess); 174 pThis->pLed->Actual.s.fReading = 0; 175 if (RT_FAILURE(rc)) 176 break; 177 STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbProcess); 178 } 179 else 180 { 181 pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1; 182 rc = pThis->pDrvMedia->pfnWrite(pThis->pDrvMedia, uOffset, 183 paSeg->pvSeg, cbProcess); 184 pThis->pLed->Actual.s.fWriting = 0; 185 if (RT_FAILURE(rc)) 186 break; 187 STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbProcess); 188 } 189 190 /* Go to the next entry. */ 191 uOffset += cbProcess; 192 cbTransfer -= cbProcess; 193 paSeg++; 194 cSeg--; 275 pThis->pLed->Asserted.s.fReading = pThis->pLed->Actual.s.fReading = 1; 276 rc = pThis->pDrvMediaEx->pfnIoReqRead(pThis->pDrvMediaEx, hIoReq, uOffset, cbTransfer); 277 STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbTransfer); 278 } 279 else 280 { 281 pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1; 282 rc = pThis->pDrvMediaEx->pfnIoReqWrite(pThis->pDrvMediaEx, hIoReq, uOffset, cbTransfer); 283 STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbTransfer); 195 284 } 196 285 … … 204 293 uOffset, 205 294 cbTransfer, rc)); 206 207 break;208 }209 case VSCSIIOREQTXDIR_UNMAP:210 {211 PCRTRANGE paRanges;212 unsigned cRanges;213 214 rc = VSCSIIoReqUnmapParamsGet(hVScsiIoReq, &paRanges, &cRanges);215 AssertRC(rc);216 217 pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;218 rc = pThis->pDrvMedia->pfnDiscard(pThis->pDrvMedia, paRanges, cRanges);219 pThis->pLed->Actual.s.fWriting = 0;220 221 if ( RT_FAILURE(rc)222 && pThis->cErrors++ < MAX_LOG_REL_ERRORS)223 LogRel(("SCSI#%u: Unmap returned rc=%Rrc\n",224 pThis->pDrvIns->iInstance, rc));225 226 295 break; 227 296 } 228 297 default: 229 AssertMsgFailed(("Invalid transfer direction %d\n", enmTxDir)); 230 } 231 232 if (RT_SUCCESS(rc)) 233 VSCSIIoReqCompleted(hVScsiIoReq, rc, false /* fRedoPossible */); 298 AssertMsgFailed(("Invalid transfer direction %u\n", enmTxDir)); 299 } 300 301 if (rc == VINF_SUCCESS) 302 { 303 if (enmTxDir == VSCSIIOREQTXDIR_READ) 304 pThis->pLed->Actual.s.fReading = 0; 305 else if (enmTxDir == VSCSIIOREQTXDIR_WRITE) 306 pThis->pLed->Actual.s.fWriting = 0; 307 else 308 AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir)); 309 310 VSCSIIoReqCompleted(hVScsiIoReq, VINF_SUCCESS, false); 311 rc = VINF_SUCCESS; 312 } 313 else if (rc == VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) 314 rc = VINF_SUCCESS; 315 else if (RT_FAILURE(rc)) 316 { 317 if (enmTxDir == VSCSIIOREQTXDIR_READ) 318 pThis->pLed->Actual.s.fReading = 0; 319 else if (enmTxDir == VSCSIIOREQTXDIR_WRITE) 320 pThis->pLed->Actual.s.fWriting = 0; 321 else 322 AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir)); 323 324 VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc)); 325 rc = VINF_SUCCESS; 326 } 234 327 else 235 VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc)); 236 237 return VINF_SUCCESS; 238 } 239 240 static DECLCALLBACK(int) drvscsiGetSize(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint64_t *pcbSize) 328 AssertMsgFailed(("Invalid return code rc=%Rrc\n", rc)); 329 330 return rc; 331 } 332 333 /** 334 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunGetFeatureFlags} 335 */ 336 static DECLCALLBACK(int) drvscsiGetFeatureFlags(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint64_t *pfFeatures) 241 337 { 242 338 RT_NOREF(hVScsiLun); 243 339 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 244 340 245 *pcbSize = pThis->pDrvMedia->pfnGetSize(pThis->pDrvMedia); 341 *pfFeatures = 0; 342 343 uint32_t fFeatures = 0; 344 int rc = pThis->pDrvMediaEx->pfnQueryFeatures(pThis->pDrvMediaEx, &fFeatures); 345 if (RT_SUCCESS(rc) && (fFeatures & PDMIMEDIAEX_FEATURE_F_DISCARD)) 346 *pfFeatures |= VSCSI_LUN_FEATURE_UNMAP; 347 348 if (pThis->fNonRotational) 349 *pfFeatures |= VSCSI_LUN_FEATURE_NON_ROTATIONAL; 350 351 if (pThis->fReadonly) 352 *pfFeatures |= VSCSI_LUN_FEATURE_READONLY; 246 353 247 354 return VINF_SUCCESS; … … 249 356 250 357 251 static DECLCALLBACK(int) drvscsiGetSectorSize(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint32_t *pcbSectorSize) 252 { 253 RT_NOREF(hVScsiLun); 254 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 255 256 *pcbSectorSize = pThis->pDrvMedia->pfnGetSectorSize(pThis->pDrvMedia); 257 258 return VINF_SUCCESS; 259 } 260 static DECLCALLBACK(int) drvscsiSetLock(VSCSILUN hVScsiLun, void *pvScsiLunUser, bool fLocked) 261 { 262 RT_NOREF(hVScsiLun); 263 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 264 265 if (fLocked) 266 pThis->pDrvMount->pfnLock(pThis->pDrvMount); 267 else 268 pThis->pDrvMount->pfnUnlock(pThis->pDrvMount); 269 270 return VINF_SUCCESS; 271 } 272 273 static DECLCALLBACK(int) drvscsiTransferCompleteNotify(PPDMIMEDIAASYNCPORT pInterface, void *pvUser, int rc) 274 { 275 PDRVSCSI pThis = PDMIMEDIAASYNCPORT_2_DRVSCSI(pInterface); 276 VSCSIIOREQ hVScsiIoReq = (VSCSIIOREQ)pvUser; 358 /* -=-=-=-=- IPortEx -=-=-=-=- */ 359 360 /** 361 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify} 362 */ 363 static DECLCALLBACK(int) drvscsiIoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 364 void *pvIoReqAlloc, int rcReq) 365 { 366 RT_NOREF1(hIoReq); 367 368 PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, IPortEx); 369 VSCSIIOREQ hVScsiIoReq = (VSCSIIOREQ)((uint8_t *)pvIoReqAlloc + sizeof(PDMMEDIAEXIOREQ)); 277 370 VSCSIIOREQTXDIR enmTxDir = VSCSIIoReqTxDirGet(hVScsiIoReq); 278 371 … … 287 380 AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir)); 288 381 289 if (RT_SUCCESS(rc ))290 VSCSIIoReqCompleted(hVScsiIoReq, rc , false /* fRedoPossible */);382 if (RT_SUCCESS(rcReq)) 383 VSCSIIoReqCompleted(hVScsiIoReq, rcReq, false /* fRedoPossible */); 291 384 else 292 385 { … … 296 389 if (enmTxDir == VSCSIIOREQTXDIR_FLUSH) 297 390 LogRel(("SCSI#%u: Flush returned rc=%Rrc\n", 298 pThis->pDrvIns->iInstance, rc ));391 pThis->pDrvIns->iInstance, rcReq)); 299 392 else if (enmTxDir == VSCSIIOREQTXDIR_UNMAP) 300 393 LogRel(("SCSI#%u: Unmap returned rc=%Rrc\n", 301 pThis->pDrvIns->iInstance, rc ));394 pThis->pDrvIns->iInstance, rcReq)); 302 395 else 303 396 { … … 317 410 : "Write", 318 411 uOffset, 319 cbTransfer, rc ));412 cbTransfer, rcReq)); 320 413 } 321 414 } 322 415 323 VSCSIIoReqCompleted(hVScsiIoReq, rc , drvscsiIsRedoPossible(rc));416 VSCSIIoReqCompleted(hVScsiIoReq, rcReq, drvscsiIsRedoPossible(rcReq)); 324 417 } 325 418 … … 327 420 } 328 421 329 static DECLCALLBACK(int) drvscsiReqTransferEnqueue(VSCSILUN hVScsiLun, void *pvScsiLunUser, VSCSIIOREQ hVScsiIoReq) 330 { 331 RT_NOREF(hVScsiLun); 332 int rc = VINF_SUCCESS; 333 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 334 335 if (pThis->pDrvMediaAsync) 336 { 337 /* async I/O path. */ 338 VSCSIIOREQTXDIR enmTxDir; 339 340 LogFlowFunc(("Enqueuing hVScsiIoReq=%#p\n", hVScsiIoReq)); 341 342 enmTxDir = VSCSIIoReqTxDirGet(hVScsiIoReq); 343 344 switch (enmTxDir) 345 { 346 case VSCSIIOREQTXDIR_FLUSH: 347 { 348 rc = pThis->pDrvMediaAsync->pfnStartFlush(pThis->pDrvMediaAsync, hVScsiIoReq); 349 if ( RT_FAILURE(rc) 350 && rc != VERR_VD_ASYNC_IO_IN_PROGRESS 351 && pThis->cErrors++ < MAX_LOG_REL_ERRORS) 352 LogRel(("SCSI#%u: Flush returned rc=%Rrc\n", 353 pThis->pDrvIns->iInstance, rc)); 354 break; 355 } 356 case VSCSIIOREQTXDIR_UNMAP: 357 { 358 PCRTRANGE paRanges; 359 unsigned cRanges; 360 361 rc = VSCSIIoReqUnmapParamsGet(hVScsiIoReq, &paRanges, &cRanges); 362 AssertRC(rc); 363 364 pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1; 365 rc = pThis->pDrvMediaAsync->pfnStartDiscard(pThis->pDrvMediaAsync, paRanges, cRanges, hVScsiIoReq); 366 if ( RT_FAILURE(rc) 367 && rc != VERR_VD_ASYNC_IO_IN_PROGRESS 368 && pThis->cErrors++ < MAX_LOG_REL_ERRORS) 369 LogRel(("SCSI#%u: Discard returned rc=%Rrc\n", 370 pThis->pDrvIns->iInstance, rc)); 371 break; 372 } 373 case VSCSIIOREQTXDIR_READ: 374 case VSCSIIOREQTXDIR_WRITE: 375 { 376 uint64_t uOffset = 0; 377 size_t cbTransfer = 0; 378 size_t cbSeg = 0; 379 PCRTSGSEG paSeg = NULL; 380 unsigned cSeg = 0; 381 382 rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer, 383 &cSeg, &cbSeg, &paSeg); 384 AssertRC(rc); 385 386 if (enmTxDir == VSCSIIOREQTXDIR_READ) 387 { 388 pThis->pLed->Asserted.s.fReading = pThis->pLed->Actual.s.fReading = 1; 389 rc = pThis->pDrvMediaAsync->pfnStartRead(pThis->pDrvMediaAsync, uOffset, 390 paSeg, cSeg, cbTransfer, 391 hVScsiIoReq); 392 STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbTransfer); 393 } 394 else 395 { 396 pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1; 397 rc = pThis->pDrvMediaAsync->pfnStartWrite(pThis->pDrvMediaAsync, uOffset, 398 paSeg, cSeg, cbTransfer, 399 hVScsiIoReq); 400 STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbTransfer); 401 } 402 403 if ( RT_FAILURE(rc) 404 && rc != VERR_VD_ASYNC_IO_IN_PROGRESS 405 && pThis->cErrors++ < MAX_LOG_REL_ERRORS) 406 LogRel(("SCSI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n", 407 pThis->pDrvIns->iInstance, 408 enmTxDir == VSCSIIOREQTXDIR_READ 409 ? "Read" 410 : "Write", 411 uOffset, 412 cbTransfer, rc)); 413 break; 414 } 415 default: 416 AssertMsgFailed(("Invalid transfer direction %u\n", enmTxDir)); 417 } 418 419 if (rc == VINF_VD_ASYNC_IO_FINISHED) 420 { 421 if (enmTxDir == VSCSIIOREQTXDIR_READ) 422 pThis->pLed->Actual.s.fReading = 0; 423 else if (enmTxDir == VSCSIIOREQTXDIR_WRITE) 424 pThis->pLed->Actual.s.fWriting = 0; 425 else 426 AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir)); 427 428 VSCSIIoReqCompleted(hVScsiIoReq, VINF_SUCCESS, false); 429 rc = VINF_SUCCESS; 430 } 431 else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 432 rc = VINF_SUCCESS; 433 else if (RT_FAILURE(rc)) 434 { 435 if (enmTxDir == VSCSIIOREQTXDIR_READ) 436 pThis->pLed->Actual.s.fReading = 0; 437 else if (enmTxDir == VSCSIIOREQTXDIR_WRITE) 438 pThis->pLed->Actual.s.fWriting = 0; 439 else 440 AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir)); 441 442 VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc)); 443 rc = VINF_SUCCESS; 444 } 445 else 446 AssertMsgFailed(("Invalid return code rc=%Rrc\n", rc)); 447 } 448 else 449 { 450 /* I/O thread. */ 451 rc = RTReqQueueCallEx(pThis->hQueueRequests, NULL, 0, RTREQFLAGS_NO_WAIT, 452 (PFNRT)drvscsiProcessRequestOne, 2, pThis, hVScsiIoReq); 453 } 454 455 return rc; 456 } 457 458 static DECLCALLBACK(int) drvscsiGetFeatureFlags(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint64_t *pfFeatures) 459 { 460 RT_NOREF(hVScsiLun); 461 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 462 463 *pfFeatures = 0; 464 465 if ( pThis->pDrvMedia->pfnDiscard 466 || ( pThis->pDrvMediaAsync 467 && pThis->pDrvMediaAsync->pfnStartDiscard)) 468 *pfFeatures |= VSCSI_LUN_FEATURE_UNMAP; 469 470 if (pThis->fNonRotational) 471 *pfFeatures |= VSCSI_LUN_FEATURE_NON_ROTATIONAL; 472 473 if (pThis->fReadonly) 474 *pfFeatures |= VSCSI_LUN_FEATURE_READONLY; 475 476 return VINF_SUCCESS; 422 /** 423 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf} 424 */ 425 static DECLCALLBACK(int) drvscsiIoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 426 void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, 427 size_t cbCopy) 428 { 429 RT_NOREF2(pInterface, hIoReq); 430 431 VSCSIIOREQ hVScsiIoReq = DRVSCSI_PDMMEDIAEXIOREQ_2_VSCSIIOREQ(pvIoReqAlloc); 432 uint64_t uOffset = 0; 433 size_t cbTransfer = 0; 434 size_t cbSeg = 0; 435 PCRTSGSEG paSeg = NULL; 436 unsigned cSeg = 0; 437 size_t cbCopied = 0; 438 439 int rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer, &cSeg, &cbSeg, &paSeg); 440 if (RT_SUCCESS(rc)) 441 { 442 RTSGBUF SgBuf; 443 RTSgBufInit(&SgBuf, paSeg, cSeg); 444 445 RTSgBufAdvance(&SgBuf, offDst); 446 cbCopied = RTSgBufCopy(&SgBuf, pSgBuf, cbCopy); 447 } 448 449 return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_OVERFLOW; 450 } 451 452 /** 453 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf} 454 */ 455 static DECLCALLBACK(int) drvscsiIoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 456 void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, 457 size_t cbCopy) 458 { 459 RT_NOREF2(pInterface, hIoReq); 460 461 VSCSIIOREQ hVScsiIoReq = DRVSCSI_PDMMEDIAEXIOREQ_2_VSCSIIOREQ(pvIoReqAlloc); 462 uint64_t uOffset = 0; 463 size_t cbTransfer = 0; 464 size_t cbSeg = 0; 465 PCRTSGSEG paSeg = NULL; 466 unsigned cSeg = 0; 467 size_t cbCopied = 0; 468 469 int rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer, &cSeg, &cbSeg, &paSeg); 470 if (RT_SUCCESS(rc)) 471 { 472 RTSGBUF SgBuf; 473 RTSgBufInit(&SgBuf, paSeg, cSeg); 474 475 RTSgBufAdvance(&SgBuf, offSrc); 476 cbCopied = RTSgBufCopy(pSgBuf, &SgBuf, cbCopy); 477 } 478 479 return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_UNDERRUN; 480 } 481 482 /** 483 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged} 484 */ 485 static DECLCALLBACK(void) drvscsiIoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 486 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState) 487 { 488 RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState); 489 AssertLogRelMsgFailed(("This should not be hit because I/O requests should not be suspended\n")); 477 490 } 478 491 … … 490 503 if (RT_UNLIKELY(pThis->fDummySignal) && !pThis->StatIoDepth) 491 504 PDMDrvHlpAsyncNotificationCompleted(pThis->pDrvIns); 492 }493 494 /**495 * Dummy request function used by drvscsiReset to wait for all pending requests496 * to complete prior to the device reset.497 *498 * @param pThis Pointer to the instance data.499 * @returns VINF_SUCCESS.500 */501 static int drvscsiAsyncIOLoopSyncCallback(PDRVSCSI pThis)502 {503 if (pThis->fDummySignal)504 PDMDrvHlpAsyncNotificationCompleted(pThis->pDrvIns);505 return VINF_SUCCESS;506 }507 508 /**509 * Request function to wakeup the thread.510 *511 * @param pThis Pointer to the instance data.512 * @returns VWRN_STATE_CHANGED.513 */514 static int drvscsiAsyncIOLoopWakeupFunc(PDRVSCSI pThis)515 {516 if (pThis->fDummySignal)517 PDMDrvHlpAsyncNotificationCompleted(pThis->pDrvIns);518 return VWRN_STATE_CHANGED;519 }520 521 /**522 * The thread function which processes the requests asynchronously.523 *524 * @returns VBox status code.525 * @param pDrvIns Pointer to the driver instance data.526 * @param pThread Pointer to the thread instance data.527 */528 static DECLCALLBACK(int) drvscsiAsyncIOLoop(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)529 {530 int rc = VINF_SUCCESS;531 PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);532 533 LogFlowFunc(("Entering async IO loop.\n"));534 535 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)536 return VINF_SUCCESS;537 538 while (pThread->enmState == PDMTHREADSTATE_RUNNING)539 {540 rc = RTReqQueueProcess(pThis->hQueueRequests, RT_INDEFINITE_WAIT);541 AssertMsg(rc == VWRN_STATE_CHANGED, ("Left RTReqProcess and error code is not VWRN_STATE_CHANGED rc=%Rrc\n", rc));542 }543 544 return VINF_SUCCESS;545 }546 547 /**548 * Deals with any pending dummy request549 *550 * @returns true if no pending dummy request, false if still pending.551 * @param pThis The instance data.552 * @param cMillies The number of milliseconds to wait for any553 * pending request to finish.554 */555 static bool drvscsiAsyncIOLoopNoPendingDummy(PDRVSCSI pThis, uint32_t cMillies)556 {557 if (!pThis->pPendingDummyReq)558 return true;559 int rc = RTReqWait(pThis->pPendingDummyReq, cMillies);560 if (RT_FAILURE(rc))561 return false;562 RTReqRelease(pThis->pPendingDummyReq);563 pThis->pPendingDummyReq = NULL;564 return true;565 }566 567 static DECLCALLBACK(int) drvscsiAsyncIOLoopWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)568 {569 RT_NOREF(pThread);570 PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);571 PRTREQ pReq;572 int rc;573 574 AssertMsgReturn(pThis->hQueueRequests != NIL_RTREQQUEUE, ("hQueueRequests is NULL\n"), VERR_INVALID_STATE);575 576 if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 10000 /* 10 sec */))577 {578 LogRel(("drvscsiAsyncIOLoopWakeup#%u: previous dummy request is still pending\n", pDrvIns->iInstance));579 return VERR_TIMEOUT;580 }581 582 rc = RTReqQueueCall(pThis->hQueueRequests, &pReq, 10000 /* 10 sec. */, (PFNRT)drvscsiAsyncIOLoopWakeupFunc, 1, pThis);583 if (RT_SUCCESS(rc))584 RTReqRelease(pReq);585 else586 {587 pThis->pPendingDummyReq = pReq;588 LogRel(("drvscsiAsyncIOLoopWakeup#%u: %Rrc pReq=%p\n", pDrvIns->iInstance, rc, pReq));589 }590 591 return rc;592 505 } 593 506 … … 623 536 { 624 537 int rc; 625 PDRVSCSI pThis = PDMISCSICONNECTOR_2_DRVSCSI(pInterface);538 PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, ISCSIConnector); 626 539 VSCSIREQ hVScsiReq; 627 540 … … 652 565 static DECLCALLBACK(int) drvscsiQueryLUNType(PPDMISCSICONNECTOR pInterface, uint32_t iLun, PPDMSCSILUNTYPE pLunType) 653 566 { 654 int rc; 655 PDRVSCSI pThis = PDMISCSICONNECTOR_2_DRVSCSI(pInterface); 567 PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, ISCSIConnector); 656 568 VSCSILUNTYPE enmLunType; 657 569 658 rc = VSCSIDeviceLunQueryType(pThis->hVScsiDevice, iLun, &enmLunType);570 int rc = VSCSIDeviceLunQueryType(pThis->hVScsiDevice, iLun, &enmLunType); 659 571 if (RT_FAILURE(rc)) 660 572 return rc; … … 686 598 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pThis->IPort); 687 599 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUNTNOTIFY, &pThis->IMountNotify); 688 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA ASYNCPORT, &pThis->IPortAsync);600 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pThis->IPortEx); 689 601 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, pThis->pDrvMedia); 690 602 return NULL; … … 694 606 uint32_t *piInstance, uint32_t *piLUN) 695 607 { 696 PDRVSCSI pThis = PDMIMEDIAPORT_2_DRVSCSI(pInterface);608 PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, IPort); 697 609 698 610 return pThis->pDevScsiPort->pfnQueryDeviceLocation(pThis->pDevScsiPort, ppcszController, … … 707 619 static DECLCALLBACK(void) drvscsiMountNotify(PPDMIMOUNTNOTIFY pInterface) 708 620 { 709 PDRVSCSI pThis = PDMIMOUNTNOTIFY_2_DRVSCSI(pInterface);621 PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, IMountNotify); 710 622 LogFlowFunc(("mounting LUN#%p\n", pThis->hVScsiLun)); 711 623 … … 725 637 static DECLCALLBACK(void) drvscsiUnmountNotify(PPDMIMOUNTNOTIFY pInterface) 726 638 { 727 PDRVSCSI pThis = PDMIMOUNTNOTIFY_2_DRVSCSI(pInterface);639 PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, IMountNotify); 728 640 LogFlowFunc(("unmounting LUN#%p\n", pThis->hVScsiLun)); 729 641 … … 740 652 static void drvscsiR3ResetOrSuspendOrPowerOff(PPDMDRVINS pDrvIns, PFNPDMDRVASYNCNOTIFY pfnAsyncNotify) 741 653 { 654 RT_NOREF1(pfnAsyncNotify); 655 742 656 PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI); 743 657 744 if (!pThis->pDrvMediaAsync) 745 { 746 if (pThis->hQueueRequests != NIL_RTREQQUEUE) 747 return; 748 658 if (pThis->StatIoDepth > 0) 749 659 ASMAtomicWriteBool(&pThis->fDummySignal, true); 750 if (drvscsiAsyncIOLoopNoPendingDummy(pThis, 0 /*ms*/))751 {752 if (!RTReqQueueIsBusy(pThis->hQueueRequests))753 {754 ASMAtomicWriteBool(&pThis->fDummySignal, false);755 return;756 }757 758 PRTREQ pReq;759 int rc = RTReqQueueCall(pThis->hQueueRequests, &pReq, 0 /*ms*/, (PFNRT)drvscsiAsyncIOLoopSyncCallback, 1, pThis);760 if (RT_SUCCESS(rc))761 {762 ASMAtomicWriteBool(&pThis->fDummySignal, false);763 RTReqRelease(pReq);764 return;765 }766 767 pThis->pPendingDummyReq = pReq;768 }769 }770 else771 {772 if (pThis->StatIoDepth > 0)773 {774 ASMAtomicWriteBool(&pThis->fDummySignal, true);775 }776 return;777 }778 779 PDMDrvHlpSetAsyncNotification(pDrvIns, pfnAsyncNotify);780 660 } 781 661 … … 790 670 PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI); 791 671 792 if (pThis->pDrvMediaAsync) 793 { 794 if (pThis->StatIoDepth > 0) 795 return false; 796 else 797 return true; 798 } 672 if (pThis->StatIoDepth > 0) 673 return false; 799 674 else 800 {801 if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 0 /*ms*/))802 return false;803 ASMAtomicWriteBool(&pThis->fDummySignal, false);804 PDMR3ThreadSuspend(pThis->pAsyncIOThread);805 675 return true; 806 }807 676 } 808 677 … … 833 702 PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI); 834 703 835 if (pThis->pDrvMediaAsync) 836 { 837 if (pThis->StatIoDepth > 0) 838 return false; 839 else 840 return true; 841 } 704 if (pThis->StatIoDepth > 0) 705 return false; 842 706 else 843 {844 if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 0 /*ms*/))845 return false;846 ASMAtomicWriteBool(&pThis->fDummySignal, false);847 707 return true; 848 }849 708 } 850 709 … … 869 728 PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI); 870 729 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns); 871 872 if (pThis->hQueueRequests != NIL_RTREQQUEUE)873 {874 if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 100 /*ms*/))875 LogRel(("drvscsiDestruct#%u: previous dummy request is still pending\n", pDrvIns->iInstance));876 877 int rc = RTReqQueueDestroy(pThis->hQueueRequests);878 AssertMsgRC(rc, ("Failed to destroy queue rc=%Rrc\n", rc));879 pThis->hQueueRequests = NIL_RTREQQUEUE;880 }881 730 882 731 /* Free the VSCSI device and LUN handle. */ … … 926 775 pThis->IMountNotify.pfnUnmountNotify = drvscsiUnmountNotify; 927 776 pThis->IPort.pfnQueryDeviceLocation = drvscsiQueryDeviceLocation; 928 pThis->IPortAsync.pfnTransferCompleteNotify = drvscsiTransferCompleteNotify; 929 pThis->hQueueRequests = NIL_RTREQQUEUE; 777 pThis->IPortEx.pfnIoReqCompleteNotify = drvscsiIoReqCompleteNotify; 778 pThis->IPortEx.pfnIoReqCopyFromBuf = drvscsiIoReqCopyFromBuf; 779 pThis->IPortEx.pfnIoReqCopyToBuf = drvscsiIoReqCopyToBuf; 780 pThis->IPortEx.pfnIoReqStateChanged = drvscsiIoReqStateChanged; 930 781 931 782 /* Query the SCSI port interface above. */ … … 972 823 */ 973 824 pThis->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMEDIA); 974 if (!pThis->pDrvMedia) 975 { 976 AssertMsgFailed(("Configuration error: No block interface!\n")); 977 return VERR_PDM_MISSING_INTERFACE; 978 } 825 AssertMsgReturn(VALID_PTR(pThis->pDrvMedia), ("VSCSI configuration error: No media interface!\n"), 826 VERR_PDM_MISSING_INTERFACE); 827 828 /* Query the extended media interface. */ 829 pThis->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMEDIAEX); 830 AssertMsgReturn(VALID_PTR(pThis->pDrvMediaEx), ("VSCSI configuration error: No extended media interface!\n"), 831 VERR_PDM_MISSING_INTERFACE); 979 832 980 833 pThis->pDrvMount = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMOUNT); 981 982 /* Try to get the optional async block interface. */983 pThis->pDrvMediaAsync = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMEDIAASYNC);984 834 985 835 PDMMEDIATYPE enmType = pThis->pDrvMedia->pfnGetType(pThis->pDrvMedia); … … 1008 858 1009 859 /* Create VSCSI device and LUN. */ 860 pThis->VScsiIoCallbacks.pfnVScsiLunReqAllocSizeSet = drvscsiReqAllocSizeSet; 861 pThis->VScsiIoCallbacks.pfnVScsiLunReqAlloc = drvscsiReqAlloc; 862 pThis->VScsiIoCallbacks.pfnVScsiLunReqFree = drvscsiReqFree; 1010 863 pThis->VScsiIoCallbacks.pfnVScsiLunMediumGetSize = drvscsiGetSize; 1011 864 pThis->VScsiIoCallbacks.pfnVScsiLunMediumGetSectorSize = drvscsiGetSectorSize; … … 1059 912 pThis->StatIoDepth = 0; 1060 913 1061 if (!pThis->pDrvMediaAsync) 1062 { 1063 /* Create request queue. */ 1064 rc = RTReqQueueCreate(&pThis->hQueueRequests); 1065 AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create request queue rc=%Rrc\n", rc), rc); 1066 /* Create I/O thread. */ 1067 rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pAsyncIOThread, pThis, drvscsiAsyncIOLoop, 1068 drvscsiAsyncIOLoopWakeup, 0, RTTHREADTYPE_IO, "SCSI async IO"); 1069 AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create async I/O thread rc=%Rrc\n", rc), rc); 1070 1071 LogRel(("SCSI#%d: using normal I/O\n", pDrvIns->iInstance)); 1072 } 1073 else 1074 LogRel(("SCSI#%d: using async I/O\n", pDrvIns->iInstance)); 1075 1076 if ( pThis->pDrvMedia->pfnDiscard 1077 || ( pThis->pDrvMediaAsync 1078 && pThis->pDrvMediaAsync->pfnStartDiscard)) 914 uint32_t fFeatures = 0; 915 rc = pThis->pDrvMediaEx->pfnQueryFeatures(pThis->pDrvMediaEx, &fFeatures); 916 if (RT_FAILURE(rc)) 917 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, 918 N_("VSCSI configuration error: Failed to query features of device")); 919 if (fFeatures & PDMIMEDIAEX_FEATURE_F_DISCARD) 1079 920 LogRel(("SCSI#%d: Enabled UNMAP support\n", pDrvIns->iInstance)); 1080 921 -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h
r62506 r63992 321 321 322 322 /** 323 * Inits the I/O request related state for the LUN. 324 * 325 * @returns VBox status code. 326 * @param pVScsiLun The LUN instance. 327 */ 328 int vscsiIoReqInit(PVSCSILUNINT pVScsiLun); 329 330 /** 323 331 * Enqueues a new flush request 324 332 * … … 364 372 365 373 /** 374 * Wrapper for the set I/O request allocation size I/O callback. 375 * 376 * @returns VBox status code. 377 * @param pVScsiLun The LUN. 378 * @param cbVScsiIoReqAlloc The additional size for the request to allocate. 379 */ 380 DECLINLINE(int) vscsiLunReqAllocSizeSet(PVSCSILUNINT pVScsiLun, size_t cbVScsiIoReqAlloc) 381 { 382 return pVScsiLun->pVScsiLunIoCallbacks->pfnVScsiLunReqAllocSizeSet(pVScsiLun, 383 pVScsiLun->pvVScsiLunUser, 384 cbVScsiIoReqAlloc); 385 } 386 387 /** 388 * Wrapper for the allocate I/O request I/O callback. 389 * 390 * @returns VBox status code. 391 * @param pVScsiLun The LUN. 392 * @param u64Tag A unique tag to assign to the request. 393 * @param ppVScsiIoReq Where to store the pointer to the request on success. 394 */ 395 DECLINLINE(int) vscsiLunReqAlloc(PVSCSILUNINT pVScsiLun, uint64_t u64Tag, PVSCSIIOREQINT *ppVScsiIoReq) 396 { 397 return pVScsiLun->pVScsiLunIoCallbacks->pfnVScsiLunReqAlloc(pVScsiLun, 398 pVScsiLun->pvVScsiLunUser, 399 u64Tag, ppVScsiIoReq); 400 } 401 402 /** 403 * Wrapper for the free I/O request I/O callback. 404 * 405 * @returns VBox status code. 406 * @param pVScsiLun The LUN. 407 * @param pVScsiIoReq The request to free. 408 */ 409 DECLINLINE(int) vscsiLunReqFree(PVSCSILUNINT pVScsiLun, PVSCSIIOREQINT pVScsiIoReq) 410 { 411 return pVScsiLun->pVScsiLunIoCallbacks->pfnVScsiLunReqFree(pVScsiLun, 412 pVScsiLun->pvVScsiLunUser, 413 pVScsiIoReq); 414 } 415 416 /** 366 417 * Wrapper for the get medium size I/O callback. 367 418 * -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSIIoReq.cpp
r62506 r63992 26 26 #include "VSCSIInternal.h" 27 27 28 int vscsiIoReqInit(PVSCSILUNINT pVScsiLun) 29 { 30 return vscsiLunReqAllocSizeSet(pVScsiLun, sizeof(VSCSIIOREQINT)); 31 } 32 28 33 int vscsiIoReqFlushEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq) 29 34 { … … 31 36 PVSCSIIOREQINT pVScsiIoReq = NULL; 32 37 33 pVScsiIoReq = (PVSCSIIOREQINT)RTMemAllocZ(sizeof(VSCSIIOREQINT));34 if ( !pVScsiIoReq)35 return VERR_NO_MEMORY;36 37 pVScsiIoReq->pVScsiReq = pVScsiReq;38 pVScsiIoReq->pVScsiLun = pVScsiLun;39 pVScsiIoReq->enmTxDir = VSCSIIOREQTXDIR_FLUSH; 40 41 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding); 42 43 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);44 if (RT_FAILURE(rc))45 {46 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);47 RTMemFree(pVScsiIoReq);38 rc = vscsiLunReqAlloc(pVScsiLun, (uint64_t)pVScsiReq, &pVScsiIoReq); 39 if (RT_SUCCESS(rc)) 40 { 41 pVScsiIoReq->pVScsiReq = pVScsiReq; 42 pVScsiIoReq->pVScsiLun = pVScsiLun; 43 pVScsiIoReq->enmTxDir = VSCSIIOREQTXDIR_FLUSH; 44 45 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding); 46 47 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq); 48 if (RT_FAILURE(rc)) 49 { 50 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding); 51 RTMemFree(pVScsiIoReq); 52 } 48 53 } 49 54 … … 62 67 pVScsiLun, pVScsiReq, enmTxDir, uOffset, cbTransfer)); 63 68 64 pVScsiIoReq = (PVSCSIIOREQINT)RTMemAllocZ(sizeof(VSCSIIOREQINT));65 if ( !pVScsiIoReq)66 return VERR_NO_MEMORY;67 68 pVScsiIoReq->pVScsiReq = pVScsiReq;69 pVScsiIoReq->pVScsiLun = pVScsiLun;70 pVScsiIoReq->enmTxDir = enmTxDir;71 pVScsiIoReq->u.Io.uOffset = uOffset;72 pVScsiIoReq->u.Io.cbTransfer = cbTransfer;73 pVScsiIoReq->u.Io.paSeg = pVScsiReq->SgBuf.paSegs;74 pVScsiIoReq->u.Io.cSeg = pVScsiReq->SgBuf.cSegs; 75 76 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding); 77 78 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);79 if (RT_FAILURE(rc))80 {81 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);82 RTMemFree(pVScsiIoReq);69 rc = vscsiLunReqAlloc(pVScsiLun, (uint64_t)pVScsiReq, &pVScsiIoReq); 70 if (RT_SUCCESS(rc)) 71 { 72 pVScsiIoReq->pVScsiReq = pVScsiReq; 73 pVScsiIoReq->pVScsiLun = pVScsiLun; 74 pVScsiIoReq->enmTxDir = enmTxDir; 75 pVScsiIoReq->u.Io.uOffset = uOffset; 76 pVScsiIoReq->u.Io.cbTransfer = cbTransfer; 77 pVScsiIoReq->u.Io.paSeg = pVScsiReq->SgBuf.paSegs; 78 pVScsiIoReq->u.Io.cSeg = pVScsiReq->SgBuf.cSegs; 79 80 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding); 81 82 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq); 83 if (RT_FAILURE(rc)) 84 { 85 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding); 86 vscsiLunReqFree(pVScsiLun, pVScsiIoReq); 87 } 83 88 } 84 89 … … 96 101 pVScsiLun, pVScsiReq, paRanges, cRanges)); 97 102 98 pVScsiIoReq = (PVSCSIIOREQINT)RTMemAllocZ(sizeof(VSCSIIOREQINT));99 if ( !pVScsiIoReq)100 return VERR_NO_MEMORY;101 102 pVScsiIoReq->pVScsiReq = pVScsiReq;103 pVScsiIoReq->pVScsiLun = pVScsiLun;104 pVScsiIoReq->enmTxDir = VSCSIIOREQTXDIR_UNMAP;105 pVScsiIoReq->u.Unmap.paRanges = paRanges;106 pVScsiIoReq->u.Unmap.cRanges = cRanges; 107 108 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding); 109 110 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);111 if (RT_FAILURE(rc))112 {113 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);114 RTMemFree(pVScsiIoReq);103 rc = vscsiLunReqAlloc(pVScsiLun, (uint64_t)pVScsiReq, &pVScsiIoReq); 104 if (RT_SUCCESS(rc)) 105 { 106 pVScsiIoReq->pVScsiReq = pVScsiReq; 107 pVScsiIoReq->pVScsiLun = pVScsiLun; 108 pVScsiIoReq->enmTxDir = VSCSIIOREQTXDIR_UNMAP; 109 pVScsiIoReq->u.Unmap.paRanges = paRanges; 110 pVScsiIoReq->u.Unmap.cRanges = cRanges; 111 112 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding); 113 114 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq); 115 if (RT_FAILURE(rc)) 116 { 117 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding); 118 vscsiLunReqFree(pVScsiLun, pVScsiIoReq); 119 } 115 120 } 116 121 … … 163 168 164 169 /* Free the I/O request */ 165 RTMemFree(pVScsiIoReq);170 vscsiLunReqFree(pVScsiLun, pVScsiIoReq); 166 171 167 172 /* Notify completion of the SCSI request. */ -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSILun.cpp
r62506 r63992 72 72 pVScsiLun->pVScsiLunDesc = pVScsiLunDesc; 73 73 74 int rc = vscsi LunGetFeatureFlags(pVScsiLun, &pVScsiLun->fFeatures);74 int rc = vscsiIoReqInit(pVScsiLun); 75 75 if (RT_SUCCESS(rc)) 76 76 { 77 rc = pVScsiLunDesc->pfnVScsiLunInit(pVScsiLun);77 rc = vscsiLunGetFeatureFlags(pVScsiLun, &pVScsiLun->fFeatures); 78 78 if (RT_SUCCESS(rc)) 79 79 { 80 *phVScsiLun = pVScsiLun; 81 return VINF_SUCCESS; 80 rc = pVScsiLunDesc->pfnVScsiLunInit(pVScsiLun); 81 if (RT_SUCCESS(rc)) 82 { 83 *phVScsiLun = pVScsiLun; 84 return VINF_SUCCESS; 85 } 82 86 } 83 87 }
Note:
See TracChangeset
for help on using the changeset viewer.