📄 generic.c
字号:
goto errorout;
}
}
Skip = Vcb->NumBlocks[Layer] * i;
if (i == 0) {
if (Layer > 1) {
Slot = Start / Vcb->NumBlocks[Layer - 1];
Start = Start % Vcb->NumBlocks[Layer - 1];
Skip += Slot * Vcb->NumBlocks[Layer - 1];
} else {
Slot = Start;
Start = 0;
Skip += Slot;
}
} else {
Start = 0;
Slot = 0;
}
Status = Ext2ExpandBlock(
IrpContext,
Vcb,
Mcb,
Base + Skip,
Layer - 1,
Start,
BLOCK_SIZE/4 - Slot,
&pData[Slot],
Hint,
Extra
);
if (Bcb) {
CcSetDirtyPinnedData(Bcb, NULL);
if (!Ext2AddBlockExtent(Vcb, NULL,
BlockArray[i],
BlockArray[i], 1)) {
DbgBreak();
Ext2Sleep(500);
if (!Ext2AddBlockExtent(Vcb, NULL,
BlockArray[i],
BlockArray[i], 1)) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto errorout;
}
}
} else {
Ext2SaveBlock(IrpContext, Vcb, BlockArray[i], (PVOID)pData);
}
if (pData) {
if (Bcb) {
CcUnpinData(Bcb);
Bcb = NULL;
} else {
ExFreePoolWithTag(pData, EXT2_DATA_MAGIC);
DEC_MEM_COUNT(PS_BLOCK_DATA, pData, BLOCK_SIZE);
}
pData = NULL;
}
if (!NT_SUCCESS(Status)) {
DbgBreak();
break;
}
}
}
errorout:
return Status;
}
BOOLEAN
Ext2IsBlockEmpty(PULONG BlockArray, ULONG SizeArray)
{
ULONG i = 0;
for (i=0; i < SizeArray; i++) {
if (BlockArray[i]) {
break;
}
}
return (i == SizeArray);
}
NTSTATUS
Ext2TruncateBlock(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_MCB Mcb,
IN ULONG Base,
IN ULONG Start,
IN ULONG Layer,
IN ULONG SizeArray,
IN PULONG BlockArray,
IN PULONG Extra
)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG i = 0;
ULONG Slot = 0;
ULONG Skip = 0;
LONGLONG Offset;
PBCB Bcb = NULL;
PULONG pData = NULL;
for (i = 0; i < SizeArray; i++) {
if (Layer == 0) {
ULONG Number = 1;
while (Extra && SizeArray > i + 1 && Number < *Extra) {
if (BlockArray[SizeArray - i - 1] ==
BlockArray[SizeArray - i - 2] + 1) {
BlockArray[SizeArray - i - 1] = 0;
Number++;
SizeArray--;
} else {
break;
}
}
if (BlockArray[SizeArray - i - 1]) {
Status = Ext2FreeBlock(IrpContext, Vcb, BlockArray[SizeArray - i - 1], Number);
if (NT_SUCCESS(Status)) {
#if EXT2_DEBUG
if (i == 0 || i == SizeArray - 1 || *Extra == Number) {
DEBUG(DL_BLK, ("Ext2TruncateBlock: Vbn: %xh Lbn: %xh Num: %xh\n",
Base + SizeArray - 1 - i, BlockArray[SizeArray - i - 1], Number));
}
#endif
ASSERT(Mcb->Inode->i_blocks >= Number * (BLOCK_SIZE >> 9));
if (Mcb->Inode->i_blocks < Number * (BLOCK_SIZE >> 9)) {
Mcb->Inode->i_blocks = 0;
DbgBreak();
} else {
Mcb->Inode->i_blocks -= Number * (BLOCK_SIZE >> 9);
}
BlockArray[SizeArray - i - 1] = 0;
}
}
if (Extra) {
/* dec blocks count */
ASSERT(*Extra >= Number);
*Extra = *Extra - Number;
/* remove block mapping frm Mcb Extents */
if (!Ext2RemoveBlockExtent(Vcb, Mcb, Base + SizeArray - 1 - i, Number)) {
DbgBreak();
ClearFlag(Mcb->Flags, MCB_ZONE_INIT);
Ext2ClearAllExtents(&Mcb->Extents);
}
}
} else {
ASSERT(Layer <= 3);
if (BlockArray[SizeArray - i - 1] >= TOTAL_BLOCKS) {
DbgBreak();
BlockArray[SizeArray - i - 1] = 0;
}
if (i == 0) {
if (Layer > 1) {
Slot = Start / Vcb->NumBlocks[Layer - 1];
Start = Start % Vcb->NumBlocks[Layer - 1];
} else {
Slot = Start;
Start = (BLOCK_SIZE / 4) - 1;
}
} else {
Slot = Start = (BLOCK_SIZE / 4) - 1;
}
Skip = (SizeArray - i - 1) * Vcb->NumBlocks[Layer];
if (BlockArray[SizeArray - i - 1]) {
Offset = (LONGLONG) (BlockArray[SizeArray - i - 1]);
Offset = Offset << BLOCK_BITS;
if (!CcPinRead( Vcb->Volume,
(PLARGE_INTEGER) (&Offset),
BLOCK_SIZE,
Ext2CanIWait(),
&Bcb,
&pData )) {
DEBUG(DL_ERR, ( "Ext2TruncateBlock: PinLock failed on block %xh ...\n",
BlockArray[SizeArray - i - 1]));
Status = STATUS_CANT_WAIT;
DbgBreak();
goto errorout;
}
Status = Ext2TruncateBlock(
IrpContext,
Vcb,
Mcb,
Base + Skip,
Start,
Layer - 1,
Slot + 1,
&pData[0],
Extra
);
if (!NT_SUCCESS(Status)) {
break;
}
CcSetDirtyPinnedData(Bcb, NULL);
Ext2AddVcbExtent(Vcb, Offset, (LONGLONG)BLOCK_SIZE);
if (*Extra || Ext2IsBlockEmpty(pData, BLOCK_SIZE/4)) {
Status = Ext2TruncateBlock(
IrpContext,
Vcb,
Mcb,
Base + Skip, /* base */
0, /* start */
0, /* layer */
1,
&BlockArray[SizeArray - i - 1],
NULL
);
}
if (pData) {
CcUnpinData(Bcb);
Bcb = NULL;
pData = NULL;
}
} else {
if (Layer > 1) {
if (*Extra > Slot * Vcb->NumBlocks[Layer - 1] + Start + 1) {
*Extra -= (Slot * Vcb->NumBlocks[Layer - 1] + Start + 1);
} else {
*Extra = 0;
}
} else {
if (*Extra > Slot + 1) {
*Extra -= (Slot + 1);
} else {
*Extra = 0;
}
}
if (!Ext2RemoveBlockExtent(Vcb, Mcb, Base + Skip, (Start + 1))) {
DbgBreak();
ClearFlag(Mcb->Flags, MCB_ZONE_INIT);
Ext2ClearAllExtents(&Mcb->Extents);
}
}
}
if (Extra && *Extra == 0) {
break;
}
}
errorout:
if (pData) {
CcUnpinData(Bcb);
}
return Status;
}
NTSTATUS
Ext2NewInode(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN ULONG GroupHint,
IN ULONG Type,
OUT PULONG Inode
)
{
RTL_BITMAP InodeBitmap;
PVOID BitmapCache;
PBCB BitmapBcb;
ULONG Group, i, j;
ULONG Average, Length;
LARGE_INTEGER Offset;
ULONG dwInode;
NTSTATUS Status = STATUS_DISK_FULL;
*Inode = dwInode = 0XFFFFFFFF;
ExAcquireResourceExclusiveLite(&Vcb->MetaLock, TRUE);
repeat:
Group = i = 0;
if (Type == EXT2_FT_DIR) {
Average = Vcb->SuperBlock->s_free_inodes_count / Vcb->NumOfGroups;
for (j = 0; j < Vcb->NumOfGroups; j++) {
i = (j + GroupHint) % (Vcb->NumOfGroups);
if ((Vcb->GroupDesc[i].bg_used_dirs_count << 8) <
Vcb->GroupDesc[i].bg_free_inodes_count ) {
Group = i + 1;
break;
}
}
if (!Group) {
/* get the group with the biggest vacancy */
for (j = 0; j < Vcb->NumOfGroups; j++) {
if (!Group) {
if (Vcb->GroupDesc[j].bg_free_inodes_count > 0) {
Group = j + 1;
}
} else {
if ( Vcb->GroupDesc[j].bg_free_blocks_count >
Vcb->GroupDesc[Group - 1].bg_free_blocks_count ) {
Group = j + 1;
}
}
}
}
} else {
/*
* Try to place the inode in its parent directory (GroupHint)
*/
if (Vcb->GroupDesc[GroupHint].bg_free_inodes_count) {
Group = GroupHint + 1;
} else {
i = GroupHint;
/*
* Use a quadratic hash to find a group with a free inode
*/
for (j = 1; j < Vcb->NumOfGroups; j <<= 1) {
i = (i + j) % Vcb->NumOfGroups;
if (Vcb->GroupDesc[i].bg_free_inodes_count) {
Group = i + 1;
break;
}
}
}
if (!Group) {
/*
* That failed: try linear search for a free inode
*/
i = GroupHint;
for (j = 2; j < Vcb->NumOfGroups; j++) {
i = (i + 1) % Vcb->NumOfGroups;
if (Vcb->GroupDesc[i].bg_free_inodes_count) {
Group = i + 1;
break;
}
}
}
}
if (Group == 0) {
goto errorout;
}
Group -= 1;
/* finally we got the group */
if (Group >= Vcb->NumOfGroups) {
DbgBreak();
goto errorout;
}
/* check the block is valid or not */
if (Vcb->GroupDesc[Group].bg_inode_bitmap >= TOTAL_BLOCKS) {
DbgBreak();
Status = STATUS_DISK_CORRUPT_ERROR;
goto errorout;
}
/* this group is used up, we should go here */
if (Vcb->GroupDesc[Group].bg_inode_bitmap == 0) {
DbgBreak();
goto errorout;
}
Offset.QuadPart = (LONGLONG) Vcb->GroupDesc[Group].bg_inode_bitmap;
Offset.QuadPart = Offset.QuadPart << BLOCK_BITS ;
if (Vcb->NumOfGroups == 1) {
Length = INODES_COUNT;
} else {
if (Group + 1 == Vcb->NumOfGroups) {
Length = INODES_COUNT % INODES_PER_GROUP;
if (!Length) {
/* INODES_COUNT is integer multiple of INODES_PER_GROUP */
Length = INODES_PER_GROUP;
}
} else {
Length = INODES_PER_GROUP;
}
}
if (!CcPinRead( Vcb->Volume,
&Offset,
Vcb->BlockSize,
Ext2CanIWait(),
&BitmapBcb,
&BitmapCache ) ) {
DEBUG(DL_ERR, ( "Ext2NewInode: Failed to PinLock inode bitmap block %xh ...\n",
Vcb->GroupDesc[Group].bg_inode_bitmap ));
Status = STATUS_CANT_WAIT;
DbgBreak();
goto errorout;
}
RtlInitializeBitMap(&InodeBitmap, BitmapCache, Length);
dwInode = RtlFindClearBits(&InodeBitmap, 1, 0);
if (dwInode == 0xFFFFFFFF || dwInode >= Length) {
CcUnpinData(BitmapBcb);
BitmapBcb = NULL;
BitmapCache = NULL;
RtlZeroMemory(&InodeBitmap, sizeof(RTL_BITMAP));
if (Vcb->GroupDesc[Group].bg_free_inodes_count > 0) {
Vcb->GroupDesc[Group].bg_free_inodes_count = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -