From patchwork Wed Jun 13 21:23:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Weinberger X-Patchwork-Id: 929104 X-Patchwork-Delegate: richard@nod.at Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=nod.at Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="V4Y7xxNN"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 415g0r60Wcz9s01 for ; Thu, 14 Jun 2018 07:31:08 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=AHT2xGlycFVNdV7U4YJr2tzxjkCwvt5IkORs4RPSrac=; b=V4Y7xxNNf/alVj7BCr/80V4MWf 2Ec0r+ozBBSQ5UnuspDz/SX0xM6d2L12hrOdPb6WwVSvQw00nbd+Pz6Q2LYFZPsAurlw/IX7DCFVm ofQZdKEpgWtfTxc2V8b6M2EOqCJiI1HqIe5h6k5N1vfdPpRTiKmJavL/fN3p6TLFmANpvFeVRpWoD MtITt34jLgrRssGy3yrToloZxipgws4kodWrsl5qgacfrFBSZE3x4rJLNJF1Ayk33/tc8OWHBh/Ec 5ywUuEkN3Bb4oYB2zx35MBeg2xl/LpkjLwTtNIUQoXMxizU9Rq17Bj4ZHvZvOoHXfNKXrvCwLYFNu /LfwvBtA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fTDM1-00038k-HG; Wed, 13 Jun 2018 21:30:57 +0000 Received: from lilium.sigma-star.at ([109.75.188.150]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1fTDFi-0004u6-Ni for linux-mtd@lists.infradead.org; Wed, 13 Jun 2018 21:25:01 +0000 Received: from localhost (localhost [127.0.0.1]) by lilium.sigma-star.at (Postfix) with ESMTP id 85D32181B5055; Wed, 13 Jun 2018 23:24:03 +0200 (CEST) From: Richard Weinberger To: linux-mtd@lists.infradead.org Subject: [PATCH 05/14] ubi: fastmap: Implement PEB translation Date: Wed, 13 Jun 2018 23:23:35 +0200 Message-Id: <20180613212344.11608-6-richard@nod.at> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180613212344.11608-1-richard@nod.at> References: <20180613212344.11608-1-richard@nod.at> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180613_142427_171848_308B2ED1 X-CRM114-Status: GOOD ( 19.75 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 T_SPF_PERMERROR SPF: test of record failed (permerror) X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Weinberger , linux-kernel@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org When a fastmap is preseeded we have to translate PEB numbers because during the creation of the fastmap the creation tool cannot know which blocks are bad on the target(s). Therefore fastmap has to learn all bad blocks during attach and changes PEB numbers accordingly. This feature assumes that bad blocks are skipped while the image was flashed, what nandwrite does by default. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/attach.c | 1 + drivers/mtd/ubi/fastmap.c | 74 +++++++++++++++++++++++++++++++++++++++++++++-- drivers/mtd/ubi/ubi.h | 2 ++ 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index 93ceea4f27d5..9a8072cf458c 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -1370,6 +1370,7 @@ static void destroy_ai(struct ubi_attach_info *ai) } kmem_cache_destroy(ai->aeb_slab_cache); + kfree(ai->bb_trans); kfree(ai); } diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 1ebb5d15ab1a..279d02874297 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -107,6 +107,9 @@ static bool read_pnum(struct ubi_device *ubi, struct ubi_attach_info *ai, int ret = true; int max_pnum = ubi->peb_count; + if (ai->bb_trans) + max_pnum -= ai->bad_peb_count; + pnum = be32_to_cpu(pnum); if (pnum == UBI_UNKNOWN) { *out_pnum = pnum; @@ -117,10 +120,13 @@ static bool read_pnum(struct ubi_device *ubi, struct ubi_attach_info *ai, ubi_err(ubi, "fastmap references PEB out of range: %i", pnum); ret = false; goto out; - } else { - *out_pnum = pnum; } + if (!ai->bb_trans) + *out_pnum = pnum; + else + *out_pnum = ai->bb_trans[pnum]; + out: return ret; } @@ -880,6 +886,61 @@ static struct ubi_ainf_peb *clone_aeb(struct ubi_attach_info *ai, return new; } +/* + * build_bb_trans_table - create a translation table to fix PEB numbers. + * @ubi: UBI device object + * @ai: UBI attach info object + * + * A preseeded Fastmap has no knowledge of bad blocks. During first attach + * UBI has to update PEB numbers to leave out existing bad blocks. + */ +static int build_bb_trans_table(struct ubi_device *ubi, + struct ubi_attach_info *ai) +{ + int pnum, new_pnum, ret; + unsigned long *claimed_blocks; + + ret = -ENOMEM; + claimed_blocks = kcalloc(BITS_TO_LONGS(ubi->peb_count), + sizeof(unsigned long), GFP_KERNEL); + if (!claimed_blocks) + goto out; + + /* ai->bb_trans will get free'ed via destroy_ai() */ + ai->bb_trans = kcalloc(ubi->peb_count, sizeof(int), GFP_KERNEL); + if (!ai->bb_trans) + goto out; + + /* Find all bad blocks and mark them as claimed */ + for (pnum = 0; pnum < ubi->peb_count; pnum++) { + ret = ubi_io_is_bad(ubi, pnum); + if (ret < 0) + goto out; + + if (ret == 1) { + set_bit(pnum, claimed_blocks); + ai->bad_peb_count++; + } + } + + /* + * Start with PEB 0 and try to place each PEB around all bad blocks + * to create the translation table. + */ + for (pnum = 0; pnum < ubi->peb_count - ai->bad_peb_count; pnum++) { + ubi_assert(!bitmap_full(claimed_blocks, ubi->peb_count)); + + new_pnum = find_first_zero_bit(claimed_blocks, ubi->peb_count); + ai->bb_trans[pnum] = new_pnum; + set_bit(new_pnum, claimed_blocks); + } + +out: + kfree(claimed_blocks); + + return ret; +} + /** * ubi_scan_fastmap - scan the fastmap. * @ubi: UBI device object @@ -987,6 +1048,15 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, goto free_fm_sb; } + if (fm->flags & UBI_FM_SB_PRESEEDED_FLG) { + ubi_msg(ubi, "preseeded fastmap found"); + ret = build_bb_trans_table(ubi, ai); + if (ret) { + ubi_err(ubi, "failed to construct bb translation table"); + goto free_fm_sb; + } + } + ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); if (!ech) { ret = -ENOMEM; diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 4fab3790733b..28af5115d180 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -760,6 +760,7 @@ struct ubi_ainf_volume { * @aeb_slab_cache: slab cache for &struct ubi_ainf_peb objects * @ech: temporary EC header. Only available during scan * @vidh: temporary VID buffer. Only available during scan + * @bb_trans: bad block translation table, used by fastmap, NULL otherwise * * This data structure contains the result of attaching an MTD device and may * be used by other UBI sub-systems to build final UBI data structures, further @@ -790,6 +791,7 @@ struct ubi_attach_info { struct kmem_cache *aeb_slab_cache; struct ubi_ec_hdr *ech; struct ubi_vid_io_buf *vidb; + int *bb_trans; }; /**