Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

largemcb.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 LargeMcb.c 00008 00009 Abstract: 00010 00011 The MCB routines provide support for maintaining an in-memory copy of 00012 the retrieval mapping information for a file. The general idea is to 00013 have the file system lookup the retrieval mapping for a VBN once from 00014 the disk, add the mapping to the MCB structure, and then utilize the 00015 MCB to retrieve the mapping for subsequent accesses to the file. A 00016 variable of type MCB is used to store the mapping information. 00017 00018 The routines provided here allow the user to incrementally store some 00019 or all of the retrieval mapping for a file and to do so in any order. 00020 That is, the mapping can be inserted to the MCB structure all at once 00021 starting from the beginning and working to the end of the file, or it 00022 can be randomly scattered throughout the file. 00023 00024 The package identifies each contiguous run of sectors mapping VBNs 00025 and LBNs indenpendent of the order they are added to the MCB 00026 structure. For example a user can define a mapping between VBN 00027 sector 0 and LBN sector 107, and between VBN sector 2 and LBN sector 00028 109. The mapping now contains two runs each one sector in length. 00029 Now if the user adds an additional mapping between VBN sector 1 and 00030 LBN sector 106 the MCB structure will contain only one run 3 sectors 00031 in length. 00032 00033 Concurrent access to the MCB structure is control by this package. 00034 00035 The following routines are provided by this package: 00036 00037 o FsRtlInitializeMcb - Initialize a new MCB structure. There 00038 should be one MCB for every opened file. Each MCB structure 00039 must be initialized before it can be used by the system. 00040 00041 o FsRtlUninitializeMcb - Uninitialize an MCB structure. This call 00042 is used to cleanup any anciallary structures allocated and 00043 maintained by the MCB. After being uninitialized the MCB must 00044 again be initialized before it can be used by the system. 00045 00046 o FsRtlAddMcbEntry - This routine adds a new range of mappings 00047 between LBNs and VBNs to the MCB structure. 00048 00049 o FsRtlRemoveMcbEntry - This routines removes an existing range of 00050 mappings between LBNs and VBNs from the MCB structure. 00051 00052 o FsRtlLookupMcbEntry - This routine returns the LBN mapped to by 00053 a VBN, and indicates, in sectors, the length of the run. 00054 00055 o FsRtlLookupLastMcbEntry - This routine returns the mapping for 00056 the largest VBN stored in the structure. 00057 00058 o FsRtlLookupLastMcbEntryAndIndex - This routine returns the mapping 00059 for the largest VBN stored in the structure as well as its index 00060 Note that calling LookupLastMcbEntry and NumberOfRunsInMcb cannot 00061 be synchronized except by the caller. 00062 00063 o FsRtlNumberOfRunsInMcb - This routine tells the caller total 00064 number of discontiguous sectors runs stored in the MCB 00065 structure. 00066 00067 o FsRtlGetNextMcbEntry - This routine returns the the caller the 00068 starting VBN and LBN of a given run stored in the MCB structure. 00069 00070 Author: 00071 00072 Gary Kimura [GaryKi] 5-Feb-1990 00073 00074 Revision History: 00075 00076 --*/ 00077 00078 #include "FsRtlP.h" 00079 00080 // 00081 // Trace level for the module 00082 // 00083 00084 #define Dbg (0x80000000) 00085 00086 00087 // 00088 // Retrieval mapping data structures. The following two structure together 00089 // are used to map a Vbn to an Lbn. It is layed out as follows: 00090 // 00091 // 00092 // MCB: 00093 // +----------------+----------------+ 00094 // | PairCount |MaximumPairCount| 00095 // +----------------+----------------+ 00096 // | Mapping | PoolType | 00097 // +----------------+----------------+ 00098 // 00099 // 00100 // MAPPING: 00101 // +----------------+----------------+ 00102 // | Lbn | NextVbn | : 0 00103 // +----------------+----------------+ 00104 // | | 00105 // / / 00106 // / / 00107 // | | 00108 // +----------------+----------------+ 00109 // | Lbn | NextVbn | : PairCount 00110 // +----------------+----------------+ 00111 // | | 00112 // / / 00113 // / / 00114 // | | 00115 // +----------------+----------------+ 00116 // | Lbn | NextVbn | 00117 // +----------------+----------------+ 00118 // 00119 // : MaximumPairCount 00120 // 00121 // The pairs from 0 to PairCount - 1 are valid. Given an index between 00122 // 0 and PairCount - 1 (inclusive) it represents the following Vbn 00123 // to Lbn mapping information 00124 // 00125 // 00126 // { if Index == 0 then 0 00127 // StartingVbn { 00128 // { if Index <> 0 then NextVbn[i-1] 00129 // 00130 // 00131 // EndingVbn = NextVbn[i] - 1 00132 // 00133 // 00134 // StartingLbn = Lbn[i] 00135 // 00136 // 00137 // To compute the mapping of a Vbn to an Lbn the following algorithm 00138 // is used 00139 // 00140 // 1. search through the pairs until we find the slot "i" that contains 00141 // the Vbn we after. Report an error if none if found. 00142 // 00143 // 2. Lbn = StartingLbn + (Vbn - StartingVbn); 00144 // 00145 // A hole in the allocation (i.e., a sparse allocation) is represented by 00146 // an Lbn value of -1 (note that is is different than Mcb.c). 00147 // 00148 00149 #define UNUSED_LBN (-1) 00150 00151 typedef struct _MAPPING { 00152 VBN NextVbn; 00153 LBN Lbn; 00154 } MAPPING; 00155 typedef MAPPING *PMAPPING; 00156 00157 typedef struct _NONOPAQUE_MCB { 00158 PFAST_MUTEX FastMutex; 00159 ULONG MaximumPairCount; 00160 ULONG PairCount; 00161 POOL_TYPE PoolType; 00162 PMAPPING Mapping; 00163 } NONOPAQUE_MCB; 00164 typedef NONOPAQUE_MCB *PNONOPAQUE_MCB; 00165 00166 // 00167 // A macro to return the size, in bytes, of a retrieval mapping structure 00168 // 00169 00170 #define SizeOfMapping(MCB) ((sizeof(MAPPING) * (MCB)->MaximumPairCount)) 00171 00172 // 00173 // The parts of a run can be computed as follows: 00174 // 00175 // 00176 // StartingVbn(MCB,I) Mapping[I].NextVbn 00177 // | | 00178 // V V 00179 // 00180 // Run-(I-1)---+ +---------Run-(I)-----------+ +---Run-(I+1) 00181 // 00182 // A A 00183 // | | 00184 // Mapping[I].Lbn EndingLbn(MCB,I) 00185 // 00186 00187 #define PreviousEndingVbn(MCB,I) ( \ 00188 (VBN)((I) == 0 ? 0xffffffff : EndingVbn(MCB,(I)-1)) \ 00189 ) 00190 00191 #define StartingVbn(MCB,I) ( \ 00192 (VBN)((I) == 0 ? 0 : (((MCB)->Mapping))[(I)-1].NextVbn) \ 00193 ) 00194 00195 #define EndingVbn(MCB,I) ( \ 00196 (VBN)((((MCB)->Mapping)[(I)].NextVbn) - 1) \ 00197 ) 00198 00199 #define NextStartingVbn(MCB,I) ( \ 00200 (VBN)((I) >= (MCB)->PairCount ? 0 : StartingVbn(MCB,(I)+1)) \ 00201 ) 00202 00203 00204 00205 00206 #define PreviousEndingLbn(MCB,I) ( \ 00207 (LBN)((I) == 0 ? UNUSED_LBN : EndingLbn(MCB,(I)-1)) \ 00208 ) 00209 00210 #define StartingLbn(MCB,I) ( \ 00211 (LBN)(((MCB)->Mapping)[(I)].Lbn) \ 00212 ) 00213 00214 #define EndingLbn(MCB,I) ( \ 00215 (LBN)(StartingLbn(MCB,I) == UNUSED_LBN ? \ 00216 UNUSED_LBN : \ 00217 ((MCB)->Mapping[(I)].Lbn + \ 00218 (MCB)->Mapping[(I)].NextVbn - StartingVbn(MCB,I) - 1) \ 00219 ) \ 00220 ) 00221 00222 #define NextStartingLbn(MCB,I) ( \ 00223 (LBN)((I) >= (MCB)->PairCount - 1 ? UNUSED_LBN : StartingLbn(MCB,(I)+1)) \ 00224 ) 00225 00226 #if 0 00227 LBN 00228 NextStartingLbn( 00229 PNONOPAQUE_MCB Mcb, 00230 ULONG I 00231 ) 00232 { 00233 if ( I >= Mcb->PairCount - 1 ) { 00234 return (LBN)UNUSED_LBN; 00235 } 00236 else { 00237 return StartingLbn(Mcb,I+1); 00238 } 00239 } 00240 #endif 00241 00242 #define SectorsWithinRun(MCB,I) ( \ 00243 (ULONG)(EndingVbn(MCB,I) - StartingVbn(MCB,I) + 1) \ 00244 ) 00245 00246 // 00247 // Define a tag for general pool allocations from this module 00248 // 00249 00250 #undef MODULE_POOL_TAG 00251 #define MODULE_POOL_TAG ('mrSF') 00252 00253 VOID 00254 FsRtlRemoveMcbEntryPrivate ( 00255 IN PNONOPAQUE_MCB OpaqueMcb, 00256 IN ULONG Vbn, 00257 IN ULONG SectorCount 00258 ); 00259 00260 // 00261 // A private routine to search a mapping structure for a Vbn 00262 // 00263 00264 BOOLEAN 00265 FsRtlFindLargeIndex ( 00266 IN PNONOPAQUE_MCB Mcb, 00267 IN VBN Vbn, 00268 OUT PULONG Index 00269 ); 00270 00271 VOID 00272 FsRtlAddLargeEntry ( 00273 IN PNONOPAQUE_MCB Mcb, 00274 IN ULONG WhereToAddIndex, 00275 IN ULONG AmountToAdd 00276 ); 00277 00278 VOID 00279 FsRtlRemoveLargeEntry ( 00280 IN PNONOPAQUE_MCB Mcb, 00281 IN ULONG WhereToRemoveIndex, 00282 IN ULONG AmountToRemove 00283 ); 00284 00285 // 00286 // Some private routines to handle common allocations. 00287 // 00288 00289 #define FsRtlAllocateFirstMapping() \ 00290 (PVOID)ExAllocateFromPagedLookasideList( &FsRtlFirstMappingLookasideList ) 00291 00292 #define FsRtlFreeFirstMapping(Mapping) \ 00293 ExFreeToPagedLookasideList( &FsRtlFirstMappingLookasideList, (Mapping) ) 00294 00295 #define FsRtlAllocateFastMutex() \ 00296 (PFAST_MUTEX)ExAllocateFromNPagedLookasideList( &FsRtlFastMutexLookasideList ) 00297 00298 #define FsRtlFreeFastMutex(FastMutex) \ 00299 ExFreeToNPagedLookasideList( &FsRtlFastMutexLookasideList, (FastMutex) ) 00300 00301 #ifdef ALLOC_PRAGMA 00302 #pragma alloc_text(PAGE, FsRtlInitializeLargeMcbs) 00303 #pragma alloc_text(PAGE, FsRtlInitializeMcb) 00304 #pragma alloc_text(PAGE, FsRtlUninitializeMcb) 00305 #endif 00306 00307 00308 // 00309 // Define a small cache of free mapping pairs structures and also the 00310 // initial size of the mapping pair 00311 // 00312 00313 #define INITIAL_MAXIMUM_PAIR_COUNT (15) 00314 00315 PAGED_LOOKASIDE_LIST FsRtlFirstMappingLookasideList; 00316 00317 // 00318 // The following lookaside is used to keep all the Fast Mutexes we will need to 00319 // boot contiguous. 00320 // 00321 00322 NPAGED_LOOKASIDE_LIST FsRtlFastMutexLookasideList; 00323 00324 00325 // 00326 // The following few routines define the small mcb package which is 00327 // implemented behind everyones back as large mcbs. The only funny 00328 // thing we really need to do here is to make sure that unused Lbns 00329 // get returned as 0 and not -1. This is the result of an historical 00330 // difference between the original Mcb and LargeMcb packages. 00331 // 00332 00333 VOID 00334 FsRtlInitializeMcb ( 00335 IN PMCB Mcb, 00336 IN POOL_TYPE PoolType 00337 ) 00338 { 00339 PAGED_CODE(); 00340 00341 FsRtlInitializeLargeMcb( (PLARGE_MCB)Mcb, 00342 PoolType ); 00343 00344 return; 00345 } 00346 00347 VOID 00348 FsRtlUninitializeMcb ( 00349 IN PMCB Mcb 00350 ) 00351 00352 { 00353 PAGED_CODE(); 00354 00355 FsRtlUninitializeLargeMcb( (PLARGE_MCB)Mcb ); 00356 00357 return; 00358 } 00359 00360 VOID 00361 FsRtlTruncateMcb ( 00362 IN PMCB Mcb, 00363 IN VBN Vbn 00364 ) 00365 { 00366 PAGED_CODE(); 00367 00368 FsRtlTruncateLargeMcb( (PLARGE_MCB)Mcb, 00369 (LONGLONG)(Vbn) ); 00370 00371 return; 00372 } 00373 00374 BOOLEAN 00375 FsRtlAddMcbEntry ( 00376 IN PMCB Mcb, 00377 IN VBN Vbn, 00378 IN LBN Lbn, 00379 IN ULONG SectorCount 00380 ) 00381 00382 { 00383 PAGED_CODE(); 00384 00385 return FsRtlAddLargeMcbEntry( (PLARGE_MCB)Mcb, 00386 (LONGLONG)(Vbn), 00387 (LONGLONG)(Lbn), 00388 (LONGLONG)(SectorCount) ); 00389 } 00390 00391 VOID 00392 FsRtlRemoveMcbEntry ( 00393 IN PMCB OpaqueMcb, 00394 IN VBN Vbn, 00395 IN ULONG SectorCount 00396 ) 00397 00398 { 00399 PNONOPAQUE_MCB Mcb = (PNONOPAQUE_MCB)OpaqueMcb; 00400 00401 PAGED_CODE(); 00402 00403 DebugTrace(+1, Dbg, "FsRtlRemoveMcbEntry, Mcb = %08lx\n", Mcb ); 00404 DebugTrace( 0, Dbg, " Vbn = %08lx\n", Vbn ); 00405 DebugTrace( 0, Dbg, " SectorCount = %08lx\n", SectorCount ); 00406 00407 ExAcquireFastMutex( Mcb->FastMutex ); 00408 00409 try { 00410 00411 FsRtlRemoveMcbEntryPrivate( Mcb, 00412 Vbn, 00413 SectorCount ); 00414 00415 } finally { 00416 00417 ExReleaseFastMutex( Mcb->FastMutex ); 00418 00419 DebugTrace(-1, Dbg, "FsRtlRemoveMcbEntry -> VOID\n", 0 ); 00420 } 00421 00422 return; 00423 } 00424 00425 BOOLEAN 00426 FsRtlLookupMcbEntry ( 00427 IN PMCB Mcb, 00428 IN VBN Vbn, 00429 OUT PLBN Lbn, 00430 OUT PULONG SectorCount OPTIONAL, 00431 OUT PULONG Index OPTIONAL 00432 ) 00433 00434 { 00435 BOOLEAN Results; 00436 LONGLONG LiLbn; 00437 LONGLONG LiSectorCount; 00438 00439 Results = FsRtlLookupLargeMcbEntry( (PLARGE_MCB)Mcb, 00440 (LONGLONG)(Vbn), 00441 &LiLbn, 00442 ARGUMENT_PRESENT(SectorCount) ? &LiSectorCount : NULL, 00443 NULL, 00444 NULL, 00445 Index ); 00446 00447 *Lbn = (((ULONG)LiLbn) == -1 ? 0 : ((ULONG)LiLbn)); 00448 00449 if (ARGUMENT_PRESENT(SectorCount)) { *SectorCount = ((ULONG)LiSectorCount); } 00450 00451 return Results; 00452 } 00453 00454 BOOLEAN 00455 FsRtlLookupLastMcbEntry ( 00456 IN PMCB Mcb, 00457 OUT PVBN Vbn, 00458 OUT PLBN Lbn 00459 ) 00460 00461 { 00462 BOOLEAN Results; 00463 LONGLONG LiVbn; 00464 LONGLONG LiLbn; 00465 00466 PAGED_CODE(); 00467 00468 Results = FsRtlLookupLastLargeMcbEntry( (PLARGE_MCB)Mcb, 00469 &LiVbn, 00470 &LiLbn ); 00471 00472 *Vbn = ((ULONG)LiVbn); 00473 *Lbn = (((ULONG)LiLbn) == -1 ? 0 : ((ULONG)LiLbn)); 00474 00475 return Results; 00476 } 00477 00478 ULONG 00479 FsRtlNumberOfRunsInMcb ( 00480 IN PMCB Mcb 00481 ) 00482 00483 { 00484 PAGED_CODE(); 00485 00486 return FsRtlNumberOfRunsInLargeMcb( (PLARGE_MCB)Mcb ); 00487 } 00488 00489 BOOLEAN 00490 FsRtlGetNextMcbEntry ( 00491 IN PMCB Mcb, 00492 IN ULONG RunIndex, 00493 OUT PVBN Vbn, 00494 OUT PLBN Lbn, 00495 OUT PULONG SectorCount 00496 ) 00497 00498 { 00499 BOOLEAN Results; 00500 LONGLONG LiVbn; 00501 LONGLONG LiLbn; 00502 LONGLONG LiSectorCount; 00503 00504 PAGED_CODE(); 00505 00506 Results = FsRtlGetNextLargeMcbEntry( (PLARGE_MCB)Mcb, 00507 RunIndex, 00508 &LiVbn, 00509 &LiLbn, 00510 &LiSectorCount ); 00511 00512 *Vbn = ((ULONG)LiVbn); 00513 *Lbn = (((ULONG)LiLbn) == -1 ? 0 : ((ULONG)LiLbn)); 00514 *SectorCount = ((ULONG)LiSectorCount); 00515 00516 return Results; 00517 } 00518 00519 00520 VOID 00521 FsRtlInitializeLargeMcbs ( 00522 VOID 00523 ) 00524 00525 /*++ 00526 00527 Routine Description: 00528 00529 This routine initializes the global portion of the large mcb package 00530 at system initialization time. 00531 00532 Arguments: 00533 00534 None. 00535 00536 Return Value: 00537 00538 None. 00539 00540 --*/ 00541 00542 { 00543 // 00544 // Initialize the lookaside of paged initial mapping arrays. 00545 // 00546 00547 ExInitializePagedLookasideList( &FsRtlFirstMappingLookasideList, 00548 NULL, 00549 NULL, 00550 POOL_RAISE_IF_ALLOCATION_FAILURE, 00551 sizeof( MAPPING ) * INITIAL_MAXIMUM_PAIR_COUNT, 00552 'miSF', 00553 4 ); 00554 00555 // 00556 // Initialize the Fast Mutex lookaside list. 00557 // 00558 00559 ExInitializeNPagedLookasideList( &FsRtlFastMutexLookasideList, 00560 NULL, 00561 NULL, 00562 POOL_RAISE_IF_ALLOCATION_FAILURE, 00563 sizeof( FAST_MUTEX), 00564 'mfSF', 00565 32 ); 00566 00567 00568 } 00569 00570 00571 VOID 00572 FsRtlInitializeLargeMcb ( 00573 IN PLARGE_MCB OpaqueMcb, 00574 IN POOL_TYPE PoolType 00575 ) 00576 00577 /*++ 00578 00579 Routine Description: 00580 00581 This routine initializes a new Mcb structure. The caller must 00582 supply the memory for the Mcb structure. This call must precede all 00583 other calls that set/query the Mcb structure. 00584 00585 If pool is not available this routine will raise a status value 00586 indicating insufficient resources. 00587 00588 Arguments: 00589 00590 OpaqueMcb - Supplies a pointer to the Mcb structure to initialize. 00591 00592 PoolType - Supplies the pool type to use when allocating additional 00593 internal Mcb memory. 00594 00595 Return Value: 00596 00597 None. 00598 00599 --*/ 00600 00601 { 00602 PNONOPAQUE_MCB Mcb = (PNONOPAQUE_MCB)OpaqueMcb; 00603 00604 DebugTrace(+1, Dbg, "FsRtlInitializeLargeMcb, Mcb = %08lx\n", Mcb ); 00605 00606 // 00607 // Preset the following fields to null so we know to deallocate them 00608 // during an abnormal termination 00609 // 00610 00611 Mcb->FastMutex = NULL; 00612 Mcb->Mapping = NULL; 00613 00614 try { 00615 00616 // 00617 // Initialize the fields in the Mcb 00618 // 00619 00620 Mcb->FastMutex = FsRtlAllocateFastMutex(); 00621 00622 ExInitializeFastMutex( Mcb->FastMutex ); 00623 00624 Mcb->PairCount = 0; 00625 Mcb->PoolType = PoolType; 00626 00627 // 00628 // Allocate a new buffer an initial size is one that will hold 00629 // 16 runs 00630 // 00631 00632 if (PoolType == PagedPool) { 00633 00634 Mcb->Mapping = FsRtlAllocateFirstMapping(); 00635 00636 } else { 00637 00638 Mcb->Mapping = FsRtlpAllocatePool( Mcb->PoolType, sizeof(MAPPING) * INITIAL_MAXIMUM_PAIR_COUNT ); 00639 } 00640 00641 //**** RtlZeroMemory( Mcb->Mapping, sizeof(MAPPING) * INITIAL_MAXIMUM_PAIR_COUNT ); 00642 00643 Mcb->MaximumPairCount = INITIAL_MAXIMUM_PAIR_COUNT; 00644 00645 } finally { 00646 00647 // 00648 // If this is an abnormal termination then we need to deallocate 00649 // the FastMutex and/or mapping (but once the mapping is allocated, 00650 // we can't raise). 00651 // 00652 00653 if (AbnormalTermination()) { 00654 00655 if (Mcb->FastMutex != NULL) { FsRtlFreeFastMutex( Mcb->FastMutex ); } 00656 } 00657 00658 DebugTrace(-1, Dbg, "FsRtlInitializeLargeMcb -> VOID\n", 0 ); 00659 } 00660 00661 // 00662 // And return to our caller 00663 // 00664 00665 return; 00666 } 00667 00668 00669 VOID 00670 FsRtlUninitializeLargeMcb ( 00671 IN PLARGE_MCB OpaqueMcb 00672 ) 00673 00674 /*++ 00675 00676 Routine Description: 00677 00678 This routine uninitializes an Mcb structure. After calling this routine 00679 the input Mcb structure must be re-initialized before being used again. 00680 00681 Arguments: 00682 00683 OpaqueMcb - Supplies a pointer to the Mcb structure to uninitialize. 00684 00685 Return Value: 00686 00687 None. 00688 00689 --*/ 00690 00691 { 00692 PNONOPAQUE_MCB Mcb = (PNONOPAQUE_MCB)OpaqueMcb; 00693 00694 DebugTrace(+1, Dbg, "FsRtlUninitializeLargeMcb, Mcb = %08lx\n", Mcb ); 00695 00696 // 00697 // Protect against some user calling us to uninitialize an mcb twice 00698 // 00699 00700 if (Mcb->FastMutex == NULL) { 00701 00702 // ASSERTMSG("Being called to uninitialize an Mcb that is already Uninitialized ", FALSE); 00703 00704 return; 00705 } 00706 00707 // 00708 // Deallocate the FastMutex and mapping buffer 00709 // 00710 00711 FsRtlFreeFastMutex( Mcb->FastMutex ); 00712 00713 Mcb->FastMutex = NULL; 00714 00715 if ((Mcb->PoolType == PagedPool) && (Mcb->MaximumPairCount == INITIAL_MAXIMUM_PAIR_COUNT)) { 00716 00717 FsRtlFreeFirstMapping( Mcb->Mapping ); 00718 00719 } else { 00720 00721 ExFreePool( Mcb->Mapping ); 00722 } 00723 00724 // 00725 // Now zero our all of the fields in the Mcb 00726 // 00727 00728 //**** Mcb->MaximumPairCount = 0; 00729 //**** Mcb->PairCount = 0; 00730 //**** Mcb->Mapping = NULL; 00731 00732 // 00733 // And return to our caller 00734 // 00735 00736 DebugTrace(-1, Dbg, "FsRtlUninitializeLargeMcb -> VOID\n", 0 ); 00737 00738 return; 00739 } 00740 00741 00742 VOID 00743 FsRtlTruncateLargeMcb ( 00744 IN PLARGE_MCB OpaqueMcb, 00745 IN LONGLONG LargeVbn 00746 ) 00747 00748 /*++ 00749 00750 Routine Description: 00751 00752 This routine truncates an Mcb structure to the specified Vbn. 00753 After calling this routine the Mcb will only contain mappings 00754 up to and not including the input vbn. 00755 00756 Arguments: 00757 00758 OpaqueMcb - Supplies a pointer to the Mcb structure to truncate. 00759 00760 LargeVbn - Specifies the last Vbn at which is no longer to be 00761 mapped. 00762 00763 Return Value: 00764 00765 None. 00766 00767 --*/ 00768 00769 { 00770 PNONOPAQUE_MCB Mcb = (PNONOPAQUE_MCB)OpaqueMcb; 00771 00772 VBN Vbn = ((ULONG)LargeVbn); 00773 ULONG Index; 00774 00775 PAGED_CODE(); 00776 00777 DebugTrace(+1, Dbg, "FsRtlTruncateLargeMcb, Mcb = %08lx\n", Mcb ); 00778 00779 ExAcquireFastMutex( Mcb->FastMutex ); 00780 00781 ASSERTMSG("LargeInteger not supported yet ", ((((PLARGE_INTEGER)&LargeVbn)->HighPart == 0) || 00782 (Mcb->PairCount == 0) || 00783 ((((PLARGE_INTEGER)&LargeVbn)->HighPart == 0x7FFFFFFF) && 00784 (((ULONG)LargeVbn) == 0xFFFFFFFF)))); 00785 00786 try { 00787 00788 // 00789 // Do a quick test to see if we are truncating the entire Mcb. 00790 // 00791 00792 if (Vbn == 0) { 00793 00794 Mcb->PairCount = 0; 00795 00796 } else if (Mcb->PairCount > 0) { 00797 00798 // 00799 // Find the index for the entry with the last Vcn we want to keep. 00800 // There is nothing to do if the Mcb already ends prior to 00801 // this point. 00802 // 00803 00804 if (FsRtlFindLargeIndex(Mcb, Vbn - 1, &Index)) { 00805 00806 // 00807 // If this entry currently describes a hole then 00808 // truncate to the previous entry. 00809 // 00810 00811 if (StartingLbn(Mcb, Index) == UNUSED_LBN) { 00812 00813 Mcb->PairCount = Index; 00814 00815 // 00816 // Otherwise we will truncate the Mcb to this point. Truncate 00817 // the number of Vbns of this run if necessary. 00818 // 00819 00820 } else { 00821 00822 Mcb->PairCount = Index + 1; 00823 00824 if (NextStartingVbn(Mcb, Index) > Vbn) { 00825 00826 (Mcb->Mapping)[Index].NextVbn = Vbn; 00827 } 00828 } 00829 } 00830 } 00831 00832 // 00833 // Now see if we can shrink the allocation for the mapping pairs. 00834 // We'll shrink the mapping pair buffer if the new pair count will 00835 // fit within a quarter of the current maximum pair count and the 00836 // current maximum is greater than the initial pair count. 00837 // 00838 00839 if ((Mcb->PairCount < (Mcb->MaximumPairCount / 4)) && 00840 (Mcb->MaximumPairCount > INITIAL_MAXIMUM_PAIR_COUNT)) { 00841 00842 ULONG NewMax; 00843 PMAPPING Mapping; 00844 00845 // 00846 // We need to allocate a new mapping so compute a new maximum pair 00847 // count. We'll allocate double the current pair count, but never 00848 // less than the initial pair count. 00849 // 00850 00851 NewMax = Mcb->PairCount * 2; 00852 00853 if (NewMax < INITIAL_MAXIMUM_PAIR_COUNT) { 00854 NewMax = INITIAL_MAXIMUM_PAIR_COUNT; 00855 } 00856 00857 // 00858 // Be careful to trap failures due to resource exhaustion. 00859 // 00860 00861 try { 00862 00863 if (NewMax == INITIAL_MAXIMUM_PAIR_COUNT && Mcb->PoolType == PagedPool) { 00864 00865 Mapping = FsRtlAllocateFirstMapping(); 00866 00867 } else { 00868 00869 Mapping = FsRtlpAllocatePool( Mcb->PoolType, sizeof(MAPPING) * NewMax ); 00870 } 00871 00872 } except (EXCEPTION_EXECUTE_HANDLER) { 00873 00874 Mapping = NULL; 00875 } 00876 00877 // 00878 // Now check if we really got a new buffer 00879 // 00880 00881 if (Mapping != NULL) { 00882 00883 // 00884 // Now copy over the old mapping to the new buffer 00885 // 00886 00887 RtlCopyMemory( Mapping, Mcb->Mapping, sizeof(MAPPING) * Mcb->PairCount ); 00888 00889 // 00890 // Deallocate the old buffer. This should never be the size of an 00891 // initial mapping ... 00892 // 00893 00894 ExFreePool( Mcb->Mapping ); 00895 00896 // 00897 // And set up the new buffer in the Mcb 00898 // 00899 00900 Mcb->Mapping = Mapping; 00901 Mcb->MaximumPairCount = NewMax; 00902 } 00903 } 00904 00905 } finally { 00906 00907 ExReleaseFastMutex( Mcb->FastMutex ); 00908 } 00909 00910 // 00911 // And return to our caller 00912 // 00913 00914 DebugTrace(-1, Dbg, "FsRtlTruncateLargeMcb -> VOID\n", 0 ); 00915 00916 return; 00917 } 00918 00919 00920 NTKERNELAPI 00921 VOID 00922 FsRtlResetLargeMcb ( 00923 IN PLARGE_MCB OpaqueMcb, 00924 IN BOOLEAN SelfSynchronized 00925 ) 00926 00927 /*++ 00928 00929 Routine Description: 00930 00931 This routine truncates an Mcb structure to contain zero mapping 00932 pairs. It does not shrink the mapping pairs array. 00933 00934 Arguments: 00935 00936 OpaqueMcb - Supplies a pointer to the Mcb structure to truncate. 00937 00938 SelfSynchronized - Indicates whether the caller is already synchronized 00939 with respect to the Mcb. 00940 00941 Return Value: 00942 00943 None. 00944 00945 --*/ 00946 00947 { 00948 PNONOPAQUE_MCB Mcb = (PNONOPAQUE_MCB)OpaqueMcb; 00949 00950 if (SelfSynchronized) { 00951 00952 // 00953 // If we are self-synchronized, then all we do is clear out the 00954 // current mapping pair count. 00955 // 00956 00957 Mcb->PairCount = 0; 00958 00959 } else { 00960 00961 // 00962 // Since we are not self-synchronized, we must serialize access to 00963 // the Mcb before clearing the pair count 00964 // 00965 00966 ExAcquireFastMutex( Mcb->FastMutex ); 00967 Mcb->PairCount = 0; 00968 ExReleaseFastMutex( Mcb->FastMutex ); 00969 00970 } 00971 00972 return; 00973 } 00974 00975 00976 BOOLEAN 00977 FsRtlAddLargeMcbEntry ( 00978 IN PLARGE_MCB OpaqueMcb, 00979 IN LONGLONG LargeVbn, 00980 IN LONGLONG LargeLbn, 00981 IN LONGLONG LargeSectorCount 00982 ) 00983 00984 /*++ 00985 00986 Routine Description: 00987 00988 This routine is used to add a new mapping of VBNs to LBNs to an existing 00989 Mcb. The information added will map 00990 00991 Vbn to Lbn, 00992 00993 Vbn+1 to Lbn+1,... 00994 00995 Vbn+(SectorCount-1) to Lbn+(SectorCount-1). 00996 00997 The mapping for the VBNs must not already exist in the Mcb. If the 00998 mapping continues a previous run, then this routine will actually coalesce 00999 them into 1 run. 01000 01001 If pool is not available to store the information this routine will raise a 01002 status value indicating insufficient resources. 01003 01004 An input Lbn value of zero is illegal (i.e., the Mcb structure will never 01005 map a Vbn to a zero Lbn value). 01006 01007 Arguments: 01008 01009 OpaqueMcb - Supplies the Mcb in which to add the new mapping. 01010 01011 Vbn - Supplies the starting Vbn of the new mapping run to add to the Mcb. 01012 01013 Lbn - Supplies the starting Lbn of the new mapping run to add to the Mcb. 01014 01015 SectorCount - Supplies the size of the new mapping run (in sectors). 01016 01017 Return Value: 01018 01019 BOOLEAN - TRUE if the mapping was added successfully (i.e., the new 01020 Vbns did not collide with existing Vbns), and FALSE otherwise. If 01021 FALSE is returned then the Mcb is not changed. 01022 01023 --*/ 01024 01025 { 01026 PNONOPAQUE_MCB Mcb = (PNONOPAQUE_MCB)OpaqueMcb; 01027 01028 VBN Vbn = ((ULONG)LargeVbn); 01029 LBN Lbn = ((ULONG)LargeLbn); 01030 ULONG SectorCount = ((ULONG)LargeSectorCount); 01031 01032 ULONG Index; 01033 01034 VBN LastVbn; 01035 01036 BOOLEAN Result; 01037 01038 ASSERTMSG("LargeInteger not supported yet ", ((PLARGE_INTEGER)&LargeVbn)->HighPart == 0); 01039 ASSERTMSG("LargeInteger not supported yet ", ((PLARGE_INTEGER)&LargeLbn)->HighPart == 0); 01040 ASSERTMSG("LargeInteger not supported yet ", ((PLARGE_INTEGER)&LargeSectorCount)->HighPart == 0); 01041 01042 PAGED_CODE(); 01043 01044 DebugTrace(+1, Dbg, "FsRtlAddLargeMcbEntry, Mcb = %08lx\n", Mcb ); 01045 DebugTrace( 0, Dbg, " Vbn = %08lx\n", Vbn ); 01046 DebugTrace( 0, Dbg, " Lbn = %08lx\n", Lbn ); 01047 DebugTrace( 0, Dbg, " SectorCount = %08lx\n", SectorCount ); 01048 01049 ExAcquireFastMutex( Mcb->FastMutex ); 01050 01051 try { 01052 01053 if (FsRtlFindLargeIndex(Mcb, Vbn, &Index)) { 01054 01055 ULONG EndVbn = Vbn + SectorCount - 1; 01056 ULONG EndIndex; 01057 01058 // 01059 // First check the case where we are adding to an existing mcb run 01060 // and if so then we will modify the insertion to complete the run 01061 // 01062 // --ExistingRun--| ==becomes==> --ExistingRun--| 01063 // |--NewRun--| |---| 01064 // 01065 // --ExistingRun----| ==becomes==> a noop 01066 // |--NewRun--| 01067 // 01068 01069 if (StartingLbn(Mcb, Index) != UNUSED_LBN) { 01070 01071 // 01072 // Check that the Lbn's line up between the new and existing run 01073 // 01074 01075 if (Lbn != (StartingLbn(Mcb, Index) + (Vbn - StartingVbn(Mcb, Index)))) { 01076 01077 // 01078 // Let our caller know we couldn't insert the run. 01079 // 01080 01081 try_return(Result = FALSE); 01082 } 01083 01084 // 01085 // Check if the new run is contained in the existing run 01086 // 01087 01088 if (EndVbn <= EndingVbn(Mcb, Index)) { 01089 01090 // 01091 // Do nothing because the run is contained within the existing run 01092 // 01093 01094 try_return(Result = TRUE); 01095 } 01096 01097 // 01098 // Otherwise we will simply trim off the request for the new run 01099 // to not overlap with the existing run 01100 // 01101 01102 Vbn = NextStartingVbn(Mcb, Index); 01103 Lbn = EndingLbn(Mcb, Index) + 1; 01104 01105 ASSERT(EndVbn >= Vbn); 01106 01107 SectorCount = EndVbn - Vbn + 1; 01108 01109 // 01110 // At this point the new run start in a hole, now check that if 01111 // crosses into a non hole and if so then adjust new run to fit 01112 // in the hole 01113 // 01114 // 01115 // |--ExistingRun-- ==becomes==> |--ExistingRun-- 01116 // |--NewRun--| |--New| 01117 // 01118 01119 } else if (FsRtlFindLargeIndex(Mcb, EndVbn, &EndIndex) && (Index == (EndIndex-1))) { 01120 01121 // 01122 // Check that the Lbn's line up in the overlap 01123 // 01124 01125 if (StartingLbn(Mcb, EndIndex) != Lbn + (StartingVbn(Mcb, EndIndex) - Vbn)) { 01126 01127 // 01128 // Let our caller know we couldn't insert the run. 01129 // 01130 01131 try_return(Result = FALSE); 01132 } 01133 01134 // 01135 // Truncate the sector count to go up to but not include 01136 // the existing run 01137 // 01138 01139 SectorCount = StartingVbn(Mcb, EndIndex) - Vbn; 01140 } 01141 } 01142 01143 // 01144 // Find the index for the starting Vbn of our new run, if there isn't 01145 // a hole found then index will be set to paircount. 01146 // 01147 01148 if (((Index = Mcb->PairCount) == 0) || 01149 (PreviousEndingVbn(Mcb,Index)+1 <= Vbn) || 01150 !FsRtlFindLargeIndex(Mcb, Vbn, &Index)) { 01151 01152 // 01153 // We didn't find a mapping, therefore this new mapping must 01154 // go on at the end of the current mapping. 01155 // 01156 // See if we can just grow the last mapping in the current mcb. 01157 // We can grow the last entry if (1) the Vbns follow on, and (2) 01158 // the Lbns follow on. We can only grow the last mapping if the 01159 // index is not 0. 01160 // 01161 01162 if ((Index != 0) && 01163 (PreviousEndingVbn(Mcb,Index) + 1 == Vbn) && 01164 (PreviousEndingLbn(Mcb,Index) + 1 == Lbn)) { 01165 01166 // 01167 // --LastRun--|---NewRun--| 01168 // 01169 01170 // 01171 // Extend the last run in the mcb 01172 // 01173 01174 DebugTrace( 0, Dbg, "Continuing last run\n", 0); 01175 01176 (Mcb->Mapping)[Mcb->PairCount-1].NextVbn += SectorCount; 01177 01178 try_return (Result = TRUE); 01179 } 01180 01181 // 01182 // We couldn't grow the last mapping, now check to see if 01183 // this is a continuation of the last Vbn (i.e., there isn't 01184 // going to be a hole in the mapping). Or if this is the first 01185 // run in the mapping 01186 // 01187 01188 if ((Vbn == 0) || 01189 (PreviousEndingVbn(Mcb,Index) + 1 == Vbn)) { 01190 01191 // 01192 // --LastRun--||---NewRun--| 01193 // 01194 // 0:|--NewRun--| 01195 // 01196 01197 // 01198 // We only need to add one more run to the mcb, so make sure 01199 // there is enough room for one. 01200 // 01201 01202 DebugTrace( 0, Dbg, "Adding new contiguous last run\n", 0); 01203 01204 FsRtlAddLargeEntry( Mcb, Index, 1 ); 01205 01206 // 01207 // Add the new mapping 01208 // 01209 01210 (Mcb->Mapping)[Index].Lbn = Lbn; 01211 (Mcb->Mapping)[Index].NextVbn = Vbn + SectorCount; 01212 01213 try_return (Result = TRUE); 01214 } 01215 01216 // 01217 // If we reach this point then there is going to be a hole in the 01218 // mapping. and the mapping gets appended to the end of the current 01219 // allocation. So need to make room for two more runs in the mcb. 01220 // 01221 01222 // 01223 // --LastRun--| hole |---NewRun--| 01224 // 01225 // 0: hole |--NewRun--| 01226 // 01227 01228 DebugTrace( 0, Dbg, "Adding new noncontiguous last run\n", 0); 01229 01230 FsRtlAddLargeEntry( Mcb, Index, 2 ); 01231 01232 // 01233 // Add the hole 01234 // 01235 01236 (Mcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN; 01237 (Mcb->Mapping)[Index].NextVbn = Vbn; 01238 01239 // 01240 // Add the new mapping 01241 // 01242 01243 (Mcb->Mapping)[Index+1].Lbn = Lbn; 01244 (Mcb->Mapping)[Index+1].NextVbn = Vbn + SectorCount; 01245 01246 try_return (Result = TRUE); 01247 } 01248 01249 // 01250 // We found an index for the Vbn therefore we must be trying 01251 // to fill up a hole in the mcb. So first we need to check to make 01252 // sure there really is a hole to be filled 01253 // 01254 01255 LastVbn = Vbn + SectorCount - 1; 01256 01257 if ((StartingLbn(Mcb,Index) == UNUSED_LBN) && 01258 (StartingVbn(Mcb,Index) <= Vbn) && (LastVbn <= EndingVbn(Mcb,Index))) { 01259 01260 // 01261 // The mapping fits in this hole, but now here are the following 01262 // cases we must consider for the new mapping 01263 // 01264 01265 if ((StartingVbn(Mcb,Index) < Vbn) && (LastVbn < EndingVbn(Mcb,Index))) { 01266 01267 // Leaves a hole are both ends 01268 // 01269 // --PreviousRun--| hole |--NewRun--| hole |--FollowingRun-- 01270 // 01271 // 0: hole |--NewRun--| hole |--FollowingRun-- 01272 // 01273 01274 DebugTrace( 0, Dbg, "Hole at both ends\n", 0); 01275 01276 // 01277 // Make room for two more entries. The NextVbn field of the 01278 // one we're shifting remains valid. 01279 // 01280 01281 FsRtlAddLargeEntry( Mcb, Index, 2 ); 01282 01283 // 01284 // Add the first hole 01285 // 01286 01287 (Mcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN; 01288 (Mcb->Mapping)[Index].NextVbn = Vbn; 01289 01290 // 01291 // Add the new mapping 01292 // 01293 01294 (Mcb->Mapping)[Index+1].Lbn = Lbn; 01295 (Mcb->Mapping)[Index+1].NextVbn = Vbn + SectorCount; 01296 01297 // 01298 // The second hole is already set up by the add entry call, because 01299 // that call just shift over the original hole to that slot 01300 // 01301 01302 try_return (Result = TRUE); 01303 } 01304 01305 if ((StartingVbn(Mcb,Index) == Vbn) && (LastVbn < EndingVbn(Mcb,Index))) { 01306 01307 if (PreviousEndingLbn(Mcb,Index) + 1 == Lbn) { 01308 01309 // 01310 // Leaves a hole at the rear, and continues the earlier run 01311 // 01312 // --PreviousRun--|--NewRun--| hole |--FollowingRun-- 01313 // 01314 01315 DebugTrace( 0, Dbg, "Hole at rear and continue\n", 0); 01316 01317 // 01318 // We just need to extend the previous run 01319 // 01320 01321 (Mcb->Mapping)[Index-1].NextVbn += SectorCount; 01322 01323 try_return (Result = TRUE); 01324 01325 } else { 01326 01327 // 01328 // Leaves a hole at the rear, and does not continue the 01329 // earlier run. As occurs if index is zero. 01330 // 01331 // --PreviousRun--||--NewRun--| hole |--FollowingRun-- 01332 // 01333 // 0:|--NewRun--| hole |--FollowingRun-- 01334 // 01335 01336 DebugTrace( 0, Dbg, "Hole at rear and not continue\n", 0); 01337 01338 // 01339 // Make room for one more entry. The NextVbn field of the 01340 // one we're shifting remains valid. 01341 // 01342 01343 FsRtlAddLargeEntry( Mcb, Index, 1 ); 01344 01345 // 01346 // Add the new mapping 01347 // 01348 01349 (Mcb->Mapping)[Index].Lbn = Lbn; 01350 (Mcb->Mapping)[Index].NextVbn = Vbn + SectorCount; 01351 01352 // 01353 // The hole is already set up by the add entry call, because 01354 // that call just shift over the original hole to that slot 01355 // 01356 01357 try_return (Result = TRUE); 01358 } 01359 } 01360 01361 if ((StartingVbn(Mcb,Index) < Vbn) && (LastVbn == EndingVbn(Mcb,Index))) { 01362 01363 if (NextStartingLbn(Mcb,Index) == Lbn + SectorCount) { 01364 01365 // 01366 // Leaves a hole at the front, and continues the following run 01367 // 01368 // --PreviousRun--| hole |--NewRun--|--FollowingRun-- 01369 // 01370 // 0: hole |--NewRun--|--FollowingRun-- 01371 // 01372 01373 DebugTrace( 0, Dbg, "Hole at front and continue\n", 0); 01374 01375 // 01376 // We just need to extend the following run 01377 // 01378 01379 (Mcb->Mapping)[Index].NextVbn = Vbn; 01380 (Mcb->Mapping)[Index+1].Lbn = Lbn; 01381 01382 try_return (Result = TRUE); 01383 01384 } else { 01385 01386 // 01387 // Leaves a hole at the front, and does not continue the following 01388 // run 01389 // 01390 // --PreviousRun--| hole |--NewRun--||--FollowingRun-- 01391 // 01392 // 0: hole |--NewRun--||--FollowingRun-- 01393 // 01394 01395 DebugTrace( 0, Dbg, "Hole at front and not continue\n", 0); 01396 01397 // 01398 // Make room for one more entry. The NextVbn field of the 01399 // one we're shifting remains valid. 01400 // 01401 01402 FsRtlAddLargeEntry( Mcb, Index, 1 ); 01403 01404 // 01405 // Add the hole 01406 // 01407 01408 (Mcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN; 01409 (Mcb->Mapping)[Index].NextVbn = Vbn; 01410 01411 // 01412 // Add the new mapping 01413 // 01414 01415 (Mcb->Mapping)[Index+1].Lbn = Lbn; 01416 01417 try_return (Result = TRUE); 01418 } 01419 01420 } 01421 01422 if ((PreviousEndingLbn(Mcb,Index) + 1 == Lbn) && 01423 (NextStartingLbn(Mcb,Index) == Lbn + SectorCount)) { 01424 01425 // 01426 // Leaves no holes, and continues both runs 01427 // 01428 // --PreviousRun--|--NewRun--|--FollowingRun-- 01429 // 01430 01431 DebugTrace( 0, Dbg, "No holes, and continues both runs\n", 0); 01432 01433 // 01434 // We need to collapse the current index and the following index 01435 // but first we copy the NextVbn of the follwing run into 01436 // the NextVbn field of the previous run to so it all becomes 01437 // one run 01438 // 01439 01440 (Mcb->Mapping)[Index-1].NextVbn = (Mcb->Mapping)[Index+1].NextVbn; 01441 01442 FsRtlRemoveLargeEntry( Mcb, Index, 2 ); 01443 01444 try_return (Result = TRUE); 01445 } 01446 01447 if (NextStartingLbn(Mcb,Index) == Lbn + SectorCount) { 01448 01449 // 01450 // Leaves no holes, and continues only following run 01451 // 01452 // --PreviousRun--||--NewRun--|--FollowingRun-- 01453 // 01454 // 0:|--NewRun--|--FollowingRun-- 01455 // 01456 01457 DebugTrace( 0, Dbg, "No holes, and continues following\n", 0); 01458 01459 // 01460 // This index is going away so we need to stretch the 01461 // following run to meet up with the previous run 01462 // 01463 01464 (Mcb->Mapping)[Index+1].Lbn = Lbn; 01465 01466 FsRtlRemoveLargeEntry( Mcb, Index, 1 ); 01467 01468 try_return (Result = TRUE); 01469 } 01470 01471 if (PreviousEndingLbn(Mcb,Index) + 1 == Lbn) { 01472 01473 // 01474 // Leaves no holes, and continues only earlier run 01475 // 01476 // --PreviousRun--|--NewRun--||--FollowingRun-- 01477 // 01478 01479 DebugTrace( 0, Dbg, "No holes, and continues earlier\n", 0); 01480 01481 // 01482 // This index is going away so we need to stretch the 01483 // previous run to meet up with the following run 01484 // 01485 01486 (Mcb->Mapping)[Index-1].NextVbn = (Mcb->Mapping)[Index].NextVbn; 01487 01488 FsRtlRemoveLargeEntry( Mcb, Index, 1 ); 01489 01490 try_return (Result = TRUE); 01491 } 01492 01493 // 01494 // Leaves no holes, and continues neither run 01495 // 01496 // --PreviousRun--||--NewRun--||--FollowingRun-- 01497 // 01498 // 0:|--NewRun--||--FollowingRun-- 01499 // 01500 01501 DebugTrace( 0, Dbg, "No holes, and continues none\n", 0); 01502 01503 (Mcb->Mapping)[Index].Lbn = Lbn; 01504 01505 try_return (Result = TRUE); 01506 } 01507 01508 // 01509 // We tried to overwrite an existing mapping so we'll have to 01510 // tell our caller that it's not possible 01511 // 01512 01513 Result = FALSE; 01514 01515 try_exit: NOTHING; 01516 } finally { 01517 01518 ExReleaseFastMutex( Mcb->FastMutex ); 01519 01520 DebugTrace(-1, Dbg, "FsRtlAddLargeMcbEntry -> %08lx\n", Result ); 01521 } 01522 01523 return Result; 01524 } 01525 01526 01527 VOID 01528 FsRtlRemoveLargeMcbEntry ( 01529 IN PLARGE_MCB OpaqueMcb, 01530 IN LONGLONG LargeVbn, 01531 IN LONGLONG LargeSectorCount 01532 ) 01533 01534 /*++ 01535 01536 Routine Description: 01537 01538 This routine removes a mapping of VBNs to LBNs from an Mcb. The mappings 01539 removed are for 01540 01541 Vbn, 01542 01543 Vbn+1, to 01544 01545 Vbn+(SectorCount-1). 01546 01547 The operation works even if the mapping for a Vbn in the specified range 01548 does not already exist in the Mcb. If the specified range of Vbn includes 01549 the last mapped Vbn in the Mcb then the Mcb mapping shrinks accordingly. 01550 01551 If pool is not available to store the information this routine will raise 01552 a status value indicating insufficient resources. 01553 01554 Arguments: 01555 01556 OpaqueMcb - Supplies the Mcb from which to remove the mapping. 01557 01558 Vbn - Supplies the starting Vbn of the mappings to remove. 01559 01560 SectorCount - Supplies the size of the mappings to remove (in sectors). 01561 01562 Return Value: 01563 01564 None. 01565 01566 --*/ 01567 01568 { 01569 PNONOPAQUE_MCB Mcb = (PNONOPAQUE_MCB)OpaqueMcb; 01570 01571 VBN Vbn = ((ULONG)LargeVbn); 01572 ULONG SectorCount = ((ULONG)LargeSectorCount); 01573 01574 PAGED_CODE(); 01575 01576 ASSERTMSG("LargeInteger not supported yet ", ((PLARGE_INTEGER)&LargeVbn)->HighPart == 0); 01577 01578 DebugTrace(+1, Dbg, "FsRtlRemoveLargeMcbEntry, Mcb = %08lx\n", Mcb ); 01579 DebugTrace( 0, Dbg, " Vbn = %08lx\n", Vbn ); 01580 DebugTrace( 0, Dbg, " SectorCount = %08lx\n", SectorCount ); 01581 01582 ExAcquireFastMutex( Mcb->FastMutex ); 01583 01584 try { 01585 01586 FsRtlRemoveMcbEntryPrivate( Mcb, Vbn, SectorCount ); 01587 01588 } finally { 01589 01590 ExReleaseFastMutex( Mcb->FastMutex ); 01591 01592 DebugTrace(-1, Dbg, "FsRtlRemoveLargeMcbEntry -> VOID\n", 0 ); 01593 } 01594 01595 return; 01596 } 01597 01598 01599 BOOLEAN 01600 FsRtlLookupLargeMcbEntry ( 01601 IN PLARGE_MCB OpaqueMcb, 01602 IN LONGLONG LargeVbn, 01603 OUT PLONGLONG LargeLbn OPTIONAL, 01604 OUT PLONGLONG LargeSectorCount OPTIONAL, 01605 OUT PLONGLONG LargeStartingLbn OPTIONAL, 01606 OUT PLONGLONG LargeCountFromStartingLbn OPTIONAL, 01607 OUT PULONG Index OPTIONAL 01608 ) 01609 01610 /*++ 01611 01612 Routine Description: 01613 01614 This routine retrieves the mapping of a Vbn to an Lbn from an Mcb. 01615 It indicates if the mapping exists and the size of the run. 01616 01617 Arguments: 01618 01619 OpaqueMcb - Supplies the Mcb being examined. 01620 01621 Vbn - Supplies the Vbn to lookup. 01622 01623 Lbn - Receives the Lbn corresponding to the Vbn. A value of -1 is 01624 returned if the Vbn does not have a corresponding Lbn. 01625 01626 SectorCount - Receives the number of sectors that map from the Vbn to 01627 contiguous Lbn values beginning with the input Vbn. 01628 01629 Index - Receives the index of the run found. 01630 01631 Return Value: 01632 01633 BOOLEAN - TRUE if the Vbn is within the range of VBNs mapped by the 01634 MCB (even if it corresponds to a hole in the mapping), and FALSE 01635 if the Vbn is beyond the range of the MCB's mapping. 01636 01637 For example, if an MCB has a mapping for VBNs 5 and 7 but not for 01638 6, then a lookup on Vbn 5 or 7 will yield a non zero Lbn and a sector 01639 count of 1. A lookup for Vbn 6 will return TRUE with an Lbn value of 01640 0, and lookup for Vbn 8 or above will return FALSE. 01641 01642 --*/ 01643 01644 { 01645 PNONOPAQUE_MCB Mcb = (PNONOPAQUE_MCB)OpaqueMcb; 01646 01647 BOOLEAN Result; 01648 01649 ULONG LocalIndex; 01650 01651 DebugTrace(+1, Dbg, "FsRtlLookupLargeMcbEntry, Mcb = %08lx\n", Mcb ); 01652 DebugTrace( 0, Dbg, " LargeVbn.LowPart = %08lx\n", LargeVbn.LowPart ); 01653 01654 ExAcquireFastMutex( Mcb->FastMutex ); 01655 01656 ASSERTMSG("LargeInteger not supported yet ", ((((PLARGE_INTEGER)&LargeVbn)->HighPart == 0) || 01657 (Mcb->PairCount == 0) || 01658 ((((PLARGE_INTEGER)&LargeVbn)->HighPart == 0x7FFFFFFF) && 01659 (((ULONG)LargeVbn) == 0xFFFFFFFF)))); 01660 01661 try { 01662 01663 if (!FsRtlFindLargeIndex(Mcb, ((ULONG)LargeVbn), &LocalIndex)) { 01664 01665 try_return (Result = FALSE); 01666 } 01667 01668 // 01669 // Compute the lbn for corresponding to the vbn, the value is the 01670 // starting lbn of the run plus the number of sectors offset into the 01671 // run. But if it's a hole then the sector Lbn is zero. 01672 // 01673 01674 if (ARGUMENT_PRESENT(LargeLbn)) { 01675 01676 if (StartingLbn(Mcb,LocalIndex) == UNUSED_LBN) { 01677 01678 *((PULONG)LargeLbn) = (LBN)UNUSED_LBN; 01679 01680 } else { 01681 01682 *((PULONG)LargeLbn) = StartingLbn(Mcb,LocalIndex) + (((ULONG)LargeVbn) - StartingVbn(Mcb,LocalIndex)); 01683 } 01684 } 01685 01686 // 01687 // If there sector count argument is present then we'll return the number 01688 // of sectors remaing in the run. 01689 // 01690 01691 if (ARGUMENT_PRESENT(LargeSectorCount)) { 01692 01693 *((PULONG)LargeSectorCount) = EndingVbn(Mcb,LocalIndex) - ((ULONG)LargeVbn) + 1; 01694 } 01695 01696 // 01697 // Compute the starting lbn for corresponding to the start of the run, the value is the 01698 // starting lbn of the run. But if it's a hole then the sector Lbn is zero. 01699 // 01700 01701 if (ARGUMENT_PRESENT(LargeStartingLbn)) { 01702 01703 if (StartingLbn(Mcb,LocalIndex) == UNUSED_LBN) { 01704 01705 *((PULONG)LargeStartingLbn) = (LBN)UNUSED_LBN; 01706 01707 } else { 01708 01709 *((PULONG)LargeStartingLbn) = StartingLbn(Mcb,LocalIndex); 01710 } 01711 } 01712 01713 // 01714 // If there sector count argument is present then we'll return the number 01715 // of sectors in the run. 01716 // 01717 01718 if (ARGUMENT_PRESENT(LargeCountFromStartingLbn)) { 01719 01720 *((PULONG)LargeCountFromStartingLbn) = EndingVbn(Mcb,LocalIndex) - StartingVbn(Mcb,LocalIndex) + 1; 01721 } 01722 01723 // 01724 // If the caller want to know the Index number, fill it in. 01725 // 01726 01727 if (ARGUMENT_PRESENT(Index)) { 01728 01729 *Index = LocalIndex; 01730 } 01731 01732 Result = TRUE; 01733 01734 try_exit: NOTHING; 01735 } finally { 01736 01737 ExReleaseFastMutex( Mcb->FastMutex ); 01738 01739 DebugTrace(-1, Dbg, "FsRtlLookupLargeMcbEntry -> %08lx\n", Result ); 01740 } 01741 01742 if (ARGUMENT_PRESENT(LargeLbn)) { 01743 ((PLARGE_INTEGER)LargeLbn)->HighPart = (*((PULONG)LargeLbn) == UNUSED_LBN ? UNUSED_LBN : 0); 01744 } 01745 01746 if (ARGUMENT_PRESENT(LargeSectorCount)) { 01747 ((PLARGE_INTEGER)LargeSectorCount)->HighPart = 0; 01748 } 01749 01750 if (ARGUMENT_PRESENT(LargeStartingLbn)) { 01751 ((PLARGE_INTEGER)LargeStartingLbn)->HighPart = (*((PULONG)LargeStartingLbn) == UNUSED_LBN ? UNUSED_LBN : 0); 01752 } 01753 01754 if (ARGUMENT_PRESENT(LargeCountFromStartingLbn)) { 01755 ((PLARGE_INTEGER)LargeCountFromStartingLbn)->HighPart = 0; 01756 } 01757 01758 return Result; 01759 } 01760 01761 01762 BOOLEAN 01763 FsRtlLookupLastLargeMcbEntry ( 01764 IN PLARGE_MCB OpaqueMcb, 01765 OUT PLONGLONG LargeVbn, 01766 OUT PLONGLONG LargeLbn 01767 ) 01768 01769 /*++ 01770 01771 Routine Description: 01772 01773 This routine retrieves the last Vbn to Lbn mapping stored in the Mcb. 01774 It returns the mapping for the last sector or the last run in the 01775 Mcb. The results of this function is useful when extending an existing 01776 file and needing to a hint on where to try and allocate sectors on the 01777 disk. 01778 01779 Arguments: 01780 01781 OpaqueMcb - Supplies the Mcb being examined. 01782 01783 Vbn - Receives the last Vbn value mapped. 01784 01785 Lbn - Receives the Lbn corresponding to the Vbn. 01786 01787 Return Value: 01788 01789 BOOLEAN - TRUE if there is a mapping within the Mcb and FALSE otherwise 01790 (i.e., the Mcb does not contain any mapping). 01791 01792 --*/ 01793 01794 { 01795 PNONOPAQUE_MCB Mcb = (PNONOPAQUE_MCB)OpaqueMcb; 01796 01797 BOOLEAN Result; 01798 01799 PAGED_CODE(); 01800 01801 DebugTrace(+1, Dbg, "FsRtlLookupLastLargeMcbEntry, Mcb = %08lx\n", Mcb ); 01802 01803 ExAcquireFastMutex( Mcb->FastMutex ); 01804 01805 try { 01806 01807 // 01808 // Check to make sure there is at least one run in the mcb 01809 // 01810 01811 if (Mcb->PairCount <= 0) { 01812 01813 try_return (Result = FALSE); 01814 } 01815 01816 // 01817 // Return the last mapping of the last run 01818 // 01819 01820 *((PULONG)LargeLbn) = EndingLbn(Mcb,Mcb->PairCount-1); 01821 *((PULONG)LargeVbn) = EndingVbn(Mcb,Mcb->PairCount-1); 01822 01823 Result = TRUE; 01824 01825 try_exit: NOTHING; 01826 } finally { 01827 01828 ExReleaseFastMutex( Mcb->FastMutex ); 01829 01830 DebugTrace(-1, Dbg, "FsRtlLookupLastLargeMcbEntry -> %08lx\n", Result ); 01831 } 01832 01833 ((PLARGE_INTEGER)LargeVbn)->HighPart = (*((PULONG)LargeVbn) == UNUSED_LBN ? UNUSED_LBN : 0); 01834 ((PLARGE_INTEGER)LargeLbn)->HighPart = (*((PULONG)LargeLbn) == UNUSED_LBN ? UNUSED_LBN : 0); 01835 01836 return Result; 01837 } 01838 01839 01840 BOOLEAN 01841 FsRtlLookupLastLargeMcbEntryAndIndex ( 01842 IN PLARGE_MCB OpaqueMcb, 01843 OUT PLONGLONG LargeVbn, 01844 OUT PLONGLONG LargeLbn, 01845 OUT PULONG Index 01846 ) 01847 01848 /*++ 01849 01850 Routine Description: 01851 01852 This routine retrieves the last Vbn to Lbn mapping stored in the Mcb. 01853 It returns the mapping for the last sector or the last run in the 01854 Mcb. The results of this function is useful when extending an existing 01855 file and needing to a hint on where to try and allocate sectors on the 01856 disk. 01857 01858 Arguments: 01859 01860 OpaqueMcb - Supplies the Mcb being examined. 01861 01862 Vbn - Receives the last Vbn value mapped. 01863 01864 Lbn - Receives the Lbn corresponding to the Vbn. 01865 01866 Index - Receives the index of the last run. 01867 01868 Return Value: 01869 01870 BOOLEAN - TRUE if there is a mapping within the Mcb and FALSE otherwise 01871 (i.e., the Mcb does not contain any mapping). 01872 01873 --*/ 01874 01875 { 01876 PNONOPAQUE_MCB Mcb = (PNONOPAQUE_MCB)OpaqueMcb; 01877 01878 BOOLEAN Result; 01879 01880 PAGED_CODE(); 01881 01882 DebugTrace(+1, Dbg, "FsRtlLookupLastLargeMcbEntryAndIndex, Mcb = %08lx\n", Mcb ); 01883 01884 ExAcquireFastMutex( Mcb->FastMutex ); 01885 01886 try { 01887 01888 // 01889 // Check to make sure there is at least one run in the mcb 01890 // 01891 01892 if (Mcb->PairCount <= 0) { 01893 01894 try_return (Result = FALSE); 01895 } 01896 01897 // 01898 // Return the last mapping of the last run 01899 // 01900 01901 *((PULONG)LargeLbn) = EndingLbn(Mcb,Mcb->PairCount-1); 01902 *((PULONG)LargeVbn) = EndingVbn(Mcb,Mcb->PairCount-1); 01903 01904 *Index = Mcb->PairCount - 1; 01905 01906 Result = TRUE; 01907 01908 try_exit: NOTHING; 01909 } finally { 01910 01911 ExReleaseFastMutex( Mcb->FastMutex ); 01912 01913 DebugTrace(-1, Dbg, "FsRtlLookupLastLargeMcbEntryAndIndex -> %08lx\n", Result ); 01914 } 01915 01916 ((PLARGE_INTEGER)LargeVbn)->HighPart = (*((PULONG)LargeVbn) == UNUSED_LBN ? UNUSED_LBN : 0); 01917 ((PLARGE_INTEGER)LargeLbn)->HighPart = (*((PULONG)LargeLbn) == UNUSED_LBN ? UNUSED_LBN : 0); 01918 01919 return Result; 01920 } 01921 01922 01923 ULONG 01924 FsRtlNumberOfRunsInLargeMcb ( 01925 IN PLARGE_MCB OpaqueMcb 01926 ) 01927 01928 /*++ 01929 01930 Routine Description: 01931 01932 This routine returns to the its caller the number of distinct runs 01933 mapped by an Mcb. Holes (i.e., Vbns that map to Lbn=UNUSED_LBN) are counted 01934 as runs. For example, an Mcb containing a mapping for only Vbns 0 and 3 01935 will have 3 runs, one for the first mapped sector, a second for the 01936 hole covering Vbns 1 and 2, and a third for Vbn 3. 01937 01938 Arguments: 01939 01940 OpaqueMcb - Supplies the Mcb being examined. 01941 01942 Return Value: 01943 01944 ULONG - Returns the number of distinct runs mapped by the input Mcb. 01945 01946 --*/ 01947 01948 { 01949 PNONOPAQUE_MCB Mcb = (PNONOPAQUE_MCB)OpaqueMcb; 01950 01951 ULONG Count; 01952 01953 PAGED_CODE(); 01954 01955 DebugTrace(+1, Dbg, "FsRtlNumberOfRunsInLargeMcb, Mcb = %08lx\n", Mcb ); 01956 01957 ExAcquireFastMutex( Mcb->FastMutex ); 01958 01959 Count = Mcb->PairCount; 01960 01961 ExReleaseFastMutex( Mcb->FastMutex ); 01962 01963 DebugTrace(-1, Dbg, "FsRtlNumberOfRunsInLargeMcb -> %08lx\n", Count ); 01964 01965 return Count; 01966 } 01967 01968 01969 BOOLEAN 01970 FsRtlGetNextLargeMcbEntry ( 01971 IN PLARGE_MCB OpaqueMcb, 01972 IN ULONG RunIndex, 01973 OUT PLONGLONG LargeVbn, 01974 OUT PLONGLONG LargeLbn, 01975 OUT PLONGLONG LargeSectorCount 01976 ) 01977 01978 /*++ 01979 01980 Routine Description: 01981 01982 This routine returns to its caller the Vbn, Lbn, and SectorCount for 01983 distinct runs mapped by an Mcb. Holes are counted as runs. For example, 01984 to construct to print out all of the runs in a a file is: 01985 01986 //. . for (i = 0; FsRtlGetNextLargeMcbEntry(Mcb,i,&Vbn,&Lbn,&Count); i++) { 01987 // 01988 //. . // print out vbn, lbn, and count 01989 // 01990 //. . } 01991 01992 Arguments: 01993 01994 OpaqueMcb - Supplies the Mcb being examined. 01995 01996 RunIndex - Supplies the index of the run (zero based) to return to the 01997 caller. 01998 01999 Vbn - Receives the starting Vbn of the returned run, or zero if the 02000 run does not exist. 02001 02002 Lbn - Recieves the starting Lbn of the returned run, or zero if the 02003 run does not exist. 02004 02005 SectorCount - Receives the number of sectors within the returned run, 02006 or zero if the run does not exist. 02007 02008 Return Value: 02009 02010 BOOLEAN - TRUE if the specified run (i.e., RunIndex) exists in the Mcb, 02011 and FALSE otherwise. If FALSE is returned then the Vbn, Lbn, and 02012 SectorCount parameters receive zero. 02013 02014 --*/ 02015 02016 { 02017 PNONOPAQUE_MCB Mcb = (PNONOPAQUE_MCB)OpaqueMcb; 02018 02019 BOOLEAN Result; 02020 02021 PAGED_CODE(); 02022 02023 DebugTrace(+1, Dbg, "FsRtlGetNextLargeMcbEntry, Mcb = %08lx\n", Mcb ); 02024 DebugTrace( 0, Dbg, " RunIndex = %08lx\n", RunIndex ); 02025 02026 ExAcquireFastMutex( Mcb->FastMutex ); 02027 02028 try { 02029 02030 // 02031 // Make sure the run index is within range 02032 // 02033 02034 if (RunIndex >= Mcb->PairCount) { 02035 02036 try_return (Result = FALSE); 02037 } 02038 02039 // 02040 // Set the return variables 02041 // 02042 02043 *((PULONG)LargeVbn) = StartingVbn(Mcb,RunIndex); 02044 *((PULONG)LargeLbn) = StartingLbn(Mcb,RunIndex); 02045 *((PULONG)LargeSectorCount) = SectorsWithinRun(Mcb,RunIndex); 02046 02047 Result = TRUE; 02048 02049 try_exit: NOTHING; 02050 } finally { 02051 02052 ExReleaseFastMutex( Mcb->FastMutex ); 02053 02054 DebugTrace(-1, Dbg, "FsRtlGetNextLargeMcbEntry -> %08lx\n", Result ); 02055 } 02056 02057 ((PLARGE_INTEGER)LargeVbn)->HighPart = (*((PULONG)LargeVbn) == UNUSED_LBN ? UNUSED_LBN : 0); 02058 ((PLARGE_INTEGER)LargeLbn)->HighPart = (*((PULONG)LargeLbn) == UNUSED_LBN ? UNUSED_LBN : 0); 02059 ((PLARGE_INTEGER)LargeSectorCount)->HighPart = 0; 02060 02061 return Result; 02062 } 02063 02064 02065 BOOLEAN 02066 FsRtlSplitLargeMcb ( 02067 IN PLARGE_MCB OpaqueMcb, 02068 IN LONGLONG LargeVbn, 02069 IN LONGLONG LargeAmount 02070 ) 02071 02072 /*++ 02073 02074 Routine Description: 02075 02076 This routine is used to create a hole within an MCB, by shifting the 02077 mapping of Vbns. All mappings above the input vbn are shifted by the 02078 amount specified and while keeping their current lbn value. Pictorially 02079 we have as input the following MCB 02080 02081 VBN : LargeVbn-1 LargeVbn N 02082 +-----------------+------------------+ 02083 LBN : X Y 02084 02085 And after the split we have 02086 02087 VBN : LargeVbn-1 LargeVbn+Amount N+Amount 02088 +-----------------+.............+---------------------------+ 02089 LBN : X UnusedLbn Y 02090 02091 When doing the split we have a few cases to consider. They are: 02092 02093 1. The input Vbn is beyond the last run. In this case this operation 02094 is a noop. 02095 02096 2. The input Vbn is within or adjacent to a existing run of unused Lbns. 02097 In this case we simply need to extend the size of the existing hole 02098 and shift succeeding runs. 02099 02100 3. The input Vbn is between two existing runs, including the an input vbn 02101 value of zero. In this case we need to add a new entry for the hole 02102 and shift succeeding runs. 02103 02104 4. The input Vbn is within an existing run. In this case we need to add 02105 two new entries to contain the split run and the hole. 02106 02107 If pool is not available to store the information this routine will raise a 02108 status value indicating insufficient resources. 02109 02110 Arguments: 02111 02112 OpaqueMcb - Supplies the Mcb in which to add the new mapping. 02113 02114 Vbn - Supplies the starting Vbn that is to be shifted. 02115 02116 Amount - Supplies the amount to shift by. 02117 02118 Return Value: 02119 02120 BOOLEAN - TRUE if the mapping was successfully shifted, and FALSE otherwise. 02121 If FALSE is returned then the Mcb is not changed. 02122 02123 --*/ 02124 02125 { 02126 PNONOPAQUE_MCB Mcb = (PNONOPAQUE_MCB)OpaqueMcb; 02127 02128 VBN Vbn = ((ULONG)LargeVbn); 02129 ULONG Amount = ((ULONG)LargeAmount); 02130 02131 ULONG Index; 02132 02133 BOOLEAN Result; 02134 02135 ULONG i; 02136 02137 PAGED_CODE(); 02138 02139 DebugTrace(+1, Dbg, "FsRtlSplitLargeMcb, Mcb = %08lx\n", Mcb ); 02140 DebugTrace( 0, Dbg, " Vbn = %08lx\n", Vbn ); 02141 DebugTrace( 0, Dbg, " Amount = %08lx\n", Amount ); 02142 02143 ExAcquireFastMutex( Mcb->FastMutex ); 02144 02145 ASSERTMSG("LargeInteger not supported yet ", ((((PLARGE_INTEGER)&LargeVbn)->HighPart == 0) || 02146 (Mcb->PairCount == 0))); 02147 ASSERTMSG("LargeInteger not supported yet ", ((((PLARGE_INTEGER)&LargeAmount)->HighPart == 0) || 02148 (Mcb->PairCount == 0))); 02149 02150 try { 02151 02152 // 02153 // First lookup the index for the entry that we are going to split. 02154 // If we can't find the entry then there is nothing to split. This 02155 // takes care of the case where the input vbn is beyond the last run 02156 // in the mcb 02157 // 02158 02159 if (!FsRtlFindLargeIndex( Mcb, Vbn, &Index)) { 02160 02161 try_return(Result = FALSE); 02162 } 02163 02164 // 02165 // Now check if the input Vbn is within a hole 02166 // 02167 02168 if (StartingLbn(Mcb,Index) == UNUSED_LBN) { 02169 02170 // 02171 // Before: --PreviousRun--||--IndexHole--||--FollowingRun-- 02172 // After: --PreviousRun--||----IndexHole----||--FollowingRun-- 02173 // 02174 // In this case the vbn is somewhere within the hole and we 02175 // simply need to added the amount of each existing run 02176 // beyond the hole. 02177 // 02178 02179 // 02180 // In this case there is really nothing to do here because the 02181 // ending code will already shift the runs by proper amount 02182 // starting at index 02183 // 02184 02185 NOTHING; 02186 02187 // 02188 // Now check if the input vbn is between a hole and an existing run. 02189 // 02190 02191 } else if ((StartingVbn(Mcb,Index) == Vbn) && (Index != 0) && (PreviousEndingLbn(Mcb,Index) == UNUSED_LBN)) { 02192 02193 // 02194 // Before: --Hole--||--IndexRun-- 02195 // After: --Hole------||--IndexRun-- 02196 // 02197 // In this case the vbn points to the start of the existing 02198 // run and we need to do the split between the hole and the 02199 // existing run by simply adding the amount to each existing 02200 // run beyond the hole. 02201 // 02202 02203 // 02204 // In this case we need to decement the index by 1 and then 02205 // fall to the bottom code which will do the shifting for us 02206 // 02207 02208 Index -= 1; 02209 02210 // 02211 // Now check if the input vbn is between two existing runs 02212 // 02213 02214 } else if (StartingVbn(Mcb,Index) == Vbn) { 02215 02216 // 02217 // Before: --PreviousRun--||--IndexRun-- 02218 // After: --PreviousRun--||--NewHole--||--IndexRun-- 02219 // 02220 // Before: 0:|--IndexRun-- 02221 // After: 0:|--NewHole--||--IndexRun-- 02222 // 02223 // In this case the vbn points to the start of an existing 02224 // run and the preceeding is either a real run or the start 02225 // of mapping pairs We simply add a new entry for the hole 02226 // and shift succeeding runs. 02227 // 02228 02229 FsRtlAddLargeEntry( Mcb, Index, 1 ); 02230 02231 (Mcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN; 02232 (Mcb->Mapping)[Index].NextVbn = Vbn + Amount; 02233 02234 Index += 1; 02235 02236 // 02237 // Otherwise the input vbn is inside an existing run 02238 // 02239 02240 } else { 02241 02242 // 02243 // Before: --IndexRun-- 02244 // After: --SplitRun--||--NewHole--||--SplitRun-- 02245 // 02246 // In this case the vbn points within an existing run 02247 // we need to add two new extries for hole and split 02248 // run and shift succeeding runs 02249 // 02250 02251 FsRtlAddLargeEntry( Mcb, Index, 2 ); 02252 02253 (Mcb->Mapping)[Index].Lbn = (Mcb->Mapping)[Index+2].Lbn; 02254 (Mcb->Mapping)[Index].NextVbn = Vbn; 02255 02256 (Mcb->Mapping)[Index+1].Lbn = (LBN)UNUSED_LBN; 02257 (Mcb->Mapping)[Index+1].NextVbn = Vbn + Amount; 02258 02259 (Mcb->Mapping)[Index+2].Lbn = (Mcb->Mapping)[Index+2].Lbn + 02260 StartingVbn(Mcb, Index+1) - 02261 StartingVbn(Mcb, Index); 02262 02263 Index += 2; 02264 02265 } 02266 02267 // 02268 // At this point we have completed most of the work we now need to 02269 // shift existing runs from the index to the end of the mappings 02270 // by the specified amount 02271 // 02272 02273 for (i = Index; i < Mcb->PairCount; i += 1) { 02274 02275 (Mcb->Mapping)[i].NextVbn += Amount; 02276 } 02277 02278 Result = TRUE; 02279 02280 try_exit: NOTHING; 02281 } finally { 02282 02283 ExReleaseFastMutex( Mcb->FastMutex ); 02284 02285 DebugTrace(-1, Dbg, "FsRtlSplitLargeMcb -> %08lx\n", Result ); 02286 } 02287 02288 return Result; 02289 } 02290 02291 02292 // 02293 // Private support routine 02294 // 02295 02296 VOID 02297 FsRtlRemoveMcbEntryPrivate ( 02298 IN PNONOPAQUE_MCB Mcb, 02299 IN ULONG Vbn, 02300 IN ULONG SectorCount 02301 ) 02302 02303 /*++ 02304 02305 Routine Description: 02306 02307 This is the work routine for remove large mcb entry. It does the work 02308 without taking out the mcb FastMutex. 02309 02310 Arguments: 02311 02312 Mcb - Supplies the Mcb from which to remove the mapping. 02313 02314 Vbn - Supplies the starting Vbn of the mappings to remove. 02315 02316 SectorCount - Supplies the size of the mappings to remove (in sectors). 02317 02318 Return Value: 02319 02320 None. 02321 02322 --*/ 02323 02324 { 02325 ULONG Index; 02326 02327 PAGED_CODE(); 02328 02329 // 02330 // Do a quick test to see if we are wiping out the entire MCB. 02331 // 02332 02333 if ((Vbn == 0) && (Mcb->PairCount > 0) && (SectorCount >= Mcb->Mapping[Mcb->PairCount-1].NextVbn)) { 02334 02335 Mcb->PairCount = 0; 02336 02337 return; 02338 } 02339 02340 // 02341 // While there is some more mapping to remove we'll continue 02342 // with our main loop 02343 // 02344 02345 while (SectorCount > 0) { 02346 02347 // 02348 // Locate the mapping for the vbn 02349 // 02350 02351 if (!FsRtlFindLargeIndex(Mcb, Vbn, &Index)) { 02352 02353 DebugTrace( 0, Dbg, "FsRtlRemoveLargeMcbEntry, Cannot remove an unmapped Vbn = %08lx\n", Vbn ); 02354 02355 return; 02356 } 02357 02358 // 02359 // Now that we some something to remove the following cases must 02360 // be considered 02361 // 02362 02363 if ((StartingVbn(Mcb,Index) == Vbn) && 02364 (EndingVbn(Mcb,Index) < Vbn + SectorCount)) { 02365 02366 ULONG i; 02367 02368 // 02369 // Removes the entire run 02370 // 02371 02372 // 02373 // Update the amount to remove 02374 // 02375 02376 i = SectorsWithinRun(Mcb,Index); 02377 Vbn += i; 02378 SectorCount -= i; 02379 02380 // 02381 // If already a hole then leave it alone 02382 // 02383 02384 if (StartingLbn(Mcb,Index) == UNUSED_LBN) { 02385 02386 NOTHING; 02387 02388 // 02389 // Test for last run 02390 // 02391 02392 } else if (Index == Mcb->PairCount - 1) { 02393 02394 if ((PreviousEndingLbn(Mcb,Index) != UNUSED_LBN) || 02395 (Index == 0)) { 02396 02397 // 02398 // Previous is not hole, index is last run 02399 // 02400 // --Previous--| Hole 02401 // 02402 // 0: Hole 02403 // 02404 02405 DebugTrace( 0, Dbg, "Entire run, Previous not hole, index is last run\n", 0); 02406 02407 // 02408 // Just remove this entry 02409 // 02410 02411 FsRtlRemoveLargeEntry( Mcb, Index, 1); 02412 02413 } else { 02414 02415 // 02416 // Previous is hole, index is last run 02417 // 02418 // --Hole--| Hole 02419 // 02420 02421 DebugTrace( 0, Dbg, "Entire run, Previous hole, index is last run\n", 0); 02422 02423 // 02424 // Just remove this entry, and preceding entry 02425 // 02426 02427 FsRtlRemoveLargeEntry( Mcb, Index-1, 2); 02428 } 02429 02430 } else if (((PreviousEndingLbn(Mcb,Index) != UNUSED_LBN) || (Index == 0)) && 02431 (NextStartingLbn(Mcb,Index) != UNUSED_LBN)) { 02432 02433 // 02434 // Previous and following are not holes 02435 // 02436 // --Previous--| Hole |--Following-- 02437 // 02438 // 0: Hole |--Following-- 02439 // 02440 02441 DebugTrace( 0, Dbg, "Entire run, Previous & Following not holes\n", 0); 02442 02443 // 02444 // Make this index a hole 02445 // 02446 02447 (Mcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN; 02448 02449 } else if (((PreviousEndingLbn(Mcb,Index) != UNUSED_LBN) || (Index == 0)) && 02450 (NextStartingLbn(Mcb,Index) == UNUSED_LBN)) { 02451 02452 // 02453 // Following is hole 02454 // 02455 // --Previous--| Hole |--Hole-- 02456 // 02457 // 0: Hole |--Hole-- 02458 // 02459 02460 DebugTrace( 0, Dbg, "Entire run, Following is hole\n", 0); 02461 02462 // 02463 // Simply remove this entry 02464 // 02465 02466 FsRtlRemoveLargeEntry( Mcb, Index, 1 ); 02467 02468 } else if ((PreviousEndingLbn(Mcb,Index) == UNUSED_LBN) && 02469 (NextStartingLbn(Mcb,Index) != UNUSED_LBN)) { 02470 02471 // 02472 // Previous is hole 02473 // 02474 // --Hole--| Hole |--Following-- 02475 // 02476 02477 DebugTrace( 0, Dbg, "Entire run, Previous is hole\n", 0); 02478 02479 // 02480 // Mark current entry a hole 02481 // 02482 02483 (Mcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN; 02484 02485 // 02486 // Remove previous entry 02487 // 02488 02489 FsRtlRemoveLargeEntry( Mcb, Index - 1, 1 ); 02490 02491 } else { 02492 02493 // 02494 // Previous and following are holes 02495 // 02496 // --Hole--| Hole |--Hole-- 02497 // 02498 02499 DebugTrace( 0, Dbg, "Entire run, Previous & following are holes\n", 0); 02500 02501 // 02502 // Remove previous and this entry 02503 // 02504 02505 FsRtlRemoveLargeEntry( Mcb, Index - 1, 2 ); 02506 } 02507 02508 } else if (StartingVbn(Mcb,Index) == Vbn) { 02509 02510 // 02511 // Removes first part of run 02512 // 02513 02514 // 02515 // If already a hole then leave it alone 02516 // 02517 02518 if (StartingLbn(Mcb,Index) == UNUSED_LBN) { 02519 02520 NOTHING; 02521 02522 } else if ((PreviousEndingLbn(Mcb,Index) != UNUSED_LBN) || (Index == 0)) { 02523 02524 // 02525 // Previous is not hole 02526 // 02527 // --Previous--| Hole |--Index--||--Following-- 02528 // 02529 // 0: Hole |--Index--||--Following-- 02530 // 02531 02532 DebugTrace( 0, Dbg, "1st part, Previous is not hole\n", 0); 02533 02534 // 02535 // Make room for one more entry. The NextVbn field of the 02536 // one we're shifting remains valid. 02537 // 02538 02539 FsRtlAddLargeEntry( Mcb, Index, 1 ); 02540 02541 // 02542 // Set the hole 02543 // 02544 02545 (Mcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN; 02546 (Mcb->Mapping)[Index].NextVbn = Vbn + SectorCount; 02547 02548 // 02549 // Set the new Lbn for the remaining run 02550 // 02551 02552 (Mcb->Mapping)[Index+1].Lbn += SectorCount; 02553 02554 } else { 02555 02556 // 02557 // Previous is hole 02558 // 02559 // --Hole--| Hole |--Index--||--Following-- 02560 // 02561 02562 DebugTrace( 0, Dbg, "1st part, Previous is hole\n", 0); 02563 02564 // 02565 // Expand the preceding hole 02566 // 02567 02568 (Mcb->Mapping)[Index-1].NextVbn += SectorCount; 02569 02570 // 02571 // Set the new Lbn for the remaining run 02572 // 02573 02574 (Mcb->Mapping)[Index].Lbn += SectorCount; 02575 } 02576 02577 // 02578 // Update the amount to remove 02579 // 02580 02581 Vbn += SectorCount; 02582 SectorCount = 0; 02583 02584 } else if (EndingVbn(Mcb,Index) < Vbn + SectorCount) { 02585 02586 ULONG AmountToRemove; 02587 02588 AmountToRemove = EndingVbn(Mcb,Index) - Vbn + 1; 02589 02590 // 02591 // Removes last part of run 02592 // 02593 02594 // 02595 // If already a hole then leave it alone 02596 // 02597 02598 if (StartingLbn(Mcb,Index) == UNUSED_LBN) { 02599 02600 NOTHING; 02601 02602 } else if (Index == Mcb->PairCount - 1) { 02603 02604 // 02605 // Index is last run 02606 // 02607 // --Previous--||--Index--| Hole 02608 // 02609 // 0:|--Index--| Hole 02610 // 02611 02612 DebugTrace( 0, Dbg, "last part, Index is last run\n", 0); 02613 02614 // 02615 // Shrink back the size of the current index 02616 // 02617 02618 (Mcb->Mapping)[Index].NextVbn -= AmountToRemove; 02619 02620 } else if (NextStartingLbn(Mcb,Index) == UNUSED_LBN) { 02621 02622 // 02623 // Following is hole 02624 // 02625 // --Previous--||--Index--| Hole |--Hole-- 02626 // 02627 // 0:|--Index--| Hole |--Hole-- 02628 // 02629 02630 DebugTrace( 0, Dbg, "last part, Following is hole\n", 0); 02631 02632 // 02633 // Shrink back the size of the current index 02634 // 02635 02636 (Mcb->Mapping)[Index].NextVbn -= AmountToRemove; 02637 02638 } else { 02639 02640 // 02641 // Following is not hole 02642 // 02643 // --Previous--||--Index--| Hole |--Following-- 02644 // 02645 // 02646 // 0:|--Index--| Hole |--Following-- 02647 // 02648 02649 DebugTrace( 0, Dbg, "last part, Following is not hole\n", 0); 02650 02651 // 02652 // Make room for one more entry. The NextVbn field of the 02653 // one we're shifting remains valid. 02654 // 02655 02656 FsRtlAddLargeEntry( Mcb, Index+1, 1 ); 02657 02658 // 02659 // Set the new hole 02660 // 02661 02662 (Mcb->Mapping)[Index+1].Lbn = (LBN)UNUSED_LBN; 02663 (Mcb->Mapping)[Index+1].NextVbn = (Mcb->Mapping)[Index].NextVbn; 02664 02665 // 02666 // Shrink back the size of the current index 02667 // 02668 02669 (Mcb->Mapping)[Index].NextVbn -= AmountToRemove; 02670 } 02671 02672 // 02673 // Update amount to remove 02674 // 02675 02676 Vbn += AmountToRemove; 02677 SectorCount -= AmountToRemove; 02678 02679 } else { 02680 02681 // 02682 // If already a hole then leave it alone 02683 // 02684 02685 if (StartingLbn(Mcb,Index) == UNUSED_LBN) { 02686 02687 NOTHING; 02688 02689 } else { 02690 02691 // 02692 // Remove middle of run 02693 // 02694 // --Previous--||--Index--| Hole |--Index--||--Following-- 02695 // 02696 // 0:|--Index--| Hole |--Index--||--Following-- 02697 // 02698 02699 DebugTrace( 0, Dbg, "Middle of run\n", 0); 02700 02701 // 02702 // Make room for two more entries. The NextVbn field of the 02703 // one we're shifting remains valid. 02704 // 02705 02706 FsRtlAddLargeEntry( Mcb, Index, 2 ); 02707 02708 // 02709 // Set up the first remaining run 02710 // 02711 02712 (Mcb->Mapping)[Index].Lbn = (Mcb->Mapping)[Index+2].Lbn; 02713 (Mcb->Mapping)[Index].NextVbn = Vbn; 02714 02715 // 02716 // Set up the hole 02717 // 02718 02719 (Mcb->Mapping)[Index+1].Lbn = (LBN)UNUSED_LBN; 02720 (Mcb->Mapping)[Index+1].NextVbn = Vbn + SectorCount; 02721 02722 // 02723 // Set up the second remaining run 02724 // 02725 02726 (Mcb->Mapping)[Index+2].Lbn += SectorsWithinRun(Mcb,Index) + 02727 SectorsWithinRun(Mcb,Index+1); 02728 } 02729 02730 // 02731 // Update amount to remove 02732 // 02733 02734 Vbn += SectorCount; 02735 SectorCount = 0; 02736 } 02737 } 02738 02739 return; 02740 } 02741 02742 02743 // 02744 // Private routine 02745 // 02746 02747 BOOLEAN 02748 FsRtlFindLargeIndex ( 02749 IN PNONOPAQUE_MCB Mcb, 02750 IN VBN Vbn, 02751 OUT PULONG Index 02752 ) 02753 02754 /*++ 02755 02756 Routine Description: 02757 02758 This is a private routine that locates a mapping for a Vbn 02759 in a given mapping array 02760 02761 Arguments: 02762 02763 Mcb - Supplies the mapping array to examine 02764 02765 Vbn - Supplies the Vbn to look up 02766 02767 Index - Receives the index within the mapping array of the mapping 02768 containing the Vbn. If none if found then the index is set to 02769 PairCount. 02770 02771 Return Value: 02772 02773 BOOLEAN - TRUE if Vbn is found and FALSE otherwise 02774 02775 --*/ 02776 02777 { 02778 LONG MinIndex; 02779 LONG MaxIndex; 02780 LONG MidIndex; 02781 02782 // 02783 // We'll just do a binary search for the mapping entry. Min and max 02784 // are our search boundaries 02785 // 02786 02787 MinIndex = 0; 02788 MaxIndex = Mcb->PairCount - 1; 02789 02790 while (MinIndex <= MaxIndex) { 02791 02792 // 02793 // Compute the middle index to look at 02794 // 02795 02796 MidIndex = ((MaxIndex + MinIndex) / 2); 02797 02798 // 02799 // check if the Vbn is less than the mapping at the mid index 02800 // 02801 02802 if (Vbn < StartingVbn(Mcb, MidIndex)) { 02803 02804 // 02805 // Vbn is less than the middle index so we need to drop 02806 // the max down 02807 // 02808 02809 MaxIndex = MidIndex - 1; 02810 02811 // 02812 // check if the Vbn is greater than the mapping at the mid index 02813 // 02814 02815 } else if (Vbn > EndingVbn(Mcb, MidIndex)) { 02816 02817 // 02818 // Vbn is greater than the middle index so we need to bring 02819 // up the min 02820 // 02821 02822 MinIndex = MidIndex + 1; 02823 02824 // 02825 // Otherwise we've found the index containing the Vbn so set the 02826 // index and return TRUE. 02827 // 02828 02829 } else { 02830 02831 *Index = MidIndex; 02832 02833 return TRUE; 02834 } 02835 } 02836 02837 // 02838 // A match wasn't found so set index to PairCount and return FALSE 02839 // 02840 02841 *Index = Mcb->PairCount; 02842 02843 return FALSE; 02844 } 02845 02846 02847 // 02848 // Private Routine 02849 // 02850 02851 VOID 02852 FsRtlAddLargeEntry ( 02853 IN PNONOPAQUE_MCB Mcb, 02854 IN ULONG WhereToAddIndex, 02855 IN ULONG AmountToAdd 02856 ) 02857 02858 /*++ 02859 02860 Routine Description: 02861 02862 This routine takes a current Mcb and detemines if there is enough 02863 room to add the new mapping entries. If there is not enough room 02864 it reallocates a new mcb buffer and copies over the current mapping. 02865 If also will spread out the current mappings to leave the specified 02866 index slots in the mapping unfilled. For example, if WhereToAddIndex 02867 is equal to the current pair count then we don't need to make a hole 02868 in the mapping, but if the index is less than the current pair count 02869 then we'll need to slide some of the mappings down to make room 02870 at the specified index. 02871 02872 Arguments: 02873 02874 Mcb - Supplies the mcb being checked and modified 02875 02876 WhereToAddIndex - Supplies the index of where the additional entries 02877 need to be made 02878 02879 AmountToAdd - Supplies the number of additional entries needed in the 02880 mcb 02881 02882 Return Value: 02883 02884 None. 02885 02886 --*/ 02887 02888 { 02889 PAGED_CODE(); 02890 02891 // 02892 // Check to see if the current buffer is large enough to hold 02893 // the additional entries 02894 // 02895 02896 if (Mcb->PairCount + AmountToAdd > Mcb->MaximumPairCount) { 02897 02898 ULONG NewMax; 02899 PMAPPING Mapping; 02900 02901 // 02902 // We need to allocate a new mapping so compute a new maximum pair 02903 // count. We'll only be asked to grow by at most 2 at a time, so 02904 // doubling will definitely make us large enough for the new amount. 02905 // But we won't double without bounds we'll stop doubling if the 02906 // pair count gets too high. 02907 // 02908 02909 if (Mcb->MaximumPairCount < 2048) { 02910 02911 NewMax = Mcb->MaximumPairCount * 2; 02912 02913 } else { 02914 02915 NewMax = Mcb->MaximumPairCount + 2048; 02916 } 02917 02918 Mapping = FsRtlpAllocatePool( Mcb->PoolType, sizeof(MAPPING) * NewMax ); 02919 02920 //**** RtlZeroMemory( Mapping, sizeof(MAPPING) * NewMax ); 02921 02922 // 02923 // Now copy over the old mapping to the new buffer 02924 // 02925 02926 RtlCopyMemory( Mapping, Mcb->Mapping, sizeof(MAPPING) * Mcb->PairCount ); 02927 02928 // 02929 // Deallocate the old buffer 02930 // 02931 02932 if ((Mcb->PoolType == PagedPool) && (Mcb->MaximumPairCount == INITIAL_MAXIMUM_PAIR_COUNT)) { 02933 02934 FsRtlFreeFirstMapping( Mcb->Mapping ); 02935 02936 } else { 02937 02938 ExFreePool( Mcb->Mapping ); 02939 } 02940 02941 // 02942 // And set up the new buffer in the Mcb 02943 // 02944 02945 Mcb->Mapping = Mapping; 02946 Mcb->MaximumPairCount = NewMax; 02947 } 02948 02949 // 02950 // Now see if we need to shift some entries over according to the 02951 // WhereToAddIndex value 02952 // 02953 02954 if (WhereToAddIndex < Mcb->PairCount) { 02955 02956 RtlMoveMemory( &((Mcb->Mapping)[WhereToAddIndex + AmountToAdd]), 02957 &((Mcb->Mapping)[WhereToAddIndex]), 02958 (Mcb->PairCount - WhereToAddIndex) * sizeof(MAPPING) ); 02959 } 02960 02961 // 02962 // Now zero out the new additions 02963 // 02964 02965 //**** RtlZeroMemory( &((Mcb->Mapping)[WhereToAddIndex]), sizeof(MAPPING) * AmountToAdd ); 02966 02967 // 02968 // Now increment the PairCount 02969 // 02970 02971 Mcb->PairCount += AmountToAdd; 02972 02973 // 02974 // And return to our caller 02975 // 02976 02977 return; 02978 } 02979 02980 02981 // 02982 // Private Routine 02983 // 02984 02985 VOID 02986 FsRtlRemoveLargeEntry ( 02987 IN PNONOPAQUE_MCB Mcb, 02988 IN ULONG WhereToRemoveIndex, 02989 IN ULONG AmountToRemove 02990 ) 02991 02992 /*++ 02993 02994 Routine Description: 02995 02996 This routine takes a current Mcb and removes one or more entries. 02997 02998 Arguments: 02999 03000 Mcb - Supplies the mcb being checked and modified 03001 03002 WhereToRemoveIndex - Supplies the index of the entries to remove 03003 03004 AmountToRemove - Supplies the number of entries to remove 03005 03006 Return Value: 03007 03008 None. 03009 03010 --*/ 03011 03012 { 03013 PAGED_CODE(); 03014 03015 // 03016 // Check to see if we need to shift everything down because the 03017 // entries to remove do not include the last entry in the mcb 03018 // 03019 03020 if (WhereToRemoveIndex + AmountToRemove < Mcb->PairCount) { 03021 03022 RtlMoveMemory( &((Mcb->Mapping)[WhereToRemoveIndex]), 03023 &((Mcb->Mapping)[WhereToRemoveIndex + AmountToRemove]), 03024 (Mcb->PairCount - (WhereToRemoveIndex + AmountToRemove)) 03025 * sizeof(MAPPING) ); 03026 } 03027 03028 // 03029 // Now zero out the entries beyond the part we just shifted down 03030 // 03031 03032 //**** RtlZeroMemory( &((Mcb->Mapping)[Mcb->PairCount - AmountToRemove]), AmountToRemove * sizeof(MAPPING) ); 03033 03034 // 03035 // Now decrement the PairCount 03036 // 03037 03038 Mcb->PairCount -= AmountToRemove; 03039 03040 // 03041 // And return to our caller 03042 // 03043 03044 return; 03045 } 03046

Generated on Sat May 15 19:40:35 2004 for test by doxygen 1.3.7