From patchwork Wed Jun 13 21:23:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Weinberger X-Patchwork-Id: 929103 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="Q2j6Yl8R"; 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 415g0D5g0wz9s01 for ; Thu, 14 Jun 2018 07:30:36 +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=dJ7X3pdbyrYZhn+3bjhCyAsadUS47uDlrsSNyaAmI5w=; b=Q2j6Yl8RA9CnRA3Vty9AKnnzUf pZH4XAXmmMvFSBqfbbAnLIfi9WwSvxYooO2qBBo/ba1+A1I1aAHNF375Y0xcPMzgQ80FRd4ihnHdi mlkyEJDCLiLKNgpaMJw19Jy5NnlTVqmsy0/QC3JjtzgkI4+1eLyuqk4xuz2brx1vHH/i7s0pBS7Lk nk4aN5Hy39kA4KY0TtMz1rh8sQ8Hwe27oYTar7E8YTiE+XDqcmOxSNvXX3w+mt+fdaksG9EdGKnmI 2G1KZv9yP79zJnCB3yC62ohwbm90Oj3lOXzHAovQ8ZsMZiAuJi0lk7WQdNa6sKoCijanKmqe+nTB7 8iObP2Rg==; 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 1fTDLV-0002Hs-BG; Wed, 13 Jun 2018 21:30:25 +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-0004u8-Ng 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 1185518198DC1; Wed, 13 Jun 2018 23:24:04 +0200 (CEST) From: Richard Weinberger To: linux-mtd@lists.infradead.org Subject: [PATCH 08/14] ubi: fastmap: Scan empty space if fastmap is preseeded Date: Wed, 13 Jun 2018 23:23:38 +0200 Message-Id: <20180613212344.11608-9-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_204273_4E245A04 X-CRM114-Status: GOOD ( 20.23 ) 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 The creation tool does not know the real size of the MTD, therefore the preseeded fastmap references only used PEBs. Free PEBs need to be discovered during the initial attach of the preseeded fastmap. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap.c | 123 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 117 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 976d371d7cef..09a9d3a0ccf5 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -422,6 +422,96 @@ static void unmap_peb(struct ubi_attach_info *ai, int pnum) } } } +/** + * scan_empty_space - scan empty space. + * + * @ubi: UBI device object + * @ai: attach info object + * @start: PEB number where empty space is expected to start + * + * Is is the fastmap preseeded, it references only used PEBs, the creation + * does not know the real MTD size. Therefore many PEBs are 0xff and unknown + * to the fastmap. Scan for this PEBs during attach and make them known. + * These PEBs are only allowed to be 0xff or have a valid EC header. + * EC headers are allowed because the initial scan+erase operation could be + * interrupted by a power cycle. + */ +static int scan_empty_space(struct ubi_device *ubi, struct ubi_attach_info *ai, + int start) +{ + int pnum, err, scrub, empty, image_seq; + unsigned long long ec; + struct ubi_ec_hdr *ech = NULL; + struct ubi_vid_io_buf *vb = NULL; + struct ubi_vid_hdr *vh; + + err = -ENOMEM; + + ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); + if (!ech) + goto out; + + vb = ubi_alloc_vid_buf(ubi, GFP_KERNEL); + if (!vb) + goto out; + + vh = ubi_get_vid_hdr(vb); + + ubi_msg(ubi, "scanning %i additional PEBs", ubi->peb_count - start); + + for (pnum = start; pnum < ubi->peb_count; pnum++) { + if (ubi_io_is_bad(ubi, pnum)) + continue; + + scrub = empty = ec = 0; + err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0); + switch (err) { + case UBI_IO_FF_BITFLIPS: + scrub = 1; + /* fall through */ + case UBI_IO_FF: + empty = 1; + break; + case UBI_IO_BITFLIPS: + scrub = 1; + /* fall through */ + case 0: + ec = be64_to_cpu(ech->ec); + image_seq = be32_to_cpu(ech->image_seq); + + if (image_seq && (image_seq != ubi->image_seq)) { + ubi_err(ubi, "bad image seq: 0x%x, expected: 0x%x", + image_seq, ubi->image_seq); + err = UBI_BAD_FASTMAP; + goto out; + } + break; + default: + ubi_err(ubi, "Unable to read EC header in empty space: %i", + err); + err = UBI_BAD_FASTMAP; + goto out; + } + + err = ubi_io_read_vid_hdr(ubi, pnum, vb, 0); + if (err != UBI_IO_FF && err != UBI_IO_FF_BITFLIPS) { + ubi_err(ubi, "Unexpected data in empty space: %i", err); + err = UBI_BAD_FASTMAP; + goto out; + } + + if (empty) + add_aeb(ai, &ai->erase, pnum, ec, scrub); + else + add_aeb(ai, &ai->free, pnum, ec, scrub); + } + + err = 0; +out: + kfree(ech); + ubi_free_vid_buf(vb); + return err; +} /** * scan_pool - scans a pool for changed (no longer empty PEBs). @@ -818,13 +908,34 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, } } - ret = scan_pool(ubi, ai, fmpl->pebs, pool_size, &max_sqnum, &free); - if (ret) - goto fail; + if (!(fm->flags & UBI_FM_SB_PRESEEDED_FLG)) { + ret = scan_pool(ubi, ai, fmpl->pebs, pool_size, &max_sqnum, &free); + if (ret) + goto fail; - ret = scan_pool(ubi, ai, fmpl_wl->pebs, wl_pool_size, &max_sqnum, &free); - if (ret) - goto fail; + ret = scan_pool(ubi, ai, fmpl_wl->pebs, wl_pool_size, &max_sqnum, &free); + if (ret) + goto fail; + } + + if (fm->flags & UBI_FM_SB_PRESEEDED_FLG) { + int empty_start = be32_to_cpu(fmhdr->used_peb_count) + \ + be32_to_cpu(fmhdr->erase_peb_count) + fm->used_blocks; + + if (empty_start + ai->bad_peb_count > ubi->peb_count) { + ubi_err(ubi, "fastmap points beyond end of device!"); + goto fail_bad; + } else if (empty_start + ai->bad_peb_count == ubi->peb_count) { + ubi_msg(ubi, "no need to scan empty space"); + } else { + if (!read_pnum(ubi, ai, cpu_to_be32(empty_start), &empty_start)) + goto fail_bad; + + ret = scan_empty_space(ubi, ai, empty_start); + if (ret) + goto fail; + } + } if (max_sqnum > ai->max_sqnum) ai->max_sqnum = max_sqnum;