UBIFS: fix LPT out-of-space bug (again)
The function to traverse and dirty the LPT was still not dirtying all nodes, with the result that the LPT could run out of space. Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
This commit is contained in:
parent
6f7ab6d458
commit
4a29d2005b
1 changed files with 32 additions and 12 deletions
|
@ -556,23 +556,23 @@ static int write_cnodes(struct ubifs_info *c)
|
|||
}
|
||||
|
||||
/**
|
||||
* next_pnode - find next pnode.
|
||||
* next_pnode_to_dirty - find next pnode to dirty.
|
||||
* @c: UBIFS file-system description object
|
||||
* @pnode: pnode
|
||||
*
|
||||
* This function returns the next pnode or %NULL if there are no more pnodes.
|
||||
* This function returns the next pnode to dirty or %NULL if there are no more
|
||||
* pnodes. Note that pnodes that have never been written (lnum == 0) are
|
||||
* skipped.
|
||||
*/
|
||||
static struct ubifs_pnode *next_pnode(struct ubifs_info *c,
|
||||
struct ubifs_pnode *pnode)
|
||||
static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c,
|
||||
struct ubifs_pnode *pnode)
|
||||
{
|
||||
struct ubifs_nnode *nnode;
|
||||
int iip;
|
||||
|
||||
/* Try to go right */
|
||||
nnode = pnode->parent;
|
||||
iip = pnode->iip + 1;
|
||||
if (iip < UBIFS_LPT_FANOUT) {
|
||||
/* We assume here that LEB zero is never an LPT LEB */
|
||||
for (iip = pnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) {
|
||||
if (nnode->nbranch[iip].lnum)
|
||||
return ubifs_get_pnode(c, nnode, iip);
|
||||
}
|
||||
|
@ -583,8 +583,11 @@ static struct ubifs_pnode *next_pnode(struct ubifs_info *c,
|
|||
nnode = nnode->parent;
|
||||
if (!nnode)
|
||||
return NULL;
|
||||
/* We assume here that LEB zero is never an LPT LEB */
|
||||
} while (iip >= UBIFS_LPT_FANOUT || !nnode->nbranch[iip].lnum);
|
||||
for (; iip < UBIFS_LPT_FANOUT; iip++) {
|
||||
if (nnode->nbranch[iip].lnum)
|
||||
break;
|
||||
}
|
||||
} while (iip >= UBIFS_LPT_FANOUT);
|
||||
|
||||
/* Go right */
|
||||
nnode = ubifs_get_nnode(c, nnode, iip);
|
||||
|
@ -593,12 +596,29 @@ static struct ubifs_pnode *next_pnode(struct ubifs_info *c,
|
|||
|
||||
/* Go down to level 1 */
|
||||
while (nnode->level > 1) {
|
||||
nnode = ubifs_get_nnode(c, nnode, 0);
|
||||
for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++) {
|
||||
if (nnode->nbranch[iip].lnum)
|
||||
break;
|
||||
}
|
||||
if (iip >= UBIFS_LPT_FANOUT) {
|
||||
/*
|
||||
* Should not happen, but we need to keep going
|
||||
* if it does.
|
||||
*/
|
||||
iip = 0;
|
||||
}
|
||||
nnode = ubifs_get_nnode(c, nnode, iip);
|
||||
if (IS_ERR(nnode))
|
||||
return (void *)nnode;
|
||||
}
|
||||
|
||||
return ubifs_get_pnode(c, nnode, 0);
|
||||
for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++)
|
||||
if (nnode->nbranch[iip].lnum)
|
||||
break;
|
||||
if (iip >= UBIFS_LPT_FANOUT)
|
||||
/* Should not happen, but we need to keep going if it does */
|
||||
iip = 0;
|
||||
return ubifs_get_pnode(c, nnode, iip);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -688,7 +708,7 @@ static int make_tree_dirty(struct ubifs_info *c)
|
|||
pnode = pnode_lookup(c, 0);
|
||||
while (pnode) {
|
||||
do_make_pnode_dirty(c, pnode);
|
||||
pnode = next_pnode(c, pnode);
|
||||
pnode = next_pnode_to_dirty(c, pnode);
|
||||
if (IS_ERR(pnode))
|
||||
return PTR_ERR(pnode);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue