Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44744213 authored by Artem Bityutskiy's avatar Artem Bityutskiy
Browse files

UBIFS: split ubifs_rcvry_gc_commit



Split the 'ubifs_rcvry_gc_commit()' function and introduce a 'grab_empty_leb()'
heler. This cleans 'ubifs_rcvry_gc_commit()' a little and makes it a bit less
of spagetti.

Also, add a commentary which explains why it is crucial to first search for an
empty LEB and then run commit.

Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
parent ec068142
Loading
Loading
Loading
Loading
+50 −27
Original line number Diff line number Diff line
@@ -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
@@ -1096,7 +1143,7 @@ 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
@@ -1104,7 +1151,7 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c)
	 */
	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) {
@@ -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;
	}
@@ -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);
}

/**