From: Richard Weinberger <richard@nod.at>
To: linux-mtd@lists.infradead.org
Cc: dedekind1@gmail.com, Richard Weinberger <richard@nod.at>,
linux-kernel@vger.kernel.org, Heinz.Egger@linutronix.de,
tim.bird@am.sony.com, tglx@linutronix.de
Subject: [PATCH 5/7] [RFC] UBI: Make wl subsystem fastmap aware
Date: Tue, 15 May 2012 19:11:09 +0200 [thread overview]
Message-ID: <1337101871-31181-6-git-send-email-richard@nod.at> (raw)
In-Reply-To: <1337101871-31181-1-git-send-email-richard@nod.at>
Integrates fastmapping into the wl subsystem.
Fastmapping deals with PEBs, it has to tell the wl subsystem
which PEBs are currently used and must not touched by the wl thread.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/ubi.h | 3 +
drivers/mtd/ubi/wl.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 144 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 6c89971..cf5cfaf 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -586,6 +586,9 @@ int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum);
int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
void ubi_wl_close(struct ubi_device *ubi);
int ubi_thread(void *u);
+int ubi_wl_get_fm_peb(struct ubi_device *ubi, int max_pnum);
+int ubi_wl_put_fm_peb(struct ubi_device *ubi, int pnum, int torture);
+int ubi_is_fm_block(struct ubi_device *ubi, int pnum);
/* 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 64ce993..a329358 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -169,6 +169,25 @@ static int paranoid_check_in_pq(const struct ubi_device *ubi,
#endif
/**
+ * ubi_ubi_is_fm_block - returns 1 if a PEB is currently used in a fastmap.
+ * @ubi: UBI device description object
+ * @pnum: the to be checked PEB
+ */
+int ubi_is_fm_block(struct ubi_device *ubi, int pnum)
+{
+ int i;
+
+ if (!ubi->fm)
+ return 0;
+
+ for (i = 0; i < ubi->fm->used_blocks; i++)
+ if (ubi->fm->peb[i] == pnum)
+ return 1;
+
+ return 0;
+}
+
+/**
* wl_tree_add - add a wear-leveling entry to a WL RB-tree.
* @e: the wear-leveling entry to add
* @root: the root of the tree
@@ -375,6 +394,63 @@ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int diff)
/**
* ubi_wl_get_peb - get a physical eraseblock.
+ * find_early_wl_entry - find wear-leveling entry with a low pnum.
+ * @root: the RB-tree where to look for
+ * @max_pnum: highest possible pnum
+ *
+ * This function looks for a wear leveling entry containing a eb which
+ * is in front of the memory.
+ */
+static struct ubi_wl_entry *find_early_wl_entry(struct rb_root *root,
+ int max_pnum)
+{
+ struct rb_node *p;
+ struct ubi_wl_entry *e, *victim = NULL;
+
+ ubi_rb_for_each_entry(p, e, root, u.rb) {
+ if (e->pnum < max_pnum) {
+ victim = e;
+ max_pnum = e->pnum;
+ }
+ }
+
+ return victim;
+}
+
+/**
+ * ubi_wl_get_fm_peb - find a physical erase block with a given maximal number.
+ * @ubi: UBI device description object
+ * @max_pnum: the highest acceptable erase block number
+ *
+ * The function returns a physical erase block with a given maximal number
+ * and removes it from the wl subsystem.
+ * Must be called with wl_lock held!
+ */
+int ubi_wl_get_fm_peb(struct ubi_device *ubi, int max_pnum)
+{
+ int ret = -ENOSPC;
+ struct ubi_wl_entry *e;
+
+ if (!ubi->free.rb_node) {
+ ubi_err("no free eraseblocks");
+
+ goto out;
+ }
+
+ e = find_early_wl_entry(&ubi->free, max_pnum);
+ if (!e)
+ goto out;
+
+ ret = e->pnum;
+
+ /* remove it from the free list,
+ * the wl subsystem does no longer know this erase block */
+ rb_erase(&e->u.rb, &ubi->free);
+out:
+ return ret;
+}
+
+/**
* @ubi: UBI device description object
*
* This function returns a physical eraseblock in case of success and a
@@ -596,6 +672,9 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
{
struct ubi_work *wl_wrk;
+ ubi_assert(e);
+ ubi_assert(!ubi_is_fm_block(ubi, e->pnum));
+
dbg_wl("schedule erasure of PEB %d, EC %d, torture %d",
e->pnum, e->ec, torture);
@@ -612,6 +691,56 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
}
/**
+ * ubi_wl_put_fm_peb - returns a PEB used in a fastmap to the wear-leveling
+ * sub-system.
+ *
+ * see: ubi_wl_put_peb()
+ */
+int ubi_wl_put_fm_peb(struct ubi_device *ubi, int pnum, int torture)
+{
+ int i, err = 0;
+ struct ubi_wl_entry *e;
+
+ dbg_wl("PEB %d", pnum);
+ ubi_assert(pnum >= 0);
+ ubi_assert(pnum < ubi->peb_count);
+
+ spin_lock(&ubi->wl_lock);
+ e = ubi->lookuptbl[pnum];
+
+ /* This can happen if we recovered from a fastmap the very
+ * frist time and writing now a new one. In this case the wl system
+ * has never seen any PEB used by the original fastmap.
+ */
+ if (!e) {
+ ubi_assert(ubi->old_fm);
+ e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_ATOMIC);
+ if (!e) {
+ spin_unlock(&ubi->wl_lock);
+ return -ENOMEM;
+ }
+
+ e->pnum = pnum;
+ e->ec = 0;
+ /* use the ec value from the fastmap */
+ for (i = 0; i < UBI_FM_MAX_BLOCKS; i++) {
+ if (pnum == ubi->old_fm->peb[i]) {
+ e->ec = ubi->old_fm->ec[i];
+ break;
+ }
+ }
+ ubi_assert(e->ec);
+ ubi->lookuptbl[pnum] = e;
+ }
+
+ spin_unlock(&ubi->wl_lock);
+
+ err = schedule_erase(ubi, e, torture);
+
+ return err;
+}
+
+/**
* wear_leveling_worker - wear-leveling worker function.
* @ubi: UBI device description object
* @wrk: the work object
@@ -988,6 +1117,8 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
dbg_wl("erase PEB %d EC %d", pnum, e->ec);
+ ubi_assert(!ubi_is_fm_block(ubi, e->pnum));
+
err = sync_erase(ubi, e, wl_wrk->torture);
if (!err) {
/* Fine, we've erased it successfully */
@@ -1422,6 +1553,9 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
e->pnum = seb->pnum;
e->ec = seb->ec;
+
+ ubi_assert(!ubi_is_fm_block(ubi, e->pnum));
+
ubi->lookuptbl[e->pnum] = e;
if (schedule_erase(ubi, e, 0)) {
kmem_cache_free(ubi_wl_entry_slab, e);
@@ -1439,7 +1573,10 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
e->pnum = seb->pnum;
e->ec = seb->ec;
ubi_assert(e->ec >= 0);
+ ubi_assert(!ubi_is_fm_block(ubi, e->pnum));
+
wl_tree_add(e, &ubi->free);
+
ubi->lookuptbl[e->pnum] = e;
}
@@ -1454,6 +1591,10 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
e->pnum = seb->pnum;
e->ec = seb->ec;
ubi->lookuptbl[e->pnum] = e;
+
+ if (ubi_is_fm_block(ubi, seb->pnum))
+ continue;
+
if (!seb->scrub) {
dbg_wl("add PEB %d EC %d to the used tree",
e->pnum, e->ec);
--
1.7.6.5
next prev parent reply other threads:[~2012-05-15 17:11 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-15 17:11 [RFC v4] UBI: Fastmap support (aka checkpointing) Richard Weinberger
2012-05-15 17:11 ` [PATCH 1/7] [RFC] UBI: Export next_sqnum() Richard Weinberger
2012-05-16 13:01 ` Artem Bityutskiy
2012-05-21 13:34 ` Richard Weinberger
2012-05-21 14:00 ` Artem Bityutskiy
2012-05-21 14:16 ` Richard Weinberger
2012-05-22 8:23 ` Artem Bityutskiy
2012-05-22 10:58 ` Artem Bityutskiy
2012-05-16 14:03 ` Shmulik Ladkani
2012-05-16 14:27 ` Artem Bityutskiy
2012-05-17 9:45 ` Shmulik Ladkani
2012-05-17 11:44 ` Artem Bityutskiy
2012-05-17 11:47 ` Richard Weinberger
2012-05-17 12:34 ` Artem Bityutskiy
2012-05-15 17:11 ` [PATCH 2/7] [RFC] UBI: Export compare_lebs() Richard Weinberger
2012-05-16 14:09 ` Shmulik Ladkani
2012-05-15 17:11 ` [PATCH 3/7] [RFC] UBI: Add fastmap on-flash layout Richard Weinberger
2012-05-15 17:11 ` [PATCH 4/7] [RFC] UBI: Add fastmap structs to ubi_device Richard Weinberger
2012-05-15 17:11 ` Richard Weinberger [this message]
2012-05-15 17:11 ` [PATCH 6/7] [RFC] UBI: Implement fastmapping support Richard Weinberger
2012-05-15 17:11 ` [PATCH 7/7] [RFC] UBI: Wire up fastmap support Richard Weinberger
2012-05-15 17:48 ` [RFC v4] UBI: Fastmap support (aka checkpointing) Subodh Nijsure
2012-05-15 18:10 ` Richard Weinberger
2012-05-15 18:02 ` Richard Weinberger
2012-05-15 19:46 ` Shmulik Ladkani
2012-05-16 6:54 ` Fastmap - please, review and test Artem Bityutskiy
2012-05-16 11:51 ` Richard Weinberger
2012-05-16 9:38 ` [RFC v4] UBI: Fastmap support (aka checkpointing) Artem Bityutskiy
2012-05-16 9:42 ` Artem Bityutskiy
2012-05-16 10:50 ` Richard Weinberger
2012-05-16 11:09 ` Artem Bityutskiy
2012-05-16 11:18 ` Artem Bityutskiy
2012-05-16 11:29 ` Richard Weinberger
-- strict thread matches above, loose matches on Subject: below --
2012-05-16 20:51 [RFC v5] " Richard Weinberger
2012-05-16 20:52 ` [PATCH 5/7] [RFC] UBI: Make wl subsystem fastmap aware Richard Weinberger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1337101871-31181-6-git-send-email-richard@nod.at \
--to=richard@nod.at \
--cc=Heinz.Egger@linutronix.de \
--cc=dedekind1@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=tglx@linutronix.de \
--cc=tim.bird@am.sony.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).