Skip to content

Commit

Permalink
UBIFS: fix LPT out-of-space bug (again)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Adrian Hunter authored and Artem Bityutskiy committed Jan 28, 2009
1 parent 6f7ab6d commit 4a29d20
Showing 1 changed file with 32 additions and 12 deletions.
44 changes: 32 additions & 12 deletions fs/ubifs/lpt_commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit 4a29d20

Please sign in to comment.