📄 compactor.cpp
字号:
}
//----- 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)§orMappingInfo, 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)§orMappingInfo, 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(§orMappingInfo, 0xFF, sizeof(SectorMappingInfo));
MarkSectorDirty(sectorMappingInfo);
if(!FMD.pWriteSector(physicalSectorAddr, NULL, (PSectorInfo)§orMappingInfo, 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 + -