in FreeRTOS-Plus/Source/Reliance-Edge/core/driver/inodedata.c [536:650]
static REDSTATUS TruncDindir(
CINODE *pInode,
bool *pfFreed)
{
REDSTATUS ret = 0;
if(!CINODE_IS_MOUNTED(pInode) || (pfFreed == NULL))
{
REDERROR();
ret = -RED_EINVAL;
}
else if(pInode->pDindir == NULL)
{
*pfFreed = false;
}
else
{
bool fBranch = false;
uint16_t uEntry;
/* The double indirect is definitely going to be branched (instead of
deleted) if any of its indirect pointers which are entirely prior to
the truncation boundary are non-sparse.
*/
for(uEntry = 0U; !fBranch && (uEntry < pInode->uDindirEntry); uEntry++)
{
fBranch = pInode->pDindir->aulEntries[uEntry] != BLOCK_SPARSE;
}
/* Unless we already know for a fact that the double indirect is going
to be branched, examine the contents of the indirect pointer which
straddles the truncation boundary. If the indirect is going to be
deleted, we know this indirect pointer is going away, and that might
mean the double indirect is going to be deleted also.
*/
if(!fBranch && (pInode->pDindir->aulEntries[pInode->uDindirEntry] != BLOCK_SPARSE))
{
for(uEntry = 0U; !fBranch && (uEntry < pInode->uIndirEntry); uEntry++)
{
fBranch = pInode->pIndir->aulEntries[uEntry] != BLOCK_SPARSE;
}
}
if(fBranch)
{
ret = BranchBlock(pInode, BRANCHDEPTH_DINDIR, false);
}
if(ret == 0)
{
uint32_t ulBlock = pInode->ulLogicalBlock;
uint16_t uStart = pInode->uDindirEntry; /* pInode->uDindirEntry will change. */
for(uEntry = uStart; uEntry < INDIR_ENTRIES; uEntry++)
{
/* Seek so that TruncIndir() has the correct indirect
buffer and indirect entry.
*/
ret = RedInodeDataSeek(pInode, ulBlock);
if(ret == -RED_ENODATA)
{
ret = 0;
}
if((ret == 0) && (pInode->ulIndirBlock != BLOCK_SPARSE))
{
bool fIndirFreed;
ret = TruncIndir(pInode, &fIndirFreed);
if(ret == 0)
{
/* All of the indirects after the one which straddles
the truncation boundary should definitely end up
deleted.
*/
REDASSERT((uEntry == uStart) || fIndirFreed);
/* If the double indirect is being freed, all of the
indirects should be freed too.
*/
REDASSERT(fIndirFreed || fBranch);
if(fBranch && fIndirFreed)
{
pInode->pDindir->aulEntries[uEntry] = BLOCK_SPARSE;
}
}
}
if(ret != 0)
{
break;
}
ulBlock += (INDIR_ENTRIES - pInode->uIndirEntry);
}
if(ret == 0)
{
*pfFreed = !fBranch;
if(!fBranch)
{
RedInodePutDindir(pInode);
ret = RedImapBlockSet(pInode->ulDindirBlock, false);
}
}
}
}
return ret;
}