REDSTATUS RedVolMountMetaroot()

in FreeRTOS-Plus/Source/Reliance-Edge/core/driver/volume.c [154:270]


REDSTATUS RedVolMountMetaroot(void)
{
    REDSTATUS ret;

    ret = RedIoRead(gbRedVolNum, BLOCK_NUM_FIRST_METAROOT, 1U, &gpRedCoreVol->aMR[0U]);

    if(ret == 0)
    {
        ret = RedIoRead(gbRedVolNum, BLOCK_NUM_FIRST_METAROOT + 1U, 1U, &gpRedCoreVol->aMR[1U]);
    }

    /*  Determine which metaroot is the most recent copy that was written
        completely.
    */
    if(ret == 0)
    {
        uint8_t bMR = UINT8_MAX;
        bool    fSectorCRCIsValid;

        if(MetarootIsValid(&gpRedCoreVol->aMR[0U], &fSectorCRCIsValid))
        {
            bMR = 0U;

          #ifdef REDCONF_ENDIAN_SWAP
            MetaRootEndianSwap(&gpRedCoreVol->aMR[0U]);
          #endif
        }
        else if(gpRedVolConf->fAtomicSectorWrite && !fSectorCRCIsValid)
        {
            ret = -RED_EIO;
        }
        else
        {
            /*  Metaroot is not valid, so it is ignored and there's nothing
                to do here.
            */
        }

        if(ret == 0)
        {
            if(MetarootIsValid(&gpRedCoreVol->aMR[1U], &fSectorCRCIsValid))
            {
              #ifdef REDCONF_ENDIAN_SWAP
                MetaRootEndianSwap(&gpRedCoreVol->aMR[1U]);
              #endif

                if((bMR != 0U) || (gpRedCoreVol->aMR[1U].hdr.ullSequence > gpRedCoreVol->aMR[0U].hdr.ullSequence))
                {
                    bMR = 1U;
                }
            }
            else if(gpRedVolConf->fAtomicSectorWrite && !fSectorCRCIsValid)
            {
                ret = -RED_EIO;
            }
            else
            {
                /*  Metaroot is not valid, so it is ignored and there's nothing
                    to do here.
                */
            }
        }

        if(ret == 0)
        {
            if(bMR == UINT8_MAX)
            {
                /*  Neither metaroot was valid.
                */
                ret = -RED_EIO;
            }
            else
            {
                gpRedCoreVol->bCurMR = bMR;
                gpRedMR = &gpRedCoreVol->aMR[bMR];
            }
        }
    }

    if(ret == 0)
    {
        /*  Normally the metaroot contains the highest sequence number, but the
            master block is the last block written during format, so on a
            freshly formatted volume the master block sequence number (stored in
            gpRedVolume->ullSequence) will be higher than that in the metaroot.
        */
        if(gpRedMR->hdr.ullSequence > gpRedVolume->ullSequence)
        {
            gpRedVolume->ullSequence = gpRedMR->hdr.ullSequence;
        }

        /*  gpRedVolume->ullSequence stores the *next* sequence number; to avoid
            giving the next node written to disk the same sequence number as the
            metaroot, increment it here.
        */
        ret = RedVolSeqNumIncrement();
    }

    if(ret == 0)
    {
        gpRedVolume->fMounted = true;
      #if REDCONF_READ_ONLY == 0
        gpRedVolume->fReadOnly = false;
      #endif

      #if RESERVED_BLOCKS > 0U
        gpRedCoreVol->fUseReservedBlocks = false;
      #endif
        gpRedCoreVol->ulAlmostFreeBlocks = 0U;

        gpRedCoreVol->aMR[1U - gpRedCoreVol->bCurMR] = *gpRedMR;
        gpRedCoreVol->bCurMR = 1U - gpRedCoreVol->bCurMR;
        gpRedMR = &gpRedCoreVol->aMR[gpRedCoreVol->bCurMR];
    }

    return ret;
}