📄 generic.c
字号:
IN ULONG SizeArray,
IN PULONG BlockArray,
IN BOOLEAN bAlloc,
IN OUT PULONG Hint,
OUT PULONG Block,
OUT PULONG Number
)
{
NTSTATUS Status = STATUS_SUCCESS;
PBCB Bcb = NULL;
PULONG pData = NULL;
ULONG Slot = 0, i = 0;
ULONG Unit = 1;
LARGE_INTEGER Offset;
if (Layer == 0) {
*Number = 1;
if (BlockArray[0] == 0 && bAlloc) {
/* now allocate new block */
Status = Ext2ExpandLast(
IrpContext,
Vcb,
Mcb,
Base,
Layer,
NULL,
Hint,
&BlockArray[0],
Number
);
if (!NT_SUCCESS(Status)) {
goto errorout;
}
}
*Block = BlockArray[0];
for (i=1; i < SizeArray; i++) {
if (BlockArray[i] == BlockArray[i-1] + 1) {
*Number = *Number + 1;
} else {
break;
}
}
*Hint = BlockArray[*Number - 1];
} else if (Layer <= 3) {
/* check the block is valid or not */
if (BlockArray[0] >= TOTAL_BLOCKS) {
DbgBreak();
return STATUS_DISK_CORRUPT_ERROR;
}
/* map memory in cache for the index block */
Offset.QuadPart = ((LONGLONG)BlockArray[0]) << BLOCK_BITS;
if( !CcPinRead( Vcb->Volume,
(PLARGE_INTEGER) (&Offset),
BLOCK_SIZE,
Ext2CanIWait(),
&Bcb,
&pData )) {
DEBUG(DL_ERR, ( "Ext2GetBlock: Failed to PinLock block: %xh ...\n",
BlockArray[0] ));
Status = STATUS_CANT_WAIT;
goto errorout;
}
if (Layer > 1) {
Unit = Vcb->NumBlocks[Layer - 1];
} else {
Unit = 1;
}
Slot = Start / Unit;
Start = Start % Unit;
if (pData[Slot] == 0) {
if (bAlloc) {
/* we need allocate new block and zero all data in case
it's an in-direct block. Index stores the new block no. */
ULONG Count = 1;
Status = Ext2ExpandLast(
IrpContext,
Vcb,
Mcb,
Base,
Layer,
NULL,
Hint,
&pData[Slot],
&Count
);
if (!NT_SUCCESS(Status)) {
goto errorout;
}
/* refresh hint block */
*Hint = pData[Slot];
/* set dirty bit to notify system to flush */
CcSetDirtyPinnedData(Bcb, NULL );
SetFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
if (!Ext2AddVcbExtent(Vcb, Offset.QuadPart,
(LONGLONG)BLOCK_SIZE)) {
DbgBreak();
Ext2Sleep(100);
if (!Ext2AddVcbExtent(Vcb, Offset.QuadPart,
(LONGLONG)BLOCK_SIZE)) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto errorout;
}
}
/* save inode information here */
Ext2SaveInode(IrpContext, Vcb, Mcb->iNo, Mcb->Inode);
} else {
*Number = 1;
if (Layer == 1) {
for (i = Slot + 1; i < BLOCK_SIZE/4; i++) {
if (pData[i] == 0) {
*Number = *Number + 1;
} else {
break;
}
}
} else if (Layer == 2) {
*Number = BLOCK_SIZE/4 - Start;
} else {
*Number = BLOCK_SIZE/4;
}
goto errorout;
}
}
/* transfer to next recursion call */
Status = Ext2GetBlock(
IrpContext,
Vcb,
Mcb,
Base,
Layer - 1,
Start,
BLOCK_SIZE/4 - Slot,
&pData[Slot],
bAlloc,
Hint,
Block,
Number
);
if (!NT_SUCCESS(Status)) {
goto errorout;
}
}
errorout:
/* free the memory of pData */
if (Bcb) {
CcUnpinData(Bcb);
}
if (!NT_SUCCESS(Status)) {
*Block = 0;
}
return Status;
}
NTSTATUS
Ext2BlockMap(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_MCB Mcb,
IN ULONG Index,
IN BOOLEAN bAlloc,
OUT PULONG pBlock,
OUT PULONG Number
)
{
ULONG Layer;
ULONG Slot;
ULONG Base = Index;
NTSTATUS Status = STATUS_SUCCESS;
*pBlock = 0;
*Number = 0;
for (Layer = 0; Layer < EXT2_BLOCK_TYPES; Layer++) {
if (Index < Vcb->NumBlocks[Layer]) {
ULONG dwRet = 0;
ULONG dwBlk = 0;
ULONG dwHint = 0;
Slot = (Layer==0) ? (Index):(Layer + EXT2_NDIR_BLOCKS - 1);
dwBlk = Mcb->Inode->i_block[Slot];
if (dwBlk == 0) {
if (!bAlloc) {
*Number = 1;
goto errorout;
} else {
if (Slot) {
dwHint = Mcb->Inode->i_block[Slot - 1];
}
/* allocate and zero block if necessary */
*Number = 1;
Status = Ext2ExpandLast(
IrpContext,
Vcb,
Mcb,
Base,
Layer,
NULL,
&dwHint,
&dwBlk,
Number
);
if (!NT_SUCCESS(Status)) {
goto errorout;
}
/* save the it into inode*/
Mcb->Inode->i_block[Slot] = dwBlk;
/* save the inode */
if (!Ext2SaveInode( IrpContext,
Vcb,
Mcb->iNo,
Mcb->Inode)) {
Status = STATUS_UNSUCCESSFUL;
Ext2FreeBlock(IrpContext, Vcb, dwBlk, 1);
goto errorout;
}
}
}
/* querying block number of the index-th file block */
Status = Ext2GetBlock(
IrpContext,
Vcb,
Mcb,
Base,
Layer,
Index,
(Layer == 0) ? (Vcb->NumBlocks[Layer] - Index) : 1,
&Mcb->Inode->i_block[Slot],
bAlloc,
&dwHint,
&dwRet,
Number
);
if (NT_SUCCESS(Status)) {
*pBlock = dwRet;
}
break;
}
Index -= Vcb->NumBlocks[Layer];
}
errorout:
return Status;
}
VOID
Ext2UpdateVcbStat(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb
)
{
ULONG i;
Vcb->SuperBlock->s_free_blocks_count = 0;
Vcb->SuperBlock->s_free_inodes_count = 0;
for (i = 0; i < Vcb->NumOfGroups; i++) {
Vcb->SuperBlock->s_free_blocks_count +=
Vcb->GroupDesc[i].bg_free_blocks_count;
Vcb->SuperBlock->s_free_inodes_count +=
Vcb->GroupDesc[i].bg_free_inodes_count;
}
Ext2SaveSuper(IrpContext, Vcb);
}
NTSTATUS
Ext2NewBlock(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN ULONG GroupHint,
IN ULONG BlockHint,
OUT PULONG Block,
IN OUT PULONG Number
)
{
RTL_BITMAP BlockBitmap;
LARGE_INTEGER Offset;
PBCB BitmapBcb;
PVOID BitmapCache;
ULONG Group = 0;
ULONG Index = 0xFFFFFFFF;
ULONG dwHint = 0;
ULONG Count = 0;
ULONG Length = 0;
NTSTATUS Status = STATUS_DISK_FULL;
*Block = 0;
ExAcquireResourceExclusiveLite(&Vcb->MetaLock, TRUE);
/* validate the hint group and hint block */
if (GroupHint >= Vcb->NumOfGroups) {
DbgBreak();
GroupHint = Vcb->NumOfGroups - 1;
}
if (BlockHint != 0) {
GroupHint = (BlockHint - EXT2_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
dwHint = (BlockHint - EXT2_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
}
Group = GroupHint;
Again:
if (Vcb->GroupDesc[Group].bg_free_blocks_count) {
/* check the block is valid or not */
if (Vcb->GroupDesc[Group].bg_block_bitmap >= TOTAL_BLOCKS) {
DbgBreak();
Status = STATUS_DISK_CORRUPT_ERROR;
goto errorout;
}
Offset.QuadPart = Vcb->GroupDesc[Group].bg_block_bitmap;
Offset.QuadPart = Offset.QuadPart << BLOCK_BITS;
if (Group == Vcb->NumOfGroups - 1) {
Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP;
/* s_blocks_count is integer multiple of s_blocks_per_group */
if (Length == 0) {
Length = BLOCKS_PER_GROUP;
}
} else {
Length = BLOCKS_PER_GROUP;
}
if (!CcPinRead( Vcb->Volume,
&Offset,
Vcb->BlockSize,
Ext2CanIWait(),
&BitmapBcb,
&BitmapCache ) ) {
DEBUG(DL_ERR, ("Ext2NewBlock: failed to PinLock bitmap block %xh ...\n",
Vcb->GroupDesc[Group].bg_block_bitmap ));
Status = STATUS_CANT_WAIT;
DbgBreak();
goto errorout;
}
/* initialize bitmap buffer */
RtlInitializeBitMap(&BlockBitmap, BitmapCache, Length);
/* try to find a clear bit range */
Index = RtlFindClearBits(&BlockBitmap, *Number, dwHint);
/* We could not get new block in the prefered group */
if (Index == 0xFFFFFFFF) {
/* search clear bits from the hint block */
Count = RtlFindNextForwardRunClear(&BlockBitmap, dwHint, &Index);
if (dwHint != 0 && Count == 0) {
/* search clear bits from the very beginning */
Count = RtlFindNextForwardRunClear(&BlockBitmap, 0, &Index);
}
if (Count == 0) {
/* release bitmap */
CcUnpinData(BitmapBcb);
BitmapBcb = NULL;
BitmapCache = NULL;
RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
/* no blocks found: set bg_free_blocks_count to 0 */
Vcb->GroupDesc[Group].bg_free_blocks_count = 0;
Ext2SaveGroup(IrpContext, Vcb, Group);
/* will try next group */
goto Again;
} else {
/* we got free blocks */
if (Count <= *Number) {
*Number = Count;
}
}
}
} else {
/* try next group */
dwHint = 0;
Group = (Group + 1) % Vcb->NumOfGroups;
if (Group != GroupHint) {
goto Again;
}
Index = 0xFFFFFFFF;
}
if (Index < Length) {
/* mark block bits as allocated */
RtlSetBits(&BlockBitmap, Index, *Number);
/* update group description */
Vcb->GroupDesc[Group].bg_free_blocks_count =
(USHORT)RtlNumberOfClearBits(&BlockBitmap);
/* set block bitmap dirty in cache */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -