From patchwork Fri Jun 22 16:32:25 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Weinberger X-Patchwork-Id: 166644 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from merlin.infradead.org (unknown [IPv6:2001:4978:20e::2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id F383CB6F9F for ; Sat, 23 Jun 2012 02:34:22 +1000 (EST) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1Si6mj-0008Qr-4D; Fri, 22 Jun 2012 16:32:37 +0000 Received: from a.ns.miles-group.at ([95.130.255.143] helo=radon.swed.at) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1Si6mf-0008Qd-R6 for linux-mtd@lists.infradead.org; Fri, 22 Jun 2012 16:32:35 +0000 Received: (qmail 8984 invoked by uid 89); 22 Jun 2012 16:32:35 -0000 Received: by simscan 1.3.1 ppid: 8977, pid: 8980, t: 0.1978s scanners: attach: 1.3.1 clamav: 0.96.5/m:53 Received: from unknown (HELO ?192.168.0.2?) (richard@nod.at@178.191.108.150) by radon.swed.at with ESMTPA; 22 Jun 2012 16:32:34 -0000 Message-ID: <4FE49E19.4070005@nod.at> Date: Fri, 22 Jun 2012 18:32:25 +0200 From: Richard Weinberger User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20120427 Thunderbird/12.0.1 MIME-Version: 1.0 To: "Nikita V. Youshchenko" Subject: Re: ubi_update_fastmap: could not find an early PEB References: <201206222005.02308@blacky.localdomain> In-Reply-To: <201206222005.02308@blacky.localdomain> X-Enigmail-Version: 1.4.2 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Rob Taylor , Alexander Kaliadin , linux-mtd@lists.infradead.org, Pavan Jadhav X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Am 22.06.2012 18:05, schrieb Nikita V. Youshchenko: > As far as I understand, this happens because all PEBs at the beginning of > device are occupied. But this will always be the case after creating image > with ubinize... ubinize will also get fastmap support. But first we have to finish the kernel level support. > How to overcome this? Can you please try the attached patch? This patch allows the WL-worker to produce free anchor PEBS. Thanks, //richard P.s: Please use the most current fastmap code! diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 582f5ee..4793ba8 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -1374,6 +1374,12 @@ int ubi_update_fastmap(struct ubi_device *ubi) return 0; } + ret = ubi_ensure_anchor_pebs(ubi); + if (ret) { + mutex_unlock(&ubi->fm_mutex); + return ret; + } + new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL); if (!new_fm) { mutex_unlock(&ubi->fm_mutex); diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 534e851..56b1c5c 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -663,6 +663,7 @@ struct ubi_attach_info { * @func: worker function * @e: physical eraseblock to erase * @torture: if the physical eraseblock has to be tortured + * @anchor: produce a anchor PEB to by used by fastmap * * The @func pointer points to the worker function. If the @cancel argument is * not zero, the worker has to free the resources and exit immediately. The @@ -675,6 +676,7 @@ struct ubi_work { /* The below fields are only relevant to erasure works */ struct ubi_wl_entry *e; int torture; + int anchor; }; #include "debug.h" @@ -759,6 +761,7 @@ struct ubi_wl_entry *ubi_wl_get_fm_peb(struct ubi_device *ubi, int max_pnum); int ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *used_e, int torture); int ubi_is_erase_work(struct ubi_work *wrk); void ubi_refill_pools(struct ubi_device *ubi); +int ubi_ensure_anchor_pebs(struct ubi_device *ubi); /* io.c */ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 6771f30..b4d4358 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -419,6 +419,18 @@ static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root, return victim; } +static int anchor_pebs_avalible(struct rb_root *root, int max_pnum) +{ + struct rb_node *p; + struct ubi_wl_entry *e; + + ubi_rb_for_each_entry(p, e, root, u.rb) + if (e->pnum < max_pnum) + return 1; + + return 0; +} + /** * ubi_wl_get_fm_peb - find a physical erase block with a given maximal number. * @ubi: UBI device description object @@ -901,10 +913,11 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, int cancel) { int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0; - int vol_id = -1, uninitialized_var(lnum); + int anchor, vol_id = -1, uninitialized_var(lnum); struct ubi_wl_entry *e1, *e2; struct ubi_vid_hdr *vid_hdr; + anchor = wrk->anchor; kfree(wrk); if (cancel) return 0; @@ -935,7 +948,23 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, goto out_cancel; } - if (!ubi->scrub.rb_node) { + /* Check whether we need to produce an anchor PEB */ + if (!anchor) + anchor = !anchor_pebs_avalible(&ubi->free, UBI_FM_MAX_START); + + if (anchor) { + e1 = find_anchor_wl_entry(&ubi->used, UBI_FM_MAX_START); + if (!e1) + goto out_cancel; + e2 = get_peb_for_wl(ubi); + if (!e2) + goto out_cancel; + + self_check_in_wl_tree(ubi, e1, &ubi->used); + rb_erase(&e1->u.rb, &ubi->used); + dbg_wl("anchor-move PEB %d to PEB %d", e1->pnum, e2->pnum); + } + else if (!ubi->scrub.rb_node) { /* * Now pick the least worn-out used physical eraseblock and a * highly worn-out free physical eraseblock. If the erase @@ -1229,6 +1258,7 @@ static int ensure_wear_leveling(struct ubi_device *ubi, int nested) goto out_cancel; } + wrk->anchor = 0; wrk->func = &wear_leveling_worker; if (nested) __schedule_ubi_work(ubi, wrk); @@ -1244,6 +1274,32 @@ out_unlock: return err; } +int ubi_ensure_anchor_pebs(struct ubi_device *ubi) +{ + struct ubi_work *wrk; + + spin_lock(&ubi->wl_lock); + if (ubi->wl_scheduled) { + spin_unlock(&ubi->wl_lock); + return 0; + } + ubi->wl_scheduled = 1; + spin_unlock(&ubi->wl_lock); + + wrk = kmalloc(sizeof(struct ubi_work), GFP_NOFS); + if (!wrk) { + spin_lock(&ubi->wl_lock); + ubi->wl_scheduled = 0; + spin_unlock(&ubi->wl_lock); + return -ENOMEM; + } + + wrk->anchor = 1; + wrk->func = &wear_leveling_worker; + schedule_ubi_work(ubi, wrk); + return 0; +} + /** * erase_worker - physical eraseblock erase worker function. * @ubi: UBI device description object