Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenlargemcb.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/fsrtl/largemcb.c 00005 * PURPOSE: Large Mapped Control Block (MCB) support for File System Drivers 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Pierre Schweitzer (heis_spiter@hotmail.com) 00008 * Art Yerkes (art.yerkes@gmail.com) 00009 */ 00010 00011 /* INCLUDES ******************************************************************/ 00012 00013 #include <ntoskrnl.h> 00014 //#define NDEBUG 00015 #include <debug.h> 00016 00017 /* GLOBALS *******************************************************************/ 00018 00019 #define GET_LIST_HEAD(x) ((PLIST_ENTRY)(&((PRTL_GENERIC_TABLE)x)[1])) 00020 00021 PAGED_LOOKASIDE_LIST FsRtlFirstMappingLookasideList; 00022 NPAGED_LOOKASIDE_LIST FsRtlFastMutexLookasideList; 00023 00024 typedef struct _LARGE_MCB_MAPPING_ENTRY 00025 { 00026 LARGE_INTEGER RunStartVbn; 00027 LARGE_INTEGER SectorCount; 00028 LARGE_INTEGER StartingLbn; 00029 LIST_ENTRY Sequence; 00030 } LARGE_MCB_MAPPING_ENTRY, *PLARGE_MCB_MAPPING_ENTRY; 00031 00032 static PVOID NTAPI McbMappingAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes) 00033 { 00034 PVOID Result; 00035 PBASE_MCB Mcb = (PBASE_MCB)Table->TableContext; 00036 Result = ExAllocatePoolWithTag(Mcb->PoolType, Bytes, 'LMCB'); 00037 DPRINT("McbMappingAllocate(%d) => %p\n", Bytes, Result); 00038 return Result; 00039 } 00040 00041 static VOID NTAPI McbMappingFree(PRTL_GENERIC_TABLE Table, PVOID Buffer) 00042 { 00043 DPRINT("McbMappingFree(%p)\n", Buffer); 00044 ExFreePoolWithTag(Buffer, 'LMCB'); 00045 } 00046 00047 static RTL_GENERIC_COMPARE_RESULTS NTAPI McbMappingCompare 00048 (RTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB) 00049 { 00050 PLARGE_MCB_MAPPING_ENTRY A = PtrA, B = PtrB; 00051 return 00052 (A->RunStartVbn.QuadPart + A->SectorCount.QuadPart < 00053 B->RunStartVbn.QuadPart) ? GenericLessThan : 00054 (A->RunStartVbn.QuadPart > 00055 B->RunStartVbn.QuadPart + B->SectorCount.QuadPart) ? 00056 GenericGreaterThan : GenericEqual; 00057 } 00058 00059 /* PUBLIC FUNCTIONS **********************************************************/ 00060 00061 /* 00062 * @implemented 00063 */ 00064 BOOLEAN 00065 NTAPI 00066 FsRtlAddBaseMcbEntry(IN PBASE_MCB Mcb, 00067 IN LONGLONG Vbn, 00068 IN LONGLONG Lbn, 00069 IN LONGLONG SectorCount) 00070 { 00071 LARGE_MCB_MAPPING_ENTRY Node; 00072 PLARGE_MCB_MAPPING_ENTRY Existing = NULL; 00073 BOOLEAN NewElement = FALSE; 00074 00075 Node.RunStartVbn.QuadPart = Vbn; 00076 Node.StartingLbn.QuadPart = Lbn; 00077 Node.SectorCount.QuadPart = SectorCount; 00078 00079 while (!NewElement) 00080 { 00081 DPRINT("Inserting %x:%x\n", Node.RunStartVbn.LowPart, Node.SectorCount.LowPart); 00082 Existing = RtlInsertElementGenericTable 00083 (Mcb->Mapping, &Node, sizeof(Node), &NewElement); 00084 DPRINT("Existing %x\n", Existing); 00085 if (!Existing) break; 00086 00087 DPRINT("NewElement %d\n", NewElement); 00088 if (!NewElement) 00089 { 00090 // We merge the existing runs 00091 LARGE_INTEGER StartVbn, FinalVbn; 00092 DPRINT("Existing: %x:%x\n", 00093 Existing->RunStartVbn.LowPart, Node.SectorCount.LowPart); 00094 if (Existing->RunStartVbn.QuadPart < Node.RunStartVbn.QuadPart) 00095 { 00096 StartVbn = Existing->RunStartVbn; 00097 Node.StartingLbn = Existing->StartingLbn; 00098 } 00099 else 00100 { 00101 StartVbn = Node.RunStartVbn; 00102 } 00103 DPRINT("StartVbn %x\n", StartVbn.LowPart); 00104 if (Existing->RunStartVbn.QuadPart + Existing->SectorCount.QuadPart > 00105 Node.RunStartVbn.QuadPart + Node.SectorCount.QuadPart) 00106 { 00107 FinalVbn.QuadPart = 00108 Existing->RunStartVbn.QuadPart + Existing->SectorCount.QuadPart; 00109 } 00110 else 00111 { 00112 FinalVbn.QuadPart = 00113 Node.RunStartVbn.QuadPart + Node.SectorCount.QuadPart; 00114 } 00115 DPRINT("FinalVbn %x\n", FinalVbn.LowPart); 00116 Node.RunStartVbn.QuadPart = StartVbn.QuadPart; 00117 Node.SectorCount.QuadPart = FinalVbn.QuadPart - StartVbn.QuadPart; 00118 RemoveHeadList(&Existing->Sequence); 00119 RtlDeleteElementGenericTable(Mcb->Mapping, Existing); 00120 Mcb->PairCount--; 00121 } 00122 else 00123 { 00124 DPRINT("Mapping added %x\n", Existing); 00125 Mcb->MaximumPairCount++; 00126 Mcb->PairCount++; 00127 InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Existing->Sequence); 00128 } 00129 } 00130 00131 DPRINT("!!Existing %d\n", !!Existing); 00132 return !!Existing; 00133 } 00134 00135 /* 00136 * @implemented 00137 */ 00138 BOOLEAN 00139 NTAPI 00140 FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb, 00141 IN LONGLONG Vbn, 00142 IN LONGLONG Lbn, 00143 IN LONGLONG SectorCount) 00144 { 00145 BOOLEAN Result; 00146 00147 DPRINT("Mcb %x Vbn %x Lbn %x SectorCount %x\n", Mcb, Vbn, Lbn, SectorCount); 00148 00149 KeAcquireGuardedMutex(Mcb->GuardedMutex); 00150 Result = FsRtlAddBaseMcbEntry(&(Mcb->BaseMcb), 00151 Vbn, 00152 Lbn, 00153 SectorCount); 00154 KeReleaseGuardedMutex(Mcb->GuardedMutex); 00155 00156 DPRINT("Done %d\n", Result); 00157 00158 return Result; 00159 } 00160 00161 /* 00162 * @unimplemented 00163 */ 00164 BOOLEAN 00165 NTAPI 00166 FsRtlGetNextBaseMcbEntry(IN PBASE_MCB Mcb, 00167 IN ULONG RunIndex, 00168 OUT PLONGLONG Vbn, 00169 OUT PLONGLONG Lbn, 00170 OUT PLONGLONG SectorCount) 00171 { 00172 ULONG i = 0; 00173 BOOLEAN Result = FALSE; 00174 PLARGE_MCB_MAPPING_ENTRY Entry; 00175 for (Entry = (PLARGE_MCB_MAPPING_ENTRY) 00176 RtlEnumerateGenericTable(Mcb->Mapping, TRUE); 00177 Entry && i < RunIndex; 00178 Entry = (PLARGE_MCB_MAPPING_ENTRY) 00179 RtlEnumerateGenericTable(Mcb->Mapping, FALSE), i++); 00180 if (Entry) 00181 { 00182 Result = TRUE; 00183 if (Vbn) 00184 *Vbn = Entry->RunStartVbn.QuadPart; 00185 if (Lbn) 00186 *Lbn = Entry->StartingLbn.QuadPart; 00187 if (SectorCount) 00188 *SectorCount = Entry->SectorCount.QuadPart; 00189 } 00190 00191 return Result; 00192 } 00193 00194 /* 00195 * @implemented 00196 */ 00197 BOOLEAN 00198 NTAPI 00199 FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb, 00200 IN ULONG RunIndex, 00201 OUT PLONGLONG Vbn, 00202 OUT PLONGLONG Lbn, 00203 OUT PLONGLONG SectorCount) 00204 { 00205 BOOLEAN Result; 00206 00207 DPRINT("FsRtlGetNextLargeMcbEntry Mcb %x RunIndex %x\n", Mcb, RunIndex); 00208 00209 KeAcquireGuardedMutex(Mcb->GuardedMutex); 00210 Result = FsRtlGetNextBaseMcbEntry(&(Mcb->BaseMcb), 00211 RunIndex, 00212 Vbn, 00213 Lbn, 00214 SectorCount); 00215 KeReleaseGuardedMutex(Mcb->GuardedMutex); 00216 00217 DPRINT("Done %d\n", Result); 00218 00219 return Result; 00220 } 00221 00222 /* 00223 * @implemented 00224 */ 00225 VOID 00226 NTAPI 00227 FsRtlInitializeBaseMcb(IN PBASE_MCB Mcb, 00228 IN POOL_TYPE PoolType) 00229 { 00230 Mcb->PairCount = 0; 00231 00232 if (PoolType == PagedPool) 00233 { 00234 Mcb->Mapping = ExAllocateFromPagedLookasideList(&FsRtlFirstMappingLookasideList); 00235 } 00236 else 00237 { 00238 Mcb->Mapping = ExAllocatePoolWithTag(PoolType | POOL_RAISE_IF_ALLOCATION_FAILURE, 00239 sizeof(RTL_GENERIC_TABLE) + sizeof(LIST_ENTRY), 00240 'FSBC'); 00241 } 00242 00243 Mcb->PoolType = PoolType; 00244 Mcb->MaximumPairCount = MAXIMUM_PAIR_COUNT; 00245 RtlInitializeGenericTable 00246 (Mcb->Mapping, 00247 (PRTL_GENERIC_COMPARE_ROUTINE)McbMappingCompare, 00248 McbMappingAllocate, 00249 McbMappingFree, 00250 Mcb); 00251 InitializeListHead(GET_LIST_HEAD(Mcb->Mapping)); 00252 } 00253 00254 /* 00255 * @implemented 00256 */ 00257 VOID 00258 NTAPI 00259 FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb, 00260 IN POOL_TYPE PoolType) 00261 { 00262 Mcb->GuardedMutex = ExAllocateFromNPagedLookasideList(&FsRtlFastMutexLookasideList); 00263 00264 KeInitializeGuardedMutex(Mcb->GuardedMutex); 00265 00266 _SEH2_TRY 00267 { 00268 FsRtlInitializeBaseMcb(&(Mcb->BaseMcb), PoolType); 00269 } 00270 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00271 { 00272 ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList, 00273 Mcb->GuardedMutex); 00274 Mcb->GuardedMutex = NULL; 00275 } 00276 _SEH2_END; 00277 } 00278 00279 /* 00280 * @implemented 00281 */ 00282 VOID 00283 NTAPI 00284 FsRtlInitializeLargeMcbs(VOID) 00285 { 00286 /* Initialize the list for the MCB */ 00287 ExInitializePagedLookasideList(&FsRtlFirstMappingLookasideList, 00288 NULL, 00289 NULL, 00290 POOL_RAISE_IF_ALLOCATION_FAILURE, 00291 sizeof(RTL_GENERIC_TABLE) + sizeof(LIST_ENTRY), 00292 IFS_POOL_TAG, 00293 0); /* FIXME: Should be 4 */ 00294 00295 /* Initialize the list for the guarded mutex */ 00296 ExInitializeNPagedLookasideList(&FsRtlFastMutexLookasideList, 00297 NULL, 00298 NULL, 00299 POOL_RAISE_IF_ALLOCATION_FAILURE, 00300 sizeof(KGUARDED_MUTEX), 00301 IFS_POOL_TAG, 00302 0); /* FIXME: Should be 32 */ 00303 } 00304 00305 /* 00306 * @unimplemented 00307 */ 00308 BOOLEAN 00309 NTAPI 00310 FsRtlLookupBaseMcbEntry(IN PBASE_MCB Mcb, 00311 IN LONGLONG Vbn, 00312 OUT PLONGLONG Lbn OPTIONAL, 00313 OUT PLONGLONG SectorCountFromLbn OPTIONAL, 00314 OUT PLONGLONG StartingLbn OPTIONAL, 00315 OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL, 00316 OUT PULONG Index OPTIONAL) 00317 { 00318 BOOLEAN Result = FALSE; 00319 LARGE_MCB_MAPPING_ENTRY ToLookup; 00320 PLARGE_MCB_MAPPING_ENTRY Entry; 00321 00322 ToLookup.RunStartVbn.QuadPart = Vbn; 00323 ToLookup.SectorCount.QuadPart = 1; 00324 00325 Entry = RtlLookupElementGenericTable(Mcb->Mapping, &ToLookup); 00326 if (!Entry) 00327 { 00328 // Find out if we have a following entry. The spec says we should return 00329 // found with Lbn == -1 when we're beneath the largest map. 00330 ToLookup.SectorCount.QuadPart = (1ull<<62) - ToLookup.RunStartVbn.QuadPart; 00331 Entry = RtlLookupElementGenericTable(Mcb->Mapping, &ToLookup); 00332 if (Entry) 00333 { 00334 Result = TRUE; 00335 if (Lbn) *Lbn = ~0ull; 00336 } 00337 else 00338 { 00339 Result = FALSE; 00340 } 00341 } 00342 else 00343 { 00344 LARGE_INTEGER Offset; 00345 Offset.QuadPart = Vbn - Entry->RunStartVbn.QuadPart; 00346 Result = TRUE; 00347 if (Lbn) *Lbn = Entry->StartingLbn.QuadPart + Offset.QuadPart; 00348 if (SectorCountFromLbn) *SectorCountFromLbn = Entry->SectorCount.QuadPart - Offset.QuadPart; 00349 if (StartingLbn) *StartingLbn = Entry->StartingLbn.QuadPart; 00350 if (SectorCountFromStartingLbn) *SectorCountFromStartingLbn = Entry->SectorCount.QuadPart; 00351 } 00352 00353 return Result; 00354 } 00355 00356 /* 00357 * @implemented 00358 */ 00359 BOOLEAN 00360 NTAPI 00361 FsRtlLookupLargeMcbEntry(IN PLARGE_MCB Mcb, 00362 IN LONGLONG Vbn, 00363 OUT PLONGLONG Lbn OPTIONAL, 00364 OUT PLONGLONG SectorCountFromLbn OPTIONAL, 00365 OUT PLONGLONG StartingLbn OPTIONAL, 00366 OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL, 00367 OUT PULONG Index OPTIONAL) 00368 { 00369 BOOLEAN Result; 00370 00371 DPRINT("FsRtlLookupLargeMcbEntry Mcb %x Vbn %x\n", Mcb, (ULONG)Vbn); 00372 00373 KeAcquireGuardedMutex(Mcb->GuardedMutex); 00374 Result = FsRtlLookupBaseMcbEntry(&(Mcb->BaseMcb), 00375 Vbn, 00376 Lbn, 00377 SectorCountFromLbn, 00378 StartingLbn, 00379 SectorCountFromStartingLbn, 00380 Index); 00381 KeReleaseGuardedMutex(Mcb->GuardedMutex); 00382 00383 DPRINT("Done %d\n", Result); 00384 00385 return Result; 00386 } 00387 00388 /* 00389 * @unimplemented 00390 */ 00391 BOOLEAN 00392 NTAPI 00393 FsRtlLookupLastBaseMcbEntryAndIndex(IN PBASE_MCB OpaqueMcb, 00394 IN OUT PLONGLONG LargeVbn, 00395 IN OUT PLONGLONG LargeLbn, 00396 IN OUT PULONG Index) 00397 { 00398 ULONG i = 0; 00399 BOOLEAN Result = FALSE; 00400 PLIST_ENTRY ListEntry; 00401 PLARGE_MCB_MAPPING_ENTRY Entry; 00402 PLARGE_MCB_MAPPING_ENTRY CountEntry; 00403 00404 ListEntry = GET_LIST_HEAD(OpaqueMcb->Mapping); 00405 if (!IsListEmpty(ListEntry)) 00406 { 00407 Entry = CONTAINING_RECORD(ListEntry->Flink, LARGE_MCB_MAPPING_ENTRY, Sequence); 00408 Result = TRUE; 00409 *LargeVbn = Entry->RunStartVbn.QuadPart; 00410 *LargeLbn = Entry->StartingLbn.QuadPart; 00411 00412 for (i = 0, CountEntry = RtlEnumerateGenericTable(OpaqueMcb->Mapping, TRUE); 00413 CountEntry != Entry; 00414 CountEntry = RtlEnumerateGenericTable(OpaqueMcb->Mapping, FALSE)); 00415 00416 *Index = i; 00417 } 00418 00419 return Result; 00420 } 00421 00422 /* 00423 * @implemented 00424 */ 00425 BOOLEAN 00426 NTAPI 00427 FsRtlLookupLastLargeMcbEntryAndIndex(IN PLARGE_MCB OpaqueMcb, 00428 OUT PLONGLONG LargeVbn, 00429 OUT PLONGLONG LargeLbn, 00430 OUT PULONG Index) 00431 { 00432 BOOLEAN Result; 00433 00434 DPRINT("FsRtlLookupLastLargeMcbEntryAndIndex %x\n", OpaqueMcb); 00435 00436 KeAcquireGuardedMutex(OpaqueMcb->GuardedMutex); 00437 Result = FsRtlLookupLastBaseMcbEntryAndIndex(&(OpaqueMcb->BaseMcb), 00438 LargeVbn, 00439 LargeLbn, 00440 Index); 00441 KeReleaseGuardedMutex(OpaqueMcb->GuardedMutex); 00442 00443 DPRINT("Done %d\n", Result); 00444 00445 return Result; 00446 } 00447 00448 /* 00449 * @unimplemented 00450 */ 00451 BOOLEAN 00452 NTAPI 00453 FsRtlLookupLastBaseMcbEntry(IN PBASE_MCB Mcb, 00454 OUT PLONGLONG Vbn, 00455 OUT PLONGLONG Lbn) 00456 { 00457 BOOLEAN Result = FALSE; 00458 PLIST_ENTRY ListEntry; 00459 PLARGE_MCB_MAPPING_ENTRY Entry; 00460 00461 ListEntry = GET_LIST_HEAD(Mcb->Mapping); 00462 if (!IsListEmpty(ListEntry)) 00463 { 00464 Entry = CONTAINING_RECORD(ListEntry->Flink, LARGE_MCB_MAPPING_ENTRY, Sequence); 00465 Result = TRUE; 00466 *Vbn = Entry->RunStartVbn.QuadPart; 00467 *Lbn = Entry->StartingLbn.QuadPart; 00468 } 00469 00470 return Result; 00471 } 00472 00473 /* 00474 * @implemented 00475 */ 00476 BOOLEAN 00477 NTAPI 00478 FsRtlLookupLastLargeMcbEntry(IN PLARGE_MCB Mcb, 00479 OUT PLONGLONG Vbn, 00480 OUT PLONGLONG Lbn) 00481 { 00482 BOOLEAN Result; 00483 00484 DPRINT("FsRtlLookupLastLargeMcbEntry Mcb %x\n", Mcb); 00485 00486 KeAcquireGuardedMutex(Mcb->GuardedMutex); 00487 Result = FsRtlLookupLastBaseMcbEntry(&(Mcb->BaseMcb), 00488 Vbn, 00489 Lbn); 00490 KeReleaseGuardedMutex(Mcb->GuardedMutex); 00491 00492 DPRINT("Done %d\n", Result); 00493 00494 return Result; 00495 } 00496 00497 /* 00498 * @implemented 00499 */ 00500 ULONG 00501 NTAPI 00502 FsRtlNumberOfRunsInBaseMcb(IN PBASE_MCB Mcb) 00503 { 00504 /* Return the count */ 00505 return Mcb->PairCount; 00506 } 00507 00508 /* 00509 * @implemented 00510 */ 00511 ULONG 00512 NTAPI 00513 FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb) 00514 { 00515 ULONG NumberOfRuns; 00516 00517 DPRINT("FsRtlNumberOfRunsInLargeMcb Mcb %x\n", Mcb); 00518 00519 /* Read the number of runs while holding the MCB lock */ 00520 KeAcquireGuardedMutex(Mcb->GuardedMutex); 00521 NumberOfRuns = Mcb->BaseMcb.PairCount; 00522 KeReleaseGuardedMutex(Mcb->GuardedMutex); 00523 00524 DPRINT("Done %d\n", NumberOfRuns); 00525 00526 /* Return the count */ 00527 return NumberOfRuns; 00528 } 00529 00530 /* 00531 * @unimplemented 00532 */ 00533 BOOLEAN 00534 NTAPI 00535 FsRtlRemoveBaseMcbEntry(IN PBASE_MCB Mcb, 00536 IN LONGLONG Vbn, 00537 IN LONGLONG SectorCount) 00538 { 00539 LARGE_MCB_MAPPING_ENTRY Node; 00540 PLARGE_MCB_MAPPING_ENTRY Element; 00541 00542 Node.RunStartVbn.QuadPart = Vbn; 00543 Node.SectorCount.QuadPart = SectorCount; 00544 00545 while ((Element = RtlLookupElementGenericTable(Mcb->Mapping, &Node))) 00546 { 00547 // Must split 00548 if (Element->RunStartVbn.QuadPart < Node.RunStartVbn.QuadPart && 00549 Element->SectorCount.QuadPart > Node.SectorCount.QuadPart) 00550 { 00551 LARGE_MCB_MAPPING_ENTRY Upper, Reinsert; 00552 PLARGE_MCB_MAPPING_ENTRY Reinserted, Inserted; 00553 LARGE_INTEGER StartHole = Node.RunStartVbn; 00554 LARGE_INTEGER EndHole; 00555 EndHole.QuadPart = Node.RunStartVbn.QuadPart + Node.SectorCount.QuadPart; 00556 Upper.RunStartVbn.QuadPart = EndHole.QuadPart; 00557 Upper.StartingLbn.QuadPart = 00558 Element->StartingLbn.QuadPart + 00559 EndHole.QuadPart - 00560 Element->RunStartVbn.QuadPart; 00561 Upper.SectorCount.QuadPart = 00562 Element->SectorCount.QuadPart - 00563 (EndHole.QuadPart - Element->RunStartVbn.QuadPart); 00564 Reinsert = *Element; 00565 Reinsert.SectorCount.QuadPart = 00566 Element->RunStartVbn.QuadPart - StartHole.QuadPart; 00567 RemoveEntryList(&Element->Sequence); 00568 RtlDeleteElementGenericTable(Mcb->Mapping, Element); 00569 Mcb->PairCount--; 00570 00571 Reinserted = RtlInsertElementGenericTable 00572 (Mcb->Mapping, &Reinsert, sizeof(Reinsert), NULL); 00573 InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Reinserted->Sequence); 00574 Mcb->PairCount++; 00575 00576 Inserted = RtlInsertElementGenericTable 00577 (Mcb->Mapping, &Upper, sizeof(Upper), NULL); 00578 InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Inserted->Sequence); 00579 Mcb->PairCount++; 00580 } 00581 else if (Element->RunStartVbn.QuadPart < Node.RunStartVbn.QuadPart) 00582 { 00583 LARGE_MCB_MAPPING_ENTRY NewElement; 00584 PLARGE_MCB_MAPPING_ENTRY Reinserted; 00585 LARGE_INTEGER StartHole = Node.RunStartVbn; 00586 NewElement.RunStartVbn = Element->RunStartVbn; 00587 NewElement.StartingLbn = Element->StartingLbn; 00588 NewElement.SectorCount.QuadPart = StartHole.QuadPart - Element->StartingLbn.QuadPart; 00589 00590 RemoveEntryList(&Element->Sequence); 00591 RtlDeleteElementGenericTable(Mcb->Mapping, Element); 00592 Mcb->PairCount--; 00593 00594 Reinserted = RtlInsertElementGenericTable 00595 (Mcb->Mapping, &NewElement, sizeof(NewElement), NULL); 00596 InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Reinserted->Sequence); 00597 Mcb->PairCount++; 00598 } 00599 else 00600 { 00601 LARGE_MCB_MAPPING_ENTRY NewElement; 00602 PLARGE_MCB_MAPPING_ENTRY Reinserted; 00603 LARGE_INTEGER EndHole = Element->RunStartVbn; 00604 LARGE_INTEGER EndRun; 00605 EndRun.QuadPart = Element->RunStartVbn.QuadPart + Element->SectorCount.QuadPart; 00606 NewElement.RunStartVbn = EndHole; 00607 NewElement.StartingLbn.QuadPart = Element->StartingLbn.QuadPart + 00608 (EndHole.QuadPart - Element->RunStartVbn.QuadPart); 00609 NewElement.SectorCount.QuadPart = EndRun.QuadPart - EndHole.QuadPart; 00610 00611 RemoveEntryList(&Element->Sequence); 00612 RtlDeleteElementGenericTable(Mcb->Mapping, Element); 00613 Mcb->PairCount--; 00614 00615 Reinserted = RtlInsertElementGenericTable 00616 (Mcb->Mapping, &NewElement, sizeof(NewElement), NULL); 00617 InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Reinserted->Sequence); 00618 Mcb->PairCount++; 00619 } 00620 } 00621 00622 return TRUE; 00623 } 00624 00625 /* 00626 * @implemented 00627 */ 00628 VOID 00629 NTAPI 00630 FsRtlRemoveLargeMcbEntry(IN PLARGE_MCB Mcb, 00631 IN LONGLONG Vbn, 00632 IN LONGLONG SectorCount) 00633 { 00634 DPRINT("FsRtlRemoveLargeMcbEntry Mcb %x, Vbn %x, SectorCount %x\n", Mcb, (ULONG)Vbn, (ULONG)SectorCount); 00635 00636 KeAcquireGuardedMutex(Mcb->GuardedMutex); 00637 FsRtlRemoveBaseMcbEntry(&(Mcb->BaseMcb), 00638 Vbn, 00639 SectorCount); 00640 KeReleaseGuardedMutex(Mcb->GuardedMutex); 00641 00642 DPRINT("Done\n"); 00643 } 00644 00645 /* 00646 * @implemented 00647 */ 00648 VOID 00649 NTAPI 00650 FsRtlResetBaseMcb(IN PBASE_MCB Mcb) 00651 { 00652 PLARGE_MCB_MAPPING_ENTRY Element; 00653 00654 while (RtlNumberGenericTableElements(Mcb->Mapping) && 00655 (Element = (PLARGE_MCB_MAPPING_ENTRY)RtlGetElementGenericTable(Mcb->Mapping, 0))) 00656 { 00657 RtlDeleteElementGenericTable(Mcb->Mapping, Element); 00658 } 00659 00660 Mcb->PairCount = 0; 00661 Mcb->MaximumPairCount = 0; 00662 } 00663 00664 /* 00665 * @implemented 00666 */ 00667 VOID 00668 NTAPI 00669 FsRtlResetLargeMcb(IN PLARGE_MCB Mcb, 00670 IN BOOLEAN SelfSynchronized) 00671 { 00672 if (!SelfSynchronized) 00673 { 00674 KeAcquireGuardedMutex(Mcb->GuardedMutex); 00675 } 00676 00677 FsRtlResetBaseMcb(&Mcb->BaseMcb); 00678 00679 00680 if (!SelfSynchronized) 00681 { 00682 KeReleaseGuardedMutex(Mcb->GuardedMutex); 00683 } 00684 } 00685 00686 #define MCB_BUMP_NO_MORE 0 00687 #define MCB_BUMP_AGAIN 1 00688 00689 static ULONG NTAPI McbBump(PBASE_MCB Mcb, PLARGE_MCB_MAPPING_ENTRY FixedPart) 00690 { 00691 LARGE_MCB_MAPPING_ENTRY Reimagined; 00692 PLARGE_MCB_MAPPING_ENTRY Found = NULL; 00693 00694 DPRINT("McbBump %x (%x:%x)\n", Mcb, FixedPart->RunStartVbn.LowPart, FixedPart->SectorCount.LowPart); 00695 00696 Reimagined = *FixedPart; 00697 while ((Found = RtlLookupElementGenericTable(Mcb->Mapping, &Reimagined))) 00698 { 00699 Reimagined = *Found; 00700 Reimagined.RunStartVbn.QuadPart = 00701 FixedPart->RunStartVbn.QuadPart + FixedPart->SectorCount.QuadPart; 00702 DPRINT("Reimagined %x\n", Reimagined.RunStartVbn.LowPart); 00703 } 00704 00705 DPRINT("Found %x\n", Found); 00706 if (!Found) return MCB_BUMP_NO_MORE; 00707 DPRINT1 00708 ("Moving %x-%x to %x because %x-%x overlaps\n", 00709 Found->RunStartVbn.LowPart, 00710 Found->RunStartVbn.LowPart + Found->SectorCount.QuadPart, 00711 Reimagined.RunStartVbn.LowPart + Reimagined.SectorCount.LowPart, 00712 Reimagined.RunStartVbn.LowPart, 00713 Reimagined.RunStartVbn.LowPart + Reimagined.SectorCount.LowPart); 00714 Found->RunStartVbn.QuadPart = Reimagined.RunStartVbn.QuadPart + Reimagined.SectorCount.QuadPart; 00715 Found->StartingLbn.QuadPart = Reimagined.StartingLbn.QuadPart + Reimagined.SectorCount.QuadPart; 00716 00717 DPRINT("Again\n"); 00718 return MCB_BUMP_AGAIN; 00719 } 00720 00721 /* 00722 * @unimplemented 00723 */ 00724 BOOLEAN 00725 NTAPI 00726 FsRtlSplitBaseMcb(IN PBASE_MCB Mcb, 00727 IN LONGLONG Vbn, 00728 IN LONGLONG Amount) 00729 { 00730 ULONG Result; 00731 LARGE_MCB_MAPPING_ENTRY Node; 00732 PLARGE_MCB_MAPPING_ENTRY Existing = NULL; 00733 00734 Node.RunStartVbn.QuadPart = Vbn; 00735 Node.SectorCount.QuadPart = 0; 00736 00737 Existing = RtlLookupElementGenericTable(Mcb->Mapping, &Node); 00738 00739 if (Existing) 00740 { 00741 // We're in the middle of a run 00742 LARGE_MCB_MAPPING_ENTRY UpperPart; 00743 LARGE_MCB_MAPPING_ENTRY LowerPart; 00744 PLARGE_MCB_MAPPING_ENTRY InsertedUpper; 00745 00746 UpperPart.RunStartVbn.QuadPart = Node.RunStartVbn.QuadPart + Amount; 00747 UpperPart.SectorCount.QuadPart = Existing->RunStartVbn.QuadPart + 00748 (Existing->SectorCount.QuadPart - Node.RunStartVbn.QuadPart); 00749 UpperPart.StartingLbn.QuadPart = Existing->StartingLbn.QuadPart + 00750 (Node.RunStartVbn.QuadPart - Existing->RunStartVbn.QuadPart); 00751 LowerPart.RunStartVbn.QuadPart = Existing->RunStartVbn.QuadPart; 00752 LowerPart.SectorCount.QuadPart = Node.RunStartVbn.QuadPart - Existing->RunStartVbn.QuadPart; 00753 LowerPart.StartingLbn.QuadPart = Existing->StartingLbn.QuadPart; 00754 00755 Node = UpperPart; 00756 00757 DPRINT("Loop: %x\n", Node.RunStartVbn.LowPart); 00758 while ((Result = McbBump(Mcb, &Node)) == MCB_BUMP_AGAIN) 00759 { 00760 DPRINT("Node: %x\n", Node.RunStartVbn.LowPart); 00761 } 00762 DPRINT("Done\n"); 00763 00764 if (Result == MCB_BUMP_NO_MORE) 00765 { 00766 Node = *Existing; 00767 RemoveHeadList(&Existing->Sequence); 00768 RtlDeleteElementGenericTable(Mcb->Mapping, Existing); 00769 Mcb->PairCount--; 00770 00771 // Adjust the element we found. 00772 Existing->SectorCount = LowerPart.SectorCount; 00773 00774 InsertedUpper = RtlInsertElementGenericTable 00775 (Mcb->Mapping, &UpperPart, sizeof(UpperPart), NULL); 00776 if (!InsertedUpper) 00777 { 00778 // Just make it like it was 00779 Existing->SectorCount = Node.SectorCount; 00780 return FALSE; 00781 } 00782 InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &InsertedUpper->Sequence); 00783 Mcb->PairCount++; 00784 } 00785 else 00786 { 00787 Node.RunStartVbn.QuadPart = Vbn; 00788 Node.SectorCount.QuadPart = Amount; 00789 while ((Result = McbBump(Mcb, &Node)) == MCB_BUMP_AGAIN); 00790 return Result == MCB_BUMP_NO_MORE; 00791 } 00792 } 00793 00794 DPRINT("Done\n"); 00795 00796 return TRUE; 00797 } 00798 00799 /* 00800 * @implemented 00801 */ 00802 BOOLEAN 00803 NTAPI 00804 FsRtlSplitLargeMcb(IN PLARGE_MCB Mcb, 00805 IN LONGLONG Vbn, 00806 IN LONGLONG Amount) 00807 { 00808 BOOLEAN Result; 00809 00810 DPRINT("FsRtlSplitLargeMcb %x, Vbn %x, Amount %x\n", Mcb, (ULONG)Vbn, (ULONG)Amount); 00811 00812 KeAcquireGuardedMutex(Mcb->GuardedMutex); 00813 Result = FsRtlSplitBaseMcb(&(Mcb->BaseMcb), 00814 Vbn, 00815 Amount); 00816 KeReleaseGuardedMutex(Mcb->GuardedMutex); 00817 00818 DPRINT("Done %d\n", Result); 00819 00820 return Result; 00821 } 00822 00823 /* 00824 * @unimplemented 00825 */ 00826 VOID 00827 NTAPI 00828 FsRtlTruncateBaseMcb(IN PBASE_MCB Mcb, 00829 IN LONGLONG Vbn) 00830 { 00831 if (!Vbn) 00832 { 00833 FsRtlResetBaseMcb(Mcb); 00834 } 00835 else 00836 { 00837 LARGE_MCB_MAPPING_ENTRY Truncate; 00838 PLARGE_MCB_MAPPING_ENTRY Found; 00839 Truncate.RunStartVbn.QuadPart = Vbn; 00840 Truncate.SectorCount.QuadPart = (1ull<<62) - Truncate.RunStartVbn.QuadPart; 00841 while ((Found = RtlLookupElementGenericTable(Mcb->Mapping, &Truncate))) 00842 { 00843 RemoveEntryList(&Found->Sequence); 00844 RtlDeleteElementGenericTable(Mcb->Mapping, Found); 00845 Mcb->PairCount--; 00846 } 00847 } 00848 } 00849 00850 /* 00851 * @implemented 00852 */ 00853 VOID 00854 NTAPI 00855 FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb, 00856 IN LONGLONG Vbn) 00857 { 00858 DPRINT("FsRtlTruncateLargeMcb %x Vbn %x\n", Mcb, (ULONG)Vbn); 00859 KeAcquireGuardedMutex(Mcb->GuardedMutex); 00860 FsRtlTruncateBaseMcb(&(Mcb->BaseMcb), 00861 Vbn); 00862 KeReleaseGuardedMutex(Mcb->GuardedMutex); 00863 DPRINT("Done\n"); 00864 } 00865 00866 /* 00867 * @implemented 00868 */ 00869 VOID 00870 NTAPI 00871 FsRtlUninitializeBaseMcb(IN PBASE_MCB Mcb) 00872 { 00873 FsRtlResetBaseMcb(Mcb); 00874 00875 if ((Mcb->PoolType == PagedPool) && (Mcb->MaximumPairCount == MAXIMUM_PAIR_COUNT)) 00876 { 00877 ExFreeToPagedLookasideList(&FsRtlFirstMappingLookasideList, 00878 Mcb->Mapping); 00879 } 00880 else 00881 { 00882 ExFreePoolWithTag(Mcb->Mapping, 'FSBC'); 00883 } 00884 } 00885 00886 /* 00887 * @implemented 00888 */ 00889 VOID 00890 NTAPI 00891 FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb) 00892 { 00893 if (Mcb->GuardedMutex) 00894 { 00895 ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList, 00896 Mcb->GuardedMutex); 00897 FsRtlUninitializeBaseMcb(&(Mcb->BaseMcb)); 00898 } 00899 } 00900 Generated on Sun May 27 2012 04:37:11 for ReactOS by
1.7.6.1
|