⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rfsd.c

📁 This is a ReiserFs file system driver for Windows NT/2000/XP/Vista.
💻 C
📖 第 1 页 / 共 5 页
字号:
            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 + -