ReactOS 0.4.16-dev-91-g764881a
retry.c File Reference
#include "classp.h"
#include "debug.h"
Include dependency graph for retry.c:

Go to the source code of this file.

Functions

BOOLEAN InterpretTransferPacketError (PTRANSFER_PACKET Pkt)
 
BOOLEAN RetryTransferPacket (PTRANSFER_PACKET Pkt)
 
VOID TransferPacketQueueRetryDpc (PTRANSFER_PACKET Pkt)
 
VOID NTAPI TransferPacketRetryTimerDpc (IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
 
VOID InitLowMemRetry (PTRANSFER_PACKET Pkt, PVOID BufPtr, ULONG Len, LARGE_INTEGER TargetLocation)
 
BOOLEAN StepLowMemRetry (PTRANSFER_PACKET Pkt)
 

Function Documentation

◆ InitLowMemRetry()

VOID InitLowMemRetry ( PTRANSFER_PACKET  Pkt,
PVOID  BufPtr,
ULONG  Len,
LARGE_INTEGER  TargetLocation 
)

Definition at line 670 of file retry.c.

671{
672 NT_ASSERT(Len > 0);
674
676 {
677 /*
678 * special case: StartIO-based writing must stay serialized for performance
679 * and proper operations (i.e. sequential writing mode). If need more than
680 * one transfer to perform this operation, and it's a StartIO-based driver
681 * (such as CDROM), then just use a single packet and use the retry logic
682 * that's already built-in to the packet engine. Note that low-mem retry
683 * cannot be used directly because some write methods do not work if the
684 * writes are only PAGE_SIZE (i.e. packet writing may corrupt data).
685 */
687 }
688 else
689 {
691 }
695}
_In_ PTRANSFER_PACKET Pkt
Definition: classp.h:1754
#define Len
Definition: deflate.h:82
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
PUCHAR LowMemRetry_remainingBufPtr
Definition: classp.h:545
LARGE_INTEGER LowMemRetry_nextChunkTargetLocation
Definition: classp.h:547
BOOLEAN DriverUsesStartIO
Definition: classp.h:543
ULONG LowMemRetry_remainingBufLen
Definition: classp.h:546
BOOLEAN InLowMemRetry
Definition: classp.h:544
#define NT_ASSERT
Definition: rtlfuncs.h:3324

Referenced by RetryTransferPacket(), and ServiceTransferRequest().

◆ InterpretTransferPacketError()

BOOLEAN InterpretTransferPacketError ( PTRANSFER_PACKET  Pkt)

Definition at line 40 of file retry.c.

41{
43 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
44 ULONG timesAlreadyRetried;
45 BOOLEAN shouldRetry = FALSE;
47
48 /*
49 * Interpret the error using the returned sense info first.
50 */
51 Pkt->RetryIn100nsUnits = 0;
52
53
54 /*
55 * Pre-calculate the number of times the IO has already been
56 * retried, so that all InterpretSenseInfo routines get the right value.
57 */
58 if (ClasspTransferPacketGetNumberOfRetriesDone(Pkt, pCdb, &timesAlreadyRetried) == FALSE)
59 {
60 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "Unhandled SRB Function %xh in error path for packet %p (did miniport change Srb.Cdb.OperationCode ?)", (ULONG)pCdb->CDB10.OperationCode, Pkt));
61 }
62
63 if (fdoData->InterpretSenseInfo != NULL) {
64
65 SCSI_REQUEST_BLOCK tempSrb = { 0 };
67
68 // SAL annotation and ClassInitializeEx() both validate this
70
71 //
72 // If class driver does not support extended SRB and this is
73 // an extended SRB, convert to legacy SRB and pass to class
74 // driver.
75 //
76 if ((Pkt->Srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) &&
80 srbPtr = &tempSrb;
81 }
82
83 shouldRetry = fdoData->InterpretSenseInfo->Interpret(Pkt->Fdo,
85 srbPtr,
87 0,
88 timesAlreadyRetried,
91 &Pkt->RetryIn100nsUnits);
92
93
94 } else {
95
96 //
97 // In this case, fdoData->InterpretSenseInfo == NULL so we must do our
98 // own error code and sense info processing.
99 //
100
104 UCHAR senseKey = 0;
106 UCHAR additionalSenseQual = 0;
107
109
110 validSense = ScsiGetSenseKeyAndCodes(senseInfoBuffer,
111 senseInfoBufferLength,
113 &senseKey,
115 &additionalSenseQual);
116
117 if (pCdb->MEDIA_REMOVAL.OperationCode == SCSIOP_MEDIUM_REMOVAL) {
118
119 ULONG retryIntervalSeconds = 0;
120 /*
121 * This is an Ejection Control SRB. Interpret its sense info specially.
122 */
123 shouldRetry = ClassInterpretSenseInfo(
124 Pkt->Fdo,
127 0,
128 timesAlreadyRetried,
130 &retryIntervalSeconds);
131
132 if (shouldRetry) {
133 /*
134 * If the device is not ready, wait at least 2 seconds before retrying.
135 */
136 BOOLEAN setRetryIntervalSeconds = FALSE;
137
138 if (validSense) {
139
142 setRetryIntervalSeconds = TRUE;
143 }
144 }
145
146 if (!setRetryIntervalSeconds && (SRB_STATUS(Pkt->Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT)) {
147 setRetryIntervalSeconds = TRUE;
148 }
149
150 if (setRetryIntervalSeconds) {
151 retryIntervalSeconds = MAX(retryIntervalSeconds, 2);
152 }
153 }
154
155 if (shouldRetry)
156 {
157 Pkt->RetryIn100nsUnits = retryIntervalSeconds;
158 Pkt->RetryIn100nsUnits *= 1000 * 1000 * 10;
159 }
160
161 }
162 else if ((pCdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE) ||
163 (pCdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE10)) {
164
165 ULONG retryIntervalSeconds = 0;
166 /*
167 * This is an Mode Sense SRB. Interpret its sense info specially.
168 */
169 shouldRetry = ClassInterpretSenseInfo(
170 Pkt->Fdo,
173 0,
174 timesAlreadyRetried,
176 &retryIntervalSeconds);
177 if (shouldRetry) {
178 /*
179 * If the device is not ready, wait at least 2 seconds before retrying.
180 */
181 BOOLEAN setRetryIntervalSeconds = FALSE;
182
183 if (validSense) {
186 setRetryIntervalSeconds = TRUE;
187 }
188 }
189
190 if (!setRetryIntervalSeconds && (SRB_STATUS(Pkt->Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT)) {
191 setRetryIntervalSeconds = TRUE;
192 }
193
194 if (setRetryIntervalSeconds) {
195 retryIntervalSeconds = MAX(retryIntervalSeconds, 2);
196 }
197 }
198
199 /*
200 * Some special cases for mode sense.
201 */
203 shouldRetry = TRUE;
204 }
205 else if (SRB_STATUS(Pkt->Srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
206 /*
207 * This is a HACK.
208 * Atapi returns SRB_STATUS_DATA_OVERRUN when it really means
209 * underrun (i.e. success, and the buffer is longer than needed).
210 * So treat this as a success.
211 * When the caller of this function sees that the status was changed to success,
212 * it will add the transferred length to the original irp.
213 */
215 shouldRetry = FALSE;
216 }
217
218 if (shouldRetry)
219 {
220 Pkt->RetryIn100nsUnits = retryIntervalSeconds;
221 Pkt->RetryIn100nsUnits *= 1000 * 1000 * 10;
222 }
223
224 }
225 else if ((pCdb->CDB10.OperationCode == SCSIOP_READ_CAPACITY) ||
226 (pCdb->CDB16.OperationCode == SCSIOP_READ_CAPACITY16)) {
227
228 ULONG retryIntervalSeconds = 0;
229
230 /*
231 * This is a Drive Capacity SRB. Interpret its sense info specially.
232 */
233 shouldRetry = ClassInterpretSenseInfo(
234 Pkt->Fdo,
237 0,
238 timesAlreadyRetried,
240 &retryIntervalSeconds);
242 shouldRetry = TRUE;
243 }
244#if (NTDDI_VERSION >= NTDDI_WINBLUE)
245 else if (ClasspSrbTimeOutStatus(Pkt->Srb)) {
246
247 Pkt->TimedOut = TRUE;
248
249 if (shouldRetry) {
250 //
251 // For requests that have timed-out we may only perform a limited
252 // number of retries. This is typically less than the general
253 // number of retries allowed.
254 //
255 if (Pkt->NumIoTimeoutRetries == 0) {
256 shouldRetry = FALSE;
257 } else {
259 //
260 // We expect to be able to retry if there are some general retries remaining.
261 //
262 }
263 }
264 }
265#endif
266
267 if (shouldRetry)
268 {
269 Pkt->RetryIn100nsUnits = retryIntervalSeconds;
270 Pkt->RetryIn100nsUnits *= 1000 * 1000 * 10;
271 }
272
273 }
274 else if (IS_SCSIOP_READWRITE(pCdb->CDB10.OperationCode)) {
275
276 ULONG retryIntervalSeconds = 0;
277 /*
278 * This is a Read/Write Data packet.
279 */
281
282 shouldRetry = ClassInterpretSenseInfo(Pkt->Fdo,
284 origCurrentSp->MajorFunction,
285 0,
286 timesAlreadyRetried,
288 &retryIntervalSeconds);
289
290 /*
291 * Deal with some special cases.
292 */
294 /*
295 * We are in extreme low-memory stress.
296 * We will retry in smaller chunks.
297 */
298 shouldRetry = TRUE;
299 }
300 else if (TEST_FLAG(origCurrentSp->Flags, SL_OVERRIDE_VERIFY_VOLUME) &&
302 /*
303 * We are still verifying a (possibly) reloaded disk/cdrom.
304 * So retry the request.
305 */
307 shouldRetry = TRUE;
308
309 }
310#if (NTDDI_VERSION >= NTDDI_WINBLUE)
311 else if (ClasspSrbTimeOutStatus(Pkt->Srb)) {
312
313 Pkt->TimedOut = TRUE;
314
315 if (shouldRetry) {
316 //
317 // For requests that have timed-out we may only perform a limited
318 // number of retries. This is typically less than the general
319 // number of retries allowed.
320 //
321 if (Pkt->NumIoTimeoutRetries == 0) {
322 shouldRetry = FALSE;
323 } else {
325 //
326 // We expect to be able to retry if there are some general retries remaining.
327 //
328 }
329 }
330 }
331#endif
332
333 if (shouldRetry)
334 {
335 Pkt->RetryIn100nsUnits = retryIntervalSeconds;
336 Pkt->RetryIn100nsUnits *= 1000 * 1000 * 10;
337 }
338
339 } else if (ClasspIsOffloadDataTransferCommand(pCdb)) {
340
341 ULONG retryIntervalSeconds = 0;
342
343 Pkt->TransferCount = 0;
344
345 shouldRetry = ClassInterpretSenseInfo(
346 Pkt->Fdo,
349 0,
350 timesAlreadyRetried,
352 &retryIntervalSeconds);
353
354 if (shouldRetry) {
355
356 Pkt->RetryIn100nsUnits = retryIntervalSeconds;
357 Pkt->RetryIn100nsUnits *= 1000 * 1000 * 10;
358
359 } else {
360
361 if (ClasspIsTokenOperation(pCdb)) {
362
363 BOOLEAN isInformationValid = FALSE;
365
366 if (validSense) {
367
368 //
369 // If this is a data underrun condition (i.e. target truncated the offload data transfer),
370 // the SenseData's Information field may have the TransferCount.
371 //
374
375 //
376 // Sense data in Descriptor format
377 //
379
380 PVOID startBuffer = NULL;
381 UCHAR startBufferLength = 0;
382
383
384 if (ScsiGetSenseDescriptor(senseInfoBuffer,
386 &startBuffer,
387 &startBufferLength)) {
388 UCHAR outType;
390 UCHAR outBufferLength = 0;
391
393
394 if (ScsiGetNextSenseDescriptorByType(startBuffer,
395 startBufferLength,
396 typeList,
397 ARRAYSIZE(typeList),
398 &outType,
399 &outBuffer,
400 &outBufferLength)) {
401
403
404 if (ScsiValidateInformationSenseDescriptor(outBuffer, outBufferLength)) {
406 isInformationValid = TRUE;
407 }
408
409 } else {
410
411 //
412 // ScsiGetNextDescriptorByType should only return a type that is specified by us.
413 //
415 }
416 }
417 }
418 } else {
419
420 //
421 // Sense data in Fixed format
422 //
424 isInformationValid = TRUE;
425 }
426
427 if (isInformationValid) {
429 }
430 }
431 }
432 }
433 }
434
435 }
436 else {
437 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "Unhandled SRB Function %xh in error path for packet %p (did miniport change Srb.Cdb.OperationCode ?)", (ULONG)pCdb->CDB10.OperationCode, Pkt));
438 }
439 }
440
441 return shouldRetry;
442}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned char BOOLEAN
#define MAX(x, y)
Definition: rdesktop.h:175
#define IS_SCSIOP_READWRITE(opCode)
Definition: cdrom.h:803
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
#define SCSIOP_MODE_SENSE10
Definition: cdrw_hw.h:946
#define SCSI_SENSE_COPY_ABORTED
Definition: cdrw_hw.h:1197
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
#define SCSI_SENSE_ABORTED_COMMAND
Definition: cdrw_hw.h:1198
FORCEINLINE BOOLEAN ClasspIsOffloadDataTransferCommand(_In_ PCDB Cdb)
Definition: classp.h:2087
FORCEINLINE PVOID ClasspTransferPacketGetSenseInfoBuffer(_In_ PTRANSFER_PACKET Pkt)
Definition: classp.h:2513
FORCEINLINE BOOLEAN ClasspIsTokenOperation(_In_ PCDB Cdb)
Definition: classp.h:2044
FORCEINLINE BOOLEAN ClasspTransferPacketGetNumberOfRetriesDone(_In_ PTRANSFER_PACKET Pkt, _In_ PCDB Cdb, _Out_ PULONG TimesAlreadyRetried)
Definition: classp.h:2459
FORCEINLINE PCDB ClasspTransferPacketGetCdb(_In_ PTRANSFER_PACKET Pkt)
Definition: classp.h:2445
VOID ClasspConvertToScsiRequestBlock(_Out_ PSCSI_REQUEST_BLOCK Srb, _In_ PSTORAGE_REQUEST_BLOCK SrbEx)
Definition: utils.c:6559
FORCEINLINE UCHAR ClasspTransferPacketGetSenseInfoBufferLength(_In_ PTRANSFER_PACKET Pkt)
Definition: classp.h:2521
#define CLASS_SRB_STORAGE_REQUEST_BLOCK
Definition: classpnp.h:573
static PDB_INFORMATION information
Definition: db.cpp:178
#define NULL
Definition: types.h:112
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
BOOLEAN NTAPI ClassInterpretSenseInfo(_In_ PDEVICE_OBJECT Fdo, _In_ PSCSI_REQUEST_BLOCK _Srb, _In_ UCHAR MajorFunctionCode, _In_ ULONG IoDeviceCode, _In_ ULONG RetryCount, _Out_ NTSTATUS *Status, _Out_opt_ _Deref_out_range_(0, 100) ULONG *RetryInterval)
Definition: class.c:4452
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:357
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:350
#define SRB_STATUS(Status)
Definition: srb.h:389
UCHAR additionalSenseCode
Definition: scsi.h:4020
#define SCSI_SENSE_DESCRIPTOR_TYPE_INFORMATION
Definition: scsi.h:630
#define SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED
Definition: scsi.h:3839
#define REVERSE_BYTES_QUAD(Destination, Source)
Definition: scsi.h:3452
UCHAR senseKey
Definition: scsi.h:4019
PFIXED_SENSE_DATA senseInfoBuffer
Definition: scsi.h:3710
#define SCSI_ADSENSE_COPY_TARGET_DEVICE_ERROR
Definition: scsi.h:657
#define SCSIOP_READ_CAPACITY16
Definition: scsi.h:364
#define SCSI_SENSEQ_DATA_UNDERRUN
Definition: scsi.h:761
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
PFIXED_SENSE_DATA outBuffer
Definition: scsi.h:4022
BOOLEAN validSense
Definition: scsi.h:4018
#define IsDescriptorSenseDataFormat(SenseInfoBuffer)
Definition: scsi.h:3685
#define SRB_FUNCTION_STORAGE_REQUEST_BLOCK
Definition: srb.h:108
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:661
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define STATUS_SUCCESS
Definition: shellext.h:65
FORCEINLINE UCHAR SrbGetSenseInfoBufferLength(_In_ PVOID Srb)
Definition: srbhelper.h:638
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
__callback PCLASS_INTERPRET_SENSE_INFO Interpret
Definition: classpnp.h:566
PCLASS_INTERPRET_SENSE_INFO2 InterpretSenseInfo
Definition: classp.h:958
PCLASS_DRIVER_EXTENSION DriverExtension
Definition: classpnp.h:600
PVOID DeviceExtension
Definition: env_spec_w32.h:418
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
IO_STATUS_BLOCK IoStatus
PSTORAGE_REQUEST_BLOCK_HEADER Srb
Definition: classp.h:580
UCHAR NumIoTimeoutRetries
Definition: classp.h:518
PIRP OriginalIrp
Definition: classp.h:509
PSRB_HISTORY RetryHistory
Definition: classp.h:598
ULONGLONG TransferCount
Definition: classp.h:610
PDEVICE_OBJECT Fdo
Definition: classp.h:503
UCHAR TimedOut
Definition: classp.h:519
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: cdrw_hw.h:28
struct _CDB::_CDB10 CDB10
struct _CDB::_MEDIA_REMOVAL MEDIA_REMOVAL
struct _CDB::_MODE_SENSE MODE_SENSE
struct _CDB::_CDB16 CDB16
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
#define IRP_MJ_SCSI
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by TransferPktComplete().

◆ RetryTransferPacket()

BOOLEAN RetryTransferPacket ( PTRANSFER_PACKET  Pkt)

Definition at line 453 of file retry.c.

454{
455 BOOLEAN packetDone;
456 BOOLEAN scaleDown = FALSE;
458 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
459 PCDB pCdb = SrbGetCdb(Pkt->Srb);
460
461#if !defined(__REACTOS__) && NTDDI_VERSION >= NTDDI_WINBLUE
463 (pCdb != NULL) && IS_SCSIOP_READWRITE(pCdb->CDB10.OperationCode)) {
464
466 //We've already retried this the maximum times. Bail out.
467 return TRUE;
468 }
470 }
471 else {
473 Pkt->NumRetries--;
474 }
475#else
477 Pkt->NumRetries--;
478#endif
479
480 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "retrying failed transfer (pkt=%ph, op=%s)", Pkt, DBGGETSCSIOPSTR(Pkt->Srb)));
481
482 if (!fdoData->DisableThrottling) {
483
484 //
485 // If this is the last retry, then turn off disconnect, sync transfer,
486 // and tagged queuing. On all other retries, leave the original settings.
487 // Do not apply this for thin provisioning soft threshold errors, since
488 // they should succeed as soon as they're retried on the right IT nexus.
489 //
491 scaleDown = TRUE;
492 }
493
494#if (NTDDI_VERSION >= NTDDI_WINBLUE)
495 //
496 // If this request previously timed-out and there are no more retries left
497 // for timed-out requests, then we should also apply the scale down.
498 //
499 if (Pkt->TimedOut && Pkt->NumIoTimeoutRetries == 0) {
500 scaleDown = TRUE;
501 }
502#endif
503 }
504
505
506 if (scaleDown) {
507 /*
508 * Tone down performance on the retry.
509 * This increases the chance for success on the retry.
510 * We've seen instances of drives that fail consistently but then start working
511 * once this scale-down is applied.
512 */
517 }
518
520
521 UCHAR cdbOpcode = 0;
522 BOOLEAN isReadWrite = FALSE;
523
524 if (pCdb) {
525 cdbOpcode = pCdb->CDB10.OperationCode;
526 isReadWrite = IS_SCSIOP_READWRITE(cdbOpcode);
527 }
528
529 if ((Pkt->DriverUsesStartIO) &&
530 ( (cdbOpcode == SCSIOP_WRITE6 ) ||
531 (cdbOpcode == SCSIOP_WRITE ) ||
532 (cdbOpcode == SCSIOP_WRITE12) ||
533 (cdbOpcode == SCSIOP_WRITE16) )) {
534
535 /* don't retry writes in super-low-memory conditions if the
536 * driver must serialize against StartIO. This is because
537 * some write methods used in such drivers cannot accept
538 * random-sized writes. (i.e CD-RW in packet writing mode)
539 * Reads, however, are always safe to split up.
540 */
541 SET_FLAG(fdoData->TrackingFlags, TRACKING_FORWARD_PROGRESS_PATH1);
542 packetDone = TRUE;
543 }
544 else if (Pkt->InLowMemRetry || !isReadWrite){
545 /*
546 * This should never happen under normal circumstances.
547 * The memory manager guarantees that at least four pages will
548 * be available to allow forward progress in the port driver.
549 * So a one-page transfer should never fail with insufficient resources.
550 *
551 * However, it is possible to get in here with virtual storage
552 * or thin provisioned storage for example.
553 * A single sector write can trigger an allocation request and
554 * presently a forward progress guarantee is not provided.
555 * VHD also may have some limitations in forward progress guarantee.
556 * And USB too might also fall into this category.
557 */
558 SET_FLAG(fdoData->TrackingFlags, TRACKING_FORWARD_PROGRESS_PATH2);
559 packetDone = TRUE;
560 }
561 else {
562 /*
563 * We are in low-memory stress.
564 * Start the low-memory retry state machine, which tries to
565 * resend the packet in little one-page chunks.
566 */
567 SET_FLAG(fdoData->TrackingFlags, TRACKING_FORWARD_PROGRESS_PATH3);
573 packetDone = FALSE;
574 }
575 }
576 else {
577 /*
578 * Retry the packet by simply resending it after a delay.
579 * Put the packet back in the pending queue and
580 * schedule a timer to retry the transfer.
581 *
582 * Do not call SetupReadWriteTransferPacket again because:
583 * (1) The minidriver may have set some bits
584 * in the SRB that it needs again and
585 * (2) doing so would reset numRetries.
586 *
587 * BECAUSE we do not call SetupReadWriteTransferPacket again,
588 * we have to reset a couple fields in the SRB that
589 * some miniports overwrite when they fail an SRB.
590 */
591
594
596
597 packetDone = FALSE;
598 }
599
600 return packetDone;
601}
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define SCSIOP_WRITE6
Definition: cdrw_hw.h:876
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
#define SCSIOP_WRITE12
Definition: cdrw_hw.h:957
#define NUM_THIN_PROVISIONING_RETRIES
Definition: classp.h:162
#define TRACKING_FORWARD_PROGRESS_PATH3
Definition: classp.h:2387
BOOLEAN ClasspIsThinProvisioningError(_In_ PSCSI_REQUEST_BLOCK _Srb)
Definition: utils.c:9127
#define TRACKING_FORWARD_PROGRESS_PATH2
Definition: classp.h:2386
#define TRACKING_FORWARD_PROGRESS_PATH1
Definition: classp.h:2385
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
#define DBGGETSCSIOPSTR(_pSrb)
Definition: debug.h:26
#define SCSIOP_WRITE16
Definition: scsi.h:915
#define SP_UNTAGGED
Definition: srb.h:233
#define SRB_FLAGS_DISABLE_DISCONNECT
Definition: srb.h:396
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:395
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:397
BOOLEAN StepLowMemRetry(PTRANSFER_PACKET Pkt)
Definition: retry.c:706
VOID TransferPacketQueueRetryDpc(PTRANSFER_PACKET Pkt)
Definition: retry.c:604
VOID InitLowMemRetry(PTRANSFER_PACKET Pkt, PVOID BufPtr, ULONG Len, LARGE_INTEGER TargetLocation)
Definition: retry.c:670
FORCEINLINE VOID SrbSetSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:964
FORCEINLINE VOID SrbSetDataTransferLength(_In_ PVOID Srb, _In_ ULONG DataTransferLength)
Definition: srbhelper.h:784
FORCEINLINE VOID SrbClearSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:982
FORCEINLINE VOID SrbSetDataBuffer(_In_ PVOID Srb, _In_opt_ __drv_aliasesMem PVOID DataBuffer)
Definition: srbhelper.h:747
#define SrbSetRequestTag
Definition: srbhelper.h:869
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
UCHAR NumRetries
Definition: classp.h:516
LARGE_INTEGER TargetLocationCopy
Definition: classp.h:564
UCHAR NumThinProvisioningRetries
Definition: classp.h:517
ULONG BufLenCopy
Definition: classp.h:563
PUCHAR BufPtrCopy
Definition: classp.h:562
#define SrbGetCdb(srb)
Definition: usbstor.h:18

Referenced by TransferPktComplete().

◆ StepLowMemRetry()

BOOLEAN StepLowMemRetry ( PTRANSFER_PACKET  Pkt)

Definition at line 706 of file retry.c.

707{
708 BOOLEAN packetDone;
709
711 packetDone = TRUE;
712 }
713 else {
714 ULONG thisChunkLen;
716 {
717 /*
718 * Need the fdoData for the HwMaxXferLen
719 */
721 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
722
723 /*
724 * Need the adapterDesc to limit transfers based on byte count
725 */
727 PSTORAGE_ADAPTER_DESCRIPTOR adapterDesc = commonExtension->PartitionZeroExtension->AdapterDescriptor;
728
729 ULONG hwMaxXferLen;
730
731 /*
732 * special case: StartIO-based writing must stay serialized for performance
733 * and proper operations (i.e. sequential writing mode). If need more than
734 * one transfer to perform this operation, and it's a StartIO-based driver
735 * (such as CDROM), then just use a single packet and use the retry logic
736 * that's already built-in to the packet engine. Note that low-mem retry
737 * cannot be used directly because some write methods do not work if the
738 * writes are only PAGE_SIZE (i.e. packet writing may corrupt data).
739 */
741
742 /*
743 * We precomputed fdoData->HwMaxXferLen using (MaximumPhysicalPages-1).
744 * If the buffer is page-aligned, that's one less page crossing so we can add the page back in.
745 * Note: adapters that return MaximumPhysicalPages=0x10 depend on this to
746 * transfer aligned 64K requests in one piece.
747 * Also note: make sure adding PAGE_SIZE back in doesn't wrap to zero.
748 */
749
750 if (((ULONG_PTR)(Pkt->LowMemRetry_remainingBufPtr) & (PAGE_SIZE-1)) || (fdoData->HwMaxXferLen > 0xffffffff-PAGE_SIZE)){
751 hwMaxXferLen = fdoData->HwMaxXferLen;
752 }
753 else {
755 hwMaxXferLen = min(fdoData->HwMaxXferLen+PAGE_SIZE, adapterDesc->MaximumTransferLength);
756 }
757 thisChunkLen = MIN(Pkt->LowMemRetry_remainingBufLen, hwMaxXferLen);
758 }
759 else {
760 /*
761 * Make sure the little chunk we send is <= a page length
762 * AND that it does not cross any page boundaries.
763 */
764 ULONG bytesToNextPageBoundary;
765 bytesToNextPageBoundary = PAGE_SIZE-(ULONG)((ULONG_PTR)Pkt->LowMemRetry_remainingBufPtr%PAGE_SIZE);
766 thisChunkLen = MIN(Pkt->LowMemRetry_remainingBufLen, bytesToNextPageBoundary);
768 }
769
770
771 /*
772 * Set up the transfer packet for the new little chunk.
773 * This will reset numRetries so that we retry each chunk as required.
774 */
777 thisChunkLen,
780
781 Pkt->LowMemRetry_remainingBufPtr += thisChunkLen;
782 Pkt->LowMemRetry_remainingBufLen -= thisChunkLen;
784
785 //
786 // When running in low-memory stress, always use a partial MDL.
787 // This allows lower drivers to potentially map a smaller buffer.
788 //
790
792
793 packetDone = FALSE;
794 }
795
796 return packetDone;
797}
#define MIN(x, y)
Definition: rdesktop.h:171
VOID SetupReadWriteTransferPacket(PTRANSFER_PACKET pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp)
Definition: xferpkt.c:718
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define min(a, b)
Definition: monoChain.cc:55
* PSTORAGE_ADAPTER_DESCRIPTOR
Definition: ntddstor.h:599
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:599
ULONG BytesPerSector
Definition: ntdddisk.h:404
DISK_GEOMETRY DiskGeometry
Definition: classpnp.h:888
BOOLEAN UsePartialMdl
Definition: classp.h:595
uint32_t ULONG_PTR
Definition: typedefs.h:65
LONGLONG QuadPart
Definition: typedefs.h:114

Referenced by RetryTransferPacket(), ServiceTransferRequest(), and TransferPktComplete().

◆ TransferPacketQueueRetryDpc()

VOID TransferPacketQueueRetryDpc ( PTRANSFER_PACKET  Pkt)

Definition at line 604 of file retry.c.

605{
607
608 if (Pkt->RetryIn100nsUnits == 0){
610 }
611 else {
612 LARGE_INTEGER timerPeriod;
613
614 NT_ASSERT(Pkt->RetryIn100nsUnits < 100 * 1000 * 1000 * 10); // sanity check -- 100 seconds is normally too long
615 timerPeriod.QuadPart = -(Pkt->RetryIn100nsUnits);
617 KeSetTimer(&Pkt->RetryTimer, timerPeriod, &Pkt->RetryTimerDPC);
618 }
619}
KDEFERRED_ROUTINE TransferPacketRetryTimerDpc
Definition: classp.h:1727
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:725
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
KDPC RetryTimerDPC
Definition: classp.h:524
KTIMER RetryTimer
Definition: classp.h:523
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233

Referenced by RetryTransferPacket(), ServiceTransferRequest(), and StepLowMemRetry().

◆ TransferPacketRetryTimerDpc()

VOID NTAPI TransferPacketRetryTimerDpc ( IN PKDPC  Dpc,
IN PVOID  DeferredContext,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2 
)

Definition at line 624 of file retry.c.

628{
630 PDEVICE_OBJECT fdo;
631 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
632
634
636
637 fdo = pkt->Fdo;
638 fdoExtension = fdo->DeviceExtension;
639
643
644
645 /*
646 * Sometimes the port driver can allocates a new 'sense' buffer
647 * to report transfer errors, e.g. when the default sense buffer
648 * is too small. If so, it is up to us to free it.
649 * Now that we're done using the sense info, free it if appropriate.
650 * Then clear the sense buffer so it doesn't pollute future errors returned in this packet.
651 */
652 if (PORT_ALLOCATED_SENSE_EX(fdoExtension, pkt->Srb)) {
653 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW, "Freeing port-allocated sense buffer for pkt %ph.", pkt));
654 FREE_PORT_ALLOCATED_SENSE_BUFFER_EX(fdoExtension, pkt->Srb);
657 }
658 else {
661 }
662
664
666
667}
struct _TRANSFER_PACKET * PTRANSFER_PACKET
NTSTATUS SubmitTransferPacket(PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:850
FORCEINLINE BOOLEAN PORT_ALLOCATED_SENSE_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
Definition: classp.h:2547
FORCEINLINE VOID FREE_PORT_ALLOCATED_SENSE_BUFFER_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
Definition: classp.h:2560
#define _Analysis_assume_(expr)
Definition: ms_sal.h:2901
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
FORCEINLINE VOID SrbSetSenseInfoBufferLength(_In_ PVOID Srb, _In_ UCHAR SenseInfoBufferLength)
Definition: srbhelper.h:675
FORCEINLINE VOID SrbSetSenseInfoBuffer(_In_ PVOID Srb, _In_opt_ PVOID SenseInfoBuffer)
Definition: srbhelper.h:657
FORCEINLINE PVOID SrbGetSenseInfoBuffer(_In_ PVOID Srb)
Definition: srbhelper.h:619
SENSE_DATA_EX SrbErrorSenseData
Definition: classp.h:570
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:688
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:689