📄 rfsd.c
字号:
if (bAlloc) {
DbgBreak();
/* we need allocate new block: dwBlk */
Status = RfsdNewBlock(
IrpContext,
Vcb,
0,
dwContent,
&dwBlk
);
if (!NT_SUCCESS(Status)) {
ExFreePool(pData);
goto errorout;
}
/* we need save pData now */
pData[i] = dwBlk;
/* save the block first, before next call */
if (!RfsdSaveBlock( IrpContext, Vcb,
dwContent, pData)) {
/* error occurs when saving the block */
Status = STATUS_INSUFFICIENT_RESOURCES;
/* we need free newly allocated block */
RfsdFreeBlock(IrpContext, Vcb, dwBlk);
/* free the memory of pData */
ExFreePool(pData);
goto errorout;
}
} else {
/* free the memory of pData */
ExFreePool(pData);
goto errorout;
}
}
#endif
/* free the memory of pData */
ExFreePool(pData);
/* transfer to next recursion call */
Status = RfsdGetBlock(
IrpContext,
Vcb,
dwBlk,
j,
Layer - 1,
bAlloc,
&dwRet
);
if (!NT_SUCCESS(Status)) {
dwRet = 0;
}
}
errorout:
*pBlock = dwRet;
return Status;
#endif
}
/** I think this means it maps the blocks into the cache.
Basically, it goes through and calls GetBlock for each block.
*/
NTSTATUS
RfsdBlockMap(
IN PRFSD_IRP_CONTEXT IrpContext,
IN PRFSD_VCB Vcb,
IN ULONG InodeNo,
IN PRFSD_INODE Inode,
IN ULONG Index, // Ordinal index of this block in the BDL
IN BOOLEAN bAlloc, // FALSE
OUT PULONG pBlock // <
)
{
DbgBreak();
#if DISABLED
ULONG i;
ULONG dwSizes[RFSD_BLOCK_TYPES];
NTSTATUS Status = STATUS_SUCCESS;;
*pBlock = 0;
for (i = 0; i < RFSD_BLOCK_TYPES; i++) {
dwSizes[i] = Vcb->dwData[i];
}
for (i = 0; i < RFSD_BLOCK_TYPES; i++) {
if (Index < dwSizes[i]) {
ULONG dwRet = 0;
ULONG dwBlk = 0;
// dwBlk will get the ptr to a block.
dwBlk = Inode->i_block[i==0 ? (Index):(i + RFSD_NDIR_BLOCKS - 1)];
#if DISABLED // WRITE MODE ONLY
if (dwBlk == 0) {
if (!bAlloc) {
goto errorout;
} else {
DbgBreak();
/* we need allocate new block: dwBlk */
Status = RfsdNewBlock(
IrpContext,
Vcb,
(InodeNo - 1) / BLOCKS_PER_GROUP,
0,
&dwBlk
);
if (!NT_SUCCESS(Status)) {
goto errorout;
}
/* save the it into inode*/
Inode->i_block[i==0 ? (Index):(i + RFSD_NDIR_BLOCKS - 1)] = dwBlk;
/* save the inode */
if (!RfsdSaveInode( IrpContext,
Vcb,
InodeNo,
Inode)) {
Status = STATUS_UNSUCCESSFUL;
RfsdFreeBlock(IrpContext, Vcb, dwBlk);
goto errorout;
}
}
}
#endif
Status = RfsdGetBlock(
IrpContext,
Vcb,
dwBlk,
Index,
i,
bAlloc,
&dwRet //<
);
RfsdPrint((DBG_INFO, "RfsdBlockMap: i=%xh index=%xh dwBlk=%xh (%xh)\n",
i, Index, dwRet, dwBlk));
if (NT_SUCCESS(Status)) {
*pBlock = dwRet;
}
break;
}
Index -= dwSizes[i];
}
errorout:
return Status;
#endif
}
// NOTE: ReiserFS starts it byte offsets at 1, as opposed to 0 (which is used for the buffer -- and therefore, the BDL is also 0-based).
NTSTATUS
RfsdBuildBDL2(
IN PRFSD_VCB Vcb,
IN PRFSD_KEY_IN_MEMORY pKey,
IN PRFSD_INODE pInode,
OUT PULONG out_Count,
OUT PRFSD_BDL* out_ppBdl )
{
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN done = FALSE;
RFSD_KEY_IN_MEMORY CurrentTargetKey = *pKey;
ULONGLONG CurrentOffset = 0;
PRFSD_ITEM_HEAD pItemHeader = NULL; // The temporary storage for retrieving items from disk
PUCHAR pItemBuffer = NULL;
PUCHAR pBlockBuffer = NULL;
ULONG idxCurrentBD = 0;
PRFSD_BDL pBdl = NULL; // The block descriptor list, which will be allocated, filled, and assigned to out_Bdl
// Allocate the BDL for the maximum number of block descriptors that will be needed (including the tail)
// FUTURE: sd_blocks DEFINITELY is not the number of blocks consumed by a file. (at least not the number of 4096-byte blocks)
// However, I'm unsure of how to calculate the number of blocks. Perhaps I should consider using a linked list instead?
KdPrint(("## Allocating %i BD's\n", pInode->i_size / Vcb->BlockSize + 3));
pBdl = ExAllocatePool(NonPagedPool, sizeof(RFSD_BDL) * (SIZE_T) (pInode->i_size / Vcb->BlockSize + 3));
if (!pBdl) { Status = STATUS_INSUFFICIENT_RESOURCES; goto errorout; }
//RtlZeroMemory(pBdl, sizeof(RFSD_BDL) * (pInode->sd_blocks + 1));
RtlZeroMemory(pBdl, sizeof(RFSD_BDL) * (SIZE_T) (pInode->i_size / Vcb->BlockSize + 3));
// Build descriptors for all of the indirect items associated with the file
while (!done)
{
// Search for an indirect item, corresponding to CurrentOffset...
// Create the key to search for (note that the key always start with offset 1, even though it is for byte 0)
CurrentTargetKey.k_offset = CurrentOffset + 1;
CurrentTargetKey.k_type = RFSD_KEY_TYPE_v2_INDIRECT;
// Perform the search
Status = RfsdLoadItem(
Vcb, &CurrentTargetKey,
&(pItemHeader), &(pItemBuffer), &(pBlockBuffer), NULL,
&CompareKeys
);
// If there was no such indirect item...
if (Status == STATUS_NO_SUCH_MEMBER) { Status = STATUS_SUCCESS; break; }
if (!NT_SUCCESS(Status)) { goto errorout; }
// Otherwise, create a block descriptor for each pointer in the indirect item
{
ULONG countBlockRefs = pItemHeader->ih_item_len / sizeof(ULONG);
ULONG idxBlockRef;
for (idxBlockRef = 0; idxBlockRef < countBlockRefs; idxBlockRef++)
{
PULONG BlockRef = (PULONG) ((PUCHAR) pItemBuffer + sizeof(ULONG) * idxBlockRef);
// Build a block descriptor for this block reference
pBdl[idxCurrentBD].Lba = (LONGLONG) *BlockRef * (LONGLONG) Vcb->BlockSize;
pBdl[idxCurrentBD].Length = Vcb->BlockSize;
pBdl[idxCurrentBD].Offset = CurrentOffset;
// If this is the last reference in the indirect item, subtract the free space from the end
// TODO: this may not work, because the ih_free_space_reserved seems to be wrong / not there!
if (idxBlockRef == (countBlockRefs - 1))
pBdl[idxCurrentBD].Length -= pItemHeader->u.ih_free_space_reserved;
// Advance to the next block reference
CurrentOffset += Vcb->BlockSize;
idxCurrentBD++;
}
if (countBlockRefs <= 0) { done = TRUE; }
}
if (pBlockBuffer) { ExFreePool(pBlockBuffer); pBlockBuffer = NULL; }
}
// Cleanup the last remaining block buffer, from the indirect items
if (pBlockBuffer) { ExFreePool(pBlockBuffer); pBlockBuffer = NULL; }
// Search for the tail of the file (its optional direct item), corresponding to CurrentOffset...
{
ULONG BlockNumber = 0;
// Create the key to search for
CurrentTargetKey.k_offset = CurrentOffset + 1;
CurrentTargetKey.k_type = RFSD_KEY_TYPE_v2_DIRECT;
// Perform the search
Status = RfsdLoadItem(
Vcb, &CurrentTargetKey,
&(pItemHeader), &(pItemBuffer), &(pBlockBuffer), &(BlockNumber),
&CompareKeys
);
if (Status == STATUS_SUCCESS)
{
// If there was a tail, then build a block descriptor for it
pBdl[idxCurrentBD].Lba = (LONGLONG) BlockNumber * (LONGLONG) Vcb->BlockSize + pItemHeader->ih_item_location;
pBdl[idxCurrentBD].Length = pItemHeader->ih_item_len;
pBdl[idxCurrentBD].Offset = CurrentOffset;
// Advance to the next block reference
CurrentOffset += pItemHeader->ih_item_len;
idxCurrentBD++;
}
else
{
if (Status == STATUS_NO_SUCH_MEMBER) { Status = STATUS_SUCCESS; goto errorout; } // If there wasn't a tail, it's fine
else { goto errorout; } // But if there was some other problem, let's report it.
}
}
if (pBlockBuffer) { ExFreePool(pBlockBuffer); pBlockBuffer = NULL; }
// Search for the second part of the tail of the file (its optional second direct item), corresponding to CurrentOffset...
{
ULONG BlockNumber = 0;
// Create the key to search for
CurrentTargetKey.k_offset = CurrentOffset + 1;
CurrentTargetKey.k_type = RFSD_KEY_TYPE_v2_DIRECT;
// Perform the search
Status = RfsdLoadItem(
Vcb, &CurrentTargetKey,
&(pItemHeader), &(pItemBuffer), &(pBlockBuffer), &(BlockNumber),
&CompareKeys
);
if (Status == STATUS_SUCCESS)
{
// If there was a second part of the tail, then build a block descriptor for it
pBdl[idxCurrentBD].Lba = (LONGLONG) BlockNumber * (LONGLONG) Vcb->BlockSize + pItemHeader->ih_item_location;
pBdl[idxCurrentBD].Length = pItemHeader->ih_item_len;
pBdl[idxCurrentBD].Offset = CurrentOffset;
idxCurrentBD++;
}
else
{
if (Status == STATUS_NO_SUCH_MEMBER) { Status = STATUS_SUCCESS; } // If there wasn't a second part of the tail, it's fine
else { goto errorout; } // But if there was some other problem, let's report it.
}
}
errorout:
if (pBlockBuffer) { ExFreePool(pBlockBuffer); pBlockBuffer = NULL; }
*out_ppBdl = pBdl;
*out_Count = idxCurrentBD;
return Status;
}
NTSTATUS
RfsdNewBlock(
PRFSD_IRP_CONTEXT IrpContext,
PRFSD_VCB Vcb,
ULONG GroupHint,
ULONG BlockHint,
PULONG dwRet )
{
DbgBreak();
#if DISABLED
RTL_BITMAP BlockBitmap;
LARGE_INTEGER Offset;
ULONG Length;
PBCB BitmapBcb;
PVOID BitmapCache;
ULONG Group = 0, dwBlk, dwHint = 0;
*dwRet = 0;
dwBlk = 0XFFFFFFFF;
if (GroupHint > Vcb->NumOfGroups)
GroupHint = Vcb->NumOfGroups - 1;
if (BlockHint != 0) {
GroupHint = (BlockHint - RFSD_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
dwHint = (BlockHint - RFSD_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
}
ScanBitmap:
// Perform Prefered Group
if (Vcb->GroupDesc[GroupHint].bg_free_blocks_count) {
Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
Offset.QuadPart = Offset.QuadPart *
Vcb->GroupDesc[GroupHint].bg_block_bitmap;
if (GroupHint == 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->StreamObj,
&Offset,
Vcb->BlockSize,
PIN_WAIT,
&BitmapBcb,
&BitmapCache ) ) {
RfsdPrint((DBG_ERROR, "RfsdNewBlock: PinReading error ...\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlInitializeBitMap( &BlockBitmap,
BitmapCache,
Length );
Group = GroupHint;
if (RtlCheckBit(&BlockBitmap, dwHint) == 0) {
dwBlk = dwHint;
} else {
dwBlk = RtlFindClearBits(&BlockBitmap, 1, dwHint);
}
// We could not get new block in the prefered group.
if (dwBlk == 0xFFFFFFFF) {
CcUnpinData(BitmapBcb);
BitmapBcb = NULL;
BitmapCache = NULL;
RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
}
}
if (dwBlk == 0xFFFFFFFF) {
for(Group = 0; Group < Vcb->NumOfGroups; Group++)
if (Vcb->GroupDesc[Group].bg_free_blocks_count) {
if (Group == GroupHint)
continue;
Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
Offset.QuadPart = Offset.QuadPart * Vcb->GroupDesc[Group].bg_block_bitmap;
if (Vcb->NumOfGroups == 1) {
Length = TOTAL_BLOCKS;
} else {
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->StreamObj,
&Offset,
Vcb->BlockSize,
PIN_WAIT,
&BitmapBcb,
&BitmapCache ) ) {
RfsdPrint((DBG_ERROR, "RfsdNewBlock: PinReading error ...\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlInitializeBitMap( &BlockBitmap,
BitmapCache,
Length );
dwBlk = RtlFindClearBits(&BlockBitmap, 1, 0);
if (dwBlk != 0xFFFFFFFF) {
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -