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;
}