From patchwork Mon Dec 8 09:19:26 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Weinberger X-Patchwork-Id: 418642 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2001:1868:205::9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 964F61400DD for ; Mon, 8 Dec 2014 20:21:14 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XxuU8-0003rv-4y; Mon, 08 Dec 2014 09:20:04 +0000 Received: from mail.sigma-star.at ([95.130.255.111]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XxuU5-00039R-0j for linux-mtd@lists.infradead.org; Mon, 08 Dec 2014 09:20:02 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by mail.sigma-star.at (Postfix) with ESMTP id 4596116B42FE; Mon, 8 Dec 2014 10:19:38 +0100 (CET) X-Virus-Scanned: amavisd-new at mail.sigma-star.at Received: from localhost.localdomain (chello213047235169.tirol.surfer.at [213.47.235.169]) by mail.sigma-star.at (Postfix) with ESMTPSA id AC59516B420A; Mon, 8 Dec 2014 10:19:36 +0100 (CET) From: Richard Weinberger To: dedekind1@gmail.com Subject: [PATCH] UBI: Fastmap: Fix possible fastmap inconsistency Date: Mon, 8 Dec 2014 10:19:26 +0100 Message-Id: <1418030366-9192-1-git-send-email-richard@nod.at> X-Mailer: git-send-email 1.8.4.5 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20141208_012001_482150_183E19EC X-CRM114-Status: GOOD ( 11.00 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record Cc: Richard Weinberger , linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org, tlinder@codeaurora.org X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Currently we call ubi_refill_pools() before all UBI meta data is collected for the fastmap on-flash data structure. It can happen that a second thread requests a new PEB and returns it immediately to the free list between ubi_refill_pools() and collecting meta data. In this case the same PEB will be in the free list and a fastmap pool. Upon attach time fastmap is able to detect that inconsistency and will fall back to scanning mode. But we can do better. To bypass the issue just call ubi_refill_pools() under the same wl_lock as the meta data collecting happens. If fastmap is disabled we can still call ubi_refill_pools() early. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap-wl.c | 4 ---- drivers/mtd/ubi/fastmap.c | 17 +++++++++-------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c index 8f109cc..6883146 100644 --- a/drivers/mtd/ubi/fastmap-wl.c +++ b/drivers/mtd/ubi/fastmap-wl.c @@ -226,8 +226,6 @@ void ubi_refill_pools(struct ubi_device *ubi) struct ubi_wl_entry *e; int enough; - spin_lock(&ubi->wl_lock); - return_unused_pool_pebs(ubi, wl_pool); return_unused_pool_pebs(ubi, pool); @@ -270,8 +268,6 @@ void ubi_refill_pools(struct ubi_device *ubi) wl_pool->used = 0; pool->used = 0; - - spin_unlock(&ubi->wl_lock); } /** diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 976e498..05b3c00 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -1121,6 +1121,8 @@ static int ubi_write_fastmap(struct ubi_device *ubi, spin_lock(&ubi->volumes_lock); spin_lock(&ubi->wl_lock); + ubi_refill_pools(ubi); + fmsb = (struct ubi_fm_sb *)fm_raw; fm_pos += sizeof(*fmsb); ubi_assert(fm_pos <= ubi->fm_size); @@ -1477,19 +1479,14 @@ int ubi_update_fastmap(struct ubi_device *ubi, struct ubi_wl_entry **forced_anch down_write(&ubi->fm_protect); - ubi_refill_pools(ubi); - if (ubi->ro_mode || ubi->fm_disabled) { + spin_lock(&ubi->wl_lock); + ubi_refill_pools(ubi); + spin_unlock(&ubi->wl_lock); up_write(&ubi->fm_protect); return 0; } - ret = ubi_ensure_anchor_pebs(ubi); - if (ret) { - up_write(&ubi->fm_protect); - return ret; - } - new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL); if (!new_fm) { up_write(&ubi->fm_protect); @@ -1614,6 +1611,10 @@ int ubi_update_fastmap(struct ubi_device *ubi, struct ubi_wl_entry **forced_anch if (ret) goto err; + ret = ubi_ensure_anchor_pebs(ubi); + if (ret) + goto err; + out_unlock: up_write(&ubi->fm_protect); kfree(old_fm);