Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 250436
b: refs/heads/master
c: 4474421
h: refs/heads/master
v: v3
  • Loading branch information
Artem Bityutskiy authored and Artem Bityutskiy committed May 13, 2011
1 parent 514e9c3 commit dedf227
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 28 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ec0681426526b23d3e12cf247d64676806c30b7f
refs/heads/master: 447442139c764fd75cf892905d0feb08a9b983ed
77 changes: 50 additions & 27 deletions trunk/fs/ubifs/recovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,53 @@ int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf)
return 0;
}

/**
* grab_empty_leb - grab an empty LEB to use as GC LEB and run commit.
* @c: UBIFS file-system description object
*
* This is a helper function for 'ubifs_rcvry_gc_commit()' which grabs an empty
* LEB to be used as GC LEB (@c->gc_lnum), and then runs the commit. Returns
* zero in case of success and a negative error code in case of failure.
*/
static int grab_empty_leb(struct ubifs_info *c)
{
int lnum, err;

/*
* Note, it is very important to first search for an empty LEB and then
* run the commit, not vice-versa. The reason is that there might be
* only one empty LEB at the moment, the one which has been the
* @c->gc_lnum just before the power cut happened. During the regular
* UBIFS operation (not now) @c->gc_lnum is marked as "taken", so no
* one but GC can grab it. But at this moment this single empty LEB is
* not marked as taken, so if we run commit - what happens? Right, the
* commit will grab it and write the index there. Remember that the
* index always expands as long as there is free space, and it only
* starts consolidating when we run out of space.
*
* IOW, if we run commit now, we might not be able to find a free LEB
* after this.
*/
lnum = ubifs_find_free_leb_for_idx(c);
if (lnum < 0) {
dbg_err("could not find an empty LEB");
dbg_dump_lprops(c);
dbg_dump_budg(c, &c->bi);
return lnum;
}

/* Reset the index flag */
err = ubifs_change_one_lp(c, lnum, LPROPS_NC, LPROPS_NC, 0,
LPROPS_INDEX, 0);
if (err)
return err;

c->gc_lnum = lnum;
dbg_rcvry("found empty LEB %d, run commit", lnum);

return ubifs_run_commit(c);
}

/**
* ubifs_rcvry_gc_commit - recover the GC LEB number and run the commit.
* @c: UBIFS file-system description object
Expand Down Expand Up @@ -1096,15 +1143,15 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c)
c->gc_lnum = -1;
if (wbuf->lnum == -1) {
dbg_rcvry("no GC head LEB");
goto find_free;
return grab_empty_leb(c);
}
/*
* See whether the used space in the dirtiest LEB fits in the GC head
* LEB.
*/
if (wbuf->offs == c->leb_size) {
dbg_rcvry("no room in GC head LEB");
goto find_free;
return grab_empty_leb(c);
}
err = ubifs_find_dirty_leb(c, &lp, wbuf->offs, 2);
if (err) {
Expand All @@ -1121,7 +1168,7 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c)
*/
if (err == -ENOSPC) {
dbg_rcvry("could not find a dirty LEB");
goto find_free;
return grab_empty_leb(c);
}
return err;
}
Expand Down Expand Up @@ -1167,30 +1214,6 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c)
return err;
dbg_rcvry("allocated LEB %d for GC", lnum);
return 0;

find_free:
/*
* There is no GC head LEB or the free space in the GC head LEB is too
* small, or there are not dirty LEBs. Allocate gc_lnum by calling
* 'ubifs_find_free_leb_for_idx()' so GC is not run.
*/
lnum = ubifs_find_free_leb_for_idx(c);
if (lnum < 0) {
dbg_err("could not find an empty LEB");
dbg_dump_lprops(c);
dbg_dump_budg(c, &c->bi);
return lnum;
}
/* And reset the index flag */
err = ubifs_change_one_lp(c, lnum, LPROPS_NC, LPROPS_NC, 0,
LPROPS_INDEX, 0);
if (err)
return err;
c->gc_lnum = lnum;
dbg_rcvry("allocated LEB %d for GC", lnum);
/* Run the commit */
dbg_rcvry("committing");
return ubifs_run_commit(c);
}

/**
Expand Down

0 comments on commit dedf227

Please sign in to comment.