- Timestamp:
- Jul 4, 2016 1:06:44 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/ISCSI.cpp
r61978 r62004 612 612 /** Table of commands waiting for a response from the target. */ 613 613 PISCSICMD aCmdsWaiting[ISCSI_CMD_WAITING_ENTRIES]; 614 /** Number of logins since last successful I/O. 615 * Used to catch the case where logging succeeds but 616 * processing read/write/flushes cause a disconnect. 617 */ 618 volatile uint32_t cLoginsSinceIo; 614 619 615 620 /** Release log counter. */ … … 1261 1266 1262 1267 Assert(pImage->state == ISCSISTATE_FREE); 1268 1269 /* 1270 * If there were too many logins without any successful I/O just fail 1271 * and assume the target is not working properly. 1272 */ 1273 if (ASMAtomicReadU32(&pImage->cLoginsSinceIo) == 3) 1274 return VERR_BROKEN_PIPE; 1263 1275 1264 1276 RTSemMutexRequest(pImage->Mutex, RT_INDEFINITE_WAIT); … … 1713 1725 pImage->state = ISCSISTATE_NORMAL; 1714 1726 1727 if (RT_SUCCESS(rc)) 1728 ASMAtomicIncU32(&pImage->cLoginsSinceIo); 1729 1715 1730 RTSemMutexRelease(pImage->Mutex); 1716 1731 … … 2040 2055 2041 2056 out: 2057 if (RT_SUCCESS(rc)) 2058 ASMAtomicWriteU32(&pImage->cLoginsSinceIo, 0); 2042 2059 LogFlowFunc(("returns %Rrc\n", rc)); 2043 2060 return rc; … … 3283 3300 3284 3301 /** 3302 * Clears all RX/TX PDU states and returns the command for the current 3303 * pending TX PDU if existing. 3304 * 3305 * @returns Pointer to the iSCSI command for the current PDU transmitted or NULL 3306 * if none is waiting. 3307 * @param pImage iSCSI connection state. 3308 */ 3309 static PISCSICMD iscsiPDURxTxClear(PISCSIIMAGE pImage) 3310 { 3311 PISCSICMD pIScsiCmdHead = NULL; 3312 PISCSIPDUTX pIScsiPDUTx = NULL; 3313 3314 /* Reset PDU we are receiving. */ 3315 iscsiRecvPDUReset(pImage); 3316 3317 /* 3318 * Abort all PDUs we are about to transmit, 3319 * the command need a new Itt if the relogin is successful. 3320 */ 3321 while (pImage->pIScsiPDUTxHead) 3322 { 3323 pIScsiPDUTx = pImage->pIScsiPDUTxHead; 3324 pImage->pIScsiPDUTxHead = pIScsiPDUTx->pNext; 3325 3326 PISCSICMD pIScsiCmd = pIScsiPDUTx->pIScsiCmd; 3327 if (pIScsiCmd) 3328 { 3329 /* Place on command list. */ 3330 pIScsiCmd->pNext = pIScsiCmdHead; 3331 pIScsiCmdHead = pIScsiCmd; 3332 } 3333 RTMemFree(pIScsiPDUTx); 3334 } 3335 3336 /* Clear the tail pointer (safety precaution). */ 3337 pImage->pIScsiPDUTxTail = NULL; 3338 3339 /* Clear the current PDU too. */ 3340 if (pImage->pIScsiPDUTxCur) 3341 { 3342 pIScsiPDUTx = pImage->pIScsiPDUTxCur; 3343 3344 pImage->pIScsiPDUTxCur = NULL; 3345 PISCSICMD pIScsiCmd = pIScsiPDUTx->pIScsiCmd; 3346 if (pIScsiCmd) 3347 { 3348 pIScsiCmd->pNext = pIScsiCmdHead; 3349 pIScsiCmdHead = pIScsiCmd; 3350 } 3351 RTMemFree(pIScsiPDUTx); 3352 } 3353 3354 return pIScsiCmdHead; 3355 } 3356 3357 /** 3358 * Rests the iSCSI connection state and returns a list of iSCSI commands pending 3359 * when this was called. 3360 * 3361 * @returns Pointer to the head of the pending iSCSI command list. 3362 * @param pImage iSCSI connection state. 3363 */ 3364 static PISCSICMD iscsiReset(PISCSIIMAGE pImage) 3365 { 3366 PISCSICMD pIScsiCmdHead = NULL; 3367 PISCSICMD pIScsiCmdCur = NULL; 3368 3369 /* Clear all in flight PDUs. */ 3370 pIScsiCmdHead = iscsiPDURxTxClear(pImage); 3371 3372 /* 3373 * Get all commands which are waiting for a response 3374 * They need to be resend too after a successful reconnect. 3375 */ 3376 PISCSICMD pIScsiCmd = iscsiCmdRemoveAll(pImage); 3377 if (pIScsiCmd) 3378 { 3379 pIScsiCmdCur = pIScsiCmd; 3380 while (pIScsiCmdCur->pNext) 3381 pIScsiCmdCur = pIScsiCmdCur->pNext; 3382 3383 /* 3384 * Place them in front of the list because they are the oldest requests 3385 * and need to be processed first to minimize the risk to time out. 3386 */ 3387 pIScsiCmdCur->pNext = pIScsiCmdHead; 3388 pIScsiCmdHead = pIScsiCmd; 3389 } 3390 3391 return pIScsiCmdHead; 3392 } 3393 3394 /** 3285 3395 * Reattaches the to the target after an error aborting 3286 3396 * pending commands and resending them. … … 3290 3400 static void iscsiReattach(PISCSIIMAGE pImage) 3291 3401 { 3292 int rc = VINF_SUCCESS;3293 PISCSICMD pIScsiCmdHead = NULL;3294 PISCSICMD pIScsiCmd = NULL;3295 PISCSICMD pIScsiCmdCur = NULL;3296 PISCSIPDUTX pIScsiPDUTx = NULL;3297 3298 3402 /* Close connection. */ 3299 3403 iscsiTransportClose(pImage); 3300 3404 pImage->state = ISCSISTATE_FREE; 3301 3405 3302 /* Reset PDU we are receiving. */ 3303 iscsiRecvPDUReset(pImage); 3304 3305 /* 3306 * Abort all PDUs we are about to transmit, 3307 * the command need a new Itt if the relogin is successful. 3308 */ 3309 while (pImage->pIScsiPDUTxHead) 3310 { 3311 pIScsiPDUTx = pImage->pIScsiPDUTxHead; 3312 pImage->pIScsiPDUTxHead = pIScsiPDUTx->pNext; 3313 3314 pIScsiCmd = pIScsiPDUTx->pIScsiCmd; 3315 3316 if (pIScsiCmd) 3317 { 3318 /* Place on command list. */ 3319 pIScsiCmd->pNext = pIScsiCmdHead; 3320 pIScsiCmdHead = pIScsiCmd; 3321 } 3322 RTMemFree(pIScsiPDUTx); 3323 } 3324 3325 /* Clear the tail pointer (safety precaution). */ 3326 pImage->pIScsiPDUTxTail = NULL; 3327 3328 /* Clear the current PDU too. */ 3329 if (pImage->pIScsiPDUTxCur) 3330 { 3331 pIScsiPDUTx = pImage->pIScsiPDUTxCur; 3332 3333 pImage->pIScsiPDUTxCur = NULL; 3334 pIScsiCmd = pIScsiPDUTx->pIScsiCmd; 3335 3336 if (pIScsiCmd) 3337 { 3338 pIScsiCmd->pNext = pIScsiCmdHead; 3339 pIScsiCmdHead = pIScsiCmd; 3340 } 3341 RTMemFree(pIScsiPDUTx); 3342 } 3343 3344 /* 3345 * Get all commands which are waiting for a response 3346 * They need to be resend too after a successful reconnect. 3347 */ 3348 pIScsiCmd = iscsiCmdRemoveAll(pImage); 3349 3350 if (pIScsiCmd) 3351 { 3352 pIScsiCmdCur = pIScsiCmd; 3353 while (pIScsiCmdCur->pNext) 3354 pIScsiCmdCur = pIScsiCmdCur->pNext; 3355 3356 /* 3357 * Place them in front of the list because they are the oldest requests 3358 * and need to be processed first to minimize the risk to time out. 3359 */ 3360 pIScsiCmdCur->pNext = pIScsiCmdHead; 3361 pIScsiCmdHead = pIScsiCmd; 3362 } 3406 /* Reset the state and get the currently pending commands. */ 3407 PISCSICMD pIScsiCmdHead = iscsiReset(pImage); 3363 3408 3364 3409 /* Try to attach. */ 3365 rc = iscsiAttach(pImage);3410 int rc = iscsiAttach(pImage); 3366 3411 if (RT_SUCCESS(rc)) 3367 3412 { … … 3371 3416 while (pIScsiCmdHead) 3372 3417 { 3373 pIScsiCmd = pIScsiCmdHead;3418 PISCSICMD pIScsiCmd = pIScsiCmdHead; 3374 3419 pIScsiCmdHead = pIScsiCmdHead->pNext; 3375 3420 … … 3377 3422 3378 3423 rc = iscsiPDUTxPrepare(pImage, pIScsiCmd); 3379 AssertRC(rc); 3380 } 3381 } 3382 else 3424 if (RT_FAILURE(rc)) 3425 break; 3426 } 3427 3428 if (RT_FAILURE(rc)) 3429 { 3430 /* Another error, just give up and report an error. */ 3431 PISCSICMD pIScsiCmd = iscsiReset(pImage); 3432 3433 /* Concatenate both lists together so we can abort all requests below. */ 3434 if (pIScsiCmd) 3435 { 3436 PISCSICMD pIScsiCmdCur = pIScsiCmd; 3437 while (pIScsiCmdCur->pNext) 3438 pIScsiCmdCur = pIScsiCmdCur->pNext; 3439 3440 pIScsiCmdCur->pNext = pIScsiCmdHead; 3441 pIScsiCmdHead = pIScsiCmd; 3442 } 3443 } 3444 } 3445 3446 if (RT_FAILURE(rc)) 3383 3447 { 3384 3448 /* … … 3388 3452 while (pIScsiCmdHead) 3389 3453 { 3390 pIScsiCmd = pIScsiCmdHead;3454 PISCSICMD pIScsiCmd = pIScsiCmdHead; 3391 3455 pIScsiCmdHead = pIScsiCmdHead->pNext; 3392 3456 … … 3451 3515 { 3452 3516 rc = iscsiPDUTxPrepare(pImage, pIScsiCmd); 3453 AssertRC(rc); 3517 if (RT_FAILURE(rc)) 3518 iscsiReattach(pImage); 3454 3519 } 3455 3520 else … … 3698 3763 size_t cbTransfered = 0; 3699 3764 PSCSIREQ pScsiReq = (PSCSIREQ)pvUser; 3765 3766 if (RT_SUCCESS(rcReq)) 3767 ASMAtomicWriteU32(&pImage->cLoginsSinceIo, 0); 3700 3768 3701 3769 if ( RT_SUCCESS(rcReq) … … 3894 3962 pImage->cISCSIRetries = 10; 3895 3963 pImage->state = ISCSISTATE_FREE; 3964 pImage->cLoginsSinceIo = 0; 3896 3965 pImage->pvRecvPDUBuf = RTMemAlloc(ISCSI_RECV_PDU_BUFFER_SIZE); 3897 3966 pImage->cbRecvPDUBuf = ISCSI_RECV_PDU_BUFFER_SIZE;
Note:
See TracChangeset
for help on using the changeset viewer.