Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2413 lines
62 KiB

  1. /*++
  2. Copyright (C) 1991-5 Microsoft Corporation
  3. Module Name:
  4. redist.cxx
  5. Abstract:
  6. This module contains the code specific to redistributions for the fault
  7. tolerance driver.
  8. Author:
  9. Norbert Kusters 6-Feb-1997
  10. Environment:
  11. kernel mode only
  12. Notes:
  13. Revision History:
  14. --*/
  15. extern "C" {
  16. #include <ntddk.h>
  17. }
  18. #include <ftdisk.h>
  19. class PROPOGATE_CHANGES_WORK_ITEM : public WORK_QUEUE_ITEM {
  20. public:
  21. PREDISTRIBUTION Redistribution;
  22. FT_COMPLETION_ROUTINE CompletionRoutine;
  23. PVOID Context;
  24. };
  25. typedef PROPOGATE_CHANGES_WORK_ITEM *PPROPOGATE_CHANGES_WORK_ITEM;
  26. #ifdef ALLOC_PRAGMA
  27. #pragma code_seg("PAGE")
  28. #endif
  29. NTSTATUS
  30. REDISTRIBUTION::Initialize(
  31. IN OUT PROOT_EXTENSION RootExtension,
  32. IN FT_LOGICAL_DISK_ID LogicalDiskId,
  33. IN OUT PFT_VOLUME* VolumeArray,
  34. IN USHORT ArraySize,
  35. IN PVOID ConfigInfo,
  36. IN PVOID StateInfo
  37. )
  38. /*++
  39. Routine Description:
  40. Initialize routine for FT_VOLUME of type REDISTRIBUTION.
  41. Arguments:
  42. RootExtension - Supplies the root device extension.
  43. LogicalDiskId - Supplies the logical disk id for this volume.
  44. VolumeArray - Supplies the array of volumes for this volume set.
  45. ArraySize - Supplies the number of volumes in the volume array.
  46. ConfigInfo - Supplies the configuration information.
  47. StateInfo - Supplies the state information.
  48. Return Value:
  49. NTSTATUS
  50. --*/
  51. {
  52. BOOLEAN oneGood;
  53. USHORT i;
  54. NTSTATUS status;
  55. PFT_REDISTRIBUTION_CONFIGURATION_INFORMATION configInfo;
  56. LONGLONG firstRowSize;
  57. LONGLONG secondRowSize;
  58. LONGLONG numRows;
  59. LONGLONG tmpNumRows;
  60. if (ArraySize != 2) {
  61. return STATUS_INVALID_PARAMETER;
  62. }
  63. oneGood = FALSE;
  64. for (i = 0; i < ArraySize; i++) {
  65. if (VolumeArray[i]) {
  66. oneGood = TRUE;
  67. }
  68. }
  69. if (!oneGood) {
  70. return STATUS_INVALID_PARAMETER;
  71. }
  72. status = COMPOSITE_FT_VOLUME::Initialize(RootExtension, LogicalDiskId,
  73. VolumeArray, ArraySize,
  74. ConfigInfo, StateInfo);
  75. if (!NT_SUCCESS(status)) {
  76. return status;
  77. }
  78. configInfo = (PFT_REDISTRIBUTION_CONFIGURATION_INFORMATION) ConfigInfo;
  79. _stripeSize = configInfo->StripeSize;
  80. if (_stripeSize < QuerySectorSize()) {
  81. return STATUS_INVALID_PARAMETER;
  82. }
  83. for (i = 0; _stripeSize%2 == 0; i++) {
  84. _stripeSize /= 2;
  85. }
  86. if (_stripeSize != 1) {
  87. return STATUS_INVALID_PARAMETER;
  88. }
  89. _stripeSize = configInfo->StripeSize;
  90. if( !configInfo->FirstMemberWidth || !configInfo->SecondMemberWidth) {
  91. return STATUS_INVALID_PARAMETER;
  92. }
  93. _firstWidth = configInfo->FirstMemberWidth;
  94. _totalWidth = _firstWidth + configInfo->SecondMemberWidth;
  95. if (VolumeArray[0]) {
  96. _firstSize = VolumeArray[0]->QueryVolumeSize();
  97. } else {
  98. _firstSize = 0;
  99. }
  100. if (_firstSize && VolumeArray[1]) {
  101. firstRowSize = _firstWidth*_stripeSize;
  102. numRows = _firstSize/firstRowSize;
  103. secondRowSize = configInfo->SecondMemberWidth*_stripeSize;
  104. tmpNumRows = VolumeArray[1]->QueryVolumeSize()/secondRowSize;
  105. if (tmpNumRows < numRows) {
  106. numRows = tmpNumRows;
  107. }
  108. _totalSize = numRows*_totalWidth*_stripeSize;
  109. if (_totalSize < _firstSize) {
  110. return STATUS_INVALID_PARAMETER;
  111. }
  112. } else {
  113. _totalSize = 0;
  114. }
  115. _syncOk = TRUE;
  116. _stopSyncs = FALSE;
  117. RtlCopyMemory(&_state, StateInfo, sizeof(_state));
  118. if (_state.BytesRedistributed < _firstSize) {
  119. _redistributionComplete = FALSE;
  120. } else {
  121. _redistributionComplete = TRUE;
  122. }
  123. status = _overlappedIoManager.Initialize(0);
  124. return status;
  125. }
  126. FT_LOGICAL_DISK_TYPE
  127. REDISTRIBUTION::QueryLogicalDiskType(
  128. )
  129. /*++
  130. Routine Description:
  131. This routine returns the type of the logical disk.
  132. Arguments:
  133. None.
  134. Return Value:
  135. The type of the logical disk.
  136. --*/
  137. {
  138. return FtRedistribution;
  139. }
  140. NTSTATUS
  141. REDISTRIBUTION::CheckIo(
  142. OUT PBOOLEAN IsIoOk
  143. )
  144. /*++
  145. Routine Description:
  146. This routine returns whether or not IO is possible on the given
  147. logical disk.
  148. Arguments:
  149. IsIoOk - Returns the state of IO.
  150. Return Value:
  151. NTSTATUS
  152. --*/
  153. {
  154. USHORT n, i;
  155. PFT_VOLUME vol;
  156. NTSTATUS status;
  157. n = QueryNumMembers();
  158. for (i = 0; i < n; i++) {
  159. vol = GetMemberUnprotected(i);
  160. if (!vol) {
  161. *IsIoOk = FALSE;
  162. return STATUS_SUCCESS;
  163. }
  164. status = vol->CheckIo(IsIoOk);
  165. if (!NT_SUCCESS(status)) {
  166. return status;
  167. }
  168. if (!(*IsIoOk)) {
  169. return STATUS_SUCCESS;
  170. }
  171. }
  172. return STATUS_SUCCESS;
  173. }
  174. #ifdef ALLOC_PRAGMA
  175. #pragma code_seg("PAGELK")
  176. #endif
  177. REDISTRIBUTION::~REDISTRIBUTION(
  178. )
  179. {
  180. }
  181. VOID
  182. RedistributionTwoPartCompletionRoutine(
  183. IN OUT PTRANSFER_PACKET TransferPacket
  184. )
  185. /*++
  186. Routine Description:
  187. This routine is the completion of a two part operation.
  188. Arguments:
  189. TransferPacket - Supplies the transfer packet.
  190. Return Value:
  191. None.
  192. --*/
  193. {
  194. PREDISTRIBUTION_TP transferPacket = (PREDISTRIBUTION_TP) TransferPacket;
  195. PREDISTRIBUTION_LOCK_TP lockPacket = (PREDISTRIBUTION_LOCK_TP) transferPacket->MasterPacket;
  196. PTRANSFER_PACKET masterPacket = lockPacket->MasterPacket;
  197. NTSTATUS status = transferPacket->IoStatus.Status;
  198. KIRQL irql;
  199. LONG count;
  200. KeAcquireSpinLock(&lockPacket->SpinLock, &irql);
  201. if (NT_SUCCESS(status)) {
  202. if (NT_SUCCESS(lockPacket->IoStatus.Status)) {
  203. lockPacket->IoStatus.Information +=
  204. transferPacket->IoStatus.Information;
  205. }
  206. } else {
  207. if (FtpIsWorseStatus(status, lockPacket->IoStatus.Status)) {
  208. lockPacket->IoStatus.Status = status;
  209. }
  210. }
  211. count = --lockPacket->RefCount;
  212. KeReleaseSpinLock(&lockPacket->SpinLock, irql);
  213. delete transferPacket;
  214. if (!count) {
  215. masterPacket->IoStatus = lockPacket->IoStatus;
  216. delete lockPacket;
  217. masterPacket->CompletionRoutine(masterPacket);
  218. }
  219. }
  220. VOID
  221. RedistributionRegionLockCompletion(
  222. IN OUT PTRANSFER_PACKET LockPacket
  223. )
  224. /*++
  225. Routine Description:
  226. This routine is the completion of a region lock operation.
  227. Arguments:
  228. LockPacket - Supplies the lock packet.
  229. Return Value:
  230. None.
  231. --*/
  232. {
  233. PREDISTRIBUTION_LOCK_TP lockPacket = (PREDISTRIBUTION_LOCK_TP) LockPacket;
  234. PREDISTRIBUTION t = lockPacket->Redistribution;
  235. PTRANSFER_PACKET masterPacket = lockPacket->MasterPacket;
  236. KIRQL irql;
  237. LONGLONG bytesRedistributed;
  238. LONGLONG redistOffset, regularOffset;
  239. ULONG redistLength, regularLength;
  240. PREDISTRIBUTION_TP redistPacket, regularPacket;
  241. PCHAR vp;
  242. KeAcquireSpinLock(&t->_spinLock, &irql);
  243. bytesRedistributed = t->_state.BytesRedistributed;
  244. KeReleaseSpinLock(&t->_spinLock, irql);
  245. if (lockPacket->Offset < bytesRedistributed) {
  246. redistOffset = lockPacket->Offset;
  247. redistLength = lockPacket->Length;
  248. if (redistOffset + redistLength > bytesRedistributed) {
  249. redistLength = (ULONG) (bytesRedistributed - redistOffset);
  250. }
  251. } else {
  252. redistLength = 0;
  253. }
  254. if (redistLength < lockPacket->Length) {
  255. regularLength = lockPacket->Length - redistLength;
  256. regularOffset = lockPacket->Offset + redistLength;
  257. } else {
  258. regularLength = 0;
  259. }
  260. KeInitializeSpinLock(&lockPacket->SpinLock);
  261. lockPacket->IoStatus.Status = STATUS_SUCCESS;
  262. lockPacket->IoStatus.Information = 0;
  263. lockPacket->RefCount = 0;
  264. if (lockPacket->Mdl && redistLength && regularLength) {
  265. vp = (PCHAR) MmGetMdlVirtualAddress(lockPacket->Mdl);
  266. }
  267. if (redistLength) {
  268. lockPacket->RefCount++;
  269. redistPacket = new REDISTRIBUTION_TP;
  270. if (!redistPacket) {
  271. delete lockPacket;
  272. masterPacket->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  273. masterPacket->IoStatus.Information = 0;
  274. masterPacket->CompletionRoutine(masterPacket);
  275. return;
  276. }
  277. if (regularLength) {
  278. if (lockPacket->Mdl) {
  279. if (redistPacket->AllocateMdl(vp, redistLength)) {
  280. IoBuildPartialMdl(lockPacket->Mdl, redistPacket->Mdl,
  281. vp, redistLength);
  282. } else {
  283. delete redistPacket;
  284. delete lockPacket;
  285. masterPacket->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  286. masterPacket->IoStatus.Information = 0;
  287. masterPacket->CompletionRoutine(masterPacket);
  288. return;
  289. }
  290. } else {
  291. redistPacket->Mdl = lockPacket->Mdl;
  292. }
  293. } else {
  294. redistPacket->Mdl = lockPacket->Mdl;
  295. }
  296. redistPacket->Length = redistLength;
  297. redistPacket->Offset = redistOffset;
  298. redistPacket->CompletionRoutine = RedistributionTwoPartCompletionRoutine;
  299. redistPacket->TargetVolume = t;
  300. redistPacket->Thread = lockPacket->Thread;
  301. redistPacket->IrpFlags = lockPacket->IrpFlags;
  302. redistPacket->ReadPacket = lockPacket->ReadPacket;
  303. redistPacket->MasterPacket = lockPacket;
  304. redistPacket->Redistribution = t;
  305. redistPacket->WhichMember = 0;
  306. }
  307. if (regularLength) {
  308. lockPacket->RefCount++;
  309. regularPacket = new REDISTRIBUTION_TP;
  310. if (!regularPacket) {
  311. if (redistLength) {
  312. delete redistPacket;
  313. }
  314. delete lockPacket;
  315. masterPacket->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  316. masterPacket->IoStatus.Information = 0;
  317. masterPacket->CompletionRoutine(masterPacket);
  318. return;
  319. }
  320. if (redistLength) {
  321. if (lockPacket->Mdl) {
  322. if (regularPacket->AllocateMdl(vp, regularLength)) {
  323. IoBuildPartialMdl(lockPacket->Mdl, regularPacket->Mdl,
  324. vp, regularLength);
  325. } else {
  326. if (redistLength) {
  327. delete redistPacket;
  328. }
  329. delete regularPacket;
  330. delete lockPacket;
  331. masterPacket->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  332. masterPacket->IoStatus.Information = 0;
  333. masterPacket->CompletionRoutine(masterPacket);
  334. return;
  335. }
  336. } else {
  337. regularPacket->Mdl = lockPacket->Mdl;
  338. }
  339. } else {
  340. regularPacket->Mdl = lockPacket->Mdl;
  341. }
  342. regularPacket->Length = regularLength;
  343. regularPacket->Offset = regularOffset;
  344. regularPacket->CompletionRoutine = RedistributionTwoPartCompletionRoutine;
  345. regularPacket->TargetVolume = t->GetMemberUnprotected(0);
  346. regularPacket->Thread = lockPacket->Thread;
  347. regularPacket->IrpFlags = lockPacket->IrpFlags;
  348. regularPacket->ReadPacket = lockPacket->ReadPacket;
  349. regularPacket->MasterPacket = lockPacket;
  350. regularPacket->Redistribution = t;
  351. regularPacket->WhichMember = 0;
  352. }
  353. if (redistLength) {
  354. t->RedistributeTransfer(redistPacket);
  355. }
  356. if (regularLength) {
  357. TRANSFER(regularPacket);
  358. }
  359. }
  360. VOID
  361. REDISTRIBUTION::Transfer(
  362. IN OUT PTRANSFER_PACKET TransferPacket
  363. )
  364. /*++
  365. Routine Description:
  366. Transfer routine for REDISTRIBUTION type FT_VOLUME. Figure out
  367. which volumes this request needs to be dispatched to.
  368. Arguments:
  369. TransferPacket - Supplies the transfer packet.
  370. Return Value:
  371. None.
  372. --*/
  373. {
  374. PREDISTRIBUTION_LOCK_TP lockPacket;
  375. if (!_redistributionComplete) {
  376. if (TransferPacket->Offset + TransferPacket->Length > _firstSize) {
  377. TransferPacket->IoStatus.Status = STATUS_INVALID_PARAMETER;
  378. TransferPacket->IoStatus.Information = 0;
  379. TransferPacket->CompletionRoutine(TransferPacket);
  380. return;
  381. }
  382. lockPacket = new REDISTRIBUTION_LOCK_TP;
  383. if (!lockPacket) {
  384. TransferPacket->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  385. TransferPacket->IoStatus.Information = 0;
  386. TransferPacket->CompletionRoutine(TransferPacket);
  387. return;
  388. }
  389. lockPacket->Mdl = TransferPacket->Mdl;
  390. lockPacket->Length = TransferPacket->Length;
  391. lockPacket->Offset = TransferPacket->Offset;
  392. lockPacket->CompletionRoutine = RedistributionRegionLockCompletion;
  393. lockPacket->TargetVolume = TransferPacket->TargetVolume;
  394. lockPacket->Thread = TransferPacket->Thread;
  395. lockPacket->IrpFlags = TransferPacket->IrpFlags;
  396. lockPacket->ReadPacket = TransferPacket->ReadPacket;
  397. lockPacket->MasterPacket = TransferPacket;
  398. lockPacket->Redistribution = this;
  399. _overlappedIoManager.AcquireIoRegion(lockPacket, TRUE);
  400. return;
  401. }
  402. if (TransferPacket->Offset + TransferPacket->Length > _totalSize) {
  403. TransferPacket->IoStatus.Status = STATUS_INVALID_PARAMETER;
  404. TransferPacket->IoStatus.Information = 0;
  405. TransferPacket->CompletionRoutine(TransferPacket);
  406. return;
  407. }
  408. RedistributeTransfer(TransferPacket);
  409. }
  410. VOID
  411. RedistributionReplaceCompletion(
  412. IN OUT PTRANSFER_PACKET TransferPacket
  413. )
  414. /*++
  415. Routine Description:
  416. This is the completion routine for a replace request.
  417. Arguments:
  418. TransferPacket - Supplies the transfer packet.
  419. Return Value:
  420. None.
  421. --*/
  422. {
  423. PREDISTRIBUTION_LOCK_TP transferPacket = (PREDISTRIBUTION_LOCK_TP) TransferPacket;
  424. PTRANSFER_PACKET masterPacket = transferPacket->MasterPacket;
  425. masterPacket->IoStatus = transferPacket->IoStatus;
  426. delete transferPacket;
  427. masterPacket->CompletionRoutine(masterPacket);
  428. }
  429. VOID
  430. RedistributionLockReplaceCompletion(
  431. IN OUT PTRANSFER_PACKET TransferPacket
  432. )
  433. /*++
  434. Routine Description:
  435. This is the completion routine for a lock request.
  436. Arguments:
  437. TransferPacket - Supplies the transfer packet.
  438. Return Value:
  439. None.
  440. --*/
  441. {
  442. PREDISTRIBUTION_LOCK_TP transferPacket = (PREDISTRIBUTION_LOCK_TP) TransferPacket;
  443. PREDISTRIBUTION t = transferPacket->Redistribution;
  444. KIRQL irql;
  445. LONGLONG bytesRedistributed;
  446. KeAcquireSpinLock(&t->_spinLock, &irql);
  447. bytesRedistributed = t->_state.BytesRedistributed;
  448. KeReleaseSpinLock(&t->_spinLock, irql);
  449. transferPacket->CompletionRoutine = RedistributionReplaceCompletion;
  450. if (transferPacket->Offset < bytesRedistributed) {
  451. t->RedistributeReplaceBadSector(transferPacket);
  452. } else {
  453. transferPacket->TargetVolume = t->GetMemberUnprotected(0);
  454. transferPacket->TargetVolume->ReplaceBadSector(transferPacket);
  455. }
  456. }
  457. VOID
  458. REDISTRIBUTION::ReplaceBadSector(
  459. IN OUT PTRANSFER_PACKET TransferPacket
  460. )
  461. /*++
  462. Routine Description:
  463. This routine attempts to fix the given bad sector by routing
  464. the request to the appropriate sub-volume.
  465. Arguments:
  466. TransferPacket - Supplies the transfer packet.
  467. Return Value:
  468. None.
  469. --*/
  470. {
  471. PREDISTRIBUTION_LOCK_TP lockPacket;
  472. if (!_redistributionComplete) {
  473. if (TransferPacket->Offset + TransferPacket->Length > _firstSize) {
  474. TransferPacket->IoStatus.Status = STATUS_INVALID_PARAMETER;
  475. TransferPacket->IoStatus.Information = 0;
  476. TransferPacket->CompletionRoutine(TransferPacket);
  477. return;
  478. }
  479. lockPacket = new REDISTRIBUTION_LOCK_TP;
  480. if (!lockPacket) {
  481. TransferPacket->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  482. TransferPacket->IoStatus.Information = 0;
  483. TransferPacket->CompletionRoutine(TransferPacket);
  484. return;
  485. }
  486. lockPacket->Mdl = TransferPacket->Mdl;
  487. lockPacket->Length = TransferPacket->Length;
  488. lockPacket->Offset = TransferPacket->Offset;
  489. lockPacket->CompletionRoutine = RedistributionLockReplaceCompletion;
  490. lockPacket->TargetVolume = TransferPacket->TargetVolume;
  491. lockPacket->Thread = TransferPacket->Thread;
  492. lockPacket->IrpFlags = TransferPacket->IrpFlags;
  493. lockPacket->ReadPacket = TransferPacket->ReadPacket;
  494. lockPacket->MasterPacket = TransferPacket;
  495. lockPacket->Redistribution = this;
  496. _overlappedIoManager.AcquireIoRegion(lockPacket, TRUE);
  497. return;
  498. }
  499. if (TransferPacket->Offset + TransferPacket->Length > _totalSize) {
  500. TransferPacket->IoStatus.Status = STATUS_INVALID_PARAMETER;
  501. TransferPacket->IoStatus.Information = 0;
  502. TransferPacket->CompletionRoutine(TransferPacket);
  503. return;
  504. }
  505. RedistributeReplaceBadSector(TransferPacket);
  506. }
  507. VOID
  508. RedistributionCompositeVolumeCompletionRoutine(
  509. IN PVOID Context,
  510. IN NTSTATUS Status
  511. )
  512. {
  513. PFT_COMPLETION_ROUTINE_CONTEXT context;
  514. KIRQL irql;
  515. LONG count;
  516. context = (PFT_COMPLETION_ROUTINE_CONTEXT) Context;
  517. KeAcquireSpinLock(&context->SpinLock, &irql);
  518. if (!NT_SUCCESS(Status) && FtpIsWorseStatus(Status, context->Status)) {
  519. context->Status = Status;
  520. }
  521. count = --context->RefCount;
  522. KeReleaseSpinLock(&context->SpinLock, irql);
  523. if (!count) {
  524. context->CompletionRoutine(context->Context, STATUS_SUCCESS);
  525. ExFreePool(context);
  526. }
  527. }
  528. VOID
  529. RedistributionSyncPhase6(
  530. IN OUT PVOID SyncPacket,
  531. IN NTSTATUS Status
  532. )
  533. /*++
  534. Routine Description:
  535. This is the completion routine for the update state part of a sync.
  536. Arguments:
  537. SyncPacket - Supplies the transfer packet.
  538. Status - Supplies the status.
  539. Return Value:
  540. None.
  541. --*/
  542. {
  543. PREDISTRIBUTION_SYNC_TP syncPacket = (PREDISTRIBUTION_SYNC_TP) SyncPacket;
  544. PREDISTRIBUTION_TP ioPacket = &syncPacket->IoPacket;
  545. PREDISTRIBUTION t = syncPacket->Redistribution;
  546. KIRQL irql;
  547. BOOLEAN allDone;
  548. if (!NT_SUCCESS(Status)) {
  549. KeAcquireSpinLock(&t->_spinLock, &irql);
  550. t->_state.BytesRedistributed -= ioPacket->Length;
  551. t->_syncOk = TRUE;
  552. KeReleaseSpinLock(&t->_spinLock, irql);
  553. t->_overlappedIoManager.ReleaseIoRegion(syncPacket);
  554. RedistributionCompositeVolumeCompletionRoutine(syncPacket->Context,
  555. STATUS_SUCCESS);
  556. delete syncPacket;
  557. return;
  558. }
  559. if (t->_state.BytesRedistributed == t->_firstSize) {
  560. t->_redistributionComplete = TRUE;
  561. allDone = TRUE;
  562. } else {
  563. allDone = FALSE;
  564. }
  565. t->_overlappedIoManager.ReleaseIoRegion(syncPacket);
  566. if (allDone) {
  567. RedistributionCompositeVolumeCompletionRoutine(syncPacket->Context,
  568. STATUS_SUCCESS);
  569. delete syncPacket;
  570. return;
  571. }
  572. syncPacket->Offset = t->_state.BytesRedistributed;
  573. t->_overlappedIoManager.AcquireIoRegion(syncPacket, TRUE);
  574. }
  575. VOID
  576. RedistributionSyncPhase5(
  577. IN OUT PTRANSFER_PACKET TransferPacket
  578. )
  579. /*++
  580. Routine Description:
  581. This is the completion routine for the write verify part of a sync.
  582. Arguments:
  583. TransferPacket - Supplies the transfer packet.
  584. Return Value:
  585. None.
  586. --*/
  587. {
  588. PREDISTRIBUTION_TP ioPacket = (PREDISTRIBUTION_TP) TransferPacket;
  589. PREDISTRIBUTION_SYNC_TP syncPacket = (PREDISTRIBUTION_SYNC_TP) ioPacket->MasterPacket;
  590. PREDISTRIBUTION t = syncPacket->Redistribution;
  591. NTSTATUS status = ioPacket->IoStatus.Status;
  592. KIRQL irql;
  593. if (FsRtlIsTotalDeviceFailure(status)) {
  594. KeAcquireSpinLock(&t->_spinLock, &irql);
  595. t->_syncOk = TRUE;
  596. KeReleaseSpinLock(&t->_spinLock, irql);
  597. RedistributionCompositeVolumeCompletionRoutine(syncPacket->Context,
  598. status);
  599. delete syncPacket;
  600. return;
  601. }
  602. if (!NT_SUCCESS(status)) {
  603. KeAcquireSpinLock(&t->_spinLock, &irql);
  604. t->_syncOk = TRUE;
  605. KeReleaseSpinLock(&t->_spinLock, irql);
  606. RedistributionCompositeVolumeCompletionRoutine(syncPacket->Context, status);
  607. delete syncPacket;
  608. FtpLogError(t->_rootExtension, t->QueryLogicalDiskId(),
  609. FT_REDISTRIBUTION_ERROR, status, 0);
  610. return;
  611. }
  612. KeAcquireSpinLock(&t->_spinLock, &irql);
  613. t->_state.BytesRedistributed += ioPacket->Length;
  614. KeReleaseSpinLock(&t->_spinLock, irql);
  615. t->PropogateStateChanges(RedistributionSyncPhase6, syncPacket);
  616. }
  617. VOID
  618. RedistributionSyncPhase4(
  619. IN OUT PTRANSFER_PACKET TransferPacket
  620. )
  621. /*++
  622. Routine Description:
  623. This is the completion routine for the verify write part of a sync.
  624. Arguments:
  625. TransferPacket - Supplies the transfer packet.
  626. Return Value:
  627. None.
  628. --*/
  629. {
  630. PREDISTRIBUTION_TP ioPacket = (PREDISTRIBUTION_TP) TransferPacket;
  631. PREDISTRIBUTION_SYNC_TP syncPacket = (PREDISTRIBUTION_SYNC_TP) ioPacket->MasterPacket;
  632. PREDISTRIBUTION t = syncPacket->Redistribution;
  633. NTSTATUS status = ioPacket->IoStatus.Status;
  634. KIRQL irql;
  635. if (FsRtlIsTotalDeviceFailure(status)) {
  636. KeAcquireSpinLock(&t->_spinLock, &irql);
  637. t->_syncOk = TRUE;
  638. KeReleaseSpinLock(&t->_spinLock, irql);
  639. RedistributionCompositeVolumeCompletionRoutine(syncPacket->Context,
  640. status);
  641. delete syncPacket;
  642. return;
  643. }
  644. if (!NT_SUCCESS(status)) {
  645. ioPacket->CompletionRoutine = RedistributionSyncPhase5;
  646. t->CarefulWrite(ioPacket);
  647. return;
  648. }
  649. KeAcquireSpinLock(&t->_spinLock, &irql);
  650. t->_state.BytesRedistributed += ioPacket->Length;
  651. KeReleaseSpinLock(&t->_spinLock, irql);
  652. t->PropogateStateChanges(RedistributionSyncPhase6, syncPacket);
  653. }
  654. VOID
  655. RedistributionSyncPhase3(
  656. IN OUT PTRANSFER_PACKET TransferPacket
  657. )
  658. /*++
  659. Routine Description:
  660. This is the completion routine for the initial write part of a sync.
  661. Arguments:
  662. TransferPacket - Supplies the transfer packet.
  663. Return Value:
  664. None.
  665. --*/
  666. {
  667. PREDISTRIBUTION_TP ioPacket = (PREDISTRIBUTION_TP) TransferPacket;
  668. PREDISTRIBUTION_SYNC_TP syncPacket = (PREDISTRIBUTION_SYNC_TP) ioPacket->MasterPacket;
  669. PREDISTRIBUTION t = syncPacket->Redistribution;
  670. NTSTATUS status = ioPacket->IoStatus.Status;
  671. KIRQL irql;
  672. if (FsRtlIsTotalDeviceFailure(status)) {
  673. KeAcquireSpinLock(&t->_spinLock, &irql);
  674. t->_syncOk = TRUE;
  675. KeReleaseSpinLock(&t->_spinLock, irql);
  676. RedistributionCompositeVolumeCompletionRoutine(syncPacket->Context,
  677. status);
  678. delete syncPacket;
  679. return;
  680. }
  681. if (!NT_SUCCESS(status)) {
  682. ioPacket->CompletionRoutine = RedistributionSyncPhase5;
  683. t->CarefulWrite(ioPacket);
  684. return;
  685. }
  686. ioPacket->CompletionRoutine = RedistributionSyncPhase4;
  687. t->VerifyWrite(ioPacket);
  688. }
  689. VOID
  690. RedistributionSyncPhase2(
  691. IN OUT PTRANSFER_PACKET TransferPacket
  692. )
  693. /*++
  694. Routine Description:
  695. This is the completion routine for the read part of a sync.
  696. Arguments:
  697. TransferPacket - Supplies the transfer packet.
  698. Return Value:
  699. None.
  700. --*/
  701. {
  702. PREDISTRIBUTION_TP ioPacket = (PREDISTRIBUTION_TP) TransferPacket;
  703. PREDISTRIBUTION_SYNC_TP syncPacket = (PREDISTRIBUTION_SYNC_TP) ioPacket->MasterPacket;
  704. PREDISTRIBUTION t = syncPacket->Redistribution;
  705. NTSTATUS status = ioPacket->IoStatus.Status;
  706. LONGLONG rowSize, rowNum, rowOffset, firstSize;
  707. KIRQL irql;
  708. KeAcquireSpinLock(&t->_spinLock, &irql);
  709. if (t->_stopSyncs) {
  710. t->_syncOk = TRUE;
  711. KeReleaseSpinLock(&t->_spinLock, irql);
  712. RedistributionCompositeVolumeCompletionRoutine(syncPacket->Context,
  713. STATUS_SUCCESS);
  714. delete syncPacket;
  715. return;
  716. }
  717. KeReleaseSpinLock(&t->_spinLock, irql);
  718. if (FsRtlIsTotalDeviceFailure(status)) {
  719. KeAcquireSpinLock(&t->_spinLock, &irql);
  720. t->_syncOk = TRUE;
  721. KeReleaseSpinLock(&t->_spinLock, irql);
  722. RedistributionCompositeVolumeCompletionRoutine(syncPacket->Context,
  723. status);
  724. delete syncPacket;
  725. return;
  726. }
  727. if (!NT_SUCCESS(status)) {
  728. t->MaxTransfer(ioPacket);
  729. return;
  730. }
  731. rowSize = t->_totalWidth*t->_stripeSize;
  732. rowNum = ioPacket->Offset/rowSize;
  733. rowOffset = ioPacket->Offset%rowSize;
  734. firstSize = t->_firstWidth*t->_stripeSize;
  735. ioPacket->CompletionRoutine = RedistributionSyncPhase3;
  736. ioPacket->ReadPacket = FALSE;
  737. if (rowOffset < firstSize) {
  738. ioPacket->Offset = rowNum*firstSize + rowOffset;
  739. } else {
  740. ioPacket->Offset = rowNum*(rowSize - firstSize) + rowOffset - firstSize;
  741. ioPacket->TargetVolume = t->GetMemberUnprotected(1);
  742. ioPacket->WhichMember = 1;
  743. }
  744. TRANSFER(ioPacket);
  745. }
  746. VOID
  747. RedistributionSyncPhase1(
  748. IN OUT PTRANSFER_PACKET TransferPacket
  749. )
  750. /*++
  751. Routine Description:
  752. This is the completion routine for the lock part of a sync.
  753. Arguments:
  754. TransferPacket - Supplies the transfer packet.
  755. Return Value:
  756. None.
  757. --*/
  758. {
  759. PREDISTRIBUTION_SYNC_TP syncPacket = (PREDISTRIBUTION_SYNC_TP) TransferPacket;
  760. PREDISTRIBUTION t = syncPacket->Redistribution;
  761. PREDISTRIBUTION_TP packet = &syncPacket->IoPacket;
  762. packet->Offset = t->_state.BytesRedistributed;
  763. if (packet->Offset + packet->Length > t->_firstSize) {
  764. packet->Length = (ULONG) (t->_firstSize - packet->Offset);
  765. }
  766. packet->CompletionRoutine = RedistributionSyncPhase2;
  767. packet->TargetVolume = t->GetMemberUnprotected(0);
  768. packet->Thread = PsGetCurrentThread();
  769. packet->ReadPacket = TRUE;
  770. packet->WhichMember = 0;
  771. TRANSFER(packet);
  772. }
  773. VOID
  774. REDISTRIBUTION::StartSyncOperations(
  775. IN BOOLEAN RegenerateOrphans,
  776. IN FT_COMPLETION_ROUTINE CompletionRoutine,
  777. IN PVOID Context
  778. )
  779. /*++
  780. Routine Description:
  781. This routine starts off the redistribution of the data.
  782. Arguments:
  783. RegenerateOrphans - Supplies whether or not to try and regenerate
  784. orphaned members.
  785. CompletionRoutine - Supplies the completion routine.
  786. Context - Supplies the context for the completion routine.
  787. Return Value:
  788. None.
  789. --*/
  790. {
  791. PFT_COMPLETION_ROUTINE_CONTEXT context;
  792. PREDISTRIBUTION_SYNC_TP syncPacket;
  793. KIRQL irql;
  794. PREDISTRIBUTION_TP packet;
  795. if (_redistributionComplete) {
  796. COMPOSITE_FT_VOLUME::StartSyncOperations(RegenerateOrphans,
  797. CompletionRoutine, Context);
  798. return;
  799. }
  800. context = (PFT_COMPLETION_ROUTINE_CONTEXT)
  801. ExAllocatePool(NonPagedPool,
  802. sizeof(FT_COMPLETION_ROUTINE_CONTEXT));
  803. if (!context) {
  804. CompletionRoutine(Context, STATUS_INSUFFICIENT_RESOURCES);
  805. return;
  806. }
  807. syncPacket = new REDISTRIBUTION_SYNC_TP;
  808. if (!syncPacket) {
  809. ExFreePool(context);
  810. CompletionRoutine(Context, STATUS_INSUFFICIENT_RESOURCES);
  811. return;
  812. }
  813. if (!syncPacket->IoPacket.AllocateMdl(_stripeSize)) {
  814. delete syncPacket;
  815. ExFreePool(context);
  816. CompletionRoutine(Context, STATUS_INSUFFICIENT_RESOURCES);
  817. return;
  818. }
  819. KeInitializeSpinLock(&context->SpinLock);
  820. context->Status = STATUS_SUCCESS;
  821. context->RefCount = 2;
  822. context->CompletionRoutine = CompletionRoutine;
  823. context->Context = Context;
  824. context->ParentVolume = this;
  825. COMPOSITE_FT_VOLUME::StartSyncOperations(
  826. RegenerateOrphans, RedistributionCompositeVolumeCompletionRoutine,
  827. context);
  828. KeAcquireSpinLock(&_spinLock, &irql);
  829. if (_syncOk) {
  830. _syncOk = FALSE;
  831. _stopSyncs = FALSE;
  832. } else {
  833. KeReleaseSpinLock(&_spinLock, irql);
  834. RedistributionCompositeVolumeCompletionRoutine(context, STATUS_SUCCESS);
  835. return;
  836. }
  837. KeReleaseSpinLock(&_spinLock, irql);
  838. syncPacket->Mdl = NULL;
  839. syncPacket->Offset = _state.BytesRedistributed;
  840. syncPacket->Length = _stripeSize;
  841. syncPacket->CompletionRoutine = RedistributionSyncPhase1;
  842. syncPacket->TargetVolume = this;
  843. syncPacket->Thread = PsGetCurrentThread();
  844. syncPacket->IrpFlags = SL_OVERRIDE_VERIFY_VOLUME;
  845. syncPacket->ReadPacket = TRUE;
  846. syncPacket->Context = context;
  847. syncPacket->Redistribution = this;
  848. packet = &syncPacket->IoPacket;
  849. packet->Length = _stripeSize;
  850. packet->IrpFlags = SL_OVERRIDE_VERIFY_VOLUME;
  851. packet->MasterPacket = syncPacket;
  852. packet->Redistribution = this;
  853. _overlappedIoManager.AcquireIoRegion(syncPacket, TRUE);
  854. }
  855. VOID
  856. REDISTRIBUTION::StopSyncOperations(
  857. )
  858. /*++
  859. Routine Description:
  860. This routine stops all sync operations.
  861. Arguments:
  862. None.
  863. Return Value:
  864. None.
  865. --*/
  866. {
  867. KIRQL irql;
  868. COMPOSITE_FT_VOLUME::StopSyncOperations();
  869. KeAcquireSpinLock(&_spinLock, &irql);
  870. _stopSyncs = TRUE;
  871. KeReleaseSpinLock(&_spinLock, irql);
  872. }
  873. LONGLONG
  874. REDISTRIBUTION::QueryVolumeSize(
  875. )
  876. /*++
  877. Routine Description:
  878. Returns the number of bytes on the entire volume.
  879. Arguments:
  880. None.
  881. Return Value:
  882. The volume size in bytes.
  883. --*/
  884. {
  885. return _redistributionComplete ? _totalSize : _firstSize;
  886. }
  887. VOID
  888. REDISTRIBUTION::CompleteNotification(
  889. IN BOOLEAN IoPending
  890. )
  891. /*++
  892. Routine Description:
  893. This routine is called to notify the volume that it is complete and
  894. to therefore prepare for incoming requests.
  895. Arguments:
  896. IoPending - Supplies whether or not there is IO pending.
  897. Return Value:
  898. None.
  899. --*/
  900. {
  901. LONGLONG firstRowSize, numRows, secondRowSize, tmpNumRows;
  902. COMPOSITE_FT_VOLUME::CompleteNotification(IoPending);
  903. _firstSize = GetMember(0)->QueryVolumeSize();
  904. firstRowSize = _firstWidth*_stripeSize;
  905. numRows = _firstSize/firstRowSize;
  906. secondRowSize = (_totalWidth - _firstWidth)*_stripeSize;
  907. tmpNumRows = GetMember(1)->QueryVolumeSize()/secondRowSize;
  908. if (tmpNumRows < numRows) {
  909. numRows = tmpNumRows;
  910. }
  911. _totalSize = numRows*_totalWidth*_stripeSize;
  912. if (_state.BytesRedistributed >= _firstSize) {
  913. _redistributionComplete = TRUE;
  914. }
  915. }
  916. VOID
  917. REDISTRIBUTION::NewStateArrival(
  918. IN PVOID NewStateInstance
  919. )
  920. /*++
  921. Routine Description:
  922. This routine takes the new state instance arrival combined with its
  923. current state to come up with the new current state for the volume.
  924. If the two states cannot be reconciled then this routine returns FALSE
  925. indicating that the volume is invalid and should be broken into its
  926. constituant parts.
  927. Arguments:
  928. NewStateInstance - Supplies the new state instance.
  929. Return Value:
  930. None.
  931. --*/
  932. {
  933. BOOLEAN changed = FALSE;
  934. PFT_REDISTRIBUTION_STATE_INFORMATION state;
  935. state = (PFT_REDISTRIBUTION_STATE_INFORMATION) NewStateInstance;
  936. if (state->BytesRedistributed > _state.BytesRedistributed) {
  937. _state.BytesRedistributed = state->BytesRedistributed;
  938. changed = TRUE;
  939. }
  940. if (changed) {
  941. PropogateStateChanges(NULL, NULL);
  942. }
  943. }
  944. VOID
  945. RedistributionTransferCompletionRoutine(
  946. IN OUT PTRANSFER_PACKET TransferPacket
  947. )
  948. /*++
  949. Routine Description:
  950. Completion routine for REDISTRIBUTION::RedistributionDispatch.
  951. Arguments:
  952. TransferPacket - Supplies the transfer packet.
  953. Return Value:
  954. None.
  955. --*/
  956. {
  957. PREDISTRIBUTION_TP transferPacket = (PREDISTRIBUTION_TP) TransferPacket;
  958. PTRANSFER_PACKET masterPacket = transferPacket->MasterPacket;
  959. NTSTATUS status = transferPacket->IoStatus.Status;
  960. KIRQL irql;
  961. if (!NT_SUCCESS(status)) {
  962. KeAcquireSpinLock(&masterPacket->SpinLock, &irql);
  963. if (FtpIsWorseStatus(status, masterPacket->IoStatus.Status)) {
  964. masterPacket->IoStatus.Status = status;
  965. }
  966. KeReleaseSpinLock(&masterPacket->SpinLock, irql);
  967. }
  968. delete transferPacket;
  969. if (!InterlockedDecrement(&masterPacket->RefCount)) {
  970. masterPacket->CompletionRoutine(masterPacket);
  971. }
  972. }
  973. VOID
  974. REDISTRIBUTION::RedistributeTransfer(
  975. IN OUT PTRANSFER_PACKET TransferPacket
  976. )
  977. /*++
  978. Routine Description:
  979. This routine launches the given transfer packet using the new
  980. redistributed data allocation scheme.
  981. Arguments:
  982. TransferPacket - Supplies the transfer packet to launch.
  983. Return Value:
  984. None.
  985. --*/
  986. {
  987. LONGLONG begin, end;
  988. LONGLONG rowSize, firstSize, rowBegin, rowOffsetBegin, rowEnd, rowOffsetEnd;
  989. ULONG numRequests, i, numRows;
  990. PCHAR vp;
  991. LIST_ENTRY q;
  992. LONGLONG off, off2;
  993. ULONG len, len2;
  994. USHORT whichMember;
  995. BOOLEAN two;
  996. PREDISTRIBUTION_TP p;
  997. PLIST_ENTRY l;
  998. begin = TransferPacket->Offset;
  999. end = TransferPacket->Offset + TransferPacket->Length;
  1000. rowSize = _totalWidth*_stripeSize;
  1001. rowBegin = begin/rowSize;
  1002. rowOffsetBegin = begin%rowSize;
  1003. rowEnd = end/rowSize;
  1004. rowOffsetEnd = end%rowSize;
  1005. firstSize = _firstWidth*_stripeSize;
  1006. if (TransferPacket->Mdl) {
  1007. vp = (PCHAR) MmGetMdlVirtualAddress(TransferPacket->Mdl);
  1008. }
  1009. InitializeListHead(&q);
  1010. numRows = (ULONG) (rowEnd - rowBegin + 1);
  1011. numRequests = 0;
  1012. for (i = 0; i < numRows; i++) {
  1013. if (i == 0) {
  1014. if (numRows == 1) {
  1015. if (rowOffsetBegin < firstSize) {
  1016. if (rowOffsetEnd > firstSize) {
  1017. two = TRUE;
  1018. whichMember = 0;
  1019. off = rowBegin*firstSize + rowOffsetBegin;
  1020. len = (ULONG) (firstSize - rowOffsetBegin);
  1021. off2 = rowBegin*(rowSize - firstSize);
  1022. len2 = (ULONG) (rowOffsetEnd - firstSize);
  1023. } else {
  1024. two = FALSE;
  1025. whichMember = 0;
  1026. off = rowBegin*firstSize + rowOffsetBegin;
  1027. len = (ULONG) (rowOffsetEnd - rowOffsetBegin);
  1028. }
  1029. } else {
  1030. two = FALSE;
  1031. whichMember = 1;
  1032. off = rowBegin*(rowSize - firstSize) + rowOffsetBegin -
  1033. firstSize;
  1034. len = (ULONG) (rowOffsetEnd - rowOffsetBegin);
  1035. }
  1036. } else {
  1037. if (rowOffsetBegin < firstSize) {
  1038. two = TRUE;
  1039. whichMember = 0;
  1040. off = rowBegin*firstSize + rowOffsetBegin;
  1041. len = (ULONG) (firstSize - rowOffsetBegin);
  1042. off2 = rowBegin*(rowSize - firstSize);
  1043. len2 = (ULONG) (rowSize - firstSize);
  1044. } else {
  1045. two = FALSE;
  1046. whichMember = 1;
  1047. off = rowBegin*(rowSize - firstSize) + rowOffsetBegin -
  1048. firstSize;
  1049. len = (ULONG) (rowSize - rowOffsetBegin);
  1050. }
  1051. }
  1052. } else if (i == numRows - 1) {
  1053. if (!rowOffsetEnd) {
  1054. continue;
  1055. }
  1056. if (rowOffsetEnd > firstSize) {
  1057. two = TRUE;
  1058. whichMember = 0;
  1059. off = rowEnd*firstSize;
  1060. len = (ULONG) firstSize;
  1061. off2 = rowEnd*(rowSize - firstSize);
  1062. len2 = (ULONG) (rowOffsetEnd - firstSize);
  1063. } else {
  1064. two = FALSE;
  1065. whichMember = 0;
  1066. off = rowEnd*firstSize;
  1067. len = (ULONG) rowOffsetEnd;
  1068. }
  1069. } else {
  1070. two = TRUE;
  1071. whichMember = 0;
  1072. len = (ULONG) firstSize;
  1073. len2 = (ULONG) (rowSize - firstSize);
  1074. off = (rowBegin + i)*len;
  1075. off2 = (rowBegin + i)*len2;
  1076. }
  1077. p = new REDISTRIBUTION_TP;
  1078. if (!p) {
  1079. break;
  1080. }
  1081. if (!two && numRows == 1) {
  1082. p->Mdl = TransferPacket->Mdl;
  1083. } else {
  1084. if (TransferPacket->Mdl) {
  1085. if (p->AllocateMdl(vp, len)) {
  1086. IoBuildPartialMdl(TransferPacket->Mdl, p->Mdl, vp, len);
  1087. } else {
  1088. delete p;
  1089. break;
  1090. }
  1091. vp += len;
  1092. } else {
  1093. p->Mdl = TransferPacket->Mdl;
  1094. }
  1095. }
  1096. p->Length = len;
  1097. p->Offset = off;
  1098. p->CompletionRoutine = RedistributionTransferCompletionRoutine;
  1099. p->TargetVolume = GetMemberUnprotected(whichMember);
  1100. p->Thread = TransferPacket->Thread;
  1101. p->IrpFlags = TransferPacket->IrpFlags;
  1102. p->ReadPacket = TransferPacket->ReadPacket;
  1103. p->SpecialRead = TransferPacket->SpecialRead;
  1104. p->MasterPacket = TransferPacket;
  1105. p->Redistribution = this;
  1106. p->WhichMember = whichMember;
  1107. InsertTailList(&q, &p->QueueEntry);
  1108. numRequests++;
  1109. if (!two) {
  1110. continue;
  1111. }
  1112. p = new REDISTRIBUTION_TP;
  1113. if (!p) {
  1114. break;
  1115. }
  1116. if (TransferPacket->Mdl) {
  1117. if (p->AllocateMdl(vp, len2)) {
  1118. IoBuildPartialMdl(TransferPacket->Mdl, p->Mdl, vp, len2);
  1119. } else {
  1120. delete p;
  1121. break;
  1122. }
  1123. vp += len2;
  1124. } else {
  1125. p->Mdl = TransferPacket->Mdl;
  1126. }
  1127. p->Length = len2;
  1128. p->Offset = off2;
  1129. p->CompletionRoutine = RedistributionTransferCompletionRoutine;
  1130. p->TargetVolume = GetMemberUnprotected(1);
  1131. p->Thread = TransferPacket->Thread;
  1132. p->IrpFlags = TransferPacket->IrpFlags;
  1133. p->ReadPacket = TransferPacket->ReadPacket;
  1134. p->SpecialRead = TransferPacket->SpecialRead;
  1135. p->MasterPacket = TransferPacket;
  1136. p->Redistribution = this;
  1137. p->WhichMember = 1;
  1138. InsertTailList(&q, &p->QueueEntry);
  1139. numRequests++;
  1140. }
  1141. if (i < numRows) {
  1142. while (!IsListEmpty(&q)) {
  1143. l = RemoveHeadList(&q);
  1144. p = CONTAINING_RECORD(l, REDISTRIBUTION_TP, QueueEntry);
  1145. delete p;
  1146. }
  1147. TransferPacket->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  1148. TransferPacket->IoStatus.Information = 0;
  1149. TransferPacket->CompletionRoutine(TransferPacket);
  1150. return;
  1151. }
  1152. KeInitializeSpinLock(&TransferPacket->SpinLock);
  1153. TransferPacket->IoStatus.Status = STATUS_SUCCESS;
  1154. TransferPacket->IoStatus.Information = TransferPacket->Length;
  1155. TransferPacket->RefCount = numRequests;
  1156. while (!IsListEmpty(&q)) {
  1157. l = RemoveHeadList(&q);
  1158. p = CONTAINING_RECORD(l, REDISTRIBUTION_TP, QueueEntry);
  1159. TRANSFER(p);
  1160. }
  1161. }
  1162. VOID
  1163. RedistributeReplaceBadSectorCompletion(
  1164. IN OUT PTRANSFER_PACKET TransferPacket
  1165. )
  1166. /*++
  1167. Routine Description:
  1168. Completion routine for REDISTRIBUTION::RedistributionReplaceBadSector.
  1169. Arguments:
  1170. TransferPacket - Supplies the transfer packet.
  1171. Return Value:
  1172. None.
  1173. --*/
  1174. {
  1175. PREDISTRIBUTION_TP transferPacket = (PREDISTRIBUTION_TP) TransferPacket;
  1176. PTRANSFER_PACKET masterPacket = transferPacket->MasterPacket;
  1177. masterPacket->IoStatus = transferPacket->IoStatus;
  1178. delete transferPacket;
  1179. masterPacket->CompletionRoutine(masterPacket);
  1180. }
  1181. VOID
  1182. REDISTRIBUTION::RedistributeReplaceBadSector(
  1183. IN OUT PTRANSFER_PACKET TransferPacket
  1184. )
  1185. /*++
  1186. Routine Description:
  1187. This routine launches the given transfer packet using the new
  1188. redistributed data allocation scheme.
  1189. Arguments:
  1190. TransferPacket - Supplies the transfer packet to launch.
  1191. Return Value:
  1192. None.
  1193. --*/
  1194. {
  1195. LONGLONG begin, rowSize, rowBegin, rowOffsetBegin, firstSize, offset;
  1196. USHORT whichMember;
  1197. PREDISTRIBUTION_TP p;
  1198. begin = TransferPacket->Offset;
  1199. rowSize = _totalWidth*_stripeSize;
  1200. rowBegin = begin/rowSize;
  1201. rowOffsetBegin = begin%rowSize;
  1202. firstSize = _firstWidth*_stripeSize;
  1203. if (rowOffsetBegin < firstSize) {
  1204. offset = rowBegin*firstSize + rowOffsetBegin;
  1205. whichMember = 0;
  1206. } else {
  1207. offset = rowBegin*(rowSize - firstSize) + rowOffsetBegin - firstSize;
  1208. whichMember = 1;
  1209. }
  1210. p = new REDISTRIBUTION_TP;
  1211. if (!p) {
  1212. TransferPacket->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  1213. TransferPacket->IoStatus.Information = 0;
  1214. TransferPacket->CompletionRoutine(TransferPacket);
  1215. return;
  1216. }
  1217. p->Mdl = TransferPacket->Mdl;
  1218. p->Length = TransferPacket->Length;
  1219. p->Offset = offset;
  1220. p->CompletionRoutine = RedistributeReplaceBadSectorCompletion;
  1221. p->TargetVolume = GetMemberUnprotected(whichMember);
  1222. p->Thread = TransferPacket->Thread;
  1223. p->IrpFlags = TransferPacket->IrpFlags;
  1224. p->ReadPacket = TransferPacket->ReadPacket;
  1225. p->SpecialRead = TransferPacket->SpecialRead;
  1226. p->MasterPacket = TransferPacket;
  1227. p->Redistribution = this;
  1228. p->WhichMember = whichMember;
  1229. p->TargetVolume->ReplaceBadSector(p);
  1230. }
  1231. VOID
  1232. RedistributionPropogateStateChangesWorker(
  1233. IN PVOID WorkItem
  1234. )
  1235. /*++
  1236. Routine Description:
  1237. This routine is a worker thread routine for propogating state changes.
  1238. Arguments:
  1239. Mirror - Supplies a pointer to the mirror object.
  1240. Return Value:
  1241. None.
  1242. --*/
  1243. {
  1244. PPROPOGATE_CHANGES_WORK_ITEM workItem = (PPROPOGATE_CHANGES_WORK_ITEM) WorkItem;
  1245. PREDISTRIBUTION t = workItem->Redistribution;
  1246. NTSTATUS status;
  1247. KIRQL irql;
  1248. FT_REDISTRIBUTION_STATE_INFORMATION state;
  1249. status = FtpAcquireWithTimeout(t->_rootExtension);
  1250. if (!NT_SUCCESS(status)) {
  1251. if (workItem->CompletionRoutine) {
  1252. workItem->CompletionRoutine(workItem->Context, status);
  1253. }
  1254. return;
  1255. }
  1256. KeAcquireSpinLock(&t->_spinLock, &irql);
  1257. RtlCopyMemory(&state, &t->_state, sizeof(state));
  1258. KeReleaseSpinLock(&t->_spinLock, irql);
  1259. status = t->_diskInfoSet->WriteStateInformation(t->QueryLogicalDiskId(),
  1260. &state, sizeof(state));
  1261. FtpRelease(t->_rootExtension);
  1262. if (workItem->CompletionRoutine) {
  1263. workItem->CompletionRoutine(workItem->Context, status);
  1264. }
  1265. }
  1266. VOID
  1267. REDISTRIBUTION::PropogateStateChanges(
  1268. IN FT_COMPLETION_ROUTINE CompletionRoutine,
  1269. IN PVOID Context
  1270. )
  1271. /*++
  1272. Routine Description:
  1273. This routine propogates the changes in the local memory state to
  1274. the on disk state.
  1275. Arguments:
  1276. CompletionRoutine - Supplies the completion routine.
  1277. Context - Supplies the context.
  1278. Return Value:
  1279. None.
  1280. --*/
  1281. {
  1282. PPROPOGATE_CHANGES_WORK_ITEM workItem;
  1283. workItem = (PPROPOGATE_CHANGES_WORK_ITEM)
  1284. ExAllocatePool(NonPagedPool,
  1285. sizeof(PROPOGATE_CHANGES_WORK_ITEM));
  1286. if (!workItem) {
  1287. return;
  1288. }
  1289. workItem->Redistribution = this;
  1290. workItem->CompletionRoutine = CompletionRoutine;
  1291. workItem->Context = Context;
  1292. ExInitializeWorkItem(workItem, RedistributionPropogateStateChangesWorker,
  1293. workItem);
  1294. FtpQueueWorkItem(_rootExtension, workItem);
  1295. }
  1296. VOID
  1297. RedistributionMaxTransferCompletionRoutine(
  1298. IN OUT PTRANSFER_PACKET TransferPacket
  1299. )
  1300. /*++
  1301. Routine Description:
  1302. This is the completion routine for a sector transfer subordinate
  1303. to a MAX transfer operation.
  1304. Arguments:
  1305. TransferPacket - Supplies the subordinate transfer packet.
  1306. Return Value:
  1307. None.
  1308. --*/
  1309. {
  1310. PREDISTRIBUTION_TP subPacket = (PREDISTRIBUTION_TP) TransferPacket;
  1311. PREDISTRIBUTION_TP masterPacket = (PREDISTRIBUTION_TP) subPacket->MasterPacket;
  1312. NTSTATUS status = subPacket->IoStatus.Status;
  1313. if (FsRtlIsTotalDeviceFailure(status)) {
  1314. masterPacket->IoStatus = subPacket->IoStatus;
  1315. delete subPacket;
  1316. masterPacket->CompletionRoutine(masterPacket);
  1317. return;
  1318. }
  1319. if (subPacket->Offset + subPacket->Length ==
  1320. masterPacket->Offset + masterPacket->Length) {
  1321. delete subPacket;
  1322. masterPacket->CompletionRoutine(masterPacket);
  1323. return;
  1324. }
  1325. subPacket->Offset += subPacket->Length;
  1326. MmPrepareMdlForReuse(subPacket->Mdl);
  1327. IoBuildPartialMdl(masterPacket->Mdl, subPacket->Mdl,
  1328. (PCHAR) MmGetMdlVirtualAddress(masterPacket->Mdl) +
  1329. (ULONG) (subPacket->Offset - masterPacket->Offset),
  1330. subPacket->Length);
  1331. TRANSFER(subPacket);
  1332. }
  1333. VOID
  1334. REDISTRIBUTION::MaxTransfer(
  1335. IN OUT PREDISTRIBUTION_TP TransferPacket
  1336. )
  1337. /*++
  1338. Routine Description:
  1339. This routine propogates sector by sector the given transfer packet,
  1340. ignoring errors.
  1341. Arguments:
  1342. TransferPacket - Supplies the transfer packet.
  1343. Return Value:
  1344. None.
  1345. --*/
  1346. {
  1347. PREDISTRIBUTION_TP subPacket;
  1348. TransferPacket->IoStatus.Status = STATUS_SUCCESS;
  1349. TransferPacket->IoStatus.Information = TransferPacket->Length;
  1350. subPacket = new REDISTRIBUTION_TP;
  1351. if (!subPacket) {
  1352. TransferPacket->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  1353. TransferPacket->IoStatus.Information = 0;
  1354. TransferPacket->CompletionRoutine(TransferPacket);
  1355. return;
  1356. }
  1357. subPacket->Length = QuerySectorSize();
  1358. subPacket->Offset = TransferPacket->Offset;
  1359. subPacket->CompletionRoutine = RedistributionMaxTransferCompletionRoutine;
  1360. subPacket->TargetVolume = TransferPacket->TargetVolume;
  1361. subPacket->Thread = TransferPacket->Thread;
  1362. subPacket->IrpFlags = TransferPacket->IrpFlags;
  1363. subPacket->ReadPacket = TransferPacket->ReadPacket;
  1364. subPacket->MasterPacket = TransferPacket;
  1365. subPacket->Redistribution = this;
  1366. subPacket->WhichMember = TransferPacket->WhichMember;
  1367. if (!subPacket->AllocateMdl((PVOID) (PAGE_SIZE - 1), subPacket->Length)) {
  1368. delete subPacket;
  1369. TransferPacket->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  1370. TransferPacket->IoStatus.Information = 0;
  1371. TransferPacket->CompletionRoutine(TransferPacket);
  1372. return;
  1373. }
  1374. IoBuildPartialMdl(TransferPacket->Mdl, subPacket->Mdl,
  1375. MmGetMdlVirtualAddress(TransferPacket->Mdl),
  1376. subPacket->Length);
  1377. TRANSFER(subPacket);
  1378. }
  1379. VOID
  1380. RedistributionVerifyWriteCompletion(
  1381. IN OUT PTRANSFER_PACKET TransferPacket
  1382. )
  1383. /*++
  1384. Routine Description:
  1385. This is the completion routine for a verify write operation.
  1386. Arguments:
  1387. TransferPacket - Supplies the subordinate transfer packet.
  1388. Return Value:
  1389. None.
  1390. --*/
  1391. {
  1392. PREDISTRIBUTION_TP verifyPacket = (PREDISTRIBUTION_TP) TransferPacket;
  1393. PREDISTRIBUTION_TP masterPacket = (PREDISTRIBUTION_TP) verifyPacket->MasterPacket;
  1394. NTSTATUS status = verifyPacket->IoStatus.Status;
  1395. PVOID p, q;
  1396. ULONG l;
  1397. if (!NT_SUCCESS(status)) {
  1398. masterPacket->IoStatus = verifyPacket->IoStatus;
  1399. delete verifyPacket;
  1400. masterPacket->CompletionRoutine(masterPacket);
  1401. return;
  1402. }
  1403. p = MmGetSystemAddressForMdl(verifyPacket->Mdl);
  1404. q = MmGetSystemAddressForMdl(masterPacket->Mdl);
  1405. l = (ULONG)RtlCompareMemory(p, q, verifyPacket->Length);
  1406. if (l != verifyPacket->Length) {
  1407. masterPacket->IoStatus.Status = STATUS_DEVICE_DATA_ERROR;
  1408. masterPacket->IoStatus.Information = 0;
  1409. }
  1410. delete verifyPacket;
  1411. masterPacket->CompletionRoutine(masterPacket);
  1412. }
  1413. VOID
  1414. REDISTRIBUTION::VerifyWrite(
  1415. IN OUT PREDISTRIBUTION_TP TransferPacket
  1416. )
  1417. /*++
  1418. Routine Description:
  1419. This routine verifies that the given write was success by reading
  1420. and comparing.
  1421. Arguments:
  1422. TransferPacket - Supplies the transfer packet.
  1423. Return Value:
  1424. None.
  1425. --*/
  1426. {
  1427. PREDISTRIBUTION_TP verifyPacket;
  1428. verifyPacket = new REDISTRIBUTION_TP;
  1429. if (!verifyPacket) {
  1430. TransferPacket->CompletionRoutine(TransferPacket);
  1431. return;
  1432. }
  1433. if (!verifyPacket->AllocateMdl(TransferPacket->Length)) {
  1434. delete verifyPacket;
  1435. TransferPacket->CompletionRoutine(TransferPacket);
  1436. return;
  1437. }
  1438. verifyPacket->Length = TransferPacket->Length;
  1439. verifyPacket->Offset = TransferPacket->Offset;
  1440. verifyPacket->CompletionRoutine = RedistributionVerifyWriteCompletion;
  1441. verifyPacket->TargetVolume = TransferPacket->TargetVolume;
  1442. verifyPacket->Thread = TransferPacket->Thread;
  1443. verifyPacket->IrpFlags = TransferPacket->IrpFlags;
  1444. verifyPacket->ReadPacket = TRUE;
  1445. verifyPacket->MasterPacket = TransferPacket;
  1446. verifyPacket->Redistribution = this;
  1447. verifyPacket->WhichMember = TransferPacket->WhichMember;
  1448. TRANSFER(verifyPacket);
  1449. }
  1450. VOID
  1451. RedistributionCarefulWritePhase1(
  1452. IN OUT PTRANSFER_PACKET TransferPacket
  1453. );
  1454. VOID
  1455. RedistributionCarefulWritePhase5(
  1456. IN OUT PTRANSFER_PACKET TransferPacket
  1457. )
  1458. /*++
  1459. Routine Description:
  1460. This is the completion routine for a sector read subordinate
  1461. to a carefule write operation after a replace bad sector.
  1462. Arguments:
  1463. TransferPacket - Supplies the subordinate transfer packet.
  1464. Return Value:
  1465. None.
  1466. --*/
  1467. {
  1468. PREDISTRIBUTION_CW_TP subPacket = (PREDISTRIBUTION_CW_TP) TransferPacket;
  1469. PREDISTRIBUTION_TP masterPacket = (PREDISTRIBUTION_TP) subPacket->MasterPacket;
  1470. NTSTATUS status = subPacket->IoStatus.Status;
  1471. PVOID p, q;
  1472. ULONG l;
  1473. if (NT_SUCCESS(status)) {
  1474. p = MmGetSystemAddressForMdl(subPacket->PartialMdl);
  1475. q = MmGetSystemAddressForMdl(subPacket->VerifyMdl);
  1476. l = (ULONG)RtlCompareMemory(p, q, subPacket->Length);
  1477. } else {
  1478. l = 0;
  1479. }
  1480. if (l != subPacket->Length) {
  1481. masterPacket->IoStatus = subPacket->IoStatus;
  1482. delete subPacket;
  1483. masterPacket->CompletionRoutine(masterPacket);
  1484. return;
  1485. }
  1486. if (subPacket->Offset + subPacket->Length ==
  1487. masterPacket->Offset + masterPacket->Length) {
  1488. delete subPacket;
  1489. masterPacket->IoStatus.Status = STATUS_SUCCESS;
  1490. masterPacket->IoStatus.Information = masterPacket->Length;
  1491. masterPacket->CompletionRoutine(masterPacket);
  1492. return;
  1493. }
  1494. subPacket->Offset += subPacket->Length;
  1495. subPacket->CompletionRoutine = RedistributionCarefulWritePhase1;
  1496. subPacket->ReadPacket = FALSE;
  1497. subPacket->Mdl = subPacket->PartialMdl;
  1498. MmPrepareMdlForReuse(subPacket->Mdl);
  1499. IoBuildPartialMdl(masterPacket->Mdl, subPacket->Mdl,
  1500. (PCHAR) MmGetMdlVirtualAddress(masterPacket->Mdl) +
  1501. (ULONG) (subPacket->Offset - masterPacket->Offset),
  1502. subPacket->Length);
  1503. TRANSFER(subPacket);
  1504. }
  1505. VOID
  1506. RedistributionCarefulWritePhase4(
  1507. IN OUT PTRANSFER_PACKET TransferPacket
  1508. )
  1509. /*++
  1510. Routine Description:
  1511. This is the completion routine for a sector write subordinate
  1512. to a carefule write operation after a sector replace operation.
  1513. Arguments:
  1514. TransferPacket - Supplies the subordinate transfer packet.
  1515. Return Value:
  1516. None.
  1517. --*/
  1518. {
  1519. PREDISTRIBUTION_CW_TP subPacket = (PREDISTRIBUTION_CW_TP) TransferPacket;
  1520. PREDISTRIBUTION_TP masterPacket = (PREDISTRIBUTION_TP) subPacket->MasterPacket;
  1521. NTSTATUS status = subPacket->IoStatus.Status;
  1522. if (!NT_SUCCESS(status)) {
  1523. masterPacket->IoStatus = subPacket->IoStatus;
  1524. delete subPacket;
  1525. masterPacket->CompletionRoutine(masterPacket);
  1526. return;
  1527. }
  1528. subPacket->Mdl = subPacket->VerifyMdl;
  1529. subPacket->CompletionRoutine = RedistributionCarefulWritePhase5;
  1530. subPacket->ReadPacket = TRUE;
  1531. TRANSFER(subPacket);
  1532. }
  1533. VOID
  1534. RedistributionCarefulWritePhase3(
  1535. IN OUT PTRANSFER_PACKET TransferPacket
  1536. )
  1537. /*++
  1538. Routine Description:
  1539. This is the completion routine for a sector replace subordinate
  1540. to a carefule write operation.
  1541. Arguments:
  1542. TransferPacket - Supplies the subordinate transfer packet.
  1543. Return Value:
  1544. None.
  1545. --*/
  1546. {
  1547. PREDISTRIBUTION_CW_TP subPacket = (PREDISTRIBUTION_CW_TP) TransferPacket;
  1548. PREDISTRIBUTION_TP masterPacket = (PREDISTRIBUTION_TP) subPacket->MasterPacket;
  1549. subPacket->CompletionRoutine = RedistributionCarefulWritePhase4;
  1550. subPacket->ReadPacket = FALSE;
  1551. subPacket->Mdl = subPacket->PartialMdl;
  1552. MmPrepareMdlForReuse(subPacket->Mdl);
  1553. IoBuildPartialMdl(masterPacket->Mdl, subPacket->Mdl,
  1554. (PCHAR) MmGetMdlVirtualAddress(masterPacket->Mdl) +
  1555. (ULONG) (subPacket->Offset - masterPacket->Offset),
  1556. subPacket->Length);
  1557. TRANSFER(subPacket);
  1558. }
  1559. VOID
  1560. RedistributionCarefulWritePhase2(
  1561. IN OUT PTRANSFER_PACKET TransferPacket
  1562. )
  1563. /*++
  1564. Routine Description:
  1565. This is the completion routine for a sector read subordinate
  1566. to a carefule write operation.
  1567. Arguments:
  1568. TransferPacket - Supplies the subordinate transfer packet.
  1569. Return Value:
  1570. None.
  1571. --*/
  1572. {
  1573. PREDISTRIBUTION_CW_TP subPacket = (PREDISTRIBUTION_CW_TP) TransferPacket;
  1574. PREDISTRIBUTION_TP masterPacket = (PREDISTRIBUTION_TP) subPacket->MasterPacket;
  1575. NTSTATUS status = subPacket->IoStatus.Status;
  1576. PVOID p, q;
  1577. ULONG l;
  1578. if (FsRtlIsTotalDeviceFailure(status)) {
  1579. masterPacket->IoStatus = subPacket->IoStatus;
  1580. delete subPacket;
  1581. masterPacket->CompletionRoutine(masterPacket);
  1582. return;
  1583. }
  1584. if (NT_SUCCESS(status)) {
  1585. p = MmGetSystemAddressForMdl(subPacket->PartialMdl);
  1586. q = MmGetSystemAddressForMdl(subPacket->VerifyMdl);
  1587. l = (ULONG)RtlCompareMemory(p, q, subPacket->Length);
  1588. } else {
  1589. l = 0;
  1590. }
  1591. if (l != subPacket->Length) {
  1592. subPacket->CompletionRoutine = RedistributionCarefulWritePhase3;
  1593. subPacket->TargetVolume->ReplaceBadSector(subPacket);
  1594. return;
  1595. }
  1596. if (subPacket->Offset + subPacket->Length ==
  1597. masterPacket->Offset + masterPacket->Length) {
  1598. delete subPacket;
  1599. masterPacket->IoStatus.Status = STATUS_SUCCESS;
  1600. masterPacket->IoStatus.Information = masterPacket->Length;
  1601. masterPacket->CompletionRoutine(masterPacket);
  1602. return;
  1603. }
  1604. subPacket->Offset += subPacket->Length;
  1605. subPacket->CompletionRoutine = RedistributionCarefulWritePhase1;
  1606. subPacket->ReadPacket = FALSE;
  1607. subPacket->Mdl = subPacket->PartialMdl;
  1608. MmPrepareMdlForReuse(subPacket->Mdl);
  1609. IoBuildPartialMdl(masterPacket->Mdl, subPacket->Mdl,
  1610. (PCHAR) MmGetMdlVirtualAddress(masterPacket->Mdl) +
  1611. (ULONG) (subPacket->Offset - masterPacket->Offset),
  1612. subPacket->Length);
  1613. TRANSFER(subPacket);
  1614. }
  1615. VOID
  1616. RedistributionCarefulWritePhase1(
  1617. IN OUT PTRANSFER_PACKET TransferPacket
  1618. )
  1619. /*++
  1620. Routine Description:
  1621. This is the completion routine for a sector write subordinate
  1622. to a carefule write operation.
  1623. Arguments:
  1624. TransferPacket - Supplies the subordinate transfer packet.
  1625. Return Value:
  1626. None.
  1627. --*/
  1628. {
  1629. PREDISTRIBUTION_CW_TP subPacket = (PREDISTRIBUTION_CW_TP) TransferPacket;
  1630. PREDISTRIBUTION_TP masterPacket = (PREDISTRIBUTION_TP) subPacket->MasterPacket;
  1631. NTSTATUS status = subPacket->IoStatus.Status;
  1632. if (FsRtlIsTotalDeviceFailure(status)) {
  1633. masterPacket->IoStatus = subPacket->IoStatus;
  1634. delete subPacket;
  1635. masterPacket->CompletionRoutine(masterPacket);
  1636. return;
  1637. }
  1638. if (!NT_SUCCESS(status)) {
  1639. subPacket->CompletionRoutine = RedistributionCarefulWritePhase3;
  1640. subPacket->TargetVolume->ReplaceBadSector(subPacket);
  1641. return;
  1642. }
  1643. subPacket->Mdl = subPacket->VerifyMdl;
  1644. subPacket->CompletionRoutine = RedistributionCarefulWritePhase2;
  1645. subPacket->ReadPacket = TRUE;
  1646. TRANSFER(subPacket);
  1647. }
  1648. VOID
  1649. REDISTRIBUTION::CarefulWrite(
  1650. IN OUT PREDISTRIBUTION_TP TransferPacket
  1651. )
  1652. /*++
  1653. Routine Description:
  1654. This routine writes the given packet, sector by sector, replacing
  1655. bad sectors if need be.
  1656. Arguments:
  1657. TransferPacket - Supplies the transfer packet.
  1658. Return Value:
  1659. None.
  1660. --*/
  1661. {
  1662. PREDISTRIBUTION_CW_TP subPacket;
  1663. ASSERT(!TransferPacket->ReadPacket);
  1664. subPacket = new REDISTRIBUTION_CW_TP;
  1665. if (!subPacket) {
  1666. TransferPacket->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  1667. TransferPacket->IoStatus.Information = 0;
  1668. TransferPacket->CompletionRoutine(TransferPacket);
  1669. return;
  1670. }
  1671. subPacket->Length = QuerySectorSize();
  1672. subPacket->Offset = TransferPacket->Offset;
  1673. subPacket->CompletionRoutine = RedistributionCarefulWritePhase1;
  1674. subPacket->TargetVolume = TransferPacket->TargetVolume;
  1675. subPacket->Thread = TransferPacket->Thread;
  1676. subPacket->IrpFlags = TransferPacket->IrpFlags;
  1677. subPacket->ReadPacket = FALSE;
  1678. subPacket->MasterPacket = TransferPacket;
  1679. subPacket->Redistribution = TransferPacket->Redistribution;
  1680. subPacket->WhichMember = TransferPacket->WhichMember;
  1681. if (!subPacket->AllocateMdls(subPacket->Length)) {
  1682. delete subPacket;
  1683. TransferPacket->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  1684. TransferPacket->IoStatus.Information = 0;
  1685. TransferPacket->CompletionRoutine(TransferPacket);
  1686. return;
  1687. }
  1688. subPacket->Mdl = subPacket->PartialMdl;
  1689. IoBuildPartialMdl(TransferPacket->Mdl, subPacket->Mdl,
  1690. MmGetMdlVirtualAddress(TransferPacket->Mdl),
  1691. subPacket->Length);
  1692. TRANSFER(subPacket);
  1693. }
  1694. NTSTATUS
  1695. REDISTRIBUTION::QueryPhysicalOffsets(
  1696. IN LONGLONG LogicalOffset,
  1697. OUT PVOLUME_PHYSICAL_OFFSET* PhysicalOffsets,
  1698. OUT PULONG NumberOfPhysicalOffsets
  1699. )
  1700. /*++
  1701. Routine Description:
  1702. This routine returns physical disk and offset for a given volume
  1703. logical offset.
  1704. Arguments:
  1705. LogicalOffset - Supplies the logical offset
  1706. PhysicalOffsets - Returns the physical offsets
  1707. NumberOfPhysicalOffsets - Returns the number of physical offsets
  1708. Return Value:
  1709. NTSTATUS
  1710. --*/
  1711. {
  1712. USHORT n, whichMember, whichStripeInSet;
  1713. LONGLONG whichStripe, whichSet, whichRow;
  1714. LONGLONG bytesRedistributed, logicalOffsetInMember;
  1715. PFT_VOLUME vol;
  1716. KIRQL irql;
  1717. if (LogicalOffset < 0) {
  1718. return STATUS_INVALID_PARAMETER;
  1719. }
  1720. if (_redistributionComplete) {
  1721. if (_totalSize <= LogicalOffset) {
  1722. return STATUS_INVALID_PARAMETER;
  1723. }
  1724. } else {
  1725. KeAcquireSpinLock(&_spinLock, &irql);
  1726. bytesRedistributed = _state.BytesRedistributed;
  1727. KeReleaseSpinLock(&_spinLock, irql);
  1728. if (bytesRedistributed <= LogicalOffset) {
  1729. return STATUS_INVALID_PARAMETER;
  1730. }
  1731. }
  1732. ASSERT(_stripeSize);
  1733. ASSERT(_totalWidth);
  1734. whichStripe = LogicalOffset/_stripeSize;
  1735. whichSet = whichStripe/_totalWidth;
  1736. whichStripeInSet = (USHORT) (whichStripe%_totalWidth);
  1737. if (whichStripeInSet < _firstWidth) {
  1738. whichMember = 0;
  1739. whichRow = whichSet*_firstWidth + whichStripeInSet;
  1740. } else {
  1741. whichMember = 1;
  1742. whichRow = whichSet*(_totalWidth-_firstWidth) + whichStripeInSet - _firstWidth;
  1743. }
  1744. vol = GetMember(whichMember);
  1745. if (!vol) {
  1746. return STATUS_INVALID_PARAMETER;
  1747. }
  1748. logicalOffsetInMember = whichRow*_stripeSize + LogicalOffset%_stripeSize;
  1749. return vol->QueryPhysicalOffsets(logicalOffsetInMember, PhysicalOffsets, NumberOfPhysicalOffsets);
  1750. }
  1751. NTSTATUS
  1752. REDISTRIBUTION::QueryLogicalOffset(
  1753. IN PVOLUME_PHYSICAL_OFFSET PhysicalOffset,
  1754. OUT PLONGLONG LogicalOffset
  1755. )
  1756. /*++
  1757. Routine Description:
  1758. This routine returns the volume logical offset for a given disk number
  1759. and physical offset.
  1760. Arguments:
  1761. PhysicalOffset - Supplies the physical offset
  1762. LogicalOffset - Returns the logical offset
  1763. Return Value:
  1764. NTSTATUS
  1765. --*/
  1766. {
  1767. USHORT n, i, whichStripeInSet;
  1768. LONGLONG whichStripe, whichSet, whichRow, bytesRedistributed;
  1769. LONGLONG logicalOffset, logicalOffsetInMember;
  1770. NTSTATUS status;
  1771. PFT_VOLUME vol;
  1772. KIRQL irql;
  1773. n = QueryNumMembers();
  1774. ASSERT(n == 2);
  1775. ASSERT(_stripeSize);
  1776. ASSERT(_firstWidth);
  1777. ASSERT(_totalWidth > _firstWidth);
  1778. for (i = 0; i < n; i++) {
  1779. vol = GetMember(i);
  1780. if (!vol) {
  1781. continue;
  1782. }
  1783. status = vol->QueryLogicalOffset(PhysicalOffset, &logicalOffsetInMember);
  1784. if (NT_SUCCESS(status)) {
  1785. whichRow = logicalOffsetInMember/_stripeSize;
  1786. if (i == 0) {
  1787. whichSet = whichRow/_firstWidth;
  1788. whichStripeInSet = (USHORT) (whichRow%_firstWidth);
  1789. } else {
  1790. ASSERT(i == 1);
  1791. whichSet = whichRow/(_totalWidth-_firstWidth);
  1792. whichStripeInSet = (USHORT) (whichRow%(_totalWidth-_firstWidth)) + _firstWidth;
  1793. }
  1794. whichStripe = whichSet*_totalWidth + whichStripeInSet;
  1795. logicalOffset = whichStripe*_stripeSize + logicalOffsetInMember%_stripeSize;
  1796. if (_redistributionComplete) {
  1797. if (_totalSize <= logicalOffset) {
  1798. return STATUS_INVALID_PARAMETER;
  1799. }
  1800. } else {
  1801. KeAcquireSpinLock(&_spinLock, &irql);
  1802. bytesRedistributed = _state.BytesRedistributed;
  1803. KeReleaseSpinLock(&_spinLock, irql);
  1804. if (bytesRedistributed <= logicalOffset) {
  1805. return STATUS_INVALID_PARAMETER;
  1806. }
  1807. }
  1808. *LogicalOffset = logicalOffset;
  1809. return status;
  1810. }
  1811. }
  1812. return STATUS_INVALID_PARAMETER;
  1813. }