Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3433 lines
90 KiB

  1. //depot/Lab01_N/Base/ntos/fsrtl/largemcb.c#5 - edit change 5743 (text)
  2. /*++
  3. Copyright (c) 1989 Microsoft Corporation
  4. Module Name:
  5. LargeMcb.c
  6. Abstract:
  7. The MCB routines provide support for maintaining an in-memory copy of
  8. the retrieval mapping information for a file. The general idea is to
  9. have the file system lookup the retrieval mapping for a VBN once from
  10. the disk, add the mapping to the MCB structure, and then utilize the
  11. MCB to retrieve the mapping for subsequent accesses to the file. A
  12. variable of type MCB is used to store the mapping information.
  13. The routines provided here allow the user to incrementally store some
  14. or all of the retrieval mapping for a file and to do so in any order.
  15. That is, the mapping can be inserted to the MCB structure all at once
  16. starting from the beginning and working to the end of the file, or it
  17. can be randomly scattered throughout the file.
  18. The package identifies each contiguous run of sectors mapping VBNs
  19. and LBNs indenpendent of the order they are added to the MCB
  20. structure. For example a user can define a mapping between VBN
  21. sector 0 and LBN sector 107, and between VBN sector 2 and LBN sector
  22. 109. The mapping now contains two runs each one sector in length.
  23. Now if the user adds an additional mapping between VBN sector 1 and
  24. LBN sector 106 the MCB structure will contain only one run 3 sectors
  25. in length.
  26. Concurrent access to the MCB structure is control by this package.
  27. The following routines are provided by this package:
  28. o FsRtlInitializeMcb - Initialize a new MCB structure. There
  29. should be one MCB for every opened file. Each MCB structure
  30. must be initialized before it can be used by the system.
  31. o FsRtlUninitializeMcb - Uninitialize an MCB structure. This call
  32. is used to cleanup any anciallary structures allocated and
  33. maintained by the MCB. After being uninitialized the MCB must
  34. again be initialized before it can be used by the system.
  35. o FsRtlAddMcbEntry - This routine adds a new range of mappings
  36. between LBNs and VBNs to the MCB structure.
  37. o FsRtlRemoveMcbEntry - This routines removes an existing range of
  38. mappings between LBNs and VBNs from the MCB structure.
  39. o FsRtlLookupMcbEntry - This routine returns the LBN mapped to by
  40. a VBN, and indicates, in sectors, the length of the run.
  41. o FsRtlLookupLastMcbEntry - This routine returns the mapping for
  42. the largest VBN stored in the structure.
  43. o FsRtlLookupLastMcbEntryAndIndex - This routine returns the mapping
  44. for the largest VBN stored in the structure as well as its index
  45. Note that calling LookupLastMcbEntry and NumberOfRunsInMcb cannot
  46. be synchronized except by the caller.
  47. o FsRtlNumberOfRunsInMcb - This routine tells the caller total
  48. number of discontiguous sectors runs stored in the MCB
  49. structure.
  50. o FsRtlGetNextMcbEntry - This routine returns the the caller the
  51. starting VBN and LBN of a given run stored in the MCB structure.
  52. Author:
  53. Gary Kimura [GaryKi] 5-Feb-1990
  54. Revision History:
  55. --*/
  56. #include "FsRtlP.h"
  57. //
  58. // Trace level for the module
  59. //
  60. #define Dbg (0x80000000)
  61. //
  62. // Retrieval mapping data structures. The following two structure together
  63. // are used to map a Vbn to an Lbn. It is layed out as follows:
  64. //
  65. //
  66. // MCB:
  67. // +----------------+----------------+
  68. // | PairCount |MaximumPairCount|
  69. // +----------------+----------------+
  70. // | Mapping | PoolType |
  71. // +----------------+----------------+
  72. //
  73. //
  74. // MAPPING:
  75. // +----------------+----------------+
  76. // | Lbn | NextVbn | : 0
  77. // +----------------+----------------+
  78. // | |
  79. // / /
  80. // / /
  81. // | |
  82. // +----------------+----------------+
  83. // | Lbn | NextVbn | : PairCount
  84. // +----------------+----------------+
  85. // | |
  86. // / /
  87. // / /
  88. // | |
  89. // +----------------+----------------+
  90. // | Lbn | NextVbn |
  91. // +----------------+----------------+
  92. //
  93. // : MaximumPairCount
  94. //
  95. // The pairs from 0 to PairCount - 1 are valid. Given an index between
  96. // 0 and PairCount - 1 (inclusive) it represents the following Vbn
  97. // to Lbn mapping information
  98. //
  99. //
  100. // { if Index == 0 then 0
  101. // StartingVbn {
  102. // { if Index <> 0 then NextVbn[i-1]
  103. //
  104. //
  105. // EndingVbn = NextVbn[i] - 1
  106. //
  107. //
  108. // StartingLbn = Lbn[i]
  109. //
  110. //
  111. // To compute the mapping of a Vbn to an Lbn the following algorithm
  112. // is used
  113. //
  114. // 1. search through the pairs until we find the slot "i" that contains
  115. // the Vbn we after. Report an error if none if found.
  116. //
  117. // 2. Lbn = StartingLbn + (Vbn - StartingVbn);
  118. //
  119. // A hole in the allocation (i.e., a sparse allocation) is represented by
  120. // an Lbn value of -1 (note that is is different than Mcb.c).
  121. //
  122. #define UNUSED_LBN (-1)
  123. typedef struct _MAPPING {
  124. VBN NextVbn;
  125. LBN Lbn;
  126. } MAPPING;
  127. typedef MAPPING *PMAPPING;
  128. typedef struct _NONOPAQUE_BASE_MCB {
  129. ULONG MaximumPairCount;
  130. ULONG PairCount;
  131. POOL_TYPE PoolType;
  132. PMAPPING Mapping;
  133. } NONOPAQUE_BASE_MCB, *PNONOPAQUE_BASE_MCB;
  134. //
  135. // A macro to return the size, in bytes, of a retrieval mapping structure
  136. //
  137. #define SizeOfMapping(MCB) ((sizeof(MAPPING) * (MCB)->MaximumPairCount))
  138. //
  139. // The parts of a run can be computed as follows:
  140. //
  141. //
  142. // StartingVbn(MCB,I) Mapping[I].NextVbn
  143. // | |
  144. // V V
  145. //
  146. // Run-(I-1)---+ +---------Run-(I)-----------+ +---Run-(I+1)
  147. //
  148. // A A
  149. // | |
  150. // Mapping[I].Lbn EndingLbn(MCB,I)
  151. //
  152. #define PreviousEndingVbn(MCB,I) ( \
  153. (VBN)((I) == 0 ? 0xffffffff : EndingVbn(MCB,(I)-1)) \
  154. )
  155. #define StartingVbn(MCB,I) ( \
  156. (VBN)((I) == 0 ? 0 : (((MCB)->Mapping))[(I)-1].NextVbn) \
  157. )
  158. #define EndingVbn(MCB,I) ( \
  159. (VBN)((((MCB)->Mapping)[(I)].NextVbn) - 1) \
  160. )
  161. #define NextStartingVbn(MCB,I) ( \
  162. (VBN)((I) >= (MCB)->PairCount ? 0 : StartingVbn(MCB,(I)+1)) \
  163. )
  164. #define PreviousEndingLbn(MCB,I) ( \
  165. (LBN)((I) == 0 ? UNUSED_LBN : EndingLbn(MCB,(I)-1)) \
  166. )
  167. #define StartingLbn(MCB,I) ( \
  168. (LBN)(((MCB)->Mapping)[(I)].Lbn) \
  169. )
  170. #define EndingLbn(MCB,I) ( \
  171. (LBN)(StartingLbn(MCB,I) == UNUSED_LBN ? \
  172. UNUSED_LBN : \
  173. ((MCB)->Mapping[(I)].Lbn + \
  174. (MCB)->Mapping[(I)].NextVbn - StartingVbn(MCB,I) - 1) \
  175. ) \
  176. )
  177. #define NextStartingLbn(MCB,I) ( \
  178. (LBN)((I) >= (MCB)->PairCount - 1 ? UNUSED_LBN : StartingLbn(MCB,(I)+1)) \
  179. )
  180. #define SectorsWithinRun(MCB,I) ( \
  181. (ULONG)(EndingVbn(MCB,I) - StartingVbn(MCB,I) + 1) \
  182. )
  183. //
  184. // Define a tag for general pool allocations from this module
  185. //
  186. #undef MODULE_POOL_TAG
  187. #define MODULE_POOL_TAG ('mrSF')
  188. //
  189. // A private routine to search a mapping structure for a Vbn
  190. //
  191. BOOLEAN
  192. FsRtlFindLargeIndex (
  193. IN PBASE_MCB Mcb,
  194. IN VBN Vbn,
  195. OUT PULONG Index
  196. );
  197. VOID
  198. FsRtlAddLargeEntry (
  199. IN PBASE_MCB Mcb,
  200. IN ULONG WhereToAddIndex,
  201. IN ULONG AmountToAdd
  202. );
  203. VOID
  204. FsRtlRemoveLargeEntry (
  205. IN PBASE_MCB Mcb,
  206. IN ULONG WhereToRemoveIndex,
  207. IN ULONG AmountToRemove
  208. );
  209. //
  210. // Some private routines to handle common allocations.
  211. //
  212. #define FsRtlAllocateFirstMapping() \
  213. (PVOID)ExAllocateFromPagedLookasideList( &FsRtlFirstMappingLookasideList )
  214. #define FsRtlFreeFirstMapping(Mapping) \
  215. ExFreeToPagedLookasideList( &FsRtlFirstMappingLookasideList, (Mapping) )
  216. #define FsRtlAllocateFastMutex() \
  217. (PFAST_MUTEX)ExAllocateFromNPagedLookasideList( &FsRtlFastMutexLookasideList )
  218. #define FsRtlFreeFastMutex(FastMutex) \
  219. ExFreeToNPagedLookasideList( &FsRtlFastMutexLookasideList, (FastMutex) )
  220. #ifdef ALLOC_PRAGMA
  221. #pragma alloc_text(INIT, FsRtlInitializeLargeMcbs)
  222. #pragma alloc_text(PAGE, FsRtlInitializeMcb)
  223. #pragma alloc_text(PAGE, FsRtlUninitializeMcb)
  224. #endif
  225. //
  226. // Define a small cache of free mapping pairs structures and also the
  227. // initial size of the mapping pair
  228. //
  229. #define INITIAL_MAXIMUM_PAIR_COUNT (15)
  230. PAGED_LOOKASIDE_LIST FsRtlFirstMappingLookasideList;
  231. //
  232. // The following lookaside is used to keep all the Fast Mutexes we will need to
  233. // boot contiguous.
  234. //
  235. NPAGED_LOOKASIDE_LIST FsRtlFastMutexLookasideList;
  236. //
  237. // The following few routines define the small mcb package which is
  238. // implemented behind everyones back as large mcbs. The only funny
  239. // thing we really need to do here is to make sure that unused Lbns
  240. // get returned as 0 and not -1. This is the result of an historical
  241. // difference between the original Mcb and LargeMcb packages.
  242. //
  243. VOID
  244. FsRtlInitializeMcb (
  245. IN PMCB Mcb,
  246. IN POOL_TYPE PoolType
  247. )
  248. {
  249. PAGED_CODE();
  250. FsRtlInitializeLargeMcb( (PLARGE_MCB)Mcb,
  251. PoolType );
  252. return;
  253. }
  254. VOID
  255. FsRtlUninitializeMcb (
  256. IN PMCB Mcb
  257. )
  258. {
  259. PAGED_CODE();
  260. FsRtlUninitializeLargeMcb( (PLARGE_MCB)Mcb );
  261. return;
  262. }
  263. VOID
  264. FsRtlTruncateMcb (
  265. IN PMCB Mcb,
  266. IN VBN Vbn
  267. )
  268. {
  269. PAGED_CODE();
  270. FsRtlTruncateLargeMcb( (PLARGE_MCB)Mcb,
  271. (LONGLONG)(Vbn) );
  272. return;
  273. }
  274. BOOLEAN
  275. FsRtlAddMcbEntry (
  276. IN PMCB Mcb,
  277. IN VBN Vbn,
  278. IN LBN Lbn,
  279. IN ULONG SectorCount
  280. )
  281. {
  282. PAGED_CODE();
  283. return FsRtlAddLargeMcbEntry( (PLARGE_MCB)Mcb,
  284. (LONGLONG)(Vbn),
  285. (LONGLONG)(Lbn),
  286. (LONGLONG)(SectorCount) );
  287. }
  288. VOID
  289. FsRtlRemoveMcbEntry (
  290. IN PMCB OpaqueMcb,
  291. IN VBN Vbn,
  292. IN ULONG SectorCount
  293. )
  294. {
  295. PLARGE_MCB Mcb = (PLARGE_MCB)OpaqueMcb;
  296. PAGED_CODE();
  297. FsRtlRemoveLargeMcbEntry( Mcb, Vbn, SectorCount );
  298. return;
  299. }
  300. BOOLEAN
  301. FsRtlLookupMcbEntry (
  302. IN PMCB Mcb,
  303. IN VBN Vbn,
  304. OUT PLBN Lbn,
  305. OUT PULONG SectorCount OPTIONAL,
  306. OUT PULONG Index OPTIONAL
  307. )
  308. {
  309. BOOLEAN Result;
  310. LONGLONG LiLbn;
  311. LONGLONG LiSectorCount = {0};
  312. Result = FsRtlLookupLargeMcbEntry( (PLARGE_MCB)Mcb,
  313. (LONGLONG)(Vbn),
  314. &LiLbn,
  315. ARGUMENT_PRESENT(SectorCount) ? &LiSectorCount : NULL,
  316. NULL,
  317. NULL,
  318. Index );
  319. if (Result) {
  320. *Lbn = (((ULONG)LiLbn) == -1 ? 0 : ((ULONG)LiLbn));
  321. if (ARGUMENT_PRESENT(SectorCount)) {
  322. *SectorCount = ((ULONG)LiSectorCount);
  323. }
  324. }
  325. return Result;
  326. }
  327. BOOLEAN
  328. FsRtlLookupLastMcbEntry (
  329. IN PMCB Mcb,
  330. OUT PVBN Vbn,
  331. OUT PLBN Lbn
  332. )
  333. {
  334. BOOLEAN Result;
  335. LONGLONG LiVbn;
  336. LONGLONG LiLbn;
  337. PAGED_CODE();
  338. Result = FsRtlLookupLastLargeMcbEntry( (PLARGE_MCB)Mcb,
  339. &LiVbn,
  340. &LiLbn );
  341. if (Result) {
  342. *Vbn = ((ULONG)LiVbn);
  343. *Lbn = (((ULONG)LiLbn) == -1 ? 0 : ((ULONG)LiLbn));
  344. }
  345. return Result;
  346. }
  347. ULONG
  348. FsRtlNumberOfRunsInMcb (
  349. IN PMCB Mcb
  350. )
  351. {
  352. PAGED_CODE();
  353. return FsRtlNumberOfRunsInLargeMcb( (PLARGE_MCB)Mcb );
  354. }
  355. BOOLEAN
  356. FsRtlGetNextMcbEntry (
  357. IN PMCB Mcb,
  358. IN ULONG RunIndex,
  359. OUT PVBN Vbn,
  360. OUT PLBN Lbn,
  361. OUT PULONG SectorCount
  362. )
  363. {
  364. BOOLEAN Result;
  365. LONGLONG LiVbn;
  366. LONGLONG LiLbn;
  367. LONGLONG LiSectorCount;
  368. PAGED_CODE();
  369. Result = FsRtlGetNextLargeMcbEntry( (PLARGE_MCB)Mcb,
  370. RunIndex,
  371. &LiVbn,
  372. &LiLbn,
  373. &LiSectorCount );
  374. if (Result) {
  375. *Vbn = ((ULONG)LiVbn);
  376. *Lbn = (((ULONG)LiLbn) == -1 ? 0 : ((ULONG)LiLbn));
  377. *SectorCount = ((ULONG)LiSectorCount);
  378. }
  379. return Result;
  380. }
  381. VOID
  382. FsRtlInitializeLargeMcbs (
  383. VOID
  384. )
  385. /*++
  386. Routine Description:
  387. This routine initializes the global portion of the large mcb package
  388. at system initialization time.
  389. Arguments:
  390. None.
  391. Return Value:
  392. None.
  393. --*/
  394. {
  395. //
  396. // Initialize the lookaside of paged initial mapping arrays.
  397. //
  398. ExInitializePagedLookasideList( &FsRtlFirstMappingLookasideList,
  399. NULL,
  400. NULL,
  401. POOL_RAISE_IF_ALLOCATION_FAILURE,
  402. sizeof( MAPPING ) * INITIAL_MAXIMUM_PAIR_COUNT,
  403. 'miSF',
  404. 4 );
  405. //
  406. // Initialize the Fast Mutex lookaside list.
  407. //
  408. ExInitializeNPagedLookasideList( &FsRtlFastMutexLookasideList,
  409. NULL,
  410. NULL,
  411. POOL_RAISE_IF_ALLOCATION_FAILURE,
  412. sizeof( FAST_MUTEX),
  413. 'mfSF',
  414. 32 );
  415. }
  416. VOID
  417. FsRtlInitializeBaseMcb (
  418. IN PBASE_MCB Mcb,
  419. IN POOL_TYPE PoolType
  420. )
  421. /*++
  422. Routine Description:
  423. This routine initializes a new Mcb structure. The caller must
  424. supply the memory for the Mcb structure. This call must precede all
  425. other calls that set/query the Mcb structure.
  426. If pool is not available this routine will raise a status value
  427. indicating insufficient resources.
  428. Arguments:
  429. OpaqueMcb - Supplies a pointer to the Mcb structure to initialize.
  430. PoolType - Supplies the pool type to use when allocating additional
  431. internal Mcb memory.
  432. Return Value:
  433. None.
  434. --*/
  435. {
  436. DebugTrace(+1, Dbg, "FsRtlInitializeBaseMcb, Mcb = %08lx\n", Mcb );
  437. //
  438. // Initialize the fields in the Mcb
  439. //
  440. Mcb->PairCount = 0;
  441. Mcb->PoolType = PoolType;
  442. //
  443. // Allocate a new buffer an initial size is one that will hold
  444. // 16 runs
  445. //
  446. if (PoolType == PagedPool) {
  447. Mcb->Mapping = FsRtlAllocateFirstMapping();
  448. } else {
  449. Mcb->Mapping = FsRtlpAllocatePool( Mcb->PoolType, sizeof(MAPPING) * INITIAL_MAXIMUM_PAIR_COUNT );
  450. }
  451. Mcb->MaximumPairCount = INITIAL_MAXIMUM_PAIR_COUNT;
  452. //
  453. // And return to our caller
  454. //
  455. return;
  456. }
  457. VOID
  458. FsRtlInitializeLargeMcb (
  459. IN PLARGE_MCB Mcb,
  460. IN POOL_TYPE PoolType
  461. )
  462. /*++
  463. Routine Description:
  464. This routine initializes the full large_mcb package by allocating the
  465. fast mutex and initializing the base mcb
  466. Arguments:
  467. OpaqueMcb - Supplies a pointer to the Mcb structure to initialize.
  468. PoolType - Supplies the pool type to use when allocating additional
  469. internal Mcb memory.
  470. Return Value:
  471. None.
  472. --*/
  473. {
  474. DebugTrace(+1, Dbg, "FsRtlInitializeLargeMcb, Mcb = %08lx\n", Mcb );
  475. //
  476. // Initialize the fast mutex
  477. //
  478. Mcb->FastMutex = FsRtlAllocateFastMutex();
  479. try {
  480. ExInitializeFastMutex( Mcb->FastMutex );
  481. FsRtlInitializeBaseMcb( &Mcb->BaseMcb, PoolType );
  482. } finally {
  483. //
  484. // If this is an abnormal termination then we need to deallocate
  485. // the FastMutex and/or mapping (but once the mapping is allocated,
  486. // we can't raise).
  487. //
  488. if (AbnormalTermination()) {
  489. FsRtlFreeFastMutex( Mcb->FastMutex );
  490. Mcb->FastMutex = NULL;
  491. }
  492. DebugTrace(-1, Dbg, "FsRtlInitializeLargeMcb -> VOID\n", 0 );
  493. }
  494. //
  495. // And return to our caller
  496. //
  497. return;
  498. }
  499. VOID
  500. FsRtlUninitializeBaseMcb (
  501. IN PBASE_MCB Mcb
  502. )
  503. /*++
  504. Routine Description:
  505. This routine uninitializes an Mcb structure. After calling this routine
  506. the input Mcb structure must be re-initialized before being used again.
  507. Arguments:
  508. Mcb - Supplies a pointer to the Mcb structure to uninitialize.
  509. Return Value:
  510. None.
  511. --*/
  512. {
  513. DebugTrace(+1, Dbg, "FsRtlUninitializeBaseMcb, Mcb = %08lx\n", Mcb );
  514. //
  515. // Deallocate the mapping buffer
  516. //
  517. if ((Mcb->PoolType == PagedPool) && (Mcb->MaximumPairCount == INITIAL_MAXIMUM_PAIR_COUNT)) {
  518. FsRtlFreeFirstMapping( Mcb->Mapping );
  519. } else {
  520. ExFreePool( Mcb->Mapping );
  521. }
  522. DebugTrace(-1, Dbg, "FsRtlUninitializeLargeMcb -> VOID\n", 0 );
  523. return;
  524. }
  525. VOID
  526. FsRtlUninitializeLargeMcb (
  527. IN PLARGE_MCB Mcb
  528. )
  529. /*++
  530. Routine Description:
  531. This routine uninitializes an Mcb structure. After calling this routine
  532. the input Mcb structure must be re-initialized before being used again.
  533. Arguments:
  534. Mcb - Supplies a pointer to the Mcb structure to uninitialize.
  535. Return Value:
  536. None.
  537. --*/
  538. {
  539. DebugTrace(+1, Dbg, "FsRtlUninitializeLargeMcb, Mcb = %08lx\n", Mcb );
  540. //
  541. // Protect against some user calling us to uninitialize an mcb twice
  542. //
  543. if (Mcb->FastMutex != NULL) {
  544. //
  545. // Deallocate the FastMutex and base Mcb
  546. //
  547. FsRtlFreeFastMutex( Mcb->FastMutex );
  548. Mcb->FastMutex = NULL;
  549. FsRtlUninitializeBaseMcb( &Mcb->BaseMcb );
  550. }
  551. DebugTrace(-1, Dbg, "FsRtlUninitializeLargeMcb -> VOID\n", 0 );
  552. return;
  553. }
  554. VOID
  555. FsRtlTruncateBaseMcb (
  556. IN PBASE_MCB Mcb,
  557. IN LONGLONG LargeVbn
  558. )
  559. /*++
  560. Routine Description:
  561. This routine truncates an Mcb structure to the specified Vbn.
  562. After calling this routine the Mcb will only contain mappings
  563. up to and not including the input vbn.
  564. Arguments:
  565. OpaqueMcb - Supplies a pointer to the Mcb structure to truncate.
  566. LargeVbn - Specifies the last Vbn at which is no longer to be
  567. mapped.
  568. Return Value:
  569. None.
  570. --*/
  571. {
  572. PNONOPAQUE_BASE_MCB BaseMcb = (PNONOPAQUE_BASE_MCB) Mcb;
  573. VBN Vbn = ((ULONG)LargeVbn);
  574. ULONG Index;
  575. DebugTrace(+1, Dbg, "FsRtlTruncateBaseMcb, Mcb = %08lx\n", BaseMcb );
  576. ASSERTMSG("LargeInteger not supported yet ", ((((PLARGE_INTEGER)&LargeVbn)->HighPart == 0) ||
  577. (BaseMcb->PairCount == 0) ||
  578. ((((PLARGE_INTEGER)&LargeVbn)->HighPart == 0x7FFFFFFF) &&
  579. (((ULONG)LargeVbn) == 0xFFFFFFFF))));
  580. //
  581. // Do a quick test to see if we are truncating the entire Mcb.
  582. //
  583. if (Vbn == 0) {
  584. BaseMcb->PairCount = 0;
  585. } else if (BaseMcb->PairCount > 0) {
  586. //
  587. // Find the index for the entry with the last Vcn we want to keep.
  588. // There is nothing to do if the Mcb already ends prior to
  589. // this point.
  590. //
  591. if (FsRtlFindLargeIndex(Mcb, Vbn - 1, &Index)) {
  592. //
  593. // If this entry currently describes a hole then
  594. // truncate to the previous entry.
  595. //
  596. if (StartingLbn(BaseMcb, Index) == UNUSED_LBN) {
  597. BaseMcb->PairCount = Index;
  598. //
  599. // Otherwise we will truncate the Mcb to this point. Truncate
  600. // the number of Vbns of this run if necessary.
  601. //
  602. } else {
  603. BaseMcb->PairCount = Index + 1;
  604. if (NextStartingVbn(BaseMcb, Index) > Vbn) {
  605. (BaseMcb->Mapping)[Index].NextVbn = Vbn;
  606. }
  607. }
  608. }
  609. }
  610. //
  611. // Now see if we can shrink the allocation for the mapping pairs.
  612. // We'll shrink the mapping pair buffer if the new pair count will
  613. // fit within a quarter of the current maximum pair count and the
  614. // current maximum is greater than the initial pair count.
  615. //
  616. if ((BaseMcb->PairCount < (BaseMcb->MaximumPairCount / 4)) &&
  617. (BaseMcb->MaximumPairCount > INITIAL_MAXIMUM_PAIR_COUNT)) {
  618. ULONG NewMax;
  619. PMAPPING Mapping;
  620. //
  621. // We need to allocate a new mapping so compute a new maximum pair
  622. // count. We'll allocate double the current pair count, but never
  623. // less than the initial pair count.
  624. //
  625. NewMax = BaseMcb->PairCount * 2;
  626. if (NewMax < INITIAL_MAXIMUM_PAIR_COUNT) {
  627. NewMax = INITIAL_MAXIMUM_PAIR_COUNT;
  628. }
  629. //
  630. // Be careful to trap failures due to resource exhaustion.
  631. //
  632. try {
  633. if (NewMax == INITIAL_MAXIMUM_PAIR_COUNT && BaseMcb->PoolType == PagedPool) {
  634. Mapping = FsRtlAllocateFirstMapping();
  635. } else {
  636. Mapping = FsRtlpAllocatePool( BaseMcb->PoolType, sizeof(MAPPING) * NewMax );
  637. }
  638. } except (EXCEPTION_EXECUTE_HANDLER) {
  639. Mapping = NULL;
  640. }
  641. //
  642. // Now check if we really got a new buffer
  643. //
  644. if (Mapping != NULL) {
  645. //
  646. // Now copy over the old mapping to the new buffer
  647. //
  648. RtlCopyMemory( Mapping, BaseMcb->Mapping, sizeof(MAPPING) * BaseMcb->PairCount );
  649. //
  650. // Deallocate the old buffer. This should never be the size of an
  651. // initial mapping ...
  652. //
  653. ExFreePool( BaseMcb->Mapping );
  654. //
  655. // And set up the new buffer in the Mcb
  656. //
  657. BaseMcb->Mapping = Mapping;
  658. BaseMcb->MaximumPairCount = NewMax;
  659. }
  660. }
  661. //
  662. // And return to our caller
  663. //
  664. DebugTrace(-1, Dbg, "FsRtlTruncateLargeMcb -> VOID\n", 0 );
  665. return;
  666. }
  667. VOID
  668. FsRtlTruncateLargeMcb (
  669. IN PLARGE_MCB Mcb,
  670. IN LONGLONG LargeVbn
  671. )
  672. /*++
  673. Routine Description:
  674. This routine truncates an Mcb structure to the specified Vbn.
  675. After calling this routine the Mcb will only contain mappings
  676. up to and not including the input vbn.
  677. Arguments:
  678. OpaqueMcb - Supplies a pointer to the Mcb structure to truncate.
  679. LargeVbn - Specifies the last Vbn at which is no longer to be
  680. mapped.
  681. Return Value:
  682. None.
  683. --*/
  684. {
  685. DebugTrace(+1, Dbg, "FsRtlTruncateLargeMcb, Mcb = %08lx\n", Mcb );
  686. ExAcquireFastMutex( Mcb->FastMutex );
  687. FsRtlTruncateBaseMcb( &Mcb->BaseMcb, LargeVbn );
  688. ExReleaseFastMutex( Mcb->FastMutex );
  689. //
  690. // And return to our caller
  691. //
  692. DebugTrace(-1, Dbg, "FsRtlTruncateLargeMcb -> VOID\n", 0 );
  693. return;
  694. }
  695. NTKERNELAPI
  696. VOID
  697. FsRtlResetBaseMcb (
  698. IN PBASE_MCB Mcb
  699. )
  700. /*++
  701. Routine Description:
  702. This routine truncates an Mcb structure to contain zero mapping
  703. pairs. It does not shrink the mapping pairs array.
  704. Arguments:
  705. OpaqueMcb - Supplies a pointer to the Mcb structure to truncate.
  706. Return Value:
  707. None.
  708. --*/
  709. {
  710. Mcb->PairCount = 0;
  711. return;
  712. }
  713. NTKERNELAPI
  714. VOID
  715. FsRtlResetLargeMcb (
  716. IN PLARGE_MCB Mcb,
  717. IN BOOLEAN SelfSynchronized
  718. )
  719. /*++
  720. Routine Description:
  721. This routine truncates an Mcb structure to contain zero mapping
  722. pairs. It does not shrink the mapping pairs array.
  723. Arguments:
  724. OpaqueMcb - Supplies a pointer to the Mcb structure to truncate.
  725. SelfSynchronized - Indicates whether the caller is already synchronized
  726. with respect to the Mcb.
  727. Return Value:
  728. None.
  729. --*/
  730. {
  731. if (SelfSynchronized) {
  732. //
  733. // If we are self-synchronized, then all we do is clear out the
  734. // current mapping pair count.
  735. //
  736. Mcb->BaseMcb.PairCount = 0;
  737. } else {
  738. //
  739. // Since we are not self-synchronized, we must serialize access to
  740. // the Mcb before clearing the pair count
  741. //
  742. ExAcquireFastMutex( Mcb->FastMutex );
  743. Mcb->BaseMcb.PairCount = 0;
  744. ExReleaseFastMutex( Mcb->FastMutex );
  745. }
  746. return;
  747. }
  748. BOOLEAN
  749. FsRtlAddBaseMcbEntry (
  750. IN PBASE_MCB Mcb,
  751. IN LONGLONG LargeVbn,
  752. IN LONGLONG LargeLbn,
  753. IN LONGLONG LargeSectorCount
  754. )
  755. /*++
  756. Routine Description:
  757. This routine is used to add a new mapping of VBNs to LBNs to an existing
  758. Mcb. The information added will map
  759. Vbn to Lbn,
  760. Vbn+1 to Lbn+1,...
  761. Vbn+(SectorCount-1) to Lbn+(SectorCount-1).
  762. The mapping for the VBNs must not already exist in the Mcb. If the
  763. mapping continues a previous run, then this routine will actually coalesce
  764. them into 1 run.
  765. If pool is not available to store the information this routine will raise a
  766. status value indicating insufficient resources.
  767. An input Lbn value of zero is illegal (i.e., the Mcb structure will never
  768. map a Vbn to a zero Lbn value).
  769. Arguments:
  770. OpaqueMcb - Supplies the Mcb in which to add the new mapping.
  771. Vbn - Supplies the starting Vbn of the new mapping run to add to the Mcb.
  772. Lbn - Supplies the starting Lbn of the new mapping run to add to the Mcb.
  773. SectorCount - Supplies the size of the new mapping run (in sectors).
  774. Return Value:
  775. BOOLEAN - TRUE if the mapping was added successfully (i.e., the new
  776. Vbns did not collide with existing Vbns), and FALSE otherwise. If
  777. FALSE is returned then the Mcb is not changed.
  778. --*/
  779. {
  780. PNONOPAQUE_BASE_MCB BaseMcb = (PNONOPAQUE_BASE_MCB)Mcb;
  781. VBN Vbn = ((ULONG)LargeVbn);
  782. LBN Lbn = ((ULONG)LargeLbn);
  783. ULONG SectorCount = ((ULONG)LargeSectorCount);
  784. ULONG Index;
  785. VBN LastVbn;
  786. BOOLEAN Result;
  787. ASSERTMSG("LargeInteger not supported yet ", ((PLARGE_INTEGER)&LargeVbn)->HighPart == 0);
  788. ASSERTMSG("LargeInteger not supported yet ", ((PLARGE_INTEGER)&LargeLbn)->HighPart == 0);
  789. ASSERTMSG("LargeInteger not supported yet ", ((PLARGE_INTEGER)&LargeSectorCount)->HighPart == 0);
  790. DebugTrace(+1, Dbg, "FsRtlAddLargeMcbEntry, Mcb = %08lx\n", Mcb );
  791. DebugTrace( 0, Dbg, " Vbn = %08lx\n", Vbn );
  792. DebugTrace( 0, Dbg, " Lbn = %08lx\n", Lbn );
  793. DebugTrace( 0, Dbg, " SectorCount = %08lx\n", SectorCount );
  794. if (FsRtlFindLargeIndex(Mcb, Vbn, &Index)) {
  795. ULONG EndVbn = Vbn + SectorCount - 1;
  796. ULONG EndIndex;
  797. //
  798. // First check the case where we are adding to an existing mcb run
  799. // and if so then we will modify the insertion to complete the run
  800. //
  801. // --ExistingRun--| ==becomes==> --ExistingRun--|
  802. // |--NewRun--| |---|
  803. //
  804. // --ExistingRun----| ==becomes==> a noop
  805. // |--NewRun--|
  806. //
  807. if (StartingLbn(BaseMcb, Index) != UNUSED_LBN) {
  808. //
  809. // Check that the Lbn's line up between the new and existing run
  810. //
  811. if (Lbn != (StartingLbn(BaseMcb, Index) + (Vbn - StartingVbn(BaseMcb, Index)))) {
  812. //
  813. // Let our caller know we couldn't insert the run.
  814. //
  815. try_return(Result = FALSE);
  816. }
  817. //
  818. // Check if the new run is contained in the existing run
  819. //
  820. if (EndVbn <= EndingVbn(BaseMcb, Index)) {
  821. //
  822. // Do nothing because the run is contained within the existing run
  823. //
  824. try_return(Result = TRUE);
  825. }
  826. //
  827. // Otherwise we will simply trim off the request for the new run
  828. // to not overlap with the existing run
  829. //
  830. Vbn = NextStartingVbn(BaseMcb, Index);
  831. Lbn = EndingLbn(BaseMcb, Index) + 1;
  832. ASSERT(EndVbn >= Vbn);
  833. SectorCount = EndVbn - Vbn + 1;
  834. //
  835. // At this point the new run start in a hole, now check that if
  836. // crosses into a non hole and if so then adjust new run to fit
  837. // in the hole
  838. //
  839. //
  840. // |--ExistingRun-- ==becomes==> |--ExistingRun--
  841. // |--NewRun--| |--New|
  842. //
  843. } else if (FsRtlFindLargeIndex(Mcb, EndVbn, &EndIndex) && (Index == (EndIndex-1))) {
  844. //
  845. // Check that the Lbn's line up in the overlap
  846. //
  847. if (StartingLbn(BaseMcb, EndIndex) != Lbn + (StartingVbn(BaseMcb, EndIndex) - Vbn)) {
  848. //
  849. // Let our caller know we couldn't insert the run.
  850. //
  851. try_return(Result = FALSE);
  852. }
  853. //
  854. // Truncate the sector count to go up to but not include
  855. // the existing run
  856. //
  857. SectorCount = StartingVbn(BaseMcb, EndIndex) - Vbn;
  858. }
  859. }
  860. //
  861. // Find the index for the starting Vbn of our new run, if there isn't
  862. // a hole found then index will be set to paircount.
  863. //
  864. if (((Index = Mcb->PairCount) == 0) ||
  865. (PreviousEndingVbn(BaseMcb,Index)+1 <= Vbn) ||
  866. !FsRtlFindLargeIndex(Mcb, Vbn, &Index)) {
  867. //
  868. // We didn't find a mapping, therefore this new mapping must
  869. // go on at the end of the current mapping.
  870. //
  871. // See if we can just grow the last mapping in the current mcb.
  872. // We can grow the last entry if (1) the Vbns follow on, and (2)
  873. // the Lbns follow on. We can only grow the last mapping if the
  874. // index is not 0.
  875. //
  876. if ((Index != 0) &&
  877. (PreviousEndingVbn(BaseMcb,Index) + 1 == Vbn) &&
  878. (PreviousEndingLbn(BaseMcb,Index) + 1 == Lbn)) {
  879. //
  880. // --LastRun--|---NewRun--|
  881. //
  882. //
  883. // Extend the last run in the mcb
  884. //
  885. DebugTrace( 0, Dbg, "Continuing last run\n", 0);
  886. (BaseMcb->Mapping)[Mcb->PairCount-1].NextVbn += SectorCount;
  887. try_return (Result = TRUE);
  888. }
  889. //
  890. // We couldn't grow the last mapping, now check to see if
  891. // this is a continuation of the last Vbn (i.e., there isn't
  892. // going to be a hole in the mapping). Or if this is the first
  893. // run in the mapping
  894. //
  895. if ((Vbn == 0) ||
  896. (PreviousEndingVbn(BaseMcb,Index) + 1 == Vbn)) {
  897. //
  898. // --LastRun--||---NewRun--|
  899. //
  900. // 0:|--NewRun--|
  901. //
  902. //
  903. // We only need to add one more run to the mcb, so make sure
  904. // there is enough room for one.
  905. //
  906. DebugTrace( 0, Dbg, "Adding new contiguous last run\n", 0);
  907. FsRtlAddLargeEntry( Mcb, Index, 1 );
  908. //
  909. // Add the new mapping
  910. //
  911. (BaseMcb->Mapping)[Index].Lbn = Lbn;
  912. (BaseMcb->Mapping)[Index].NextVbn = Vbn + SectorCount;
  913. try_return (Result = TRUE);
  914. }
  915. //
  916. // If we reach this point then there is going to be a hole in the
  917. // mapping. and the mapping gets appended to the end of the current
  918. // allocation. So need to make room for two more runs in the mcb.
  919. //
  920. //
  921. // --LastRun--| hole |---NewRun--|
  922. //
  923. // 0: hole |--NewRun--|
  924. //
  925. DebugTrace( 0, Dbg, "Adding new noncontiguous last run\n", 0);
  926. FsRtlAddLargeEntry( Mcb, Index, 2 );
  927. //
  928. // Add the hole
  929. //
  930. (BaseMcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN;
  931. (BaseMcb->Mapping)[Index].NextVbn = Vbn;
  932. //
  933. // Add the new mapping
  934. //
  935. (BaseMcb->Mapping)[Index+1].Lbn = Lbn;
  936. (BaseMcb->Mapping)[Index+1].NextVbn = Vbn + SectorCount;
  937. try_return (Result = TRUE);
  938. }
  939. //
  940. // We found an index for the Vbn therefore we must be trying
  941. // to fill up a hole in the mcb. So first we need to check to make
  942. // sure there really is a hole to be filled
  943. //
  944. LastVbn = Vbn + SectorCount - 1;
  945. if ((StartingLbn(BaseMcb,Index) == UNUSED_LBN) &&
  946. (StartingVbn(BaseMcb,Index) <= Vbn) && (LastVbn <= EndingVbn(BaseMcb,Index))) {
  947. //
  948. // The mapping fits in this hole, but now here are the following
  949. // cases we must consider for the new mapping
  950. //
  951. if ((StartingVbn(BaseMcb,Index) < Vbn) && (LastVbn < EndingVbn(BaseMcb,Index))) {
  952. // Leaves a hole are both ends
  953. //
  954. // --PreviousRun--| hole |--NewRun--| hole |--FollowingRun--
  955. //
  956. // 0: hole |--NewRun--| hole |--FollowingRun--
  957. //
  958. DebugTrace( 0, Dbg, "Hole at both ends\n", 0);
  959. //
  960. // Make room for two more entries. The NextVbn field of the
  961. // one we're shifting remains valid.
  962. //
  963. FsRtlAddLargeEntry( Mcb, Index, 2 );
  964. //
  965. // Add the first hole
  966. //
  967. (BaseMcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN;
  968. (BaseMcb->Mapping)[Index].NextVbn = Vbn;
  969. //
  970. // Add the new mapping
  971. //
  972. (BaseMcb->Mapping)[Index+1].Lbn = Lbn;
  973. (BaseMcb->Mapping)[Index+1].NextVbn = Vbn + SectorCount;
  974. //
  975. // The second hole is already set up by the add entry call, because
  976. // that call just shift over the original hole to that slot
  977. //
  978. try_return (Result = TRUE);
  979. }
  980. if ((StartingVbn(BaseMcb,Index) == Vbn) && (LastVbn < EndingVbn(BaseMcb,Index))) {
  981. if (PreviousEndingLbn(BaseMcb,Index) + 1 == Lbn) {
  982. //
  983. // Leaves a hole at the rear, and continues the earlier run
  984. //
  985. // --PreviousRun--|--NewRun--| hole |--FollowingRun--
  986. //
  987. DebugTrace( 0, Dbg, "Hole at rear and continue\n", 0);
  988. //
  989. // We just need to extend the previous run
  990. //
  991. (BaseMcb->Mapping)[Index-1].NextVbn += SectorCount;
  992. try_return (Result = TRUE);
  993. } else {
  994. //
  995. // Leaves a hole at the rear, and does not continue the
  996. // earlier run. As occurs if index is zero.
  997. //
  998. // --PreviousRun--||--NewRun--| hole |--FollowingRun--
  999. //
  1000. // 0:|--NewRun--| hole |--FollowingRun--
  1001. //
  1002. DebugTrace( 0, Dbg, "Hole at rear and not continue\n", 0);
  1003. //
  1004. // Make room for one more entry. The NextVbn field of the
  1005. // one we're shifting remains valid.
  1006. //
  1007. FsRtlAddLargeEntry( Mcb, Index, 1 );
  1008. //
  1009. // Add the new mapping
  1010. //
  1011. (BaseMcb->Mapping)[Index].Lbn = Lbn;
  1012. (BaseMcb->Mapping)[Index].NextVbn = Vbn + SectorCount;
  1013. //
  1014. // The hole is already set up by the add entry call, because
  1015. // that call just shift over the original hole to that slot
  1016. //
  1017. try_return (Result = TRUE);
  1018. }
  1019. }
  1020. if ((StartingVbn(BaseMcb,Index) < Vbn) && (LastVbn == EndingVbn(BaseMcb,Index))) {
  1021. if (NextStartingLbn(BaseMcb,Index) == Lbn + SectorCount) {
  1022. //
  1023. // Leaves a hole at the front, and continues the following run
  1024. //
  1025. // --PreviousRun--| hole |--NewRun--|--FollowingRun--
  1026. //
  1027. // 0: hole |--NewRun--|--FollowingRun--
  1028. //
  1029. DebugTrace( 0, Dbg, "Hole at front and continue\n", 0);
  1030. //
  1031. // We just need to extend the following run
  1032. //
  1033. (BaseMcb->Mapping)[Index].NextVbn = Vbn;
  1034. (BaseMcb->Mapping)[Index+1].Lbn = Lbn;
  1035. try_return (Result = TRUE);
  1036. } else {
  1037. //
  1038. // Leaves a hole at the front, and does not continue the following
  1039. // run
  1040. //
  1041. // --PreviousRun--| hole |--NewRun--||--FollowingRun--
  1042. //
  1043. // 0: hole |--NewRun--||--FollowingRun--
  1044. //
  1045. DebugTrace( 0, Dbg, "Hole at front and not continue\n", 0);
  1046. //
  1047. // Make room for one more entry. The NextVbn field of the
  1048. // one we're shifting remains valid.
  1049. //
  1050. FsRtlAddLargeEntry( Mcb, Index, 1 );
  1051. //
  1052. // Add the hole
  1053. //
  1054. (BaseMcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN;
  1055. (BaseMcb->Mapping)[Index].NextVbn = Vbn;
  1056. //
  1057. // Add the new mapping
  1058. //
  1059. (BaseMcb->Mapping)[Index+1].Lbn = Lbn;
  1060. try_return (Result = TRUE);
  1061. }
  1062. }
  1063. if ((PreviousEndingLbn(BaseMcb,Index) + 1 == Lbn) &&
  1064. (NextStartingLbn(BaseMcb,Index) == Lbn + SectorCount)) {
  1065. //
  1066. // Leaves no holes, and continues both runs
  1067. //
  1068. // --PreviousRun--|--NewRun--|--FollowingRun--
  1069. //
  1070. DebugTrace( 0, Dbg, "No holes, and continues both runs\n", 0);
  1071. //
  1072. // We need to collapse the current index and the following index
  1073. // but first we copy the NextVbn of the follwing run into
  1074. // the NextVbn field of the previous run to so it all becomes
  1075. // one run
  1076. //
  1077. (BaseMcb->Mapping)[Index-1].NextVbn = (BaseMcb->Mapping)[Index+1].NextVbn;
  1078. FsRtlRemoveLargeEntry( Mcb, Index, 2 );
  1079. try_return (Result = TRUE);
  1080. }
  1081. if (NextStartingLbn(BaseMcb,Index) == Lbn + SectorCount) {
  1082. //
  1083. // Leaves no holes, and continues only following run
  1084. //
  1085. // --PreviousRun--||--NewRun--|--FollowingRun--
  1086. //
  1087. // 0:|--NewRun--|--FollowingRun--
  1088. //
  1089. DebugTrace( 0, Dbg, "No holes, and continues following\n", 0);
  1090. //
  1091. // This index is going away so we need to stretch the
  1092. // following run to meet up with the previous run
  1093. //
  1094. (BaseMcb->Mapping)[Index+1].Lbn = Lbn;
  1095. FsRtlRemoveLargeEntry( Mcb, Index, 1 );
  1096. try_return (Result = TRUE);
  1097. }
  1098. if (PreviousEndingLbn(BaseMcb,Index) + 1 == Lbn) {
  1099. //
  1100. // Leaves no holes, and continues only earlier run
  1101. //
  1102. // --PreviousRun--|--NewRun--||--FollowingRun--
  1103. //
  1104. DebugTrace( 0, Dbg, "No holes, and continues earlier\n", 0);
  1105. //
  1106. // This index is going away so we need to stretch the
  1107. // previous run to meet up with the following run
  1108. //
  1109. (BaseMcb->Mapping)[Index-1].NextVbn = (BaseMcb->Mapping)[Index].NextVbn;
  1110. FsRtlRemoveLargeEntry( Mcb, Index, 1 );
  1111. try_return (Result = TRUE);
  1112. }
  1113. //
  1114. // Leaves no holes, and continues neither run
  1115. //
  1116. // --PreviousRun--||--NewRun--||--FollowingRun--
  1117. //
  1118. // 0:|--NewRun--||--FollowingRun--
  1119. //
  1120. DebugTrace( 0, Dbg, "No holes, and continues none\n", 0);
  1121. (BaseMcb->Mapping)[Index].Lbn = Lbn;
  1122. try_return (Result = TRUE);
  1123. }
  1124. //
  1125. // We tried to overwrite an existing mapping so we'll have to
  1126. // tell our caller that it's not possible
  1127. //
  1128. Result = FALSE;
  1129. try_exit: NOTHING;
  1130. return Result;
  1131. }
  1132. BOOLEAN
  1133. FsRtlAddLargeMcbEntry (
  1134. IN PLARGE_MCB Mcb,
  1135. IN LONGLONG LargeVbn,
  1136. IN LONGLONG LargeLbn,
  1137. IN LONGLONG LargeSectorCount
  1138. )
  1139. /*++
  1140. Routine Description:
  1141. This routine is used to add a new mapping of VBNs to LBNs to an existing
  1142. Mcb. The information added will map
  1143. Vbn to Lbn,
  1144. Vbn+1 to Lbn+1,...
  1145. Vbn+(SectorCount-1) to Lbn+(SectorCount-1).
  1146. The mapping for the VBNs must not already exist in the Mcb. If the
  1147. mapping continues a previous run, then this routine will actually coalesce
  1148. them into 1 run.
  1149. If pool is not available to store the information this routine will raise a
  1150. status value indicating insufficient resources.
  1151. An input Lbn value of zero is illegal (i.e., the Mcb structure will never
  1152. map a Vbn to a zero Lbn value).
  1153. Arguments:
  1154. OpaqueMcb - Supplies the Mcb in which to add the new mapping.
  1155. Vbn - Supplies the starting Vbn of the new mapping run to add to the Mcb.
  1156. Lbn - Supplies the starting Lbn of the new mapping run to add to the Mcb.
  1157. SectorCount - Supplies the size of the new mapping run (in sectors).
  1158. Return Value:
  1159. BOOLEAN - TRUE if the mapping was added successfully (i.e., the new
  1160. Vbns did not collide with existing Vbns), and FALSE otherwise. If
  1161. FALSE is returned then the Mcb is not changed.
  1162. --*/
  1163. {
  1164. BOOLEAN Result = FALSE;
  1165. ExAcquireFastMutex( Mcb->FastMutex );
  1166. try {
  1167. Result = FsRtlAddBaseMcbEntry( &Mcb->BaseMcb, LargeVbn, LargeLbn, LargeSectorCount );
  1168. } finally {
  1169. ExReleaseFastMutex( Mcb->FastMutex );
  1170. DebugTrace(-1, Dbg, "FsRtlAddLargeMcbEntry -> %08lx\n", Result );
  1171. }
  1172. return Result;
  1173. }
  1174. //
  1175. // Private support routine
  1176. //
  1177. VOID
  1178. FsRtlRemoveBaseMcbEntry (
  1179. IN PBASE_MCB Mcb,
  1180. IN LONGLONG Vbn,
  1181. IN LONGLONG SectorCount
  1182. )
  1183. /*++
  1184. Routine Description:
  1185. This is the work routine for remove large mcb entry. It does the work
  1186. without taking out the mcb FastMutex.
  1187. Arguments:
  1188. Mcb - Supplies the Mcb from which to remove the mapping.
  1189. Vbn - Supplies the starting Vbn of the mappings to remove.
  1190. SectorCount - Supplies the size of the mappings to remove (in sectors).
  1191. Return Value:
  1192. None.
  1193. --*/
  1194. {
  1195. PNONOPAQUE_BASE_MCB BaseMcb = (PNONOPAQUE_BASE_MCB) Mcb;
  1196. ULONG Index;
  1197. //
  1198. // Do a quick test to see if we are wiping out the entire MCB.
  1199. //
  1200. if ((Vbn == 0) && (Mcb->PairCount > 0) && (SectorCount >= BaseMcb->Mapping[Mcb->PairCount-1].NextVbn)) {
  1201. Mcb->PairCount = 0;
  1202. return;
  1203. }
  1204. //
  1205. // While there is some more mapping to remove we'll continue
  1206. // with our main loop
  1207. //
  1208. while (SectorCount > 0) {
  1209. //
  1210. // Locate the mapping for the vbn
  1211. //
  1212. if (!FsRtlFindLargeIndex(Mcb, (VBN)Vbn, &Index)) {
  1213. DebugTrace( 0, Dbg, "FsRtlRemoveLargeMcbEntry, Cannot remove an unmapped Vbn = %08lx\n", Vbn );
  1214. return;
  1215. }
  1216. //
  1217. // Now that we some something to remove the following cases must
  1218. // be considered
  1219. //
  1220. if ((StartingVbn(BaseMcb,Index) == Vbn) &&
  1221. (EndingVbn(BaseMcb,Index) < Vbn + SectorCount)) {
  1222. ULONG i;
  1223. //
  1224. // Removes the entire run
  1225. //
  1226. //
  1227. // Update the amount to remove
  1228. //
  1229. i = SectorsWithinRun(BaseMcb,Index);
  1230. Vbn += i;
  1231. SectorCount -= i;
  1232. //
  1233. // If already a hole then leave it alone
  1234. //
  1235. if (StartingLbn(BaseMcb,Index) == UNUSED_LBN) {
  1236. NOTHING;
  1237. //
  1238. // Test for last run
  1239. //
  1240. } else if (Index == Mcb->PairCount - 1) {
  1241. if ((PreviousEndingLbn(BaseMcb,Index) != UNUSED_LBN) ||
  1242. (Index == 0)) {
  1243. //
  1244. // Previous is not hole, index is last run
  1245. //
  1246. // --Previous--| Hole
  1247. //
  1248. // 0: Hole
  1249. //
  1250. DebugTrace( 0, Dbg, "Entire run, Previous not hole, index is last run\n", 0);
  1251. //
  1252. // Just remove this entry
  1253. //
  1254. FsRtlRemoveLargeEntry( Mcb, Index, 1);
  1255. } else {
  1256. //
  1257. // Previous is hole, index is last run
  1258. //
  1259. // --Hole--| Hole
  1260. //
  1261. DebugTrace( 0, Dbg, "Entire run, Previous hole, index is last run\n", 0);
  1262. //
  1263. // Just remove this entry, and preceding entry
  1264. //
  1265. FsRtlRemoveLargeEntry( Mcb, Index-1, 2);
  1266. }
  1267. } else if (((PreviousEndingLbn(BaseMcb,Index) != UNUSED_LBN) || (Index == 0)) &&
  1268. (NextStartingLbn(BaseMcb,Index) != UNUSED_LBN)) {
  1269. //
  1270. // Previous and following are not holes
  1271. //
  1272. // --Previous--| Hole |--Following--
  1273. //
  1274. // 0: Hole |--Following--
  1275. //
  1276. DebugTrace( 0, Dbg, "Entire run, Previous & Following not holes\n", 0);
  1277. //
  1278. // Make this index a hole
  1279. //
  1280. (BaseMcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN;
  1281. } else if (((PreviousEndingLbn(BaseMcb,Index) != UNUSED_LBN) || (Index == 0)) &&
  1282. (NextStartingLbn(BaseMcb,Index) == UNUSED_LBN)) {
  1283. //
  1284. // Following is hole
  1285. //
  1286. // --Previous--| Hole |--Hole--
  1287. //
  1288. // 0: Hole |--Hole--
  1289. //
  1290. DebugTrace( 0, Dbg, "Entire run, Following is hole\n", 0);
  1291. //
  1292. // Simply remove this entry
  1293. //
  1294. FsRtlRemoveLargeEntry( Mcb, Index, 1 );
  1295. } else if ((PreviousEndingLbn(BaseMcb,Index) == UNUSED_LBN) &&
  1296. (NextStartingLbn(BaseMcb,Index) != UNUSED_LBN)) {
  1297. //
  1298. // Previous is hole
  1299. //
  1300. // --Hole--| Hole |--Following--
  1301. //
  1302. DebugTrace( 0, Dbg, "Entire run, Previous is hole\n", 0);
  1303. //
  1304. // Mark current entry a hole
  1305. //
  1306. (BaseMcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN;
  1307. //
  1308. // Remove previous entry
  1309. //
  1310. FsRtlRemoveLargeEntry( Mcb, Index - 1, 1 );
  1311. } else {
  1312. //
  1313. // Previous and following are holes
  1314. //
  1315. // --Hole--| Hole |--Hole--
  1316. //
  1317. DebugTrace( 0, Dbg, "Entire run, Previous & following are holes\n", 0);
  1318. //
  1319. // Remove previous and this entry
  1320. //
  1321. FsRtlRemoveLargeEntry( Mcb, Index - 1, 2 );
  1322. }
  1323. } else if (StartingVbn(BaseMcb,Index) == Vbn) {
  1324. //
  1325. // Removes first part of run
  1326. //
  1327. //
  1328. // If already a hole then leave it alone
  1329. //
  1330. if (StartingLbn(BaseMcb,Index) == UNUSED_LBN) {
  1331. NOTHING;
  1332. } else if ((PreviousEndingLbn(BaseMcb,Index) != UNUSED_LBN) || (Index == 0)) {
  1333. //
  1334. // Previous is not hole
  1335. //
  1336. // --Previous--| Hole |--Index--||--Following--
  1337. //
  1338. // 0: Hole |--Index--||--Following--
  1339. //
  1340. DebugTrace( 0, Dbg, "1st part, Previous is not hole\n", 0);
  1341. //
  1342. // Make room for one more entry. The NextVbn field of the
  1343. // one we're shifting remains valid.
  1344. //
  1345. FsRtlAddLargeEntry( Mcb, Index, 1 );
  1346. //
  1347. // Set the hole
  1348. //
  1349. (BaseMcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN;
  1350. (BaseMcb->Mapping)[Index].NextVbn = (VBN)Vbn + (VBN)SectorCount;
  1351. //
  1352. // Set the new Lbn for the remaining run
  1353. //
  1354. (BaseMcb->Mapping)[Index+1].Lbn += (LBN)SectorCount;
  1355. } else {
  1356. //
  1357. // Previous is hole
  1358. //
  1359. // --Hole--| Hole |--Index--||--Following--
  1360. //
  1361. DebugTrace( 0, Dbg, "1st part, Previous is hole\n", 0);
  1362. //
  1363. // Expand the preceding hole
  1364. //
  1365. (BaseMcb->Mapping)[Index-1].NextVbn += (VBN)SectorCount;
  1366. //
  1367. // Set the new Lbn for the remaining run
  1368. //
  1369. (BaseMcb->Mapping)[Index].Lbn += (LBN)SectorCount;
  1370. }
  1371. //
  1372. // Update the amount to remove
  1373. //
  1374. Vbn += SectorCount;
  1375. SectorCount = 0;
  1376. } else if (EndingVbn(BaseMcb,Index) < Vbn + SectorCount) {
  1377. ULONG AmountToRemove;
  1378. AmountToRemove = EndingVbn(BaseMcb,Index) - (VBN)Vbn + 1;
  1379. //
  1380. // Removes last part of run
  1381. //
  1382. //
  1383. // If already a hole then leave it alone
  1384. //
  1385. if (StartingLbn(BaseMcb,Index) == UNUSED_LBN) {
  1386. NOTHING;
  1387. } else if (Index == Mcb->PairCount - 1) {
  1388. //
  1389. // Index is last run
  1390. //
  1391. // --Previous--||--Index--| Hole
  1392. //
  1393. // 0:|--Index--| Hole
  1394. //
  1395. DebugTrace( 0, Dbg, "last part, Index is last run\n", 0);
  1396. //
  1397. // Shrink back the size of the current index
  1398. //
  1399. (BaseMcb->Mapping)[Index].NextVbn -= AmountToRemove;
  1400. } else if (NextStartingLbn(BaseMcb,Index) == UNUSED_LBN) {
  1401. //
  1402. // Following is hole
  1403. //
  1404. // --Previous--||--Index--| Hole |--Hole--
  1405. //
  1406. // 0:|--Index--| Hole |--Hole--
  1407. //
  1408. DebugTrace( 0, Dbg, "last part, Following is hole\n", 0);
  1409. //
  1410. // Shrink back the size of the current index
  1411. //
  1412. (BaseMcb->Mapping)[Index].NextVbn -= AmountToRemove;
  1413. } else {
  1414. //
  1415. // Following is not hole
  1416. //
  1417. // --Previous--||--Index--| Hole |--Following--
  1418. //
  1419. //
  1420. // 0:|--Index--| Hole |--Following--
  1421. //
  1422. DebugTrace( 0, Dbg, "last part, Following is not hole\n", 0);
  1423. //
  1424. // Make room for one more entry. The NextVbn field of the
  1425. // one we're shifting remains valid.
  1426. //
  1427. FsRtlAddLargeEntry( Mcb, Index+1, 1 );
  1428. //
  1429. // Set the new hole
  1430. //
  1431. (BaseMcb->Mapping)[Index+1].Lbn = (LBN)UNUSED_LBN;
  1432. (BaseMcb->Mapping)[Index+1].NextVbn = (BaseMcb->Mapping)[Index].NextVbn;
  1433. //
  1434. // Shrink back the size of the current index
  1435. //
  1436. (BaseMcb->Mapping)[Index].NextVbn -= AmountToRemove;
  1437. }
  1438. //
  1439. // Update amount to remove
  1440. //
  1441. Vbn += AmountToRemove;
  1442. SectorCount -= AmountToRemove;
  1443. } else {
  1444. //
  1445. // If already a hole then leave it alone
  1446. //
  1447. if (StartingLbn(BaseMcb,Index) == UNUSED_LBN) {
  1448. NOTHING;
  1449. } else {
  1450. //
  1451. // Remove middle of run
  1452. //
  1453. // --Previous--||--Index--| Hole |--Index--||--Following--
  1454. //
  1455. // 0:|--Index--| Hole |--Index--||--Following--
  1456. //
  1457. DebugTrace( 0, Dbg, "Middle of run\n", 0);
  1458. //
  1459. // Make room for two more entries. The NextVbn field of the
  1460. // one we're shifting remains valid.
  1461. //
  1462. FsRtlAddLargeEntry( Mcb, Index, 2 );
  1463. //
  1464. // Set up the first remaining run
  1465. //
  1466. (BaseMcb->Mapping)[Index].Lbn = (BaseMcb->Mapping)[Index+2].Lbn;
  1467. (BaseMcb->Mapping)[Index].NextVbn = (VBN)Vbn;
  1468. //
  1469. // Set up the hole
  1470. //
  1471. (BaseMcb->Mapping)[Index+1].Lbn = (LBN)UNUSED_LBN;
  1472. (BaseMcb->Mapping)[Index+1].NextVbn = (VBN)Vbn + (VBN)SectorCount;
  1473. //
  1474. // Set up the second remaining run
  1475. //
  1476. (BaseMcb->Mapping)[Index+2].Lbn += SectorsWithinRun(BaseMcb,Index) +
  1477. SectorsWithinRun(BaseMcb,Index+1);
  1478. }
  1479. //
  1480. // Update amount to remove
  1481. //
  1482. Vbn += SectorCount;
  1483. SectorCount = 0;
  1484. }
  1485. }
  1486. return;
  1487. }
  1488. VOID
  1489. FsRtlRemoveLargeMcbEntry (
  1490. IN PLARGE_MCB Mcb,
  1491. IN LONGLONG LargeVbn,
  1492. IN LONGLONG LargeSectorCount
  1493. )
  1494. /*++
  1495. Routine Description:
  1496. This routine removes a mapping of VBNs to LBNs from an Mcb. The mappings
  1497. removed are for
  1498. Vbn,
  1499. Vbn+1, to
  1500. Vbn+(SectorCount-1).
  1501. The operation works even if the mapping for a Vbn in the specified range
  1502. does not already exist in the Mcb. If the specified range of Vbn includes
  1503. the last mapped Vbn in the Mcb then the Mcb mapping shrinks accordingly.
  1504. If pool is not available to store the information this routine will raise
  1505. a status value indicating insufficient resources.
  1506. Arguments:
  1507. OpaqueMcb - Supplies the Mcb from which to remove the mapping.
  1508. Vbn - Supplies the starting Vbn of the mappings to remove.
  1509. SectorCount - Supplies the size of the mappings to remove (in sectors).
  1510. Return Value:
  1511. None.
  1512. --*/
  1513. {
  1514. VBN Vbn = ((ULONG)LargeVbn);
  1515. ULONG SectorCount = ((ULONG)LargeSectorCount);
  1516. ASSERTMSG("LargeInteger not supported yet ", ((PLARGE_INTEGER)&LargeVbn)->HighPart == 0);
  1517. DebugTrace(+1, Dbg, "FsRtlRemoveLargeMcbEntry, Mcb = %08lx\n", Mcb );
  1518. DebugTrace( 0, Dbg, " Vbn = %08lx\n", Vbn );
  1519. DebugTrace( 0, Dbg, " SectorCount = %08lx\n", SectorCount );
  1520. ExAcquireFastMutex( Mcb->FastMutex );
  1521. try {
  1522. FsRtlRemoveBaseMcbEntry( &Mcb->BaseMcb, Vbn, SectorCount );
  1523. } finally {
  1524. ExReleaseFastMutex( Mcb->FastMutex );
  1525. DebugTrace(-1, Dbg, "FsRtlRemoveLargeMcbEntry -> VOID\n", 0 );
  1526. }
  1527. return;
  1528. }
  1529. BOOLEAN
  1530. FsRtlLookupBaseMcbEntry (
  1531. IN PBASE_MCB Mcb,
  1532. IN LONGLONG LargeVbn,
  1533. OUT PLONGLONG LargeLbn OPTIONAL,
  1534. OUT PLONGLONG LargeSectorCount OPTIONAL,
  1535. OUT PLONGLONG LargeStartingLbn OPTIONAL,
  1536. OUT PLONGLONG LargeCountFromStartingLbn OPTIONAL,
  1537. OUT PULONG Index OPTIONAL
  1538. )
  1539. /*++
  1540. Routine Description:
  1541. This routine retrieves the mapping of a Vbn to an Lbn from an Mcb.
  1542. It indicates if the mapping exists and the size of the run.
  1543. Arguments:
  1544. OpaqueMcb - Supplies the Mcb being examined.
  1545. Vbn - Supplies the Vbn to lookup.
  1546. Lbn - Receives the Lbn corresponding to the Vbn. A value of -1 is
  1547. returned if the Vbn does not have a corresponding Lbn.
  1548. SectorCount - Receives the number of sectors that map from the Vbn to
  1549. contiguous Lbn values beginning with the input Vbn.
  1550. Index - Receives the index of the run found.
  1551. Return Value:
  1552. BOOLEAN - TRUE if the Vbn is within the range of VBNs mapped by the
  1553. MCB (even if it corresponds to a hole in the mapping), and FALSE
  1554. if the Vbn is beyond the range of the MCB's mapping.
  1555. For example, if an MCB has a mapping for VBNs 5 and 7 but not for
  1556. 6, then a lookup on Vbn 5 or 7 will yield a non zero Lbn and a sector
  1557. count of 1. A lookup for Vbn 6 will return TRUE with an Lbn value of
  1558. 0, and lookup for Vbn 8 or above will return FALSE.
  1559. --*/
  1560. {
  1561. PNONOPAQUE_BASE_MCB BaseMcb = (PNONOPAQUE_BASE_MCB)Mcb;
  1562. ULONG LocalIndex;
  1563. BOOLEAN Result;
  1564. DebugTrace(+1, Dbg, "FsRtlLookupBaseMcbEntry, Mcb = %08lx\n", Mcb );
  1565. DebugTrace( 0, Dbg, " LargeVbn.LowPart = %08lx\n", LargeVbn.LowPart );
  1566. ASSERTMSG("LargeInteger not supported yet ", ((((PLARGE_INTEGER)&LargeVbn)->HighPart == 0) ||
  1567. (Mcb->PairCount == 0) ||
  1568. ((((PLARGE_INTEGER)&LargeVbn)->HighPart == 0x7FFFFFFF) &&
  1569. (((ULONG)LargeVbn) == 0xFFFFFFFF))));
  1570. if (!FsRtlFindLargeIndex(Mcb, ((ULONG)LargeVbn), &LocalIndex)) {
  1571. try_return (Result = FALSE);
  1572. }
  1573. //
  1574. // Compute the lbn for corresponding to the vbn, the value is the
  1575. // starting lbn of the run plus the number of sectors offset into the
  1576. // run. But if it's a hole then the sector Lbn is zero.
  1577. //
  1578. if (ARGUMENT_PRESENT(LargeLbn)) {
  1579. if (StartingLbn(BaseMcb,LocalIndex) == UNUSED_LBN) {
  1580. *LargeLbn = UNUSED_LBN;
  1581. } else {
  1582. *LargeLbn = StartingLbn(BaseMcb,LocalIndex) + (((ULONG)LargeVbn) - StartingVbn(BaseMcb,LocalIndex));
  1583. }
  1584. }
  1585. //
  1586. // If there sector count argument is present then we'll return the number
  1587. // of sectors remaing in the run.
  1588. //
  1589. if (ARGUMENT_PRESENT(LargeSectorCount)) {
  1590. *LargeSectorCount = EndingVbn(BaseMcb,LocalIndex) - ((ULONG)LargeVbn) + 1;
  1591. }
  1592. //
  1593. // Compute the starting lbn for corresponding to the start of the run, the value is the
  1594. // starting lbn of the run. But if it's a hole then the sector Lbn is zero.
  1595. //
  1596. if (ARGUMENT_PRESENT(LargeStartingLbn)) {
  1597. if (StartingLbn(BaseMcb,LocalIndex) == UNUSED_LBN) {
  1598. *LargeStartingLbn = UNUSED_LBN;
  1599. } else {
  1600. *LargeStartingLbn = StartingLbn(BaseMcb,LocalIndex);
  1601. }
  1602. }
  1603. //
  1604. // If there sector count argument is present then we'll return the number
  1605. // of sectors in the run.
  1606. //
  1607. if (ARGUMENT_PRESENT(LargeCountFromStartingLbn)) {
  1608. *LargeCountFromStartingLbn = EndingVbn(BaseMcb,LocalIndex) - StartingVbn(BaseMcb,LocalIndex) + 1;
  1609. }
  1610. //
  1611. // If the caller want to know the Index number, fill it in.
  1612. //
  1613. if (ARGUMENT_PRESENT(Index)) {
  1614. *Index = LocalIndex;
  1615. }
  1616. Result = TRUE;
  1617. try_exit: NOTHING;
  1618. return Result;
  1619. }
  1620. BOOLEAN
  1621. FsRtlLookupLargeMcbEntry (
  1622. IN PLARGE_MCB Mcb,
  1623. IN LONGLONG LargeVbn,
  1624. OUT PLONGLONG LargeLbn OPTIONAL,
  1625. OUT PLONGLONG LargeSectorCount OPTIONAL,
  1626. OUT PLONGLONG LargeStartingLbn OPTIONAL,
  1627. OUT PLONGLONG LargeCountFromStartingLbn OPTIONAL,
  1628. OUT PULONG Index OPTIONAL
  1629. )
  1630. /*++
  1631. Routine Description:
  1632. This routine retrieves the mapping of a Vbn to an Lbn from an Mcb.
  1633. It indicates if the mapping exists and the size of the run.
  1634. Arguments:
  1635. OpaqueMcb - Supplies the Mcb being examined.
  1636. Vbn - Supplies the Vbn to lookup.
  1637. Lbn - Receives the Lbn corresponding to the Vbn. A value of -1 is
  1638. returned if the Vbn does not have a corresponding Lbn.
  1639. SectorCount - Receives the number of sectors that map from the Vbn to
  1640. contiguous Lbn values beginning with the input Vbn.
  1641. Index - Receives the index of the run found.
  1642. Return Value:
  1643. BOOLEAN - TRUE if the Vbn is within the range of VBNs mapped by the
  1644. MCB (even if it corresponds to a hole in the mapping), and FALSE
  1645. if the Vbn is beyond the range of the MCB's mapping.
  1646. For example, if an MCB has a mapping for VBNs 5 and 7 but not for
  1647. 6, then a lookup on Vbn 5 or 7 will yield a non zero Lbn and a sector
  1648. count of 1. A lookup for Vbn 6 will return TRUE with an Lbn value of
  1649. 0, and lookup for Vbn 8 or above will return FALSE.
  1650. --*/
  1651. {
  1652. BOOLEAN Result = FALSE;
  1653. ExAcquireFastMutex( Mcb->FastMutex );
  1654. try {
  1655. Result = FsRtlLookupBaseMcbEntry( &Mcb->BaseMcb, LargeVbn, LargeLbn, LargeSectorCount, LargeStartingLbn, LargeCountFromStartingLbn, Index );
  1656. } finally {
  1657. ExReleaseFastMutex( Mcb->FastMutex );
  1658. DebugTrace(-1, Dbg, "FsRtlLookupLargeMcbEntry -> %08lx\n", Result );
  1659. }
  1660. return Result;
  1661. }
  1662. BOOLEAN
  1663. FsRtlLookupLastBaseMcbEntry (
  1664. IN PBASE_MCB Mcb,
  1665. OUT PLONGLONG LargeVbn,
  1666. OUT PLONGLONG LargeLbn
  1667. )
  1668. /*++
  1669. Routine Description:
  1670. This routine retrieves the last Vbn to Lbn mapping stored in the Mcb.
  1671. It returns the mapping for the last sector or the last run in the
  1672. Mcb. The results of this function is useful when extending an existing
  1673. file and needing to a hint on where to try and allocate sectors on the
  1674. disk.
  1675. Arguments:
  1676. Mcb - Supplies the Mcb being examined.
  1677. Vbn - Receives the last Vbn value mapped.
  1678. Lbn - Receives the Lbn corresponding to the Vbn.
  1679. Return Value:
  1680. BOOLEAN - TRUE if there is a mapping within the Mcb and FALSE otherwise
  1681. (i.e., the Mcb does not contain any mapping).
  1682. --*/
  1683. {
  1684. PNONOPAQUE_BASE_MCB BaseMcb = (PNONOPAQUE_BASE_MCB)Mcb;
  1685. BOOLEAN Result = FALSE;
  1686. DebugTrace(+1, Dbg, "FsRtlLookupLastLargeBaseEntry, Mcb = %08lx\n", Mcb );
  1687. //
  1688. // Check to make sure there is at least one run in the mcb
  1689. //
  1690. if (BaseMcb->PairCount > 0) {
  1691. //
  1692. // Return the last mapping of the last run
  1693. //
  1694. *LargeLbn = EndingLbn(BaseMcb, BaseMcb->PairCount-1);
  1695. *LargeVbn = EndingVbn(BaseMcb, BaseMcb->PairCount-1);
  1696. Result = TRUE;
  1697. }
  1698. return Result;
  1699. }
  1700. BOOLEAN
  1701. FsRtlLookupLastLargeMcbEntry (
  1702. IN PLARGE_MCB Mcb,
  1703. OUT PLONGLONG LargeVbn,
  1704. OUT PLONGLONG LargeLbn
  1705. )
  1706. /*++
  1707. Routine Description:
  1708. This routine retrieves the last Vbn to Lbn mapping stored in the Mcb.
  1709. It returns the mapping for the last sector or the last run in the
  1710. Mcb. The results of this function is useful when extending an existing
  1711. file and needing to a hint on where to try and allocate sectors on the
  1712. disk.
  1713. Arguments:
  1714. OpaqueMcb - Supplies the Mcb being examined.
  1715. Vbn - Receives the last Vbn value mapped.
  1716. Lbn - Receives the Lbn corresponding to the Vbn.
  1717. Return Value:
  1718. BOOLEAN - TRUE if there is a mapping within the Mcb and FALSE otherwise
  1719. (i.e., the Mcb does not contain any mapping).
  1720. --*/
  1721. {
  1722. BOOLEAN Result = FALSE;
  1723. DebugTrace(+1, Dbg, "FsRtlLookupLastLargeMcbEntry, Mcb = %08lx\n", Mcb );
  1724. ExAcquireFastMutex( Mcb->FastMutex );
  1725. try {
  1726. Result = FsRtlLookupLastBaseMcbEntry( &Mcb->BaseMcb, LargeVbn, LargeLbn );
  1727. } finally {
  1728. ExReleaseFastMutex( Mcb->FastMutex );
  1729. DebugTrace(-1, Dbg, "FsRtlLookupLastLargeMcbEntry -> %08lx\n", Result );
  1730. }
  1731. return Result;
  1732. }
  1733. BOOLEAN
  1734. FsRtlLookupLastBaseMcbEntryAndIndex (
  1735. IN PBASE_MCB Mcb,
  1736. OUT PLONGLONG LargeVbn,
  1737. OUT PLONGLONG LargeLbn,
  1738. OUT PULONG Index
  1739. )
  1740. /*++
  1741. Routine Description:
  1742. This routine retrieves the last Vbn to Lbn mapping stored in the Mcb.
  1743. It returns the mapping for the last sector or the last run in the
  1744. Mcb. The results of this function is useful when extending an existing
  1745. file and needing to a hint on where to try and allocate sectors on the
  1746. disk.
  1747. Arguments:
  1748. Mcb - Supplies the Mcb being examined.
  1749. Vbn - Receives the last Vbn value mapped.
  1750. Lbn - Receives the Lbn corresponding to the Vbn.
  1751. Index - Receives the index of the last run.
  1752. Return Value:
  1753. BOOLEAN - TRUE if there is a mapping within the Mcb and FALSE otherwise
  1754. (i.e., the Mcb does not contain any mapping).
  1755. --*/
  1756. {
  1757. PNONOPAQUE_BASE_MCB BaseMcb = (PNONOPAQUE_BASE_MCB)Mcb;
  1758. BOOLEAN Result = FALSE;
  1759. PAGED_CODE();
  1760. DebugTrace(+1, Dbg, "FsRtlLookupLastBaseMcbEntryAndIndex, Mcb = %08lx\n", Mcb );
  1761. //
  1762. // Check to make sure there is at least one run in the mcb
  1763. //
  1764. if (BaseMcb->PairCount > 0) {
  1765. //
  1766. // Return the last mapping of the last run
  1767. //
  1768. *((PULONG)LargeLbn) = EndingLbn(BaseMcb, BaseMcb->PairCount-1);
  1769. *((PULONG)LargeVbn) = EndingVbn(BaseMcb, BaseMcb->PairCount-1);
  1770. *Index = BaseMcb->PairCount - 1;
  1771. Result = TRUE;
  1772. }
  1773. ((PLARGE_INTEGER)LargeVbn)->HighPart = (*((PULONG)LargeVbn) == UNUSED_LBN ? UNUSED_LBN : 0);
  1774. ((PLARGE_INTEGER)LargeLbn)->HighPart = (*((PULONG)LargeLbn) == UNUSED_LBN ? UNUSED_LBN : 0);
  1775. return Result;
  1776. }
  1777. BOOLEAN
  1778. FsRtlLookupLastLargeMcbEntryAndIndex (
  1779. IN PLARGE_MCB Mcb,
  1780. OUT PLONGLONG LargeVbn,
  1781. OUT PLONGLONG LargeLbn,
  1782. OUT PULONG Index
  1783. )
  1784. /*++
  1785. Routine Description:
  1786. This routine retrieves the last Vbn to Lbn mapping stored in the Mcb.
  1787. It returns the mapping for the last sector or the last run in the
  1788. Mcb. The results of this function is useful when extending an existing
  1789. file and needing to a hint on where to try and allocate sectors on the
  1790. disk.
  1791. Arguments:
  1792. OpaqueMcb - Supplies the Mcb being examined.
  1793. Vbn - Receives the last Vbn value mapped.
  1794. Lbn - Receives the Lbn corresponding to the Vbn.
  1795. Index - Receives the index of the last run.
  1796. Return Value:
  1797. BOOLEAN - TRUE if there is a mapping within the Mcb and FALSE otherwise
  1798. (i.e., the Mcb does not contain any mapping).
  1799. --*/
  1800. {
  1801. BOOLEAN Result = FALSE;
  1802. PAGED_CODE();
  1803. DebugTrace(+1, Dbg, "FsRtlLookupLastLargeMcbEntryAndIndex, Mcb = %08lx\n", Mcb );
  1804. ExAcquireFastMutex( Mcb->FastMutex );
  1805. try {
  1806. Result = FsRtlLookupLastBaseMcbEntryAndIndex( &Mcb->BaseMcb, LargeVbn, LargeLbn, Index );
  1807. } finally {
  1808. ExReleaseFastMutex( Mcb->FastMutex );
  1809. DebugTrace(-1, Dbg, "FsRtlLookupLastLargeMcbEntryAndIndex -> %08lx\n", Result );
  1810. }
  1811. return Result;
  1812. }
  1813. ULONG
  1814. FsRtlNumberOfRunsInBaseMcb (
  1815. IN PBASE_MCB Mcb
  1816. )
  1817. /*++
  1818. Routine Description:
  1819. This routine returns to the its caller the number of distinct runs
  1820. mapped by an Mcb. Holes (i.e., Vbns that map to Lbn=UNUSED_LBN) are counted
  1821. as runs. For example, an Mcb containing a mapping for only Vbns 0 and 3
  1822. will have 3 runs, one for the first mapped sector, a second for the
  1823. hole covering Vbns 1 and 2, and a third for Vbn 3.
  1824. Arguments:
  1825. Mcb - Supplies the Mcb being examined.
  1826. Return Value:
  1827. ULONG - Returns the number of distinct runs mapped by the input Mcb.
  1828. --*/
  1829. {
  1830. return Mcb->PairCount;
  1831. }
  1832. ULONG
  1833. FsRtlNumberOfRunsInLargeMcb (
  1834. IN PLARGE_MCB Mcb
  1835. )
  1836. /*++
  1837. Routine Description:
  1838. This routine returns to the its caller the number of distinct runs
  1839. mapped by an Mcb. Holes (i.e., Vbns that map to Lbn=UNUSED_LBN) are counted
  1840. as runs. For example, an Mcb containing a mapping for only Vbns 0 and 3
  1841. will have 3 runs, one for the first mapped sector, a second for the
  1842. hole covering Vbns 1 and 2, and a third for Vbn 3.
  1843. Arguments:
  1844. OpaqueMcb - Supplies the Mcb being examined.
  1845. Return Value:
  1846. ULONG - Returns the number of distinct runs mapped by the input Mcb.
  1847. --*/
  1848. {
  1849. ULONG Count;
  1850. DebugTrace(+1, Dbg, "FsRtlNumberOfRunsInLargeMcb, Mcb = %08lx\n", Mcb );
  1851. ExAcquireFastMutex( Mcb->FastMutex );
  1852. Count = FsRtlNumberOfRunsInBaseMcb( &Mcb->BaseMcb );
  1853. ExReleaseFastMutex( Mcb->FastMutex );
  1854. DebugTrace(-1, Dbg, "FsRtlNumberOfRunsInLargeMcb -> %08lx\n", Count );
  1855. return Count;
  1856. }
  1857. BOOLEAN
  1858. FsRtlGetNextBaseMcbEntry (
  1859. IN PBASE_MCB Mcb,
  1860. IN ULONG RunIndex,
  1861. OUT PLONGLONG LargeVbn,
  1862. OUT PLONGLONG LargeLbn,
  1863. OUT PLONGLONG LargeSectorCount
  1864. )
  1865. /*++
  1866. Routine Description:
  1867. This routine returns to its caller the Vbn, Lbn, and SectorCount for
  1868. distinct runs mapped by an Mcb. Holes are counted as runs. For example,
  1869. to construct to print out all of the runs in a a file is:
  1870. //. . for (i = 0; FsRtlGetNextLargeMcbEntry(Mcb,i,&Vbn,&Lbn,&Count); i++) {
  1871. //
  1872. //. . // print out vbn, lbn, and count
  1873. //
  1874. //. . }
  1875. Arguments:
  1876. OpaqueMcb - Supplies the Mcb being examined.
  1877. RunIndex - Supplies the index of the run (zero based) to return to the
  1878. caller.
  1879. Vbn - Receives the starting Vbn of the returned run, or zero if the
  1880. run does not exist.
  1881. Lbn - Recieves the starting Lbn of the returned run, or zero if the
  1882. run does not exist.
  1883. SectorCount - Receives the number of sectors within the returned run,
  1884. or zero if the run does not exist.
  1885. Return Value:
  1886. BOOLEAN - TRUE if the specified run (i.e., RunIndex) exists in the Mcb,
  1887. and FALSE otherwise. If FALSE is returned then the Vbn, Lbn, and
  1888. SectorCount parameters receive zero.
  1889. --*/
  1890. {
  1891. PNONOPAQUE_BASE_MCB BaseMcb = (PNONOPAQUE_BASE_MCB)Mcb;
  1892. BOOLEAN Result = FALSE;
  1893. DebugTrace(+1, Dbg, "FsRtlGetNextLargeMcbEntry, Mcb = %08lx\n", Mcb );
  1894. DebugTrace( 0, Dbg, " RunIndex = %08lx\n", RunIndex );
  1895. //
  1896. // Make sure the run index is within range
  1897. //
  1898. if (RunIndex < BaseMcb->PairCount) {
  1899. //
  1900. // Set the return variables
  1901. //
  1902. *((PULONG)LargeVbn) = StartingVbn(BaseMcb, RunIndex);
  1903. ((PLARGE_INTEGER)LargeVbn)->HighPart = (*((PULONG)LargeVbn) == UNUSED_LBN ? UNUSED_LBN : 0);
  1904. *((PULONG)LargeLbn) = StartingLbn(BaseMcb, RunIndex);
  1905. ((PLARGE_INTEGER)LargeLbn)->HighPart = (*((PULONG)LargeLbn) == UNUSED_LBN ? UNUSED_LBN : 0);
  1906. *LargeSectorCount = SectorsWithinRun(BaseMcb, RunIndex);
  1907. Result = TRUE;
  1908. }
  1909. return Result;
  1910. }
  1911. BOOLEAN
  1912. FsRtlGetNextLargeMcbEntry (
  1913. IN PLARGE_MCB Mcb,
  1914. IN ULONG RunIndex,
  1915. OUT PLONGLONG LargeVbn,
  1916. OUT PLONGLONG LargeLbn,
  1917. OUT PLONGLONG LargeSectorCount
  1918. )
  1919. /*++
  1920. Routine Description:
  1921. This routine returns to its caller the Vbn, Lbn, and SectorCount for
  1922. distinct runs mapped by an Mcb. Holes are counted as runs. For example,
  1923. to construct to print out all of the runs in a a file is:
  1924. //. . for (i = 0; FsRtlGetNextLargeMcbEntry(Mcb,i,&Vbn,&Lbn,&Count); i++) {
  1925. //
  1926. //. . // print out vbn, lbn, and count
  1927. //
  1928. //. . }
  1929. Arguments:
  1930. OpaqueMcb - Supplies the Mcb being examined.
  1931. RunIndex - Supplies the index of the run (zero based) to return to the
  1932. caller.
  1933. Vbn - Receives the starting Vbn of the returned run, or zero if the
  1934. run does not exist.
  1935. Lbn - Recieves the starting Lbn of the returned run, or zero if the
  1936. run does not exist.
  1937. SectorCount - Receives the number of sectors within the returned run,
  1938. or zero if the run does not exist.
  1939. Return Value:
  1940. BOOLEAN - TRUE if the specified run (i.e., RunIndex) exists in the Mcb,
  1941. and FALSE otherwise. If FALSE is returned then the Vbn, Lbn, and
  1942. SectorCount parameters receive zero.
  1943. --*/
  1944. {
  1945. BOOLEAN Result = FALSE;
  1946. DebugTrace(+1, Dbg, "FsRtlGetNextLargeMcbEntry, Mcb = %08lx\n", Mcb );
  1947. DebugTrace( 0, Dbg, " RunIndex = %08lx\n", RunIndex );
  1948. ExAcquireFastMutex( Mcb->FastMutex );
  1949. try {
  1950. Result = FsRtlGetNextBaseMcbEntry( &Mcb->BaseMcb, RunIndex, LargeVbn, LargeLbn, LargeSectorCount );
  1951. } finally {
  1952. ExReleaseFastMutex( Mcb->FastMutex );
  1953. DebugTrace(-1, Dbg, "FsRtlGetNextLargeMcbEntry -> %08lx\n", Result );
  1954. }
  1955. return Result;
  1956. }
  1957. BOOLEAN
  1958. FsRtlSplitBaseMcb (
  1959. IN PBASE_MCB Mcb,
  1960. IN LONGLONG LargeVbn,
  1961. IN LONGLONG LargeAmount
  1962. )
  1963. /*++
  1964. Routine Description:
  1965. This routine is used to create a hole within an MCB, by shifting the
  1966. mapping of Vbns. All mappings above the input vbn are shifted by the
  1967. amount specified and while keeping their current lbn value. Pictorially
  1968. we have as input the following MCB
  1969. VBN : LargeVbn-1 LargeVbn N
  1970. +-----------------+------------------+
  1971. LBN : X Y
  1972. And after the split we have
  1973. VBN : LargeVbn-1 LargeVbn+Amount N+Amount
  1974. +-----------------+.............+---------------------------+
  1975. LBN : X UnusedLbn Y
  1976. When doing the split we have a few cases to consider. They are:
  1977. 1. The input Vbn is beyond the last run. In this case this operation
  1978. is a noop.
  1979. 2. The input Vbn is within or adjacent to a existing run of unused Lbns.
  1980. In this case we simply need to extend the size of the existing hole
  1981. and shift succeeding runs.
  1982. 3. The input Vbn is between two existing runs, including the an input vbn
  1983. value of zero. In this case we need to add a new entry for the hole
  1984. and shift succeeding runs.
  1985. 4. The input Vbn is within an existing run. In this case we need to add
  1986. two new entries to contain the split run and the hole.
  1987. If pool is not available to store the information this routine will raise a
  1988. status value indicating insufficient resources.
  1989. Arguments:
  1990. OpaqueMcb - Supplies the Mcb in which to add the new mapping.
  1991. Vbn - Supplies the starting Vbn that is to be shifted.
  1992. Amount - Supplies the amount to shift by.
  1993. Return Value:
  1994. BOOLEAN - TRUE if the mapping was successfully shifted, and FALSE otherwise.
  1995. If FALSE is returned then the Mcb is not changed.
  1996. --*/
  1997. {
  1998. PNONOPAQUE_BASE_MCB BaseMcb = (PNONOPAQUE_BASE_MCB)Mcb;
  1999. VBN Vbn = ((ULONG)LargeVbn);
  2000. ULONG Amount = ((ULONG)LargeAmount);
  2001. ULONG Index;
  2002. BOOLEAN Result;
  2003. ULONG i;
  2004. PAGED_CODE();
  2005. DebugTrace(+1, Dbg, "FsRtlSplitLargeMcb, Mcb = %08lx\n", Mcb );
  2006. DebugTrace( 0, Dbg, " Vbn = %08lx\n", Vbn );
  2007. DebugTrace( 0, Dbg, " Amount = %08lx\n", Amount );
  2008. ASSERTMSG("LargeInteger not supported yet ", ((((PLARGE_INTEGER)&LargeVbn)->HighPart == 0) ||
  2009. (Mcb->PairCount == 0)));
  2010. ASSERTMSG("LargeInteger not supported yet ", ((((PLARGE_INTEGER)&LargeAmount)->HighPart == 0) ||
  2011. (Mcb->PairCount == 0)));
  2012. //
  2013. // First lookup the index for the entry that we are going to split.
  2014. // If we can't find the entry then there is nothing to split. This
  2015. // takes care of the case where the input vbn is beyond the last run
  2016. // in the mcb
  2017. //
  2018. if (!FsRtlFindLargeIndex( Mcb, Vbn, &Index)) {
  2019. try_return(Result = FALSE);
  2020. }
  2021. //
  2022. // Now check if the input Vbn is within a hole
  2023. //
  2024. if (StartingLbn(BaseMcb, Index) == UNUSED_LBN) {
  2025. //
  2026. // Before: --PreviousRun--||--IndexHole--||--FollowingRun--
  2027. // After: --PreviousRun--||----IndexHole----||--FollowingRun--
  2028. //
  2029. // In this case the vbn is somewhere within the hole and we
  2030. // simply need to added the amount of each existing run
  2031. // beyond the hole.
  2032. //
  2033. //
  2034. // In this case there is really nothing to do here because the
  2035. // ending code will already shift the runs by proper amount
  2036. // starting at index
  2037. //
  2038. NOTHING;
  2039. //
  2040. // Now check if the input vbn is between a hole and an existing run.
  2041. //
  2042. } else if ((StartingVbn(BaseMcb,Index) == Vbn) && (Index != 0) && (PreviousEndingLbn(BaseMcb,Index) == UNUSED_LBN)) {
  2043. //
  2044. // Before: --Hole--||--IndexRun--
  2045. // After: --Hole------||--IndexRun--
  2046. //
  2047. // In this case the vbn points to the start of the existing
  2048. // run and we need to do the split between the hole and the
  2049. // existing run by simply adding the amount to each existing
  2050. // run beyond the hole.
  2051. //
  2052. //
  2053. // In this case we need to decement the index by 1 and then
  2054. // fall to the bottom code which will do the shifting for us
  2055. //
  2056. Index -= 1;
  2057. //
  2058. // Now check if the input vbn is between two existing runs
  2059. //
  2060. } else if (StartingVbn(BaseMcb,Index) == Vbn) {
  2061. //
  2062. // Before: --PreviousRun--||--IndexRun--
  2063. // After: --PreviousRun--||--NewHole--||--IndexRun--
  2064. //
  2065. // Before: 0:|--IndexRun--
  2066. // After: 0:|--NewHole--||--IndexRun--
  2067. //
  2068. // In this case the vbn points to the start of an existing
  2069. // run and the preceeding is either a real run or the start
  2070. // of mapping pairs We simply add a new entry for the hole
  2071. // and shift succeeding runs.
  2072. //
  2073. FsRtlAddLargeEntry( Mcb, Index, 1 );
  2074. (BaseMcb->Mapping)[Index].Lbn = (LBN)UNUSED_LBN;
  2075. (BaseMcb->Mapping)[Index].NextVbn = Vbn + Amount;
  2076. Index += 1;
  2077. //
  2078. // Otherwise the input vbn is inside an existing run
  2079. //
  2080. } else {
  2081. //
  2082. // Before: --IndexRun--
  2083. // After: --SplitRun--||--NewHole--||--SplitRun--
  2084. //
  2085. // In this case the vbn points within an existing run
  2086. // we need to add two new extries for hole and split
  2087. // run and shift succeeding runs
  2088. //
  2089. FsRtlAddLargeEntry( Mcb, Index, 2 );
  2090. (BaseMcb->Mapping)[Index].Lbn = (BaseMcb->Mapping)[Index+2].Lbn;
  2091. (BaseMcb->Mapping)[Index].NextVbn = Vbn;
  2092. (BaseMcb->Mapping)[Index+1].Lbn = (LBN)UNUSED_LBN;
  2093. (BaseMcb->Mapping)[Index+1].NextVbn = Vbn + Amount;
  2094. (BaseMcb->Mapping)[Index+2].Lbn = (BaseMcb->Mapping)[Index+2].Lbn +
  2095. StartingVbn(BaseMcb, Index+1) -
  2096. StartingVbn(BaseMcb, Index);
  2097. Index += 2;
  2098. }
  2099. //
  2100. // At this point we have completed most of the work we now need to
  2101. // shift existing runs from the index to the end of the mappings
  2102. // by the specified amount
  2103. //
  2104. for (i = Index; i < BaseMcb->PairCount; i += 1) {
  2105. (BaseMcb->Mapping)[i].NextVbn += Amount;
  2106. }
  2107. Result = TRUE;
  2108. try_exit: NOTHING;
  2109. return Result;
  2110. }
  2111. BOOLEAN
  2112. FsRtlSplitLargeMcb (
  2113. IN PLARGE_MCB Mcb,
  2114. IN LONGLONG LargeVbn,
  2115. IN LONGLONG LargeAmount
  2116. )
  2117. /*++
  2118. Routine Description:
  2119. This routine is used to create a hole within an MCB, by shifting the
  2120. mapping of Vbns. All mappings above the input vbn are shifted by the
  2121. amount specified and while keeping their current lbn value. Pictorially
  2122. we have as input the following MCB
  2123. VBN : LargeVbn-1 LargeVbn N
  2124. +-----------------+------------------+
  2125. LBN : X Y
  2126. And after the split we have
  2127. VBN : LargeVbn-1 LargeVbn+Amount N+Amount
  2128. +-----------------+.............+---------------------------+
  2129. LBN : X UnusedLbn Y
  2130. When doing the split we have a few cases to consider. They are:
  2131. 1. The input Vbn is beyond the last run. In this case this operation
  2132. is a noop.
  2133. 2. The input Vbn is within or adjacent to a existing run of unused Lbns.
  2134. In this case we simply need to extend the size of the existing hole
  2135. and shift succeeding runs.
  2136. 3. The input Vbn is between two existing runs, including the an input vbn
  2137. value of zero. In this case we need to add a new entry for the hole
  2138. and shift succeeding runs.
  2139. 4. The input Vbn is within an existing run. In this case we need to add
  2140. two new entries to contain the split run and the hole.
  2141. If pool is not available to store the information this routine will raise a
  2142. status value indicating insufficient resources.
  2143. Arguments:
  2144. OpaqueMcb - Supplies the Mcb in which to add the new mapping.
  2145. Vbn - Supplies the starting Vbn that is to be shifted.
  2146. Amount - Supplies the amount to shift by.
  2147. Return Value:
  2148. BOOLEAN - TRUE if the mapping was successfully shifted, and FALSE otherwise.
  2149. If FALSE is returned then the Mcb is not changed.
  2150. --*/
  2151. {
  2152. BOOLEAN Result = FALSE;
  2153. PAGED_CODE();
  2154. ExAcquireFastMutex( Mcb->FastMutex );
  2155. try {
  2156. Result = FsRtlSplitBaseMcb( &Mcb->BaseMcb, LargeVbn, LargeAmount );
  2157. } finally {
  2158. ExReleaseFastMutex( Mcb->FastMutex );
  2159. DebugTrace(-1, Dbg, "FsRtlSplitLargeMcb -> %08lx\n", Result );
  2160. }
  2161. return Result;
  2162. }
  2163. //
  2164. // Private routine
  2165. //
  2166. BOOLEAN
  2167. FsRtlFindLargeIndex (
  2168. IN PBASE_MCB Mcb,
  2169. IN VBN Vbn,
  2170. OUT PULONG Index
  2171. )
  2172. /*++
  2173. Routine Description:
  2174. This is a private routine that locates a mapping for a Vbn
  2175. in a given mapping array
  2176. Arguments:
  2177. Mcb - Supplies the mapping array to examine
  2178. Vbn - Supplies the Vbn to look up
  2179. Index - Receives the index within the mapping array of the mapping
  2180. containing the Vbn. If none if found then the index is set to
  2181. PairCount.
  2182. Return Value:
  2183. BOOLEAN - TRUE if Vbn is found and FALSE otherwise
  2184. --*/
  2185. {
  2186. PNONOPAQUE_BASE_MCB BaseMcb = (PNONOPAQUE_BASE_MCB)Mcb;
  2187. LONG MinIndex;
  2188. LONG MaxIndex;
  2189. LONG MidIndex;
  2190. //
  2191. // We'll just do a binary search for the mapping entry. Min and max
  2192. // are our search boundaries
  2193. //
  2194. MinIndex = 0;
  2195. MaxIndex = BaseMcb->PairCount - 1;
  2196. while (MinIndex <= MaxIndex) {
  2197. //
  2198. // Compute the middle index to look at
  2199. //
  2200. MidIndex = ((MaxIndex + MinIndex) / 2);
  2201. //
  2202. // check if the Vbn is less than the mapping at the mid index
  2203. //
  2204. if (Vbn < StartingVbn(BaseMcb, MidIndex)) {
  2205. //
  2206. // Vbn is less than the middle index so we need to drop
  2207. // the max down
  2208. //
  2209. MaxIndex = MidIndex - 1;
  2210. //
  2211. // check if the Vbn is greater than the mapping at the mid index
  2212. //
  2213. } else if (Vbn > EndingVbn(BaseMcb, MidIndex)) {
  2214. //
  2215. // Vbn is greater than the middle index so we need to bring
  2216. // up the min
  2217. //
  2218. MinIndex = MidIndex + 1;
  2219. //
  2220. // Otherwise we've found the index containing the Vbn so set the
  2221. // index and return TRUE.
  2222. //
  2223. } else {
  2224. *Index = MidIndex;
  2225. return TRUE;
  2226. }
  2227. }
  2228. //
  2229. // A match wasn't found so set index to PairCount and return FALSE
  2230. //
  2231. *Index = BaseMcb->PairCount;
  2232. return FALSE;
  2233. }
  2234. //
  2235. // Private Routine
  2236. //
  2237. VOID
  2238. FsRtlAddLargeEntry (
  2239. IN PBASE_MCB Mcb,
  2240. IN ULONG WhereToAddIndex,
  2241. IN ULONG AmountToAdd
  2242. )
  2243. /*++
  2244. Routine Description:
  2245. This routine takes a current Mcb and detemines if there is enough
  2246. room to add the new mapping entries. If there is not enough room
  2247. it reallocates a new mcb buffer and copies over the current mapping.
  2248. If also will spread out the current mappings to leave the specified
  2249. index slots in the mapping unfilled. For example, if WhereToAddIndex
  2250. is equal to the current pair count then we don't need to make a hole
  2251. in the mapping, but if the index is less than the current pair count
  2252. then we'll need to slide some of the mappings down to make room
  2253. at the specified index.
  2254. Arguments:
  2255. Mcb - Supplies the mcb being checked and modified
  2256. WhereToAddIndex - Supplies the index of where the additional entries
  2257. need to be made
  2258. AmountToAdd - Supplies the number of additional entries needed in the
  2259. mcb
  2260. Return Value:
  2261. None.
  2262. --*/
  2263. {
  2264. PNONOPAQUE_BASE_MCB BaseMcb = (PNONOPAQUE_BASE_MCB)Mcb;
  2265. //
  2266. // Check to see if the current buffer is large enough to hold
  2267. // the additional entries
  2268. //
  2269. if (BaseMcb->PairCount + AmountToAdd > BaseMcb->MaximumPairCount) {
  2270. ULONG NewMax;
  2271. PMAPPING Mapping;
  2272. //
  2273. // We need to allocate a new mapping so compute a new maximum pair
  2274. // count. We'll only be asked to grow by at most 2 at a time, so
  2275. // doubling will definitely make us large enough for the new amount.
  2276. // But we won't double without bounds we'll stop doubling if the
  2277. // pair count gets too high.
  2278. //
  2279. if (BaseMcb->MaximumPairCount < 2048) {
  2280. NewMax = BaseMcb->MaximumPairCount * 2;
  2281. } else {
  2282. NewMax = BaseMcb->MaximumPairCount + 2048;
  2283. }
  2284. Mapping = FsRtlpAllocatePool( BaseMcb->PoolType, sizeof(MAPPING) * NewMax );
  2285. //**** RtlZeroMemory( Mapping, sizeof(MAPPING) * NewMax );
  2286. //
  2287. // Now copy over the old mapping to the new buffer
  2288. //
  2289. RtlCopyMemory( Mapping, BaseMcb->Mapping, sizeof(MAPPING) * BaseMcb->PairCount );
  2290. //
  2291. // Deallocate the old buffer
  2292. //
  2293. if ((BaseMcb->PoolType == PagedPool) && (BaseMcb->MaximumPairCount == INITIAL_MAXIMUM_PAIR_COUNT)) {
  2294. FsRtlFreeFirstMapping( BaseMcb->Mapping );
  2295. } else {
  2296. ExFreePool( BaseMcb->Mapping );
  2297. }
  2298. //
  2299. // And set up the new buffer in the Mcb
  2300. //
  2301. BaseMcb->Mapping = Mapping;
  2302. BaseMcb->MaximumPairCount = NewMax;
  2303. }
  2304. //
  2305. // Now see if we need to shift some entries over according to the
  2306. // WhereToAddIndex value
  2307. //
  2308. if (WhereToAddIndex < BaseMcb->PairCount) {
  2309. RtlMoveMemory( &((BaseMcb->Mapping)[WhereToAddIndex + AmountToAdd]),
  2310. &((BaseMcb->Mapping)[WhereToAddIndex]),
  2311. (BaseMcb->PairCount - WhereToAddIndex) * sizeof(MAPPING) );
  2312. }
  2313. //
  2314. // Now zero out the new additions
  2315. //
  2316. //**** RtlZeroMemory( &((Mcb->Mapping)[WhereToAddIndex]), sizeof(MAPPING) * AmountToAdd );
  2317. //
  2318. // Now increment the PairCount
  2319. //
  2320. BaseMcb->PairCount += AmountToAdd;
  2321. //
  2322. // And return to our caller
  2323. //
  2324. return;
  2325. }
  2326. //
  2327. // Private Routine
  2328. //
  2329. VOID
  2330. FsRtlRemoveLargeEntry (
  2331. IN PBASE_MCB Mcb,
  2332. IN ULONG WhereToRemoveIndex,
  2333. IN ULONG AmountToRemove
  2334. )
  2335. /*++
  2336. Routine Description:
  2337. This routine takes a current Mcb and removes one or more entries.
  2338. Arguments:
  2339. Mcb - Supplies the mcb being checked and modified
  2340. WhereToRemoveIndex - Supplies the index of the entries to remove
  2341. AmountToRemove - Supplies the number of entries to remove
  2342. Return Value:
  2343. None.
  2344. --*/
  2345. {
  2346. PNONOPAQUE_BASE_MCB BaseMcb = (PNONOPAQUE_BASE_MCB)Mcb;
  2347. //
  2348. // Check to see if we need to shift everything down because the
  2349. // entries to remove do not include the last entry in the mcb
  2350. //
  2351. if (WhereToRemoveIndex + AmountToRemove < BaseMcb->PairCount) {
  2352. RtlMoveMemory( &((BaseMcb->Mapping)[WhereToRemoveIndex]),
  2353. &((BaseMcb->Mapping)[WhereToRemoveIndex + AmountToRemove]),
  2354. (BaseMcb->PairCount - (WhereToRemoveIndex + AmountToRemove))
  2355. * sizeof(MAPPING) );
  2356. }
  2357. //
  2358. // Now zero out the entries beyond the part we just shifted down
  2359. //
  2360. //**** RtlZeroMemory( &((Mcb->Mapping)[Mcb->PairCount - AmountToRemove]), AmountToRemove * sizeof(MAPPING) );
  2361. //
  2362. // Now decrement the PairCount
  2363. //
  2364. BaseMcb->PairCount -= AmountToRemove;
  2365. //
  2366. // And return to our caller
  2367. //
  2368. return;
  2369. }