📄 generic.c
字号:
CcSetDirtyPinnedData(BitmapBcb, NULL);
CcUnpinData(BitmapBcb);
BitmapBcb = NULL;
Ext2SaveGroup(IrpContext, Vcb, Group);
/* add group bitmap block to dirty range */
Ext2AddVcbExtent(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
/* update Vcb free blocks */
Ext2UpdateVcbStat(IrpContext, Vcb);
/* validate the new allocated block number */
*Block = Index + EXT2_FIRST_DATA_BLOCK + Group * BLOCKS_PER_GROUP;
if (*Block >= TOTAL_BLOCKS || *Block + *Number >= TOTAL_BLOCKS) {
DbgBreak();
dwHint = 0;
goto Again;
}
{
ULONG i=0;
for (i=0; i < Vcb->NumOfGroups; i++) {
if ((Vcb->GroupDesc[i].bg_block_bitmap == *Block) ||
(Vcb->GroupDesc[i].bg_inode_bitmap == *Block) ||
(Vcb->GroupDesc[i].bg_inode_table == *Block) ) {
DbgBreak();
dwHint = 0;
goto Again;
}
}
}
Status = STATUS_SUCCESS;
}
errorout:
ExReleaseResourceLite(&Vcb->MetaLock);
return Status;
}
NTSTATUS
Ext2FreeBlock(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN ULONG Block,
IN ULONG Number
)
{
RTL_BITMAP BlockBitmap;
LARGE_INTEGER Offset;
PBCB BitmapBcb;
PVOID BitmapCache;
ULONG Group;
ULONG Index;
ULONG Length;
ULONG Count;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ExAcquireResourceExclusiveLite(&Vcb->MetaLock, TRUE);
DEBUG(DL_INF, ("Ext2FreeBlock: Block %xh to be freed.\n", Block));
Group = (Block - EXT2_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
Index = (Block - EXT2_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
Again:
if ( Block < EXT2_FIRST_DATA_BLOCK ||
Block >= TOTAL_BLOCKS ||
Group >= Vcb->NumOfGroups) {
DbgBreak();
Status = STATUS_SUCCESS;
} else {
/* check the block is valid or not */
if (Vcb->GroupDesc[Group].bg_block_bitmap >= TOTAL_BLOCKS) {
DbgBreak();
Status = STATUS_DISK_CORRUPT_ERROR;
goto errorout;
}
/* get bitmap block offset and length */
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;
}
/* read and initialize bitmap */
if (!CcPinRead( Vcb->Volume,
&Offset,
Vcb->BlockSize,
Ext2CanIWait(),
&BitmapBcb,
&BitmapCache ) ) {
DEBUG(DL_ERR, ("Ext2FreeBlock: failed to PinLock bitmap block %xh.\n",
Vcb->GroupDesc[Group].bg_block_bitmap));
Status = STATUS_CANT_WAIT;
DbgBreak();
goto errorout;
}
/* clear usused bits */
RtlInitializeBitMap(&BlockBitmap, BitmapCache, Length);
Count = min(Length - Index, Number);
RtlClearBits(&BlockBitmap, Index, Count);
/* update group description table */
Vcb->GroupDesc[Group].bg_free_blocks_count =
(USHORT)RtlNumberOfClearBits(&BlockBitmap);
/* indict the cache range is dirty */
CcSetDirtyPinnedData(BitmapBcb, NULL );
CcUnpinData(BitmapBcb);
BitmapBcb = NULL;
BitmapCache = NULL;
Ext2AddVcbExtent(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
Ext2SaveGroup(IrpContext, Vcb, Group);
/* save super block (used/unused blocks statics) */
Ext2UpdateVcbStat(IrpContext, Vcb);
/* try next group to clear all remaining */
Number -= Count;
if (Number) {
Group += 1;
if (Group < Vcb->NumOfGroups) {
Index = 0; Block += Count;
goto Again;
} else {
DEBUG(DL_ERR, ("Ext2FreeBlock: block number beyonds max group.\n"));
goto errorout;
}
}
}
Status = STATUS_SUCCESS;
errorout:
ExReleaseResourceLite(&Vcb->MetaLock);
return Status;
}
NTSTATUS
Ext2ExpandLast(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_MCB Mcb,
IN ULONG Base,
IN ULONG Layer,
IN PULONG * Data,
IN PULONG Hint,
IN PULONG Block,
IN OUT PULONG Number
)
{
PULONG pData = NULL;
ULONG i;
NTSTATUS Status = STATUS_SUCCESS;
if (Layer > 0 || IsMcbDirectory(Mcb)) {
/* allocate buffer for new block */
pData = (ULONG *) ExAllocatePoolWithTag(
PagedPool,
BLOCK_SIZE,
EXT2_DATA_MAGIC
);
if (!pData) {
DEBUG(DL_ERR, ( "Ex2ExpandBlock: failed to allocate memory for Data.\n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
goto errorout;
}
RtlZeroMemory(pData, BLOCK_SIZE);
INC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE);
}
/* allocate block from disk */
Status = Ext2NewBlock(
IrpContext,
Vcb,
(Mcb->iNo - 1) / BLOCKS_PER_GROUP,
*Hint,
Block,
Number
);
if (!NT_SUCCESS(Status)) {
goto errorout;
}
/* increase inode i_blocks */
Mcb->Inode->i_blocks += (*Number * (BLOCK_SIZE >> 9));
if (Layer == 0) {
if (IsMcbDirectory(Mcb)) {
/* for directory we need initialize it's entry structure */
PEXT2_DIR_ENTRY2 pEntry;
pEntry = (PEXT2_DIR_ENTRY2) pData;
pEntry->rec_len = (USHORT)(BLOCK_SIZE);
ASSERT(*Number == 1);
Ext2SaveBlock(IrpContext, Vcb, *Block, (PVOID)pData);
} else {
/* for file we need remove dirty MCB to prevent Volume's writing */
if (!Ext2RemoveBlockExtent(Vcb, NULL, (*Block), *Number)) {
DbgBreak();
Status = STATUS_INSUFFICIENT_RESOURCES;
goto errorout;
}
}
/* add new Extent into Mcb */
if (!Ext2AddBlockExtent(Vcb, Mcb, Base, (*Block), *Number)) {
DbgBreak();
ClearFlag(Mcb->Flags, MCB_ZONE_INIT);
Ext2ClearAllExtents(&Mcb->Extents);
}
} else {
/* zero the content of all meta blocks */
for (i = 0; i < *Number; i++) {
Ext2SaveBlock(IrpContext, Vcb, *Block + i, (PVOID)pData);
}
}
errorout:
if (NT_SUCCESS(Status)) {
*Hint = *Block + *Number;
if (Data) {
*Data = pData;
ASSERT(*Number == 1);
} else {
if (pData) {
ExFreePoolWithTag(pData, EXT2_DATA_MAGIC);
DEC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE);
}
}
} else {
if (pData) {
ExFreePoolWithTag(pData, EXT2_DATA_MAGIC);
DEC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE);
}
if (*Block) {
Ext2FreeBlock(IrpContext, Vcb, *Block, *Number);
*Block = 0;
}
}
return Status;
}
NTSTATUS
Ext2ExpandBlock(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_MCB Mcb,
IN ULONG Base,
IN ULONG Layer,
IN ULONG Start,
IN ULONG SizeArray,
IN PULONG BlockArray,
IN PULONG Hint,
IN PULONG Extra
)
{
ULONG i = 0;
ULONG j;
ULONG Slot;
ULONG Block = 0;
LARGE_INTEGER Offset;
PBCB Bcb = NULL;
PULONG pData = NULL;
ULONG Skip = 0;
ULONG Number;
ULONG Wanted;
NTSTATUS Status = STATUS_SUCCESS;
if (Layer == 1) {
/* try to make all leaf block continuous to avoid fragments */
Number = min(SizeArray, ((*Extra + (Start & (BLOCK_SIZE/4 - 1))) * 4 / BLOCK_SIZE));
Wanted = 0;
DEBUG(DL_BLK, ("Ext2ExpandBlock: SizeArray=%xh Extra=%xh Start=%xh %xh\n",
SizeArray, *Extra, Start, Number ));
for (i=0; i < Number; i++) {
if (BlockArray[i] == 0) {
Wanted += 1;
}
}
i = 0;
while (Wanted > 0) {
Number = Wanted;
Status = Ext2ExpandLast(
IrpContext,
Vcb,
Mcb,
Base,
Layer,
NULL,
Hint,
&Block,
&Number
);
if (!NT_SUCCESS(Status)) {
goto errorout;
}
ASSERT(Number > 0);
Wanted -= Number;
while (Number) {
if (BlockArray[i] == 0) {
BlockArray[i] = Block++;
Number--;
}
i++;
}
}
} else if (Layer == 0) {
/* bulk allocation for inode data blocks */
i = 0;
while (*Extra && i < SizeArray) {
Wanted = 0;
Number = 1;
for (j = i; j < SizeArray && j < i + *Extra; j++) {
if (BlockArray[j] >= TOTAL_BLOCKS) {
DbgBreak();
BlockArray[j] = 0;
}
if (BlockArray[j] == 0) {
Wanted += 1;
} else {
break;
}
}
if (Wanted == 0) {
/* add block extent into Mcb */
ASSERT(BlockArray[i] != 0);
if (!Ext2AddBlockExtent(Vcb, Mcb, Base + i, BlockArray[i], 1)) {
DbgBreak();
ClearFlag(Mcb->Flags, MCB_ZONE_INIT);
Ext2ClearAllExtents(&Mcb->Extents);
}
} else {
Number = Wanted;
Status = Ext2ExpandLast(
IrpContext,
Vcb,
Mcb,
Base + i,
0,
NULL,
Hint,
&Block,
&Number
);
if (!NT_SUCCESS(Status)) {
goto errorout;
}
ASSERT(Number > 0);
for (j = 0; j < Number; j++) {
BlockArray[i + j] = Block++;
}
}
*Extra -= Number;
i += Number;
}
goto errorout;
}
for (i = 0; *Extra && i < SizeArray; i++) {
if (Layer <= 3) {
if (BlockArray[i] >= TOTAL_BLOCKS) {
DbgBreak();
BlockArray[i] = 0;
}
if (BlockArray[i] == 0) {
Number = 1;
Status = Ext2ExpandLast(
IrpContext,
Vcb,
Mcb,
Base,
Layer,
&pData,
Hint,
&BlockArray[i],
&Number
);
if (!NT_SUCCESS(Status)) {
goto errorout;
}
} else {
Offset.QuadPart = (((LONGLONG)BlockArray[i]) << BLOCK_BITS);
if (!CcPinRead(
Vcb->Volume,
&Offset,
BLOCK_SIZE,
Ext2CanIWait(),
&Bcb,
&pData )) {
DEBUG(DL_ERR, ( "Ext2ExpandInode: failed to PinLock offset :%I64xh...\n",
Offset.QuadPart));
Status = STATUS_CANT_WAIT;
DbgBreak();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -