REDSTATUS RedImapBlockSet()

in FreeRTOS-Plus/Source/Reliance-Edge/core/driver/imap.c [106:195]


REDSTATUS RedImapBlockSet(
    uint32_t    ulBlock,
    bool        fAllocated)
{
    REDSTATUS   ret;

    if(    (ulBlock < gpRedCoreVol->ulInodeTableStartBN)
        || (ulBlock >= gpRedVolume->ulBlockCount))
    {
        REDERROR();
        ret = -RED_EINVAL;
    }
    else if(    (ulBlock >= gpRedCoreVol->ulFirstAllocableBN)
             && (    (fAllocated && (gpRedMR->ulFreeBlocks == 0U))
                  || ((!fAllocated) && (gpRedMR->ulFreeBlocks >= gpRedVolume->ulBlocksAllocable))))
    {
        /*  Attempting either to free more blocks than are allocable, or
            allocate a block when there are none available.  This could indicate
            metadata corruption.
        */
        CRITICAL_ERROR();
        ret = -RED_EFUBAR;
    }
    else
    {
      #if (REDCONF_IMAP_INLINE == 1) && (REDCONF_IMAP_EXTERNAL == 1)
        if(gpRedCoreVol->fImapInline)
        {
            ret = RedImapIBlockSet(ulBlock, fAllocated);
        }
        else
        {
            ret = RedImapEBlockSet(ulBlock, fAllocated);
        }
      #elif REDCONF_IMAP_INLINE == 1
        ret = RedImapIBlockSet(ulBlock, fAllocated);
      #else
        ret = RedImapEBlockSet(ulBlock, fAllocated);
      #endif

        /*  Any change to the allocation state of a block indicates that the
            volume is now branched.
        */
        gpRedCoreVol->fBranched = true;
    }

    /*  If a block was marked as no longer in use, discard it from the buffers.
    */
    if((ret == 0) && (!fAllocated))
    {
        ret = RedBufferDiscardRange(ulBlock, 1U);
        CRITICAL_ASSERT(ret == 0);
    }

    /*  Adjust the free/almost free block count if the block was allocable.
        Discard the block if required.
    */
    if((ret == 0) && (ulBlock >= gpRedCoreVol->ulFirstAllocableBN))
    {
        if(fAllocated)
        {
            gpRedMR->ulFreeBlocks--;
        }
        else
        {
            bool fWasAllocated;

            /*  Whether the block became free or almost free depends on its
                previous allocation state.  If it was used, then it is now
                almost free.  Otherwise, it was new and is now free.
            */
            ret = RedImapBlockGet(1U - gpRedCoreVol->bCurMR, ulBlock, &fWasAllocated);
            CRITICAL_ASSERT(ret == 0);

            if(ret == 0)
            {
                if(fWasAllocated)
                {
                    gpRedCoreVol->ulAlmostFreeBlocks++;
                }
                else
                {
                    gpRedMR->ulFreeBlocks++;
                }
            }
        }
    }

    return ret;
}