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

📄 sectormgr.cpp

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

    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 + -