📄 allocsup.c
字号:
/*++
Copyright (c) 1990-2000 Microsoft Corporation
Module Name:
AllocSup.c
Abstract:
This module implements the Allocation support routines for Fat.
--*/
#include "FatProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (FAT_BUG_CHECK_ALLOCSUP)
//
// Local debug trace level
//
#define Dbg (DEBUG_TRACE_ALLOCSUP)
#define FatMin(a, b) ((a) < (b) ? (a) : (b))
//
// This strucure is used by FatLookupFatEntry to remember a pinned page
// of fat.
//
typedef struct _FAT_ENUMERATION_CONTEXT {
VBO VboOfPinnedPage;
PBCB Bcb;
PVOID PinnedPage;
} FAT_ENUMERATION_CONTEXT, *PFAT_ENUMERATION_CONTEXT;
//
// Local support routine prototypes
//
VOID
FatLookupFatEntry(
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN ULONG FatIndex,
IN OUT PULONG FatEntry,
IN OUT PFAT_ENUMERATION_CONTEXT Context
);
VOID
FatSetFatRun(
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN ULONG StartingFatIndex,
IN ULONG ClusterCount,
IN BOOLEAN ChainTogether
);
UCHAR
FatLogOf(
IN ULONG Value
);
//
// Note that the KdPrint below will ONLY fire when the assert does. Leave it
// alone.
//
#if DBG
#define ASSERT_CURRENT_WINDOW_GOOD(VCB) { \
ULONG FreeClusterBitMapClear; \
ASSERT( (VCB)->FreeClusterBitMap.Buffer != NULL ); \
FreeClusterBitMapClear = RtlNumberOfClearBits(&(VCB)->FreeClusterBitMap); \
if ((VCB)->CurrentWindow->ClustersFree != FreeClusterBitMapClear) { \
KdPrint(("FAT: ClustersFree %x h != FreeClusterBitMapClear %x h\n", \
(VCB)->CurrentWindow->ClustersFree, \
FreeClusterBitMapClear)); \
} \
ASSERT( (VCB)->CurrentWindow->ClustersFree == FreeClusterBitMapClear ); \
}
#else
#define ASSERT_CURRENT_WINDOW_GOOD(VCB)
#endif
//
// The following macros provide a convenient way of hiding the details
// of bitmap allocation schemes.
//
//
// VOID
// FatLockFreeClusterBitMap (
// IN PVCB Vcb
// );
//
#define FatLockFreeClusterBitMap(VCB) { \
ASSERT(KeAreApcsDisabled()); \
ExAcquireFastMutexUnsafe( &(VCB)->FreeClusterBitMapMutex ); \
ASSERT_CURRENT_WINDOW_GOOD(VCB) \
}
//
// VOID
// FatUnlockFreeClusterBitMap (
// IN PVCB Vcb
// );
//
#define FatUnlockFreeClusterBitMap(VCB) { \
ASSERT_CURRENT_WINDOW_GOOD(VCB) \
ASSERT(KeAreApcsDisabled()); \
ExReleaseFastMutexUnsafe( &(VCB)->FreeClusterBitMapMutex ); \
}
//
// BOOLEAN
// FatIsClusterFree (
// IN PIRP_CONTEXT IrpContext,
// IN PVCB Vcb,
// IN ULONG FatIndex
// );
//
#define FatIsClusterFree(IRPCONTEXT,VCB,FAT_INDEX) \
(RtlCheckBit(&(VCB)->FreeClusterBitMap,(FAT_INDEX)-2) == 0)
//
// VOID
// FatFreeClusters (
// IN PIRP_CONTEXT IrpContext,
// IN PVCB Vcb,
// IN ULONG FatIndex,
// IN ULONG ClusterCount
// );
//
#define FatFreeClusters(IRPCONTEXT,VCB,FAT_INDEX,CLUSTER_COUNT) { \
if ((CLUSTER_COUNT) == 1) { \
FatSetFatEntry((IRPCONTEXT),(VCB),(FAT_INDEX),FAT_CLUSTER_AVAILABLE); \
} else { \
FatSetFatRun((IRPCONTEXT),(VCB),(FAT_INDEX),(CLUSTER_COUNT),FALSE); \
} \
}
//
// VOID
// FatAllocateClusters (
// IN PIRP_CONTEXT IrpContext,
// IN PVCB Vcb,
// IN ULONG FatIndex,
// IN ULONG ClusterCount
// );
//
#define FatAllocateClusters(IRPCONTEXT,VCB,FAT_INDEX,CLUSTER_COUNT) { \
if ((CLUSTER_COUNT) == 1) { \
FatSetFatEntry((IRPCONTEXT),(VCB),(FAT_INDEX),FAT_CLUSTER_LAST); \
} else { \
FatSetFatRun((IRPCONTEXT),(VCB),(FAT_INDEX),(CLUSTER_COUNT),TRUE); \
} \
}
//
// VOID
// FatUnreserveClusters (
// IN PIRP_CONTEXT IrpContext,
// IN PVCB Vcb,
// IN ULONG FatIndex,
// IN ULONG ClusterCount
// );
//
#define FatUnreserveClusters(IRPCONTEXT,VCB,FAT_INDEX,CLUSTER_COUNT) { \
ASSERT( (FAT_INDEX) + (CLUSTER_COUNT) - 2 <= (VCB)->FreeClusterBitMap.SizeOfBitMap ); \
ASSERT( (FAT_INDEX) >= 2); \
RtlClearBits(&(VCB)->FreeClusterBitMap,(FAT_INDEX)-2,(CLUSTER_COUNT)); \
if ((FAT_INDEX) < (VCB)->ClusterHint) { \
(VCB)->ClusterHint = (FAT_INDEX); \
} \
}
//
// VOID
// FatReserveClusters (
// IN PIRP_CONTEXT IrpContext,
// IN PVCB Vcb,
// IN ULONG FatIndex,
// IN ULONG ClusterCount
// );
//
// Handle wrapping the hint back to the front.
//
#define FatReserveClusters(IRPCONTEXT,VCB,FAT_INDEX,CLUSTER_COUNT) { \
ULONG _AfterRun = (FAT_INDEX) + (CLUSTER_COUNT); \
ASSERT( (FAT_INDEX) + (CLUSTER_COUNT) - 2 <= (VCB)->FreeClusterBitMap.SizeOfBitMap ); \
ASSERT( (FAT_INDEX) >= 2); \
RtlSetBits(&(VCB)->FreeClusterBitMap,(FAT_INDEX)-2,(CLUSTER_COUNT)); \
\
if (_AfterRun - 2 >= (VCB)->FreeClusterBitMap.SizeOfBitMap) { \
_AfterRun = 2; \
} \
if (RtlCheckBit(&(VCB)->FreeClusterBitMap, _AfterRun - 2)) { \
(VCB)->ClusterHint = RtlFindClearBits( &(VCB)->FreeClusterBitMap, 1, _AfterRun - 2) + 2; \
if (1 == (VCB)->ClusterHint) { \
(VCB)->ClusterHint = 2; \
} \
} \
else { \
(VCB)->ClusterHint = _AfterRun; \
} \
}
//
// ULONG
// FatFindFreeClusterRun (
// IN PIRP_CONTEXT IrpContext,
// IN PVCB Vcb,
// IN ULONG ClusterCount,
// IN ULONG AlternateClusterHint
// );
//
// Do a special check if only one cluster is desired.
//
#define FatFindFreeClusterRun(IRPCONTEXT,VCB,CLUSTER_COUNT,CLUSTER_HINT) ( \
(CLUSTER_COUNT == 1) && \
FatIsClusterFree((IRPCONTEXT), (VCB), (CLUSTER_HINT)) ? \
(CLUSTER_HINT) : \
RtlFindClearBits( &(VCB)->FreeClusterBitMap, \
(CLUSTER_COUNT), \
(CLUSTER_HINT) - 2) + 2 \
)
//
// FAT32: Define the maximum size of the FreeClusterBitMap to be the
// maximum size of a FAT16 FAT. If there are more clusters on the
// volume than can be represented by this many bytes of bitmap, the
// FAT will be split into "buckets", each of which does fit.
//
// Note this count is in clusters/bits of bitmap.
//
#define MAX_CLUSTER_BITMAP_SIZE (1 << 16)
//
// Calculate the window a given cluster number is in.
//
#define FatWindowOfCluster(C) (((C) - 2) / MAX_CLUSTER_BITMAP_SIZE)
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FatAddFileAllocation)
#pragma alloc_text(PAGE, FatAllocateDiskSpace)
#pragma alloc_text(PAGE, FatDeallocateDiskSpace)
#pragma alloc_text(PAGE, FatExamineFatEntries)
#pragma alloc_text(PAGE, FatInterpretClusterType)
#pragma alloc_text(PAGE, FatLogOf)
#pragma alloc_text(PAGE, FatLookupFatEntry)
#pragma alloc_text(PAGE, FatLookupFileAllocation)
#pragma alloc_text(PAGE, FatLookupFileAllocationSize)
#pragma alloc_text(PAGE, FatMergeAllocation)
#pragma alloc_text(PAGE, FatSetFatEntry)
#pragma alloc_text(PAGE, FatSetFatRun)
#pragma alloc_text(PAGE, FatSetupAllocationSupport)
#pragma alloc_text(PAGE, FatSplitAllocation)
#pragma alloc_text(PAGE, FatTearDownAllocationSupport)
#pragma alloc_text(PAGE, FatTruncateFileAllocation)
#endif
INLINE
ULONG
FatSelectBestWindow(
IN PVCB Vcb
)
/*++
Routine Description:
Choose a window to allocate clusters from. Order of preference is:
1. First window with >50% free clusters
2. First empty window
3. Window with greatest number of free clusters.
Arguments:
Vcb - Supplies the Vcb for the volume
Return Value:
'Best window' number (index into Vcb->Windows[])
--*/
{
ULONG i, Fave = 0;
ULONG MaxFree = 0;
ULONG FirstEmpty = -1;
ULONG ClustersPerWindow = MAX_CLUSTER_BITMAP_SIZE;
ASSERT( 1 != Vcb->NumberOfWindows);
for (i = 0; i < Vcb->NumberOfWindows; i++) {
if (Vcb->Windows[i].ClustersFree == ClustersPerWindow) {
if (-1 == FirstEmpty) {
//
// Keep note of the first empty window on the disc
//
FirstEmpty = i;
}
}
else if (Vcb->Windows[i].ClustersFree > MaxFree) {
//
// This window has the most free clusters, so far
//
MaxFree = Vcb->Windows[i].ClustersFree;
Fave = i;
//
// If this window has >50% free clusters, then we will take it,
// so don't bother considering more windows.
//
if (MaxFree >= (ClustersPerWindow >> 1)) {
break;
}
}
}
//
// If there were no windows with 50% or more freespace, then select the
// first empty window on the disc, if any - otherwise we'll just go with
// the one with the most free clusters.
//
if ((MaxFree < (ClustersPerWindow >> 1)) && (-1 != FirstEmpty)) {
Fave = FirstEmpty;
}
return Fave;
}
VOID
FatSetupAllocationSupport (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
)
/*++
Routine Description:
This routine fills in the Allocation Support structure in the Vcb.
Most entries are computed using fat.h macros supplied with data from
the Bios Parameter Block. The free cluster count, however, requires
going to the Fat and actually counting free sectors. At the same time
the free cluster bit map is initalized.
Arguments:
Vcb - Supplies the Vcb to fill in.
--*/
{
ULONG BitMapSize;
PVOID BitMapBuffer;
ULONG BitIndex;
PBCB Bcb;
ULONG Page;
ULONG Offset;
ULONG FatIndexBitSize;
ULONG ClustersDescribableByFat;
PAGED_CODE();
DebugTrace(+1, Dbg, "FatSetupAllocationSupport\n", 0);
DebugTrace( 0, Dbg, " Vcb = %8lx\n", Vcb);
//
// Compute a number of fields for Vcb.AllocationSupport
//
Vcb->AllocationSupport.RootDirectoryLbo = FatRootDirectoryLbo( &Vcb->Bpb );
Vcb->AllocationSupport.RootDirectorySize = FatRootDirectorySize( &Vcb->Bpb );
Vcb->AllocationSupport.FileAreaLbo = FatFileAreaLbo( &Vcb->Bpb );
Vcb->AllocationSupport.NumberOfClusters = FatNumberOfClusters( &Vcb->Bpb );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -