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

📄 rfsd.c

📁 This is a ReiserFs file system driver for Windows NT/2000/XP/Vista.
💻 C
📖 第 1 页 / 共 5 页
字号:
            } else {

                CcUnpinData(BitmapBcb);
                BitmapBcb = NULL;
                BitmapCache = NULL;

                RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
            }
        }
    }
        
    if (dwBlk < Length) {

        RtlSetBits(&BlockBitmap, dwBlk, 1);

        CcSetDirtyPinnedData(BitmapBcb, NULL );

        RfsdRepinBcb(IrpContext, BitmapBcb);

        CcUnpinData(BitmapBcb);

        RfsdAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);

        *dwRet = dwBlk + RFSD_FIRST_DATA_BLOCK + Group * BLOCKS_PER_GROUP;

        //Updating Group Desc / Superblock
        Vcb->GroupDesc[Group].bg_free_blocks_count--;
        RfsdSaveGroup(IrpContext, Vcb, Group);

        Vcb->SuperBlock->s_free_blocks_count--;
        RfsdSaveSuper(IrpContext, Vcb);

        {
            ULONG i=0;
            for (i=0; i < Vcb->NumOfGroups; i++)
            {
                if ((Vcb->GroupDesc[i].bg_block_bitmap == *dwRet) ||
                    (Vcb->GroupDesc[i].bg_inode_bitmap == *dwRet) ||
                    (Vcb->GroupDesc[i].bg_inode_table == *dwRet) ) {
                    DbgBreak();
                    GroupHint = Group;
                    goto ScanBitmap;
                }
            }
        }

        return STATUS_SUCCESS;
    }

    return STATUS_DISK_FULL;
#endif
}

NTSTATUS
RfsdFreeBlock(
    PRFSD_IRP_CONTEXT IrpContext,
    PRFSD_VCB Vcb,
    ULONG     Block )
{
DbgBreak();
#if DISABLED

	RTL_BITMAP      BlockBitmap;
    LARGE_INTEGER   Offset;
    ULONG           Length;

    PBCB            BitmapBcb;
    PVOID           BitmapCache;

    ULONG           Group, dwBlk;
    BOOLEAN         bModified = FALSE;

    if ( Block < RFSD_FIRST_DATA_BLOCK || 
         (Block / BLOCKS_PER_GROUP) >= Vcb->NumOfGroups) {

        DbgBreak();
        return STATUS_INVALID_PARAMETER;
    }

    RfsdPrint((DBG_INFO, "RfsdFreeBlock: Block %xh to be freed.\n", Block));

    Group = (Block - RFSD_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;

    dwBlk = (Block - RFSD_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
    
    {
        Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
        Offset.QuadPart = Offset.QuadPart * Vcb->GroupDesc[Group].bg_block_bitmap;

        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, "RfsdDeleteBlock: PinReading error ...\n"));
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        RtlInitializeBitMap( &BlockBitmap,
                             BitmapCache,
                             Length );

        if (RtlCheckBit(&BlockBitmap, dwBlk) == 0) {
            
        } else {
            RtlClearBits(&BlockBitmap, dwBlk, 1);
            bModified = TRUE;
        }

        if (!bModified) {

            CcUnpinData(BitmapBcb);
            BitmapBcb = NULL;
            BitmapCache = NULL;

            RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
        }
    }
        
    if (bModified) {

        CcSetDirtyPinnedData(BitmapBcb, NULL );

        RfsdRepinBcb(IrpContext, BitmapBcb);

        CcUnpinData(BitmapBcb);

        RfsdAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);

        //Updating Group Desc / Superblock
        Vcb->GroupDesc[Group].bg_free_blocks_count++;
        RfsdSaveGroup(IrpContext, Vcb, Group);

        Vcb->SuperBlock->s_free_blocks_count++;
        RfsdSaveSuper(IrpContext, Vcb);

        return STATUS_SUCCESS;
    }

    return STATUS_UNSUCCESSFUL;
#endif
}


NTSTATUS
RfsdExpandBlock(
    PRFSD_IRP_CONTEXT IrpContext,
    PRFSD_VCB   Vcb,
    PRFSD_FCB   Fcb,
    ULONG   dwContent,
    ULONG   Index,
    ULONG   layer,
    BOOLEAN bNew,
    ULONG   *dwRet )
{
DbgBreak();
#if DISABLED

    ULONG       *pData = NULL;
    ULONG       i = 0, j = 0, temp = 1;
    ULONG       dwNewBlk = 0, dwBlk = 0;
    BOOLEAN     bDirty = FALSE;
    NTSTATUS    Status = STATUS_SUCCESS;

    PRFSD_INODE       Inode  = Fcb->Inode;
    PRFSD_SUPER_BLOCK RfsdSb = Vcb->SuperBlock;

    pData = (ULONG *) ExAllocatePool(PagedPool, Vcb->BlockSize);

    if (!pData) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory(pData, Vcb->BlockSize);

    if (bNew) {

        if (layer == 0) {

            if (IsDirectory(Fcb)) {

                PRFSD_DIR_ENTRY2 pEntry;

                pEntry = (PRFSD_DIR_ENTRY2) pData;
                pEntry->rec_len = (USHORT)(Vcb->BlockSize);

                if (!RfsdSaveBlock(IrpContext, Vcb, dwContent, (PVOID)pData)) {

                    Status = STATUS_UNSUCCESSFUL;
                    goto errorout;
                }

            } else {

                LARGE_INTEGER   Offset;
            
                Offset.QuadPart  = (LONGLONG) dwContent;
                Offset.QuadPart = Offset.QuadPart * Vcb->BlockSize;

                RfsdRemoveMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
            }
        } else {

            if (!RfsdSaveBlock(IrpContext, Vcb, dwContent, (PVOID)pData)) {

                Status = STATUS_UNSUCCESSFUL;
                goto errorout;
            }
        }
    }

    if (layer == 0) {

        dwNewBlk = dwContent;

    } else if (layer <= 3) {

        if (!bNew) {

            if (!RfsdLoadBlock(Vcb, dwContent, (void *)pData)) {

                Status = STATUS_UNSUCCESSFUL;
                goto errorout;
            }
        }

        temp = 1 << ((BLOCK_BITS - 2) * (layer - 1));

        i = Index / temp;
        j = Index % temp;

        dwBlk = pData[i];

        if (dwBlk == 0) {

            Status = RfsdNewBlock(
                        IrpContext,
                        Vcb, 0,
                        dwContent,
                       &dwBlk);

            if (!NT_SUCCESS(Status)) {

                RfsdPrint((DBG_ERROR, "RfsdExpandBlock: get new block error.\n"));
                goto errorout;
            }

            Inode->i_blocks += (Vcb->BlockSize / SECTOR_SIZE);

            pData[i] = dwBlk;
            bDirty = TRUE;
        }

        Status = RfsdExpandBlock(
                    IrpContext,
                    Vcb, Fcb,
                    dwBlk, j,
                    layer - 1,
                    bDirty,
                    &dwNewBlk );

        if (!NT_SUCCESS(Status))
        {
            RfsdPrint((DBG_ERROR, "RfsdExpandBlockk: ... error recuise...\n"));
            goto errorout;
        }
        
        if (bDirty)
        {
            RfsdSaveBlock( IrpContext,
                            Vcb, dwContent,
                            (void *)pData );
        }
    }

errorout:

    if (pData)
        ExFreePool(pData);

    if (NT_SUCCESS(Status) && dwRet)
        *dwRet = dwNewBlk;

    return Status;
#endif
}


NTSTATUS
RfsdExpandInode(
    IN PRFSD_IRP_CONTEXT    IrpContext,
    IN PRFSD_VCB            Vcb,
    IN PRFSD_FCB            Fcb,
    OUT PULONG              dwRet
    )
{
DbgBreak();
#if DISABLED

    ULONG dwSizes[RFSD_BLOCK_TYPES];
    ULONG Index = 0;
    ULONG dwTotal = 0;
    ULONG dwBlk = 0, dwNewBlk = 0;
    ULONG    i;
    NTSTATUS Status = STATUS_SUCCESS;
    BOOLEAN  bNewBlock = FALSE;

    PRFSD_INODE Inode = Fcb->Inode;

    Index = (ULONG)(Fcb->Header.AllocationSize.QuadPart >> BLOCK_BITS);

    for (i = 0; i < RFSD_BLOCK_TYPES; i++) {
        dwSizes[i] = Vcb->dwData[i];
        dwTotal += dwSizes[i];
    }

    if (Index >= dwTotal) {

        RfsdPrint((DBG_ERROR, "RfsdExpandInode: beyond the maxinum size of an inode.\n"));
        return STATUS_UNSUCCESSFUL;
    }

    for (i = 0; i < RFSD_BLOCK_TYPES; i++) {

        if (Index < dwSizes[i]) {

            dwBlk = Inode->i_block[i==0 ? (Index):(i + RFSD_NDIR_BLOCKS - 1)];

            if (dwBlk == 0) {

                Status = RfsdNewBlock(
                            IrpContext,
                            Vcb,
                            Fcb->BlkHint ? 0 : ((Fcb->RfsdMcb->Inode - 1) / INODES_PER_GROUP),
                            Fcb->BlkHint,
                            &dwBlk );

                if (!NT_SUCCESS(Status) ) {
                    RfsdPrint((DBG_ERROR, "RfsdExpandInode: get new block error.\n"));
                    break;
                }

                Inode->i_block[i==0 ? (Index):(i + RFSD_NDIR_BLOCKS - 1)] = dwBlk;

                Inode->i_blocks += (Vcb->BlockSize / SECTOR_SIZE);

                bNewBlock = TRUE;
            }

            Status = RfsdExpandBlock (
                            IrpContext,
                            Vcb, Fcb,
                            dwBlk, Index,
                            i, bNewBlock,
                            &dwNewBlk  ); 

            if (NT_SUCCESS(Status)) {
                Fcb->Header.AllocationSize.QuadPart += Vcb->BlockSize;
            }

            break;
        }

        Index -= dwSizes[i];
    }

    RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, Inode);

    if (NT_SUCCESS(Status)) {
        if (dwNewBlk) {
            if (dwRet) {
                Fcb->BlkHint = dwNewBlk+1;
                *dwRet = dwNewBlk;

                RfsdPrint((DBG_INFO, "RfsdExpandInode: %S (%xh) i=%2.2xh Index=%8.8xh New Block=%8.8xh\n",
                           Fcb->RfsdMcb->ShortName.Buffer, Fcb->RfsdMcb->Inode, i, Index, dwNewBlk));
            }
        } else {
            DbgBreak();
            Status = STATUS_UNSUCCESSFUL;
        }
    }

    return Status;
#endif
}

NTSTATUS
RfsdNewInode(
            PRFSD_IRP_CONTEXT IrpContext,
            PRFSD_VCB Vcb,
            ULONG   GroupHint,
            ULONG   Type,
            PULONG  Inode )
{
DbgBreak();
#if DISABLED

    RTL_BITMAP      InodeBitmap;
    PVOID           BitmapCache;
    PBCB            BitmapBcb;

    ULONG           Group, i, j;
    ULONG           Average, Length;
    LARGE_INTEGER   Offset;
    
    ULONG           dwInode;

    *Inode = dwInode = 0XFFFFFFFF;

repeat:

    Group = i = 0;
    
    if (Type == RFSD_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) {

            for (j = 0; j < Vcb->NumOfGroups; j++) {

                if (Vcb->GroupDesc[j].bg_free_inodes_count >= Average) {
                    if (!Group || (Vcb->GroupDesc[j].bg_free_blocks_count >
                                   Vcb->GroupDesc[Group].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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -