static REDSTATUS BranchOneBlock()

in FreeRTOS-Plus/Source/Reliance-Edge/core/driver/inodedata.c [1649:1751]


static REDSTATUS BranchOneBlock(
    uint32_t   *pulBlock,
    void      **ppBuffer,
    uint16_t    uBFlag)
{
    REDSTATUS   ret = 0;

    if(pulBlock == NULL)
    {
        REDERROR();
        ret = -RED_EINVAL;
    }
    else
    {
        ALLOCSTATE  state = ALLOCSTATE_FREE;
        uint32_t    ulPrevBlock = *pulBlock;

        if(ulPrevBlock != BLOCK_SPARSE)
        {
            ret = RedImapBlockState(ulPrevBlock, &state);
        }

        if(ret == 0)
        {
            if(state == ALLOCSTATE_NEW)
            {
                /*  Block is already branched, so simply get it buffered dirty
                    if requested.
                */
                if(ppBuffer != NULL)
                {
                    if(*ppBuffer != NULL)
                    {
                        RedBufferDirty(*ppBuffer);
                    }
                    else
                    {
                        ret = RedBufferGet(ulPrevBlock, uBFlag | BFLAG_DIRTY, ppBuffer);
                    }
                }
            }
            else
            {
                /*  Block does not exist or is committed state, so allocate a
                    new block for the branch.
                */
                ret = RedImapAllocBlock(pulBlock);

                if(ret == 0)
                {
                    if(ulPrevBlock == BLOCK_SPARSE)
                    {
                        /*  Block did not exist previously, so just get it
                            buffered if requested.
                        */
                        if(ppBuffer != NULL)
                        {
                            if(*ppBuffer != NULL)
                            {
                                /*  How could there be an existing buffer when
                                    the block did not exist?
                                */
                                REDERROR();
                                ret = -RED_EINVAL;
                            }
                            else
                            {
                                ret = RedBufferGet(*pulBlock, (uint16_t)((uint32_t)uBFlag | BFLAG_NEW | BFLAG_DIRTY), ppBuffer);
                            }
                        }
                    }
                    else
                    {
                        /*  Branch the buffer for the committed state block to
                            the newly allocated location.
                        */
                        if(ppBuffer != NULL)
                        {
                            if(*ppBuffer == NULL)
                            {
                                ret = RedBufferGet(ulPrevBlock, uBFlag, ppBuffer);
                            }

                            if(ret == 0)
                            {
                                RedBufferBranch(*ppBuffer, *pulBlock);
                            }
                        }

                        /*  Mark the committed state block almost free.
                        */
                        if(ret == 0)
                        {
                            ret = RedImapBlockSet(ulPrevBlock, false);
                        }
                    }
                }
            }
        }
    }

    return ret;
}