From patchwork Thu Jun 21 21:50:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [13/15] UBI: Fastmap: Add new self check Date: Thu, 21 Jun 2012 11:50:06 -0000 From: Richard Weinberger X-Patchwork-Id: 166408 Message-Id: <1340315408-27375-14-git-send-email-richard@nod.at> To: linux-mtd@lists.infradead.org Cc: artem.bityutskiy@linux.intel.com, linux-kernel@vger.kernel.org, adrian.hunter@intel.com, Heinz.Egger@linutronix.de, thomas.wucher@linutronix.de, shmulik.ladkani@gmail.com, Richard Weinberger , tglx@linutronix.de, Marius.Mazarel@ugal.ro, tim.bird@am.sony.com If fastmap is able to detect that it's missing PEBs fall back to scanning mode and print a fat warning. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap.c | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 76b0d2f..68be3d5 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -461,6 +461,26 @@ out: return ret; } +static int self_check_fastmap(struct ubi_attach_info *ai) +{ + struct ubi_ainf_peb *aeb; + struct ubi_ainf_volume *av; + struct rb_node *rb1, *rb2; + int n = 0; + + list_for_each_entry(aeb, &ai->erase, u.list) + n++; + + list_for_each_entry(aeb, &ai->free, u.list) + n++; + + ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) + ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) + n++; + + return n; +} + /** * ubi_attach_fastmap - creates ubi_attach_info from a fastmap. * @ubi: UBI device object @@ -978,6 +998,19 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai) goto free_hdr; } + /* + * If fastmap is leaking PEBs (must not happen), raise a + * fat warning and fall back to scanning mode. + * We do this here because in ubi_wl_init() it's too late + * and we cannot fall back to scanning. + */ + if (WARN_ON(self_check_fastmap(ai) != ubi->peb_count - + ubi->bad_peb_count - used_blocks)) { + ret = UBI_BAD_FASTMAP; + kfree(fm); + goto free_hdr; + } + fm->size = fm_size; fm->used_blocks = used_blocks;