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

📄 compactor.cpp

📁 基于WINCE的文件系统FAL驱动
💻 CPP
📖 第 1 页 / 共 3 页
字号:
                }

                //----- For debugging purposes, print out where the MAPPED data is being moved... -----
                DEBUGMSG(ZONE_COMPACTOR, (TEXT("FLASHDRV.DLL     >>> Moving data from physical sector 0x%08x to physical sector 0x%08x\r\n"), 
                                                physicalSectorAddr, newPhysicalSectorAddr));        


                //----- 8. Start the write operation (used to safeguard against power failure conditions) -----
                //         The rationale is as follows: If we lose power during before the data is written
                //         to the media, this bit should be set and this will allow us to detect that a 
                //         WRITE was in progress when the power failed.
                MarkSectorFree(sectorMappingInfo);
                MarkSectorWriteInProgress(sectorMappingInfo);
    
                if(!FMD.pWriteSector(newPhysicalSectorAddr, NULL, (PSectorInfo)&sectorMappingInfo, 1))
                {
                    ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to start write operation.  FMD_WriteSector() failed.\r\n")));
                                                
                    // WRITE operation failed, try to recover only if it is within the maximum number of nested compactions...
                    if(++m_dwNestedCompactions < MAX_NUM_NESTED_COMPACTIONS)
                    {
                        if(!m_pFal->HandleWriteFailure(newPhysicalSectorAddr))
                        {
                            ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to handle the WRITE failure to sector 0x%08x\r\n"), physicalSectorAddr));
                            goto COMPACTION_ERROR;
                        }
                        m_dwNestedCompactions--;
                    }
                    continue;   
                }


                //----- 9. Invoke the FLASH Media Driver (FMD) to write the sector data to the media -----
                //         NOTE: The write will be marked as "completed" if FMD_WriteSector() succeeeds
                //
                MarkSectorWriteCompleted(sectorMappingInfo);
                if(!FMD.pWriteSector(newPhysicalSectorAddr, m_pSectorData, (PSectorInfo)&sectorMappingInfo, 1))  
                {   
                    ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to write to physical sector 0x%08x!\r\n"), newPhysicalSectorAddr));
                        
                    // WRITE operation failed, try to recover only if it is within the maximum number of nested compactions...
                    if(++m_dwNestedCompactions < MAX_NUM_NESTED_COMPACTIONS)
                    {
                        if(!m_pFal->HandleWriteFailure(newPhysicalSectorAddr))
                        {
                            ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to handle the WRITE failure to sector 0x%08x\r\n"), physicalSectorAddr));
                            goto COMPACTION_ERROR;
                        }
                        m_dwNestedCompactions--;
                    }
                    continue;
                }

                //----- 10. Perform the LOGICAL -> PHYSICAL mapping -----
                if(!m_pMap->MapLogicalSector(sectorMappingInfo.logicalSectorAddr, newPhysicalSectorAddr, &physicalSectorAddr))
                {
                    ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to map logical sector 0x%08x to physical sector 0x%08x\r\n"), 
                                       sectorMappingInfo.logicalSectorAddr, newPhysicalSectorAddr));
                    goto COMPACTION_ERROR;
                }

                //----- 11. Mark the "stale data" in the existing physical sector as DIRTY -----
                //          NOTE: This is done in case of a power failure before the whole
                //                block is compacted.
                        
                //NOTE: Since we don't know the contents of the sector mapping info for this physical sector,
                //      we can safely write all '1's (except the bit used to indicate the sector is "dirty").
                memset(&sectorMappingInfo, 0xFF, sizeof(SectorMappingInfo));
                MarkSectorDirty(sectorMappingInfo);                   

                if(!FMD.pWriteSector(physicalSectorAddr, NULL, (PSectorInfo)&sectorMappingInfo, 1))
                {   
                    ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to mark old physical sector 0x%08x as DIRTY!\r\n"), physicalSectorAddr));
                    
                    // WRITE operation failed, try to recover only if it is within the maximum number of nested compactions...
                    if(++m_dwNestedCompactions < MAX_NUM_NESTED_COMPACTIONS)
                    {
                        if(!m_pFal->HandleWriteFailure(physicalSectorAddr))
                        {
                            ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to handle the WRITE failure to sector 0x%08x\r\n"), physicalSectorAddr));
                            goto COMPACTION_ERROR;
                        }
                        m_dwNestedCompactions--;
                    }
                    continue;
                }

                //----- 12. At this point, the WRITE operation has completed successfully. -----
                break;
            }
        }

    }   

    //----- 13. Compaction on this block is complete.  Erase the block and recycle the DIRTY sectors -----
    //          into FREE sectors.
    if(!FMD.pEraseBlock(compactionBlockID))
    {       
        ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to erase block %d!!!  These sectors can't be reused...\r\n"), compactionBlockID));
        
        if(!IsBlockBad(compactionBlockID))
        {
            if(!FMD.pSetBlockStatus(compactionBlockID, BLOCK_STATUS_BAD))
            {
                ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to mark block %d as BAD!!!\r\n"), compactionBlockID));
            }
        }

        if(!m_pSectorMgr->MarkBlockUnusable(compactionBlockID))
        {
            ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - m_pSectorMgr->MarkBlockUnusable(%d) failed.\r\n"), compactionBlockID));
        }

    }else
    {
        //----- 14. Inform the Sector Manager that these sectors are now FREE. -----
        //          NOTE: Notice that the starting address for the FREE sectors is
        //                (physicalSectorAddr - m_pFlashMediaInfo->wSectorsPerBlock)
        //                This is to account for the fact that physicalSectorAddr
        //                was incremented (above) and points to the next block!
        if(!m_pSectorMgr->AddSectorsToList (SectorMgr::Free, (physicalSectorAddr - m_pRegion->dwSectorsPerBlock), m_pRegion->dwSectorsPerBlock))
        {
            ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to mark physical sectors 0x%08x - 0x%08x as free...\r\n"), 
                               physicalSectorAddr, (physicalSectorAddr + m_pRegion->dwSectorsPerBlock) ));
        }
    }

    return dwNumDirtySectorsFound;

COMPACTION_ERROR:
    return 0;
}



/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       Compactor::GetNextCompactionBlock()

Description:    Gets the next FLASH block on the media to compact based upon
                the specified "current" compaction block.

Returns:        ID for the next block to compact.
------------------------------------------------------------------------------*/
BLOCK_ID Compactor::GetNextCompactionBlock(BLOCK_ID blockID)
{
    BLOCK_ID nextBlockID;
    static BOOL bRandomBlock = FALSE;
    
    if (m_bCritical) 
    {
        nextBlockID = GetDirtiestBlock(blockID);
    }    
    else
    {        
        // Idle compaction will alternate between compacting the dirtiest block
        // and compacting a random block to provide even wear leveling
        
        if (bRandomBlock)
        {
            nextBlockID = GetNextRandomBlock(blockID);

            // Don't bother to compact a block that is completely free
            if ((nextBlockID == INVALID_BLOCK_ID) || m_pSectorMgr->IsBlockFree (blockID))
            {
                nextBlockID = GetDirtiestBlock(blockID);
            }
        }
        else
        {
            nextBlockID = GetDirtiestBlock(blockID);
        }

        // Toggle the random block flag
        bRandomBlock = !bRandomBlock;        
    }
    
    return nextBlockID;
}

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       Compactor::GetDirtiestBlock()

Description:    Gets the next FLASH block on the media to compact based upon
                the specified "current" compaction block.

Returns:        ID for the next block to compact.
------------------------------------------------------------------------------*/
BLOCK_ID Compactor::GetDirtiestBlock(BLOCK_ID blockID)
{
    DWORD dwEndBlock = m_pRegion->dwStartPhysBlock + m_pRegion->dwNumPhysBlocks - 1;
    
    DWORD iBlock = (blockID + 1) <= dwEndBlock ? blockID + 1: m_pRegion->dwStartPhysBlock;
    DWORD dwBestBlock = iBlock;
    DWORD dwMaxDirtySectors = 0;
    
    while (iBlock != blockID)
    {
        DWORD dwDirtyCount = m_pSectorMgr->GetDirtyCount (iBlock);
        
        if (dwDirtyCount > dwMaxDirtySectors)
        {
            dwBestBlock = iBlock;
            dwMaxDirtySectors = dwDirtyCount;
        }

        iBlock++;
        if (iBlock > dwEndBlock)
        {
            iBlock = m_pRegion->dwStartPhysBlock;        
        }
    }

    if (!IsBlockWriteable(dwBestBlock))
    {
        RETAILMSG(1, (TEXT("FLASHDRV.DLL:Compactor::GetNextCompactionBlock() Error: Cannot write to block %x!\r\n"), dwBestBlock));
        ASSERT (0);
        return INVALID_BLOCK_ID;
    }    

    return dwBestBlock;
}




/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       Compactor::GetNextRandomBlock()

Description:    Gets the next FLASH block on the media to compact based upon
                the specified "current" compaction block.

Returns:        ID for the next block to compact.
------------------------------------------------------------------------------*/
BLOCK_ID Compactor::GetNextRandomBlock(BLOCK_ID blockID)
{
    DWORD dwNextBlock = INVALID_BLOCK_ID;
    DWORD dwLoopCount = 0;
        
    do
    {           
        dwNextBlock = m_pRegion->dwStartPhysBlock + (Random() % m_pRegion->dwNumPhysBlocks);

        if (++dwLoopCount > m_pRegion->dwNumPhysBlocks)
        {
            return INVALID_BLOCK_ID;
        }
        
    } while (!IsBlockWriteable(dwNextBlock));
  
    return dwNextBlock;
}

DWORD WINAPI CompactorThread(LPVOID lpParameter)
{
    Compactor* compactor = (Compactor*)lpParameter;
    return compactor->CompactorThread();
}

⌨️ 快捷键说明

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