📄 sectormgr.cpp
字号:
m_dirtyList.Deinit();
return TRUE;
}
BOOL SectorMgr::AddSectorsToList (ListType listType, SECTOR_ADDR startingSectorAddr, DWORD dwNumSectors)
{
return m_lists[listType].AddSectors (startingSectorAddr, dwNumSectors);
}
DWORD SectorMgr::AreSectorsInList (ListType listType, DWORD dwStartSector, DWORD dwNumSectors)
{
return m_lists[listType].AreSectorsInList (dwStartSector, dwNumSectors);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: SectorMgr::UnmarkSectorsAsFree()
Description: Unmarks the specified physical sectors as being FREE.
Notes: Currently, this routine assumes that the specified physical
sectors are consecutively arranged starting from the starting
sector address of the node containing the free sectors to
unmark.
Returns: Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL SectorMgr::UnmarkSectorsAsFree(SECTOR_ADDR startingPhysicalSectorAddr, DWORD dwNumSectors)
{
SMList* pFreeList = &m_lists[Free];
PSMNode pPrevNode = NULL;
DWORD endSectorAddr = startingPhysicalSectorAddr + dwNumSectors - 1;
//----- 1. Obtain a pointer to the first node in the FREE sector list -----
if((pFreeList->m_cursor = pFreeList->m_head) == NULL)
{
ReportError((TEXT("FLASHDRV.DLL:SectorMgr::UnmarkSectorsAsFree() - Unable to unmark sectors 0x%08x - 0x%08x as FREE\r\n"),
startingPhysicalSectorAddr, endSectorAddr));
return FALSE;
}
//----- 2. Find the node that falls within the specified range... -----
while ((pFreeList->m_cursor->startSectorAddr < startingPhysicalSectorAddr) ||
(pFreeList->m_cursor->startSectorAddr > endSectorAddr))
{
pPrevNode = pFreeList->m_cursor;
pFreeList->m_cursor = pFreeList->m_cursor->pNext;
if (pFreeList->m_cursor == NULL)
{
// The block doesn't have any free sectors.
return TRUE;
}
}
//----- 3. Remove the specified sectors from this node -----
while (pFreeList->m_cursor->startSectorAddr <= endSectorAddr)
{
pFreeList->m_dwNumSectors--;
pFreeList->m_cursor->startSectorAddr++;
}
//----- 4. If this is the last physical sector address for this node, remove the node from the free sector list -----
if(pFreeList->m_cursor->startSectorAddr >= (pFreeList->m_cursor->lastSectorAddr+1))
{
if (pPrevNode)
{
// Not removing head node
pPrevNode->pNext = pFreeList->m_cursor->pNext;
}
else
{
// Removing head node
pFreeList->m_head = pFreeList->m_cursor->pNext;
ASSERT(pFreeList->m_head != NULL);
}
if (pFreeList->m_cursor == pFreeList->m_tail)
{
pFreeList->m_tail = pPrevNode;
}
if(LocalFree(pFreeList->m_cursor) != NULL)
{
ReportError((TEXT("FLASHDRV.DLL:SectorMgr::UnmarkSectorsAsFree() - Unable to free physical sector node memory!\r\n")));
}
pFreeList->m_cursor = NULL;
}
return TRUE;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: SectorMgr::GetNextFreeSector()
Description: Returns the next FREE physical sector (if there is one). This
physical sector is also REMOVED from the free sector list.
Notes: This function automatically determines when/if the Compactor
needs to be restarted in order to reclaim DIRTY sectors and
recycle them into FREE sectors. However, if bCritical == TRUE,
the compaction step is SKIPPED and free sectors are returned
until the supply is exhausted.
Returns: Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL SectorMgr::GetNextFreeSector(PSECTOR_ADDR pPhysicalSectorAddr, BOOL bCritical)
{
SMList* pFreeList = &m_lists[Free];
//----- 1. Check the parameters to insure they are legitimate -----
if(pPhysicalSectorAddr == NULL)
{
goto GETFREE_ERROR;
}
//----- 2. Is this request critical? If so, SKIP compaction and simply try to fulfill the request -----
if(m_pCompactor && (bCritical == FALSE))
{
//----- 3. Request is NOT critical; do we need to start the compactor? -----
if(pFreeList->m_dwNumSectors <= m_dwCritCompactThreshold)
{
DWORD dwCritPriority = g_dwCompactionCritPrio256;
if (dwCritPriority == 0xffffffff)
{
// Setting priority to -1 means that we should use the caller's thread priority if it is above normal
dwCritPriority = min (CeGetThreadPriority (GetCurrentThread()), THREAD_PRIORITY_NORMAL + 248);
}
//----- 4. Critical threshold exceeded! We must compact BEFORE we can return a free sector. -----
// NOTE: This call is SYNCHRONOUS (a.k.a. it will not return until the compaction stage completes)
if(!m_pCompactor->StartCompactor(dwCritPriority, CRITICAL_SECTORS_TO_RECLAIM, TRUE))
{
ReportError((TEXT("FLASHDRV.DLL:SectorMgr::GetNextFreeSector() - Unable to start compactor in critical situation!!!\r\n")));
}
// Compaction stage complete - check to make sure that some free sectors were reclaimed. If no free sectors
// were reclaimed, then we must FAIL
if(pFreeList->m_dwNumSectors <= m_dwCritCompactThreshold)
{
ReportError((TEXT("FLASHDRV.DLL:SectorMgr::GetNextFreeSector() - Unable to reclaim any free sectors in a critical compaction stage. Media must be full.\r\n")));
goto GETFREE_ERROR;
}
}
else if(pFreeList->m_dwNumSectors < m_dwNumDirtySectors)
{
//----- 5. "Service" threshold exceeded (i.e. there are more DIRTY sectors than FREE sectors on the media) -----
// Start the compactor in the background (asynchronously) to reclaim these sectors
if(!m_pCompactor->StartCompactor(g_dwCompactionPrio256, m_dwNumDirtySectors, FALSE))
{
ReportError((TEXT("FLASHDRV.DLL:SectorMgr::GetNextFreeSector() - Unable to start compactor in background!!!\r\n")));
}
}
}
//----- 6. Are we out of free sectors entirely? -----
if(((pFreeList->m_cursor = pFreeList->m_head) == NULL) || (pFreeList->m_dwNumSectors == 0))
{
ReportError((TEXT("FLASHDRV.DLL:SectorMgr::GetNextFreeSector() - Unable to retreive free physical sector... ALL OUT!!!\r\n")));
goto GETFREE_ERROR;
}
//----- 7. Copy the physical sector address -----
*pPhysicalSectorAddr = pFreeList->m_cursor->startSectorAddr++;
//----- 8. If this is the last physical sector address for this node, remove the node from the free sector list -----
if(pFreeList->m_cursor->startSectorAddr >= (pFreeList->m_cursor->lastSectorAddr+1))
{
pFreeList->m_head = pFreeList->m_head->pNext;
if(LocalFree(pFreeList->m_cursor) != NULL)
{
ReportError((TEXT("FLASHDRV.DLL:SectorMgr::GetNextFreeSector() - Unable to free physical sector %x node memory!\r\n"), *pPhysicalSectorAddr));
goto GETFREE_ERROR;
}
pFreeList->m_cursor = NULL;
}
//----- 9. Decrease the number of free sectors -----
pFreeList->m_dwNumSectors--;
return TRUE;
GETFREE_ERROR:
return FALSE;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: SectorMgr::GetNumberOfFreeSectors()
Description: Returns the number of FREE physical sectors.
Returns: Number of free physical sectors.
------------------------------------------------------------------------------*/
DWORD SectorMgr::GetNumberOfFreeSectors(VOID)
{
return m_lists[Free].m_dwNumSectors;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: SectorMgr::IsBlockFree()
Description: Determines whether entire block contains free sectors.
------------------------------------------------------------------------------*/
BOOL SectorMgr::IsBlockFree(BLOCK_ID blockID)
{
SECTOR_ADDR startSector = GetStartSectorInBlock(blockID);
return m_lists[Free].AreSectorsInList(startSector, m_pRegion->dwSectorsPerBlock) == EntirelyInList;
}
//******************************************************************************//
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: SectorMgr::MarkSectorsAsDirty()
Description: Marks the specified physical sectors as being DIRTY.
Returns: Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL SectorMgr::MarkSectorsAsDirty(SECTOR_ADDR startingPhysicalSectorAddr, DWORD dwNumSectors)
{
// Since dwNumSectors always is 1, no need to check if the sectors span a block
// This code needs to be modified if the assumption no longer holds.
DWORD dwBlock = GetBlockFromSector (startingPhysicalSectorAddr);
if (dwBlock < m_pRegion->dwStartPhysBlock || dwBlock >= (m_pRegion->dwStartPhysBlock + m_pRegion->dwNumPhysBlocks))
{
RETAILMSG (1, (TEXT("MarkSectorsAsDirty: Invalid Block 0x%x\r\n"), dwBlock));
return FALSE;
}
// RETAILMSG(1,(TEXT("Marking sector %d(block:%d) dirty\r\n"),startingPhysicalSectorAddr,dwBlock));
m_dirtyList.AddDirtySectors (dwBlock, dwNumSectors);
m_dwNumDirtySectors += dwNumSectors;
return TRUE;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: SectorMgr::UnmarkSectorsAsDirty()
Description: Unmarks the specified physical sectors as being DIRTY.
Returns: Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL SectorMgr::UnmarkSectorsAsDirty(SECTOR_ADDR startingPhysicalSectorAddr, DWORD dwNumSectors)
{
// Since dwNumSectors always is 1, no need to check if the sectors span a block
// This code needs to be modified if the assumption no longer holds.
DWORD dwBlock = GetBlockFromSector (startingPhysicalSectorAddr);
if (dwBlock < m_pRegion->dwStartPhysBlock || dwBlock >= (m_pRegion->dwStartPhysBlock + m_pRegion->dwNumPhysBlocks))
{
RETAILMSG (1, (TEXT("UnmarkSectorsAsDirty: Invalid Block 0x%x\r\n"), dwBlock));
return FALSE;
}
// RETAILMSG(1,(TEXT("UnMarking sector %d(block:%d) dirty\r\n"),startingPhysicalSectorAddr,dwBlock));
if (!m_dirtyList.RemoveDirtySectors (dwBlock, dwNumSectors))
return FALSE;
ASSERT (m_dwNumDirtySectors >= dwNumSectors);
m_dwNumDirtySectors -= dwNumSectors;
return TRUE;
}
DWORD SectorMgr::GetDirtyCount(BLOCK_ID blockID)
{
return m_dirtyList.GetDirtyCount (blockID);
}
//------------------------- General Purpose Public Routines --------------------------
SECTOR_ADDR SectorMgr::GetStartSectorInBlock (DWORD dwBlockID)
{
return m_pFal->GetStartPhysSector() + (dwBlockID - m_pRegion->dwStartPhysBlock) * m_pRegion->dwSectorsPerBlock;
}
BLOCK_ID SectorMgr::GetBlockFromSector (DWORD dwSector)
{
return m_pRegion->dwStartPhysBlock + (dwSector - m_pFal->GetStartPhysSector()) / m_pRegion->dwSectorsPerBlock;
}
//-------------------------------- Helper Functions -------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -