22#define BugCheckFileId (FAT_BUG_CHECK_ALLOCSUP)
28#define Dbg (DEBUG_TRACE_ALLOCSUP)
30#define FatMin(a, b) ((a) < (b) ? (a) : (b))
36#define FAT_PREFETCH_PAGE_COUNT 0x100
71#define ASSERT_CURRENT_WINDOW_GOOD(VCB) { \
72 ULONG FreeClusterBitMapClear; \
73 NT_ASSERT( (VCB)->FreeClusterBitMap.Buffer != NULL ); \
74 FreeClusterBitMapClear = RtlNumberOfClearBits(&(VCB)->FreeClusterBitMap); \
75 if ((VCB)->CurrentWindow->ClustersFree != FreeClusterBitMapClear) { \
76 KdPrint(("FAT: ClustersFree %x h != FreeClusterBitMapClear %x h\n", \
77 (VCB)->CurrentWindow->ClustersFree, \
78 FreeClusterBitMapClear)); \
80 NT_ASSERT( (VCB)->CurrentWindow->ClustersFree == FreeClusterBitMapClear ); \
83#define ASSERT_CURRENT_WINDOW_GOOD(VCB)
99#define FatLockFreeClusterBitMap(VCB) { \
100 NT_ASSERT(KeAreApcsDisabled()); \
101 ExAcquireFastMutexUnsafe( &(VCB)->FreeClusterBitMapMutex ); \
102 ASSERT_CURRENT_WINDOW_GOOD(VCB) \
112#define FatUnlockFreeClusterBitMap(VCB) { \
113 ASSERT_CURRENT_WINDOW_GOOD(VCB) \
114 NT_ASSERT(KeAreApcsDisabled()); \
115 ExReleaseFastMutexUnsafe( &(VCB)->FreeClusterBitMapMutex ); \
127#define FatIsClusterFree(IRPCONTEXT,VCB,FAT_INDEX) \
128 (RtlCheckBit(&(VCB)->FreeClusterBitMap,(FAT_INDEX)-2) == 0)
140#define FatFreeClusters(IRPCONTEXT,VCB,FAT_INDEX,CLUSTER_COUNT) { \
141 if ((CLUSTER_COUNT) == 1) { \
142 FatSetFatEntry((IRPCONTEXT),(VCB),(FAT_INDEX),FAT_CLUSTER_AVAILABLE); \
144 FatSetFatRun((IRPCONTEXT),(VCB),(FAT_INDEX),(CLUSTER_COUNT),FALSE); \
158#define FatAllocateClusters(IRPCONTEXT,VCB,FAT_INDEX,CLUSTER_COUNT) { \
159 if ((CLUSTER_COUNT) == 1) { \
160 FatSetFatEntry((IRPCONTEXT),(VCB),(FAT_INDEX),FAT_CLUSTER_LAST); \
162 FatSetFatRun((IRPCONTEXT),(VCB),(FAT_INDEX),(CLUSTER_COUNT),TRUE); \
176#define FatUnreserveClusters(IRPCONTEXT,VCB,FAT_INDEX,CLUSTER_COUNT) { \
177 NT_ASSERT( (FAT_INDEX) + (CLUSTER_COUNT) - 2 <= (VCB)->FreeClusterBitMap.SizeOfBitMap );\
178 NT_ASSERT( (FAT_INDEX) >= 2); \
179 RtlClearBits(&(VCB)->FreeClusterBitMap,(FAT_INDEX)-2,(CLUSTER_COUNT)); \
180 if ((FAT_INDEX) < (VCB)->ClusterHint) { \
181 (VCB)->ClusterHint = (FAT_INDEX); \
197#define FatReserveClusters(IRPCONTEXT,VCB,FAT_INDEX,CLUSTER_COUNT) { \
198 ULONG _AfterRun = (FAT_INDEX) + (CLUSTER_COUNT); \
199 NT_ASSERT( (FAT_INDEX) + (CLUSTER_COUNT) - 2 <= (VCB)->FreeClusterBitMap.SizeOfBitMap );\
200 NT_ASSERT( (FAT_INDEX) >= 2); \
201 RtlSetBits(&(VCB)->FreeClusterBitMap,(FAT_INDEX)-2,(CLUSTER_COUNT)); \
203 if (_AfterRun - 2 >= (VCB)->FreeClusterBitMap.SizeOfBitMap) { \
206 if (RtlCheckBit(&(VCB)->FreeClusterBitMap, _AfterRun - 2)) { \
207 (VCB)->ClusterHint = RtlFindClearBits( &(VCB)->FreeClusterBitMap, 1, _AfterRun - 2) + 2; \
208 if (1 == (VCB)->ClusterHint) { \
209 (VCB)->ClusterHint = 2; \
213 (VCB)->ClusterHint = _AfterRun; \
229#define FatFindFreeClusterRun(IRPCONTEXT,VCB,CLUSTER_COUNT,CLUSTER_HINT) ( \
230 (CLUSTER_COUNT == 1) && \
231 FatIsClusterFree((IRPCONTEXT), (VCB), (CLUSTER_HINT)) ? \
233 RtlFindClearBits( &(VCB)->FreeClusterBitMap, \
235 (CLUSTER_HINT) - 2) + 2 \
247#define MAX_CLUSTER_BITMAP_SIZE (1 << 16)
253#define FatWindowOfCluster(C) (((C) - 2) / MAX_CLUSTER_BITMAP_SIZE)
256#pragma alloc_text(PAGE, FatAddFileAllocation)
257#pragma alloc_text(PAGE, FatAllocateDiskSpace)
258#pragma alloc_text(PAGE, FatDeallocateDiskSpace)
259#pragma alloc_text(PAGE, FatExamineFatEntries)
260#pragma alloc_text(PAGE, FatInterpretClusterType)
261#pragma alloc_text(PAGE, FatLogOf)
262#pragma alloc_text(PAGE, FatLookupFatEntry)
263#pragma alloc_text(PAGE, FatLookupFileAllocation)
264#pragma alloc_text(PAGE, FatLookupFileAllocationSize)
265#pragma alloc_text(PAGE, FatMergeAllocation)
266#pragma alloc_text(PAGE, FatSetFatEntry)
267#pragma alloc_text(PAGE, FatSetFatRun)
268#pragma alloc_text(PAGE, FatSetupAllocationSupport)
269#pragma alloc_text(PAGE, FatSplitAllocation)
270#pragma alloc_text(PAGE, FatTearDownAllocationSupport)
271#pragma alloc_text(PAGE, FatTruncateFileAllocation)
309 for (
i = 0;
i <
Vcb->NumberOfWindows;
i++) {
311 if (
Vcb->Windows[
i].ClustersFree == ClustersPerWindow) {
313 if (-1 == FirstEmpty) {
322 else if (
Vcb->Windows[
i].ClustersFree > MaxFree) {
328 MaxFree =
Vcb->Windows[
i].ClustersFree;
336 if (MaxFree >= (ClustersPerWindow >> 1)) {
349 if ((MaxFree < (ClustersPerWindow >> 1)) && (-1 != FirstEmpty)) {
382 ULONG ClustersDescribableByFat;
402 Vcb->AllocationSupport.LogOfBytesPerSector =
FatLogOf(
Vcb->Bpb.BytesPerSector);
404 Vcb->AllocationSupport.NumberOfFreeClusters = 0;
415 ClustersDescribableByFat = ( ((
FatIsFat32(
Vcb)?
Vcb->Bpb.LargeSectorsPerFat :
416 Vcb->Bpb.SectorsPerFat) *
417 Vcb->Bpb.BytesPerSector * 8)
420 if (
Vcb->AllocationSupport.NumberOfClusters > ClustersDescribableByFat) {
422 Vcb->AllocationSupport.NumberOfClusters = ClustersDescribableByFat;
437 if (
Vcb->VirtualVolumeFile->PrivateCacheMap ==
NULL ) {
456 Vcb->NumberOfWindows = (
Vcb->AllocationSupport.NumberOfClusters +
462 Vcb->NumberOfWindows = 1;
477 if (
Vcb->NumberOfWindows > 1) {
486 Vcb->AllocationSupport.NumberOfClusters + 2 - 1,
500 Vcb->CurrentWindow = &
Vcb->Windows[0];
506 Vcb->CurrentWindow->FirstCluster = 2;
507 Vcb->CurrentWindow->LastCluster =
Vcb->AllocationSupport.NumberOfClusters + 2 - 1;
592 if (
Vcb->FreeClusterBitMap.Buffer !=
NULL ) {
600 Vcb->FreeClusterBitMap.Buffer =
NULL;
609 DebugTrace(-1,
Dbg,
"FatTearDownAllocationSupport -> (VOID)\n", 0);
619FatLookupFileAllocation (
665 VBO FirstVboOfCurrentRun = 0;
666 LBO FirstLboOfCurrentRun;
673 ULONG BytesPerCluster;
715 DebugTrace(-1,
Dbg,
"FatLookupFileAllocation -> (VOID)\n", 0);
725 BytesPerCluster = 1 <<
Vcb->AllocationSupport.LogOfBytesPerCluster;
730 FirstLboOfCurrentRun = 0;
743 DebugTrace(-1,
Dbg,
"FatLookupFileAllocation -> (VOID)\n", 0);
758 DebugTrace( 0,
Dbg,
"Current Mcb size = %8lx.\n", CurrentVbo + 1);
760 CurrentVbo -= (BytesPerCluster - 1);
761 CurrentLbo -= (BytesPerCluster - 1);
782 DebugTrace(-1,
Dbg,
"FatLookupFileAllocation -> (VOID)\n", 0);
789 FirstVboOfCurrentRun = CurrentVbo;
790 FirstLboOfCurrentRun = CurrentLbo;
794 DebugTrace( 0,
Dbg,
"First Lbo of file = %8lx\n", CurrentLbo);
819 NT_ASSERT( ((CurrentLbo -
Vcb->AllocationSupport.FileAreaLbo)
820 % BytesPerCluster == 0) &&
821 (CurrentVbo % BytesPerCluster == 0) );
829 while ( !LastCluster ) {
837 PriorLbo = CurrentLbo;
839 CurrentVbo += BytesPerCluster;
852 DebugTrace(-1,
Dbg,
"FatLookupFileAllocation -> Fat Corrupt. Raise Status.\n", 0);
854 FatPopUpFileCorrupt( IrpContext,
FcbOrDcb );
893 if (CurrentVbo == 0) {
901 if (FirstLboOfCurrentRun != 0 ) {
904 DebugTrace( 0,
Dbg,
" Vbo = %08lx.\n", FirstVboOfCurrentRun);
905 DebugTrace( 0,
Dbg,
" Lbo = %08lx.\n", FirstLboOfCurrentRun);
906 DebugTrace( 0,
Dbg,
" Length = %08lx.\n", CurrentVbo - FirstVboOfCurrentRun);
910 FirstVboOfCurrentRun,
911 FirstLboOfCurrentRun,
912 CurrentVbo - FirstVboOfCurrentRun );
938 DebugTrace( 0,
Dbg,
"New file allocation size = %08lx.\n", CurrentVbo);
970 if ( CurrentVbo == 0 ||
973 FatPopUpFileCorrupt( IrpContext,
FcbOrDcb );
977 if ( PriorLbo + BytesPerCluster != CurrentLbo ) {
986 if ( FirstLboOfCurrentRun != 0 ) {
989 DebugTrace( 0,
Dbg,
" Vbo = %08lx.\n", FirstVboOfCurrentRun);
990 DebugTrace( 0,
Dbg,
" Lbo = %08lx.\n", FirstLboOfCurrentRun);
991 DebugTrace( 0,
Dbg,
" Length = %08lx.\n", CurrentVbo - FirstVboOfCurrentRun);
995 FirstVboOfCurrentRun,
996 FirstLboOfCurrentRun,
997 CurrentVbo - FirstVboOfCurrentRun );
1010 if (CurrentVbo >
Vbo) {
1016 FirstVboOfCurrentRun = CurrentVbo;
1017 FirstLboOfCurrentRun = CurrentLbo;
1027#pragma prefast( suppress: 28159, "we bugcheck here because our internal data structures are seriously corrupted if this happens" )
1046 *
Lbo = FirstLboOfCurrentRun + (
Vbo - FirstVboOfCurrentRun);
1074 DebugTrace(-1,
Dbg,
"FatLookupFileAllocation -> (VOID)\n", 0);
1083FatAddFileAllocation (
1087 IN ULONG DesiredAllocationSize
1117 ULONG NewAllocation = 0;
1128 DebugTrace( 0,
Dbg,
" DesiredAllocationSize = %8lx\n", DesiredAllocationSize);
1138 FatLookupFileAllocationSize( IrpContext,
FcbOrDcb );
1146 if (DesiredAllocationSize <= FcbOrDcb->
Header.AllocationSize.LowPart) {
1148 DebugTrace(0,
Dbg,
"Desired size within current allocation.\n", 0);
1174 FatGetDirentFromFcbOrDcb( IrpContext,
1183 FatSetDirtyBcb( IrpContext,
Bcb,
Vcb,
TRUE );
1185 FatAllocateDiskSpace( IrpContext,
1188 &DesiredAllocationSize,
1192 UnwindWeAllocatedDiskSpace =
TRUE;
1207 DebugTrace( 0,
Dbg,
"First Lbo of file will be %08lx.\n", FirstLboOfFile );
1222 NewAllocation = DesiredAllocationSize;
1226 LBO LastAllocatedLbo;
1241 NewAllocation = DesiredAllocationSize -
FcbOrDcb->
Header.AllocationSize.LowPart;
1244 UnwindWeInitializedMcb =
TRUE;
1245 McbToCleanup = &NewMcb;
1247 FatAllocateDiskSpace( IrpContext,
1249 (LastAllocatedLbo != ~0 ?
1256 UnwindWeAllocatedDiskSpace =
TRUE;
1280 UnwindAllocationSizeSet =
TRUE;
1290 UnwindCacheManagerInformed =
TRUE;
1309 FatMergeAllocation( IrpContext,
1337 if (UnwindAllocationSizeSet) {
1342 if (UnwindCacheManagerInformed) {
1362 Dirent->FirstClusterOfFileHi = 0;
1380 if ( UnwindWeAllocatedDiskSpace ) {
1382 FatDeallocateDiskSpace( IrpContext,
Vcb, McbToCleanup,
FALSE );
1392 if (UnwindWeInitializedMcb ==
TRUE) {
1422 if (UnwindWeInitializedMcb ==
TRUE) {
1430FatTruncateFileAllocation (
1433 IN ULONG DesiredAllocationSize
1466 ULONG BytesPerCluster;
1470 ULONG UnwindInitialAllocationSize;
1471 ULONG UnwindInitialFirstClusterOfFile;
1480 DebugTrace( 0,
Dbg,
" DesiredAllocationSize = %8lx\n", DesiredAllocationSize);
1497 FatLookupFileAllocationSize( IrpContext,
FcbOrDcb );
1504 BytesPerCluster = 1 <<
Vcb->AllocationSupport.LogOfBytesPerCluster;
1511 if (DesiredAllocationSize != 0) {
1513 DesiredAllocationSize = (DesiredAllocationSize + (BytesPerCluster - 1)) &
1514 ~(BytesPerCluster - 1);
1522 if (DesiredAllocationSize == 0 ||
1523 DesiredAllocationSize >=
FcbOrDcb->
Header.AllocationSize.LowPart) {
1525 DebugTrace(0,
Dbg,
"Desired size within current allocation.\n", 0);
1527 DebugTrace(-1,
Dbg,
"FatTruncateFileAllocation -> (VOID)\n", 0);
1537 if (DesiredAllocationSize ==
FcbOrDcb->
Header.AllocationSize.LowPart) {
1539 DebugTrace(0,
Dbg,
"Desired size equals current allocation.\n", 0);
1540 DebugTrace(-1,
Dbg,
"FatTruncateFileAllocation -> (VOID)\n", 0);
1544 UnwindInitialAllocationSize =
FcbOrDcb->
Header.AllocationSize.LowPart;
1561 FcbOrDcb->
Header.AllocationSize.QuadPart = DesiredAllocationSize;
1567 if (DesiredAllocationSize == 0) {
1582 Dirent->FirstClusterOfFileHi = 0;
1587 FatSetDirtyBcb( IrpContext,
Bcb,
Vcb,
TRUE );
1588 UpdatedDirent =
TRUE;
1602 UnwindWeAllocatedMcb =
TRUE;
1604 FatSplitAllocation( IrpContext,
1607 DesiredAllocationSize,
1627 FcbOrDcb->
Header.AllocationSize.LowPart = UnwindInitialAllocationSize;
1629 if ( (DesiredAllocationSize == 0) && (
Dirent !=
NULL)) {
1631 if (UpdatedDirent) {
1651 Dirent->FirstClusterOfFileHi =
1652 (
USHORT)(UnwindInitialFirstClusterOfFile >> 16);
1659 if ( UnwindWeAllocatedMcb ) {
1678 DebugTrace(-1,
Dbg,
"FatTruncateFileAllocation -> (VOID)\n", 0);
1685FatLookupFileAllocationSize (
1717 FatLookupFileAllocation( IrpContext,
1734 FatPopUpFileCorrupt( IrpContext,
FcbOrDcb );
1738 DebugTrace(-1,
Dbg,
"FatLookupFileAllocationSize -> (VOID)\n", 0);
1745FatAllocateDiskSpace (
1808 UCHAR LogOfBytesPerCluster;
1809 ULONG BytesPerCluster;
1810 ULONG StartingCluster;
1812 ULONG WindowRelativeHint;
1814 ULONG PreviousClear = 0;
1849 LogOfBytesPerCluster =
Vcb->AllocationSupport.LogOfBytesPerCluster;
1850 BytesPerCluster = 1 << LogOfBytesPerCluster;
1853 & ~(BytesPerCluster - 1);
1863 ClusterCount = 1 << (32 - LogOfBytesPerCluster);
1867 ClusterCount = (*
ByteCount >> LogOfBytesPerCluster);
1884 if (ClusterCount <= Vcb->AllocationSupport.NumberOfFreeClusters) {
1886 Vcb->AllocationSupport.NumberOfFreeClusters -= ClusterCount;
1903 if (
Vcb->NumberOfWindows > 1) {
1914 if (AbsoluteClusterHint < Vcb->CurrentWindow->FirstCluster ||
1919 NT_ASSERT( BucketNum < Vcb->NumberOfWindows);
1973 Vcb->AllocationSupport.NumberOfFreeClusters += ClusterCount;
2008 WindowRelativeHint =
Vcb->ClusterHint;
2015 if (-1 == WindowRelativeHint) {
2017 WindowRelativeHint = 2;
2021 NT_ASSERT((WindowRelativeHint >= 2) && (WindowRelativeHint < Vcb->FreeClusterBitMap.SizeOfBitMap + 2));
2038 WindowRelativeHint );
2048 if ((StartingCluster != 1) &&
2062 Window->ClustersFree -= ClusterCount;
2064 StartingCluster +=
Window->FirstCluster;
2065 StartingCluster -= 2;
2113 StartingCluster -
Window->FirstCluster + 2,
2117 Window->ClustersFree += ClusterCount;
2118 Vcb->AllocationSupport.NumberOfFreeClusters += ClusterCount;
2136 ULONG CurrentVbo = 0;
2137 ULONG PriorLastCluster = 0;
2138 ULONG BytesFound = 0;
2140 ULONG ClustersFound = 0;
2141 ULONG ClustersRemaining = 0;
2155 LockedBitMap =
TRUE;
2178 ClustersRemaining = ClusterCount;
2180 PriorLastCluster = 0;
2182 while (ClustersRemaining != 0) {
2188 if ( !LockedBitMap ) {
2191 LockedBitMap =
TRUE;
2208 if (!SelectNextContigWindow) {
2210 if ( 0 != WindowRelativeHint) {
2212 ULONG Desired =
Vcb->FreeClusterBitMap.SizeOfBitMap - (WindowRelativeHint - 2);
2219 if (Desired > ClustersRemaining) {
2221 Desired = ClustersRemaining;
2225 WindowRelativeHint - 2,
2232 Index = WindowRelativeHint - 2;
2233 ClustersFound = Desired;
2244 SelectNextContigWindow =
TRUE;
2245 WindowRelativeHint = 2;
2254 WindowRelativeHint = 0;
2275 WindowRelativeHint = 0;
2279 if ((0 == WindowRelativeHint) && (0 == ClustersFound)) {
2281 if (ClustersRemaining <= Vcb->CurrentWindow->ClustersFree) {
2295 ClustersFound = ClustersRemaining;
2299 if (0 == ClustersFound) {
2311 if (ClustersFound >= ClustersRemaining) {
2313 ClustersFound = ClustersRemaining;
2322 if ( ((
Index + ClustersFound) ==
Vcb->FreeClusterBitMap.SizeOfBitMap) &&
2326 SelectNextContigWindow =
TRUE;
2327 WindowRelativeHint = 2;
2333 if (ClustersFound == 0) {
2335 ULONG FaveWindow = 0;
2343 if (1 ==
Vcb->NumberOfWindows) {
2346#pragma prefast( suppress: 28159, "we bugcheck here because our internal data structures are seriously corrupted if this happens" )
2356 SelectedWindow =
FALSE;
2358 if ( SelectNextContigWindow) {
2364 if ((NextWindow < Vcb->NumberOfWindows) &&
2365 (
Vcb->Windows[ NextWindow].ClustersFree > 0)
2368 FaveWindow = NextWindow;
2369 SelectedWindow =
TRUE;
2386 WindowRelativeHint = 0;
2389 SelectNextContigWindow =
FALSE;
2392 if (!SelectedWindow) {
2405 if (0 ==
Vcb->Windows[ FaveWindow].ClustersFree) {
2408#pragma prefast( suppress: 28159, "we bugcheck here because our internal data structures are seriously corrupted if this happens" )
2420 &
Vcb->Windows[FaveWindow],
2449 Window->ClustersFree -= ClustersFound;
2453 LockedBitMap =
FALSE;
2459 BytesFound = ClustersFound << LogOfBytesPerCluster;
2471 if (PriorLastCluster != 0) {
2473 FatSetFatEntry( IrpContext,
2489 CurrentVbo += BytesFound;
2490 ClustersRemaining -= ClustersFound;
2491 PriorLastCluster = Cluster + ClustersFound - 1;
2522 if (!LockedBitMap) {
2542 (Cluster -
Window->FirstCluster) + 2,
2552 Window->ClustersFree += ClustersFound;
2553 Vcb->AllocationSupport.NumberOfFreeClusters += ClustersFound;
2576 FatDeallocateDiskSpace( IrpContext,
Vcb,
Mcb,
FALSE );
2602#define MAX_ZERO_MDL_SIZE (1*1024*1024)
2606FatDeallocateDiskSpace (
2651 ULONG ClusterCount = 0;
2652 ULONG ClusterIndex = 0;
2655 UCHAR LogOfBytesPerCluster;
2667 LogOfBytesPerCluster =
Vcb->AllocationSupport.LogOfBytesPerCluster;
2671 if ( RunsInMcb == 0 ) {
2673 DebugTrace(-1,
Dbg,
"FatDeallocateDiskSpace -> (VOID)\n", 0);
2690 ULONG ByteCountToZero;
2691 ULONG MdlSizeMapped;
2701 for ( McbIndex = 0; McbIndex < RunsInMcb; McbIndex++ ) {
2751 while (ByteCountToZero != 0) {
2760 Vcb->TargetDeviceObject,
2767 if (IoIrp ==
NULL) {
2791 ZeroingStatus =
Iosb.Status;
2803 Lbo += MdlSizeMapped;
2809 ByteCountToZero -= MdlSizeMapped;
2811 if (ByteCountToZero < MdlSizeMapped) {
2812 MdlSizeMapped = ByteCountToZero;
2866 for ( McbIndex = 0; McbIndex < RunsInMcb; McbIndex++ ) {
2887 ClusterCount = (1 << (32 - LogOfBytesPerCluster));
2891 ClusterCount =
ByteCount >> LogOfBytesPerCluster;
2905 for ( McbIndex = 0; McbIndex < RunsInMcb; McbIndex++ ) {
2911 ULONG PreviousClear = 0;
2929 ClusterCount = (1 << (32 - LogOfBytesPerCluster));
2933 ClusterCount =
ByteCount >> LogOfBytesPerCluster;
2945 ClusterEnd = ClusterIndex + ClusterCount - 1;
2947 if (!(ClusterIndex >
Window->LastCluster ||
2948 ClusterEnd < Window->FirstCluster)) {
2955 if (ClusterIndex < Window->FirstCluster &&
2956 ClusterEnd >
Window->LastCluster) {
2958 MyStart =
Window->FirstCluster;
2959 MyLength =
Window->LastCluster -
Window->FirstCluster + 1;
2961 }
else if (ClusterIndex < Window->FirstCluster) {
2963 MyStart =
Window->FirstCluster;
2964 MyLength = ClusterEnd -
Window->FirstCluster + 1;
2973 MyStart = ClusterIndex;
2975 if (ClusterEnd <= Window->LastCluster) {
2977 MyLength = ClusterCount;
2981 MyLength =
Window->LastCluster - ClusterIndex + 1;
2985 if (MyLength == 0) {
2993#pragma prefast( suppress:28931, "this is DBG build only" )
3003 NT_ASSERT( MyStart + MyLength -
Window->FirstCluster <=
Vcb->FreeClusterBitMap.SizeOfBitMap );
3005 for (
i = 0;
i < MyLength;
i++) {
3008 MyStart -
Window->FirstCluster +
i) == 1 );
3013 MyStart -
Window->FirstCluster + 2,
3031 MyStart = ClusterIndex;
3033 for (MyLength = ClusterCount; MyLength > 0; MyLength -=
count) {
3043 if (MyLength !=
count) {
3046 MyStart =
Window->FirstCluster;
3054 Vcb->AllocationSupport.NumberOfFreeClusters += ClusterCount;
3058 if (
Vcb->CurrentWindow->ClustersFree !=
3061 DbgPrint(
"%x vs %x\n",
Vcb->CurrentWindow->ClustersFree,
3064 DbgPrint(
"%x for %x\n", ClusterIndex, ClusterCount);
3089 ULONG PriorLastIndex;
3116 Clusters = (1 << (32 - LogOfBytesPerCluster));
3120 Clusters =
ByteCount >> LogOfBytesPerCluster;
3130 if (PriorLastIndex != 0) {
3132 FatSetFatEntry( IrpContext,
3143 if (
Index < McbIndex ) {
3147 PriorLastIndex =
FatIndex + Clusters - 1;
3152 DebugTrace(-1,
Dbg,
"FatDeallocateDiskSpace -> (VOID)\n", 0);
3229 ULONG BytesPerCluster;
3241 BytesPerCluster = 1 <<
Vcb->AllocationSupport.LogOfBytesPerCluster;
3294 if (SourceVbo == 0) {
3308 FatSetFatEntry( IrpContext,
3422 TargetVbo = SpliceVbo + 1;
3438 FatSetFatEntry( IrpContext,
3455 if ((CutLength = TargetVbo - (SpliceVbo + 1)) != 0) {
3506 switch(
Vcb->AllocationSupport.FatIndexBitSize ) {
3513 if (
Entry >= 0x0ff0) {
3514 Entry |= 0x0FFFF000;
3521 if (
Entry >= 0x0fff0) {
3522 Entry |= 0x0FFF0000;
3529 DebugTrace(-1,
Dbg,
"FatInterpretClusterType -> FatClusterAvailable\n", 0);
3535 DebugTrace(-1,
Dbg,
"FatInterpretClusterType -> FatClusterNext\n", 0);
3541 DebugTrace(-1,
Dbg,
"FatInterpretClusterType -> FatClusterReserved\n", 0);
3547 DebugTrace(-1,
Dbg,
"FatInterpretClusterType -> FatClusterBad\n", 0);
3553 DebugTrace(-1,
Dbg,
"FatInterpretClusterType -> FatClusterLast\n", 0);
3628 if (
Vcb->AllocationSupport.FatIndexBitSize == 12) {
3651 }
else if (
Vcb->AllocationSupport.FatIndexBitSize == 32) {
3657 ULONG PageEntryOffset;
3658 ULONG OffsetIntoVolumeFile;
3682 OffsetIntoVolumeFile & ~(
PAGE_SIZE - 1),
3702 ULONG PageEntryOffset;
3703 ULONG OffsetIntoVolumeFile;
3710 PageEntryOffset = (OffsetIntoVolumeFile %
PAGE_SIZE) /
sizeof(
USHORT);
3728 OffsetIntoVolumeFile & ~(
PAGE_SIZE - 1),
3801 ULONG OffsetIntoVolumeFile;
3834 RegularOperation =
FALSE;
3839 CleaningOperation =
TRUE;
3843 switch (
Vcb->AllocationSupport.FatIndexBitSize) {
3881 SectorSize = 1 <<
Vcb->AllocationSupport.LogOfBytesPerSector;
3901 if (
Vcb->AllocationSupport.FatIndexBitSize == 12) {
3918 FatPrepareWriteVolumeFile( IrpContext,
3970 }
else if (
Vcb->AllocationSupport.FatIndexBitSize == 32) {
3985 FatPrepareWriteVolumeFile( IrpContext,
3987 OffsetIntoVolumeFile,
3990 (
PVOID *)&PinnedFatEntry32,
4014 *PinnedFatEntry32 = ((*PinnedFatEntry32 & ~FAT32_ENTRY_MASK) |
FatEntry);
4041 FatPrepareWriteVolumeFile( IrpContext,
4043 OffsetIntoVolumeFile,
4046 (
PVOID *)&PinnedFatEntry,
4111 if ((CleaningOperation ||
4119 DbgDoit( IrpContext->PinCount -= 1 );
4176#define MAXCOUNTCLUS 0x10000
4177#define COUNTSAVEDBCBS ((MAXCOUNTCLUS * sizeof(FAT_ENTRY) / PAGE_SIZE) + 2)
4191 ULONG SavedStartingFatIndex = StartingFatIndex;
4197 DebugTrace( 0,
Dbg,
" StartingFatIndex = %8x\n", StartingFatIndex);
4198 DebugTrace( 0,
Dbg,
" ClusterCount = %8lx\n", ClusterCount);
4199 DebugTrace( 0,
Dbg,
" ChainTogether = %s\n", ChainTogether ?
"TRUE":
"FALSE");
4212 if (ClusterCount == 0) {
4222 SectorSize = 1 <<
Vcb->AllocationSupport.LogOfBytesPerSector;
4241 if (
Vcb->AllocationSupport.FatIndexBitSize == 12) {
4250 FatPrepareWriteVolumeFile( IrpContext,
4272 ClusterCount) * 3 + 2) / 2) & ~(
SectorSize - 1);
4288 for (Cluster = StartingFatIndex;
4289 Cluster < StartingFatIndex + ClusterCount - 1;
4309 }
else if (
Vcb->AllocationSupport.FatIndexBitSize == 32) {
4317 VBO StartOffsetInVolume;
4318 VBO FinalOffsetInVolume;
4323 ULONG ClusterCountThisRun;
4331 ClusterCountThisRun = ClusterCount;
4334 FinalOffsetInVolume = StartOffsetInVolume +
4335 (ClusterCountThisRun - 1) *
sizeof(
FAT_ENTRY);
4338 ULONG NumberOfPages;
4341 NumberOfPages = (FinalOffsetInVolume /
PAGE_SIZE) -
4347 Page < NumberOfPages;
4350 FatPrepareWriteVolumeFile( IrpContext,
4354 &SavedBcbs[
Page][0],
4371 StartSectorLbo = StartOffsetInVolume & ~(
SectorSize - 1);
4372 FinalSectorLbo = FinalOffsetInVolume & ~(
SectorSize - 1);
4391 FinalCluster = StartingFatIndex + ClusterCountThisRun - 1;
4394 for (Cluster = StartingFatIndex;
4395 Cluster <= FinalCluster;
4403 (Cluster != StartingFatIndex) ) {
4438 SavedBcbs[
i][0] =
NULL;
4459 VBO StartOffsetInVolume;
4460 VBO FinalOffsetInVolume;
4467 StartingFatIndex *
sizeof(
USHORT);
4469 FinalOffsetInVolume = StartOffsetInVolume +
4470 (ClusterCount - 1) *
sizeof(
USHORT);
4484 ULONG NumberOfPages;
4487 NumberOfPages = (FinalOffsetInVolume /
PAGE_SIZE) -
4493 Page < NumberOfPages;
4496 FatPrepareWriteVolumeFile( IrpContext,
4500 &SavedBcbs[
Page][0],
4517 StartSectorLbo = StartOffsetInVolume & ~(
SectorSize - 1);
4518 FinalSectorLbo = FinalOffsetInVolume & ~(
SectorSize - 1);
4537 FinalCluster = StartingFatIndex + ClusterCount - 1;
4540 for (Cluster = StartingFatIndex;
4541 Cluster <= FinalCluster;
4549 (Cluster != StartingFatIndex) ) {
4563 if ( ChainTogether ) {
4566#pragma warning( suppress: 4310 )
4609 (
Vcb->AllocationSupport.FatIndexBitSize == 32) ) {
4633 while ( StartingFatIndex > SavedStartingFatIndex ) {
4637 FatSetFatEntry( IrpContext,
Vcb, StartingFatIndex,
4689 while ( (
Value & 0xfffffffe) != 0 ) {
4710#pragma prefast( suppress: 28159, "we bugcheck here because our internal data structures are seriously corrupted if this happens" )
4780 ULONG EntriesPerWindow;
4782 ULONG ClustersThisRun;
4783 ULONG StartIndexOfThisRun;
4794 ULONG PrefetchPages = 0;
4797 VBO BadClusterVbo = 0;
4814 NT_ASSERT( !(SetupWindows && (SwitchToWindow || BitMapBuffer)));
4817 if (
Vcb->NumberOfWindows > 1) {
4829 EntriesPerWindow =
Vcb->AllocationSupport.NumberOfClusters;
4838 FreeClusterCount = &
Vcb->AllocationSupport.NumberOfFreeClusters;
4855 CurrentWindow = &
Vcb->Windows[0];
4864 }
else if (BitMapBuffer ==
NULL) {
4878 CurrentWindow = SwitchToWindow;
4882 BitMap = &PrivateBitMap;
4884 (EntriesPerWindow + 7) / 8,
4889 EndIndex - StartIndex + 1);
4892 (
Vcb->NumberOfWindows > 1)) {
4898 FreeClusterCount =
NULL;
4904 BitMap = &PrivateBitMap;
4907 EndIndex - StartIndex + 1);
4913 FreeClusterCount =
NULL;
4939 (
PVOID *)&FatBuffer );
4961 PrefetchPages = FatPages -
Page;
4968#if (NTDDI_VERSION >= NTDDI_WIN8)
4970 Vcb->VirtualVolumeFile,
4988 FirstFatEntry = *((
PULONG)FatBuffer);
4996 FirstFatEntry = *FatBuffer;
5001 ClusterSize = 1 << (
Vcb->AllocationSupport.LogOfBytesPerCluster);
5006 StartIndexOfThisRun = StartIndex;
5023 (
FatIndex - 2) % EntriesPerWindow == 0) {
5036 ClustersThisRun =
FatIndex - StartIndexOfThisRun;
5039 if (FreeClusterCount) {
5040 *FreeClusterCount += ClustersThisRun;
5045 NT_ASSERT(CurrentRun == AllocatedClusters);
5050 CurrentRun = UnknownClusters;
5068#if (NTDDI_VERSION >= NTDDI_WIN8)
5073 if (--PrefetchPages == 0) {
5075 PrefetchPages = FatPages -
Page;
5083 Vcb->VirtualVolumeFile,
5103#pragma warning( suppress: 4213 )
5120 if (CurrentRun == UnknownClusters) {
5133 ClustersThisRun =
FatIndex - StartIndexOfThisRun;
5135 if (FreeClusterCount) {
5137 *FreeClusterCount += ClustersThisRun;
5144 StartIndexOfThisRun - StartIndex,
5148 CurrentRun = AllocatedClusters;
5156 if (CurrentRun == AllocatedClusters &&
5159 ClustersThisRun =
FatIndex - StartIndexOfThisRun;
5164 StartIndexOfThisRun - StartIndex,
5176 if ((SetupWindows || (
Vcb->NumberOfWindows == 1)) &&
5200 ClustersThisRun =
FatIndex - StartIndexOfThisRun;
5204 if (FreeClusterCount) {
5206 *FreeClusterCount += ClustersThisRun;
5213 StartIndexOfThisRun - StartIndex,
5222 StartIndexOfThisRun - StartIndex,
5244 if (SwitchToWindow) {
5246 if (
Vcb->FreeClusterBitMap.Buffer) {
5253 EndIndex - StartIndex + 1 );
5255 NewBitMapBuffer =
NULL;
5257 Vcb->CurrentWindow = SwitchToWindow;
5260 if (FreeClusterCount) {
5264 Vcb->CurrentWindow->ClustersFree = *FreeClusterCount;
5272 if (!SetupWindows && BitMapBuffer ==
NULL) {
5277 NT_ASSERT(
Vcb->AllocationSupport.NumberOfFreeClusters <=
Vcb->AllocationSupport.NumberOfClusters);
5287 if (NewBitMapBuffer) {
static CC_FILE_SIZES FileSizes
#define ALIGN_UP_BY(size, align)
VOID NTAPI CcUnpinRepinnedBcb(IN PVOID Bcb, IN BOOLEAN WriteThrough, OUT PIO_STATUS_BLOCK IoStatus)
VOID NTAPI CcRepinBcb(IN PVOID Bcb)
#define CcIsFileCached(FO)
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT _Inout_ PDIRENT Dirent
#define IRP_CONTEXT_FLAG_WAIT
#define _Requires_lock_held_(lock)
#define RtlInitializeBitMap
#define RtlFindLongestRunClear
#define RtlNumberOfClearBits
#define NT_SUCCESS(StatCode)
#define FatNumberOfClusters(B)
#define FatGetIndexFromLbo(VCB, LBO)
#define FatRootDirectoryLbo(B)
#define FatFileAreaLbo(B)
#define FAT12_DIRTY_ENTRY
#define FatVerifyIndexIsValid(IC, V, I)
#define FAT32_DIRTY_ENTRY
#define FatReservedBytes(B)
#define FatLookup12BitEntry(FAT, INDEX, ENTRY)
#define FAT16_DIRTY_ENTRY
#define FatIndexBitSize(B)
#define FatBytesPerCluster(B)
#define FatSet12BitEntry(FAT, INDEX, ENTRY)
#define FAT_CLUSTER_AVAILABLE
#define FatBytesPerFat(B)
#define FatGetLboFromIndex(VCB, FAT_INDEX)
#define FatRootDirectorySize(B)
#define FAT_DIRTY_BIT_INDEX
#define FAT_CLUSTER_RESERVED
#define FatBugCheck(A, B, C)
NTSTATUS FreeClusters(PNTFS_VCB Vcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, ULONG ClustersToFree)
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
#define KeInitializeEvent(pEvt, foo, foo2)
#define ExAcquireResourceExclusiveLite(res, wait)
#define ExAcquireResourceSharedLite(res, wait)
VOID NTAPI KeClearEvent(IN PKEVENT Event)
#define ClearFlag(_F, _SF)
#define BooleanFlagOn(F, SF)
#define FatWindowOfCluster(C)
#define FatReserveClusters(IRPCONTEXT, VCB, FAT_INDEX, CLUSTER_COUNT)
VOID FatExamineFatEntries(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN ULONG StartIndex OPTIONAL, IN ULONG EndIndex OPTIONAL, IN BOOLEAN SetupWindows, IN PFAT_WINDOW SwitchToWindow OPTIONAL, IN PULONG BitMapBuffer OPTIONAL)
#define FatLockFreeClusterBitMap(VCB)
CLUSTER_TYPE FatInterpretClusterType(IN PVCB Vcb, IN FAT_ENTRY Entry)
#define MAX_CLUSTER_BITMAP_SIZE
#define FatUnreserveClusters(IRPCONTEXT, VCB, FAT_INDEX, CLUSTER_COUNT)
VOID FatSetFatRun(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN ULONG StartingFatIndex, IN ULONG ClusterCount, IN BOOLEAN ChainTogether)
#define FatFindFreeClusterRun(IRPCONTEXT, VCB, CLUSTER_COUNT, CLUSTER_HINT)
INLINE ULONG FatSelectBestWindow(IN PVCB Vcb)
UCHAR FatLogOf(IN ULONG Value)
#define FatUnlockFreeClusterBitMap(VCB)
VOID FatTearDownAllocationSupport(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
#define MAX_ZERO_MDL_SIZE
VOID FatLookupFatEntry(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN ULONG FatIndex, IN OUT PULONG FatEntry, IN OUT PFAT_ENUMERATION_CONTEXT Context)
#define FAT_PREFETCH_PAGE_COUNT
#define FatAllocateClusters(IRPCONTEXT, VCB, FAT_INDEX, CLUSTER_COUNT)
VOID FatSetupAllocationSupport(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
#define FatFreeClusters(IRPCONTEXT, VCB, FAT_INDEX, CLUSTER_COUNT)
#define ASSERT_CURRENT_WINDOW_GOOD(VCB)
VOID FatInitializeCacheMap(_In_ PFILE_OBJECT FileObject, _In_ PCC_FILE_SIZES FileSizes, _In_ BOOLEAN PinAccess, _In_ PCACHE_MANAGER_CALLBACKS Callbacks, _In_ PVOID LazyWriteContext)
VOID FatReadVolumeFile(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN VBO StartingVbo, IN ULONG ByteCount, OUT PBCB *Bcb, OUT PVOID *Buffer)
NTSTATUS FatPrefetchPages(IN PIRP_CONTEXT IrpContext, IN PFILE_OBJECT FileObject, IN ULONG StartingPage, IN ULONG PageCount)
PMDL FatBuildZeroMdl(__in PIRP_CONTEXT IrpContext, __in ULONG Length)
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
LARGE_INTEGER FatMaxLarge
#define DebugTrace(INDENT, LEVEL, X, Y)
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN ExactMatchRequired
IN PVCB IN VBO IN ULONG OUT PBCB * Bcb
#define FatUnpinBcb(IRPCONTEXT, BCB)
IN PVCB IN ULONG AbsoluteClusterHint
IN PVCB IN OUT PLARGE_MCB IN VBO OUT PLARGE_MCB RemainingMcb
BOOLEAN FatLookupMcbEntry(IN PVCB Vcb, IN PLARGE_MCB Mcb, IN VBO Vbo, OUT PLBO Lbo, OUT PULONG ByteCount OPTIONAL, OUT PULONG Index OPTIONAL)
IN PFCB IN VBO OUT PLBO Lbo
BOOLEAN FatGetNextMcbEntry(IN PVCB Vcb, IN PLARGE_MCB Mcb, IN ULONG RunIndex, OUT PVBO Vbo, OUT PLBO Lbo, OUT PULONG ByteCount)
VOID FatRemoveMcbEntry(IN PVCB Vcb, IN PLARGE_MCB Mcb, IN VBO Vbo, IN ULONG SectorCount)
IN PVCB IN OUT PLARGE_MCB IN VBO SplitAtVbo
BOOLEAN FatAddMcbEntry(IN PVCB Vcb, IN PLARGE_MCB Mcb, IN VBO Vbo, IN LBO Lbo, IN ULONG SectorCount)
IN PFCB IN VBO OUT PLBO OUT PULONG OUT PBOOLEAN OUT PBOOLEAN EndOnMax
#define FatRaiseStatus(IRPCONTEXT, STATUS)
IN PFCB IN VBO OUT PLBO OUT PULONG OUT PBOOLEAN Allocated
IN PVCB IN ULONG FatIndex
IN PVCB IN ULONG IN FAT_ENTRY FatEntry
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
IN PVCB IN OUT PLARGE_MCB IN PLARGE_MCB SecondMcb
BOOLEAN FatLookupLastMcbEntry(IN PVCB Vcb, IN PLARGE_MCB Mcb, OUT PVBO Vbo, OUT PLBO Lbo, OUT PULONG Index OPTIONAL)
IN PVCB IN PLARGE_MCB IN BOOLEAN ZeroOnDeallocate
#define FCB_STATE_FLUSH_FAT
#define VCB_STATE_FLAG_BAD_BLOCKS_POPULATED
#define FCB_STATE_ZERO_ON_DEALLOCATION
#define VCB_STATE_FLAG_MOUNT_IN_PROGRESS
enum _CLUSTER_TYPE CLUSTER_TYPE
#define FCB_LOOKUP_ALLOCATIONSIZE_HINT
#define IRP_CONTEXT_FLAG_DISABLE_DIRTY
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSi