All of lore.kernel.org
 help / color / mirror / Atom feed
* (no subject)
       [not found] <UBI fastmap updates>
@ 2012-06-21 21:49 ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                     ` (14 more replies)
  0 siblings, 15 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:49 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy

This is the next round of UBI fastmap updates.

The highlights are:
        - New self checks and a better fall back to scanning mechanism
        - The attaching by fastmap code got simplified
        - invalidate_fastmap() now really invalidates the fastmap B-)
        - Minor fixes

If you want to test fastmap you can use my git repo:
git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubi2.git ubi2/v12

Enjoy!
//richard

[PATCH 01/15] UBI: Fastmap: Relax EBA selfcheck
[PATCH 02/15] UBI: Fastmap: Coding style fix...
[PATCH 03/15] UBI: Fastmap: Modify ubi_attach() to force scanning if
[PATCH 04/15] UBI: Fastmap: Always refill pools upon writing a new
[PATCH 05/15] UBI: Fastmap: Amend locking
[PATCH 06/15] UBI: Fastmap: Call ensure_wear_leveling() again in
[PATCH 07/15] UBI: Fastmap: Add a workqueue to allow delayed fastmap
[PATCH 08/15] UBI: Fastmap: Fix lock inbalance
[PATCH 09/15] UBI: Fastmap: Simplify attach by fastmap
[PATCH 10/15] UBI: Fastmap: Remove unused variable
[PATCH 11/15] UBI: Fastmap: Remove unused label
[PATCH 12/15] UBI: Fastmap: Fix ai handling
[PATCH 13/15] UBI: Fastmap: Add new self check
[PATCH 14/15] UBI: Fastmap: Improve invalidate_fastmap()
[PATCH 15/15] UBI: Fastmap: Write a fastmap also while detaching.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 01/15] UBI: Fastmap: Relax EBA selfcheck
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:49     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:49 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger

It is allowed that fastmap knows an EBA table entry
as unmapped while scanning would know this entry as
mapped.
Fastmap knows the current EBA table and scannning
reconstructs it. This case can happen if the fastmap
gets written while the entry is alredy unmapped but the
PEB has not been erased.
If the UBI device gets detached at this moment, scanning
may detect this EBA entry as mapped.
(Of course the upper layer, UBIFS, knows this LEB is no longer
used)

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/eba.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 2bee8be..6698d5e 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -1276,7 +1276,8 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
 
 		for (j = 0; j < vol->reserved_pebs; j++) {
 			if (scan_eba[i][j] != fm_eba[i][j]) {
-				if (scan_eba[i][j] == UBI_LEB_UNMAPPED)
+				if (scan_eba[i][j] == UBI_LEB_UNMAPPED ||
+					fm_eba[i][j] == UBI_LEB_UNMAPPED)
 					continue;
 
 				ubi_err("LEB:%i is mapped to PEB:%i instead of PEB:%i!", i, fm_eba[i][j], scan_eba[i][j]);
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 01/15] UBI: Fastmap: Relax EBA selfcheck
@ 2012-06-21 21:49     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:49 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird

It is allowed that fastmap knows an EBA table entry
as unmapped while scanning would know this entry as
mapped.
Fastmap knows the current EBA table and scannning
reconstructs it. This case can happen if the fastmap
gets written while the entry is alredy unmapped but the
PEB has not been erased.
If the UBI device gets detached at this moment, scanning
may detect this EBA entry as mapped.
(Of course the upper layer, UBIFS, knows this LEB is no longer
used)

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/eba.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 2bee8be..6698d5e 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -1276,7 +1276,8 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
 
 		for (j = 0; j < vol->reserved_pebs; j++) {
 			if (scan_eba[i][j] != fm_eba[i][j]) {
-				if (scan_eba[i][j] == UBI_LEB_UNMAPPED)
+				if (scan_eba[i][j] == UBI_LEB_UNMAPPED ||
+					fm_eba[i][j] == UBI_LEB_UNMAPPED)
 					continue;
 
 				ubi_err("LEB:%i is mapped to PEB:%i instead of PEB:%i!", i, fm_eba[i][j], scan_eba[i][j]);
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 02/15] UBI: Fastmap: Coding style fix...
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:49     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:49 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/eba.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 6698d5e..294ceb8 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -1280,7 +1280,8 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
 					fm_eba[i][j] == UBI_LEB_UNMAPPED)
 					continue;
 
-				ubi_err("LEB:%i is mapped to PEB:%i instead of PEB:%i!", i, fm_eba[i][j], scan_eba[i][j]);
+				ubi_err("LEB:%i:%i is PEB:%i instead of %i!",
+					vol->vol_id, i, fm_eba[i][j], scan_eba[i][j]);
 				BUG();
 			}
 		}
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 02/15] UBI: Fastmap: Coding style fix...
@ 2012-06-21 21:49     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:49 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/eba.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 6698d5e..294ceb8 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -1280,7 +1280,8 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
 					fm_eba[i][j] == UBI_LEB_UNMAPPED)
 					continue;
 
-				ubi_err("LEB:%i is mapped to PEB:%i instead of PEB:%i!", i, fm_eba[i][j], scan_eba[i][j]);
+				ubi_err("LEB:%i:%i is PEB:%i instead of %i!",
+					vol->vol_id, i, fm_eba[i][j], scan_eba[i][j]);
 				BUG();
 			}
 		}
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 03/15] UBI: Fastmap: Modify ubi_attach() to force scanning if requested
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:49     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:49 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/attach.c |   18 +++++++++++-------
 drivers/mtd/ubi/build.c  |    2 +-
 drivers/mtd/ubi/ubi.h    |    2 +-
 3 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 5cba456..7f65166 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -1207,25 +1207,29 @@ out_ai:
 /**
  * ubi_attach - attach an MTD device.
  * @ubi: UBI device descriptor
+ * @force_scan: if set to non-zero attach by scanning
  *
  * This function returns zero in case of success and a negative error code in
  * case of failure.
  */
-int ubi_attach(struct ubi_device *ubi)
+int ubi_attach(struct ubi_device *ubi, int force_scan)
 {
-	int err;
+	int err, i;
 	struct ubi_attach_info *ai;
 
 	ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
 	if (!ai)
 		return -ENOMEM;
 
-	err = ubi_scan_fastmap(ubi, ai);
-	if (err > 0) {
+	if (force_scan)
 		err = scan_all(ubi, ai);
-		if (err)
-			return err;
-	} else if (err < 0)
+	else {
+		err = ubi_scan_fastmap(ubi, ai);
+		if (err > 0)
+			err = scan_all(ubi, ai);
+	}
+
+	if (err)
 		return err;
 
 	/* TODO: currently the fastmap code assumes that the fastmap data
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 1ad128d..186bc19 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -928,7 +928,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 	if (err)
 		goto out_free;
 
-	err = ubi_attach(ubi);
+	err = ubi_attach(ubi, 0);
 	if (err) {
 		ubi_err("failed to attach mtd%d, error %d", mtd->index, err);
 		goto out_debugging;
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 8abbcd5..a568a3b 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -693,7 +693,7 @@ struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai,
 void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av);
 struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
 				       struct ubi_attach_info *ai);
-int ubi_attach(struct ubi_device *ubi);
+int ubi_attach(struct ubi_device *ubi, int force_scan);
 void ubi_destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai);
 
 /* vtbl.c */
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 03/15] UBI: Fastmap: Modify ubi_attach() to force scanning if requested
@ 2012-06-21 21:49     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:49 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/attach.c |   18 +++++++++++-------
 drivers/mtd/ubi/build.c  |    2 +-
 drivers/mtd/ubi/ubi.h    |    2 +-
 3 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 5cba456..7f65166 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -1207,25 +1207,29 @@ out_ai:
 /**
  * ubi_attach - attach an MTD device.
  * @ubi: UBI device descriptor
+ * @force_scan: if set to non-zero attach by scanning
  *
  * This function returns zero in case of success and a negative error code in
  * case of failure.
  */
-int ubi_attach(struct ubi_device *ubi)
+int ubi_attach(struct ubi_device *ubi, int force_scan)
 {
-	int err;
+	int err, i;
 	struct ubi_attach_info *ai;
 
 	ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
 	if (!ai)
 		return -ENOMEM;
 
-	err = ubi_scan_fastmap(ubi, ai);
-	if (err > 0) {
+	if (force_scan)
 		err = scan_all(ubi, ai);
-		if (err)
-			return err;
-	} else if (err < 0)
+	else {
+		err = ubi_scan_fastmap(ubi, ai);
+		if (err > 0)
+			err = scan_all(ubi, ai);
+	}
+
+	if (err)
 		return err;
 
 	/* TODO: currently the fastmap code assumes that the fastmap data
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 1ad128d..186bc19 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -928,7 +928,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 	if (err)
 		goto out_free;
 
-	err = ubi_attach(ubi);
+	err = ubi_attach(ubi, 0);
 	if (err) {
 		ubi_err("failed to attach mtd%d, error %d", mtd->index, err);
 		goto out_debugging;
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 8abbcd5..a568a3b 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -693,7 +693,7 @@ struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai,
 void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av);
 struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
 				       struct ubi_attach_info *ai);
-int ubi_attach(struct ubi_device *ubi);
+int ubi_attach(struct ubi_device *ubi, int force_scan);
 void ubi_destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai);
 
 /* vtbl.c */
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 04/15] UBI: Fastmap: Always refill pools upon writing a new fastmap.
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:49     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:49 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger

If we allow writing a new fastmap without refilling the current
pool at attach time we have to think about strange corner cases.
E.g. A PEB can be within a pool and in the free or used list.
To simplify the code for attaching this change has been made.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/fastmap.c |   14 +++++-
 drivers/mtd/ubi/ubi.h     |    1 +
 drivers/mtd/ubi/wl.c      |  100 ++++++++++++++++++++++++++-------------------
 3 files changed, 70 insertions(+), 45 deletions(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index cccb0c9..ba69267 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1362,12 +1362,20 @@ int ubi_update_fastmap(struct ubi_device *ubi)
 	struct ubi_fastmap_layout *new_fm, *old_fm;
 	struct ubi_wl_entry *tmp_e;
 
-	if (ubi->ro_mode)
+	mutex_lock(&ubi->fm_mutex);
+
+	ubi_refill_pools(ubi);
+
+	if (ubi->ro_mode) {
+		mutex_unlock(&ubi->fm_mutex);
 		return 0;
+	}
 
 	new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL);
-	if (!new_fm)
+	if (!new_fm) {
+		mutex_unlock(&ubi->fm_mutex);
 		return -ENOMEM;
+	}
 
 	new_fm->size = sizeof(struct ubi_fm_hdr) + \
 			sizeof(struct ubi_fm_scan_pool) + \
@@ -1387,11 +1395,11 @@ int ubi_update_fastmap(struct ubi_device *ubi)
 				kfree(new_fm->e[i]);
 
 			kfree(new_fm);
+			mutex_unlock(&ubi->fm_mutex);
 			return -ENOMEM;
 		}
 	}
 
-	mutex_lock(&ubi->fm_mutex);
 	old_fm = ubi->fm;
 	ubi->fm = NULL;
 
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index a568a3b..a0c2103 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -757,6 +757,7 @@ int ubi_thread(void *u);
 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);
 
 /* 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 f4d2c79..ec0a954 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -497,43 +497,76 @@ retry:
 
 	return e->pnum;
 }
-
-static int refill_wl_pool(struct ubi_device *ubi)
+/**
+ * return_unused_pool_pebs - returns unused PEB to the free tree.
+ * @ubi: UBI device description object
+ * @pool: fastmap pool description object
+ */
+static void return_unused_pool_pebs(struct ubi_device *ubi,
+				    struct ubi_fm_pool *pool)
 {
-	int ret, i;
-	struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
+	int i;
 	struct ubi_wl_entry *e;
 
-	spin_lock(&ubi->wl_lock);
-	if (pool->used != pool->size && pool->size) {
-		spin_unlock(&ubi->wl_lock);
-		return 0;
+	for (i = pool->used; i < pool->size; i++) {
+		e = ubi->lookuptbl[pool->pebs[i]];
+		wl_tree_add(e, &ubi->free);
 	}
+}
 
-	for (i = 0; i < pool->max_size; i++) {
-		if (!ubi->free.rb_node) {
-			spin_unlock(&ubi->wl_lock);
+/**
+ * refill_wl_pool - refills all the fastmap pool used by the
+ * WL sub-system.
+ * @ubi: UBI device description object
+ */
+static void refill_wl_pool(struct ubi_device *ubi)
+{
+	struct ubi_wl_entry *e;
+	struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
+
+	return_unused_pool_pebs(ubi, pool);
+
+	for (pool->size = 0; pool->size < pool->max_size; pool->size++) {
+		if (!ubi->free.rb_node)
 			break;
-		}
 
 		e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
 		self_check_in_wl_tree(ubi, e, &ubi->free);
 		rb_erase(&e->u.rb, &ubi->free);
 
-		pool->pebs[i] = e->pnum;
+		pool->pebs[pool->size] = e->pnum;
 	}
-	pool->size = i;
-	spin_unlock(&ubi->wl_lock);
+	pool->used = 0;
+}
+
+/**
+ * refill_wl_user_pool - refills all the fastmap pool used by ubi_wl_get_peb.
+ * @ubi: UBI device description object
+ */
+static void refill_wl_user_pool(struct ubi_device *ubi)
+{
+	struct ubi_fm_pool *pool = &ubi->fm_pool;
 
-	ret = ubi_update_fastmap(ubi);
-	if (ret) {
-		ubi_ro_mode(ubi);
+	return_unused_pool_pebs(ubi, pool);
 
-		return ret > 0 ? -EINVAL : ret;
+	for (pool->size = 0; pool->size < pool->max_size; pool->size++) {
+		pool->pebs[pool->size] = __ubi_wl_get_peb(ubi);
+		if (pool->pebs[pool->size] < 0)
+			break;
 	}
 	pool->used = 0;
+}
 
-	return pool->size ? 0 : -ENOSPC;
+/**
+ * ubi_refill_pools - refills all fastmap PEB pools.
+ * @ubi: UBI device description object
+ */
+void ubi_refill_pools(struct ubi_device *ubi)
+{
+	spin_lock(&ubi->wl_lock);
+	refill_wl_pool(ubi);
+	refill_wl_user_pool(ubi);
+	spin_unlock(&ubi->wl_lock);
 }
 
 /* ubi_wl_get_peb - works exaclty like __ubi_wl_get_peb but keeps track of
@@ -541,32 +574,15 @@ static int refill_wl_pool(struct ubi_device *ubi)
  */
 int ubi_wl_get_peb(struct ubi_device *ubi)
 {
-	struct ubi_fm_pool *pool = &ubi->fm_pool;
 	int ret;
+	struct ubi_fm_pool *pool = &ubi->fm_pool;
+	struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool;
 
 	mutex_lock(&ubi->fm_pool_mutex);
 
-	refill_wl_pool(ubi);
-
-	/* pool contains no free blocks, create a new one
-	 * and write a fastmap */
-	if (pool->used == pool->size || !pool->size) {
-		for (pool->size = 0; pool->size < pool->max_size;
-				pool->size++) {
-			pool->pebs[pool->size] = __ubi_wl_get_peb(ubi);
-			if (pool->pebs[pool->size] < 0)
-				break;
-		}
-
-		pool->used = 0;
-		ret = ubi_update_fastmap(ubi);
-		if (ret) {
-			ubi_ro_mode(ubi);
-			mutex_unlock(&ubi->fm_pool_mutex);
-
-			return ret > 0 ? -EINVAL : ret;
-		}
-	}
+	if (!pool->size || !wl_pool->size || pool->used == pool->size ||
+	    wl_pool->used == wl_pool->size)
+		ubi_update_fastmap(ubi);
 
 	/* we got not a single free PEB */
 	if (!pool->size)
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 04/15] UBI: Fastmap: Always refill pools upon writing a new fastmap.
@ 2012-06-21 21:49     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:49 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird

If we allow writing a new fastmap without refilling the current
pool at attach time we have to think about strange corner cases.
E.g. A PEB can be within a pool and in the free or used list.
To simplify the code for attaching this change has been made.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/fastmap.c |   14 +++++-
 drivers/mtd/ubi/ubi.h     |    1 +
 drivers/mtd/ubi/wl.c      |  100 ++++++++++++++++++++++++++-------------------
 3 files changed, 70 insertions(+), 45 deletions(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index cccb0c9..ba69267 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1362,12 +1362,20 @@ int ubi_update_fastmap(struct ubi_device *ubi)
 	struct ubi_fastmap_layout *new_fm, *old_fm;
 	struct ubi_wl_entry *tmp_e;
 
-	if (ubi->ro_mode)
+	mutex_lock(&ubi->fm_mutex);
+
+	ubi_refill_pools(ubi);
+
+	if (ubi->ro_mode) {
+		mutex_unlock(&ubi->fm_mutex);
 		return 0;
+	}
 
 	new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL);
-	if (!new_fm)
+	if (!new_fm) {
+		mutex_unlock(&ubi->fm_mutex);
 		return -ENOMEM;
+	}
 
 	new_fm->size = sizeof(struct ubi_fm_hdr) + \
 			sizeof(struct ubi_fm_scan_pool) + \
@@ -1387,11 +1395,11 @@ int ubi_update_fastmap(struct ubi_device *ubi)
 				kfree(new_fm->e[i]);
 
 			kfree(new_fm);
+			mutex_unlock(&ubi->fm_mutex);
 			return -ENOMEM;
 		}
 	}
 
-	mutex_lock(&ubi->fm_mutex);
 	old_fm = ubi->fm;
 	ubi->fm = NULL;
 
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index a568a3b..a0c2103 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -757,6 +757,7 @@ int ubi_thread(void *u);
 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);
 
 /* 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 f4d2c79..ec0a954 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -497,43 +497,76 @@ retry:
 
 	return e->pnum;
 }
-
-static int refill_wl_pool(struct ubi_device *ubi)
+/**
+ * return_unused_pool_pebs - returns unused PEB to the free tree.
+ * @ubi: UBI device description object
+ * @pool: fastmap pool description object
+ */
+static void return_unused_pool_pebs(struct ubi_device *ubi,
+				    struct ubi_fm_pool *pool)
 {
-	int ret, i;
-	struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
+	int i;
 	struct ubi_wl_entry *e;
 
-	spin_lock(&ubi->wl_lock);
-	if (pool->used != pool->size && pool->size) {
-		spin_unlock(&ubi->wl_lock);
-		return 0;
+	for (i = pool->used; i < pool->size; i++) {
+		e = ubi->lookuptbl[pool->pebs[i]];
+		wl_tree_add(e, &ubi->free);
 	}
+}
 
-	for (i = 0; i < pool->max_size; i++) {
-		if (!ubi->free.rb_node) {
-			spin_unlock(&ubi->wl_lock);
+/**
+ * refill_wl_pool - refills all the fastmap pool used by the
+ * WL sub-system.
+ * @ubi: UBI device description object
+ */
+static void refill_wl_pool(struct ubi_device *ubi)
+{
+	struct ubi_wl_entry *e;
+	struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
+
+	return_unused_pool_pebs(ubi, pool);
+
+	for (pool->size = 0; pool->size < pool->max_size; pool->size++) {
+		if (!ubi->free.rb_node)
 			break;
-		}
 
 		e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
 		self_check_in_wl_tree(ubi, e, &ubi->free);
 		rb_erase(&e->u.rb, &ubi->free);
 
-		pool->pebs[i] = e->pnum;
+		pool->pebs[pool->size] = e->pnum;
 	}
-	pool->size = i;
-	spin_unlock(&ubi->wl_lock);
+	pool->used = 0;
+}
+
+/**
+ * refill_wl_user_pool - refills all the fastmap pool used by ubi_wl_get_peb.
+ * @ubi: UBI device description object
+ */
+static void refill_wl_user_pool(struct ubi_device *ubi)
+{
+	struct ubi_fm_pool *pool = &ubi->fm_pool;
 
-	ret = ubi_update_fastmap(ubi);
-	if (ret) {
-		ubi_ro_mode(ubi);
+	return_unused_pool_pebs(ubi, pool);
 
-		return ret > 0 ? -EINVAL : ret;
+	for (pool->size = 0; pool->size < pool->max_size; pool->size++) {
+		pool->pebs[pool->size] = __ubi_wl_get_peb(ubi);
+		if (pool->pebs[pool->size] < 0)
+			break;
 	}
 	pool->used = 0;
+}
 
-	return pool->size ? 0 : -ENOSPC;
+/**
+ * ubi_refill_pools - refills all fastmap PEB pools.
+ * @ubi: UBI device description object
+ */
+void ubi_refill_pools(struct ubi_device *ubi)
+{
+	spin_lock(&ubi->wl_lock);
+	refill_wl_pool(ubi);
+	refill_wl_user_pool(ubi);
+	spin_unlock(&ubi->wl_lock);
 }
 
 /* ubi_wl_get_peb - works exaclty like __ubi_wl_get_peb but keeps track of
@@ -541,32 +574,15 @@ static int refill_wl_pool(struct ubi_device *ubi)
  */
 int ubi_wl_get_peb(struct ubi_device *ubi)
 {
-	struct ubi_fm_pool *pool = &ubi->fm_pool;
 	int ret;
+	struct ubi_fm_pool *pool = &ubi->fm_pool;
+	struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool;
 
 	mutex_lock(&ubi->fm_pool_mutex);
 
-	refill_wl_pool(ubi);
-
-	/* pool contains no free blocks, create a new one
-	 * and write a fastmap */
-	if (pool->used == pool->size || !pool->size) {
-		for (pool->size = 0; pool->size < pool->max_size;
-				pool->size++) {
-			pool->pebs[pool->size] = __ubi_wl_get_peb(ubi);
-			if (pool->pebs[pool->size] < 0)
-				break;
-		}
-
-		pool->used = 0;
-		ret = ubi_update_fastmap(ubi);
-		if (ret) {
-			ubi_ro_mode(ubi);
-			mutex_unlock(&ubi->fm_pool_mutex);
-
-			return ret > 0 ? -EINVAL : ret;
-		}
-	}
+	if (!pool->size || !wl_pool->size || pool->used == pool->size ||
+	    wl_pool->used == wl_pool->size)
+		ubi_update_fastmap(ubi);
 
 	/* we got not a single free PEB */
 	if (!pool->size)
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 05/15] UBI: Fastmap: Amend locking
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:49     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:49 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger

__ubi_wl_get_peb() gets called under wl_lock.
So need to grab it again.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/wl.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index ec0a954..e014f7e 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -255,7 +255,6 @@ static int produce_free_peb(struct ubi_device *ubi)
 {
 	int err;
 
-	spin_lock(&ubi->wl_lock);
 	while (!ubi->free.rb_node) {
 		spin_unlock(&ubi->wl_lock);
 
@@ -266,7 +265,6 @@ static int produce_free_peb(struct ubi_device *ubi)
 
 		spin_lock(&ubi->wl_lock);
 	}
-	spin_unlock(&ubi->wl_lock);
 
 	return 0;
 }
@@ -460,7 +458,6 @@ static int __ubi_wl_get_peb(struct ubi_device *ubi)
 	struct ubi_wl_entry *e;
 
 retry:
-	spin_lock(&ubi->wl_lock);
 	if (!ubi->free.rb_node) {
 		if (ubi->works_count == 0) {
 			ubi_assert(list_empty(&ubi->works));
@@ -468,7 +465,6 @@ retry:
 			spin_unlock(&ubi->wl_lock);
 			return -ENOSPC;
 		}
-		spin_unlock(&ubi->wl_lock);
 
 		err = produce_free_peb(ubi);
 		if (err < 0)
@@ -486,7 +482,6 @@ retry:
 	 */
 	rb_erase(&e->u.rb, &ubi->free);
 	dbg_wl("PEB %d EC %d", e->pnum, e->ec);
-	spin_unlock(&ubi->wl_lock);
 
 	err = ubi_self_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
 				    ubi->peb_size - ubi->vid_hdr_aloffset);
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 05/15] UBI: Fastmap: Amend locking
@ 2012-06-21 21:49     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:49 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird

__ubi_wl_get_peb() gets called under wl_lock.
So need to grab it again.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/wl.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index ec0a954..e014f7e 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -255,7 +255,6 @@ static int produce_free_peb(struct ubi_device *ubi)
 {
 	int err;
 
-	spin_lock(&ubi->wl_lock);
 	while (!ubi->free.rb_node) {
 		spin_unlock(&ubi->wl_lock);
 
@@ -266,7 +265,6 @@ static int produce_free_peb(struct ubi_device *ubi)
 
 		spin_lock(&ubi->wl_lock);
 	}
-	spin_unlock(&ubi->wl_lock);
 
 	return 0;
 }
@@ -460,7 +458,6 @@ static int __ubi_wl_get_peb(struct ubi_device *ubi)
 	struct ubi_wl_entry *e;
 
 retry:
-	spin_lock(&ubi->wl_lock);
 	if (!ubi->free.rb_node) {
 		if (ubi->works_count == 0) {
 			ubi_assert(list_empty(&ubi->works));
@@ -468,7 +465,6 @@ retry:
 			spin_unlock(&ubi->wl_lock);
 			return -ENOSPC;
 		}
-		spin_unlock(&ubi->wl_lock);
 
 		err = produce_free_peb(ubi);
 		if (err < 0)
@@ -486,7 +482,6 @@ retry:
 	 */
 	rb_erase(&e->u.rb, &ubi->free);
 	dbg_wl("PEB %d EC %d", e->pnum, e->ec);
-	spin_unlock(&ubi->wl_lock);
 
 	err = ubi_self_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
 				    ubi->peb_size - ubi->vid_hdr_aloffset);
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 06/15] UBI: Fastmap: Call ensure_wear_leveling() again in erase_worker()
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:49     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:49 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger

This call to ensure_wear_leveling() has been removed because of a restriction
in fastmap.
It's no loner valid, now we can call it again.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/wl.c |   35 +++++++++++++++++++++++++++--------
 1 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index e014f7e..7520319 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -741,16 +741,15 @@ repeat:
 }
 
 /**
- * schedule_ubi_work - schedule a work.
+ * __schedule_ubi_work - schedule a work.
  * @ubi: UBI device description object
  * @wrk: the work to schedule
  *
  * This function adds a work defined by @wrk to the tail of the pending works
- * list.
+ * list. Can only be used of ubi->work_sem is already held in read mode!
  */
-static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
+static void __schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
 {
-	down_read(&ubi->work_sem);
 	spin_lock(&ubi->wl_lock);
 	list_add_tail(&wrk->list, &ubi->works);
 	ubi_assert(ubi->works_count >= 0);
@@ -758,6 +757,20 @@ static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
 	if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled(ubi))
 		wake_up_process(ubi->bgt_thread);
 	spin_unlock(&ubi->wl_lock);
+}
+
+/**
+ * schedule_ubi_work - schedule a work.
+ * @ubi: UBI device description object
+ * @wrk: the work to schedule
+ *
+ * This function adds a work defined by @wrk to the tail of the pending works
+ * list.
+ */
+static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
+{
+	down_read(&ubi->work_sem);
+	__schedule_ubi_work(ubi, wrk);
 	up_read(&ubi->work_sem);
 }
 
@@ -1157,7 +1170,7 @@ out_cancel:
  * if yes. This function returns zero in case of success and a negative error
  * code in case of failure.
  */
-static int ensure_wear_leveling(struct ubi_device *ubi)
+static int ensure_wear_leveling(struct ubi_device *ubi, int nested)
 {
 	int err = 0;
 	struct ubi_wl_entry *e1;
@@ -1203,7 +1216,10 @@ static int ensure_wear_leveling(struct ubi_device *ubi)
 	}
 
 	wrk->func = &wear_leveling_worker;
-	schedule_ubi_work(ubi, wrk);
+	if (nested)
+		__schedule_ubi_work(ubi, wrk);
+	else
+		schedule_ubi_work(ubi, wrk);
 	return err;
 
 out_cancel:
@@ -1256,6 +1272,9 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
 		 * protected physical eraseblocks.
 		 */
 		serve_prot_queue(ubi);
+
+		/* And take care about wear-leveling */
+		ensure_wear_leveling(ubi, 1);
 		return err;
 	}
 
@@ -1479,7 +1498,7 @@ retry:
 	 * Technically scrubbing is the same as wear-leveling, so it is done
 	 * by the WL worker.
 	 */
-	return ensure_wear_leveling(ubi);
+	return ensure_wear_leveling(ubi, 0);
 }
 
 /**
@@ -1748,7 +1767,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	ubi->rsvd_pebs += WL_RESERVED_PEBS;
 
 	/* Schedule wear-leveling if needed */
-	err = ensure_wear_leveling(ubi);
+	err = ensure_wear_leveling(ubi, 0);
 	if (err)
 		goto out_free;
 
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 06/15] UBI: Fastmap: Call ensure_wear_leveling() again in erase_worker()
@ 2012-06-21 21:49     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:49 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird

This call to ensure_wear_leveling() has been removed because of a restriction
in fastmap.
It's no loner valid, now we can call it again.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/wl.c |   35 +++++++++++++++++++++++++++--------
 1 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index e014f7e..7520319 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -741,16 +741,15 @@ repeat:
 }
 
 /**
- * schedule_ubi_work - schedule a work.
+ * __schedule_ubi_work - schedule a work.
  * @ubi: UBI device description object
  * @wrk: the work to schedule
  *
  * This function adds a work defined by @wrk to the tail of the pending works
- * list.
+ * list. Can only be used of ubi->work_sem is already held in read mode!
  */
-static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
+static void __schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
 {
-	down_read(&ubi->work_sem);
 	spin_lock(&ubi->wl_lock);
 	list_add_tail(&wrk->list, &ubi->works);
 	ubi_assert(ubi->works_count >= 0);
@@ -758,6 +757,20 @@ static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
 	if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled(ubi))
 		wake_up_process(ubi->bgt_thread);
 	spin_unlock(&ubi->wl_lock);
+}
+
+/**
+ * schedule_ubi_work - schedule a work.
+ * @ubi: UBI device description object
+ * @wrk: the work to schedule
+ *
+ * This function adds a work defined by @wrk to the tail of the pending works
+ * list.
+ */
+static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
+{
+	down_read(&ubi->work_sem);
+	__schedule_ubi_work(ubi, wrk);
 	up_read(&ubi->work_sem);
 }
 
@@ -1157,7 +1170,7 @@ out_cancel:
  * if yes. This function returns zero in case of success and a negative error
  * code in case of failure.
  */
-static int ensure_wear_leveling(struct ubi_device *ubi)
+static int ensure_wear_leveling(struct ubi_device *ubi, int nested)
 {
 	int err = 0;
 	struct ubi_wl_entry *e1;
@@ -1203,7 +1216,10 @@ static int ensure_wear_leveling(struct ubi_device *ubi)
 	}
 
 	wrk->func = &wear_leveling_worker;
-	schedule_ubi_work(ubi, wrk);
+	if (nested)
+		__schedule_ubi_work(ubi, wrk);
+	else
+		schedule_ubi_work(ubi, wrk);
 	return err;
 
 out_cancel:
@@ -1256,6 +1272,9 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
 		 * protected physical eraseblocks.
 		 */
 		serve_prot_queue(ubi);
+
+		/* And take care about wear-leveling */
+		ensure_wear_leveling(ubi, 1);
 		return err;
 	}
 
@@ -1479,7 +1498,7 @@ retry:
 	 * Technically scrubbing is the same as wear-leveling, so it is done
 	 * by the WL worker.
 	 */
-	return ensure_wear_leveling(ubi);
+	return ensure_wear_leveling(ubi, 0);
 }
 
 /**
@@ -1748,7 +1767,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	ubi->rsvd_pebs += WL_RESERVED_PEBS;
 
 	/* Schedule wear-leveling if needed */
-	err = ensure_wear_leveling(ubi);
+	err = ensure_wear_leveling(ubi, 0);
 	if (err)
 		goto out_free;
 
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 07/15] UBI: Fastmap: Add a workqueue to allow delayed fastmap update
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:50     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/ubi.h |    2 ++
 drivers/mtd/ubi/wl.c  |   16 ++++++++++++++++
 2 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index a0c2103..7e0dfda 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -385,6 +385,7 @@ struct ubi_wl_entry;
  * @fm_pool_mutex: serializes ubi_wl_get_peb()
  * @fm_mutex: serializes ubi_update_fastmap()
  * @fm_sem: allows ubi_update_fastmap() to block EBA table changes
+ * @fm_work: fastmap work queue
  * @attached_by_scanning: this UBI device was attached by the old scanning
  *			  methold. All fastmap volumes have to be deleted.
  *
@@ -486,6 +487,7 @@ struct ubi_device {
 	struct rw_semaphore fm_sem;
 	struct mutex fm_mutex;
 	struct mutex fm_pool_mutex;
+	struct work_struct fm_work;
 	int attached_by_scanning;
 
 	/* Wear-leveling sub-system's stuff */
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 7520319..6f346f5 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -140,6 +140,17 @@ static int self_check_in_wl_tree(const struct ubi_device *ubi,
 				 struct ubi_wl_entry *e, struct rb_root *root);
 static int self_check_in_pq(const struct ubi_device *ubi,
 			    struct ubi_wl_entry *e);
+
+/**
+ * update_fastmap_work_fn - calls ubi_update_fastmap from a work queue
+ * @wrk: the work description object
+ */
+static void update_fastmap_work_fn(struct work_struct *wrk)
+{
+	struct ubi_device *ubi = container_of(wrk, struct ubi_device, fm_work);
+	ubi_update_fastmap(ubi);
+}
+
 /**
  *  ubi_ubi_is_fm_block - returns 1 if a PEB is currently used in a fastmap.
  *  @ubi: UBI device description object
@@ -604,6 +615,10 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
 	int pnum;
 
 	if (pool->used == pool->size || !pool->size) {
+		/* We cannot update the fastmap here because this
+		 * function is called in atomic context.
+		 * Let's fail an refill/update it as soon as possible. */
+		schedule_work(&ubi->fm_work);
 		return NULL;
 	} else {
 		pnum = pool->pebs[pool->used++];
@@ -1671,6 +1686,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	init_rwsem(&ubi->work_sem);
 	ubi->max_ec = ai->max_ec;
 	INIT_LIST_HEAD(&ubi->works);
+	INIT_WORK(&ubi->fm_work, update_fastmap_work_fn);
 
 	sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num);
 
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 07/15] UBI: Fastmap: Add a workqueue to allow delayed fastmap update
@ 2012-06-21 21:50     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/ubi.h |    2 ++
 drivers/mtd/ubi/wl.c  |   16 ++++++++++++++++
 2 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index a0c2103..7e0dfda 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -385,6 +385,7 @@ struct ubi_wl_entry;
  * @fm_pool_mutex: serializes ubi_wl_get_peb()
  * @fm_mutex: serializes ubi_update_fastmap()
  * @fm_sem: allows ubi_update_fastmap() to block EBA table changes
+ * @fm_work: fastmap work queue
  * @attached_by_scanning: this UBI device was attached by the old scanning
  *			  methold. All fastmap volumes have to be deleted.
  *
@@ -486,6 +487,7 @@ struct ubi_device {
 	struct rw_semaphore fm_sem;
 	struct mutex fm_mutex;
 	struct mutex fm_pool_mutex;
+	struct work_struct fm_work;
 	int attached_by_scanning;
 
 	/* Wear-leveling sub-system's stuff */
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 7520319..6f346f5 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -140,6 +140,17 @@ static int self_check_in_wl_tree(const struct ubi_device *ubi,
 				 struct ubi_wl_entry *e, struct rb_root *root);
 static int self_check_in_pq(const struct ubi_device *ubi,
 			    struct ubi_wl_entry *e);
+
+/**
+ * update_fastmap_work_fn - calls ubi_update_fastmap from a work queue
+ * @wrk: the work description object
+ */
+static void update_fastmap_work_fn(struct work_struct *wrk)
+{
+	struct ubi_device *ubi = container_of(wrk, struct ubi_device, fm_work);
+	ubi_update_fastmap(ubi);
+}
+
 /**
  *  ubi_ubi_is_fm_block - returns 1 if a PEB is currently used in a fastmap.
  *  @ubi: UBI device description object
@@ -604,6 +615,10 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
 	int pnum;
 
 	if (pool->used == pool->size || !pool->size) {
+		/* We cannot update the fastmap here because this
+		 * function is called in atomic context.
+		 * Let's fail an refill/update it as soon as possible. */
+		schedule_work(&ubi->fm_work);
 		return NULL;
 	} else {
 		pnum = pool->pebs[pool->used++];
@@ -1671,6 +1686,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	init_rwsem(&ubi->work_sem);
 	ubi->max_ec = ai->max_ec;
 	INIT_LIST_HEAD(&ubi->works);
+	INIT_WORK(&ubi->fm_work, update_fastmap_work_fn);
 
 	sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num);
 
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 08/15] UBI: Fastmap: Fix lock inbalance
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:50     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/wl.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 6f346f5..6771f30 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -473,7 +473,6 @@ retry:
 		if (ubi->works_count == 0) {
 			ubi_assert(list_empty(&ubi->works));
 			ubi_err("no free eraseblocks");
-			spin_unlock(&ubi->wl_lock);
 			return -ENOSPC;
 		}
 
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 08/15] UBI: Fastmap: Fix lock inbalance
@ 2012-06-21 21:50     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/wl.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 6f346f5..6771f30 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -473,7 +473,6 @@ retry:
 		if (ubi->works_count == 0) {
 			ubi_assert(list_empty(&ubi->works));
 			ubi_err("no free eraseblocks");
-			spin_unlock(&ubi->wl_lock);
 			return -ENOSPC;
 		}
 
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 09/15] UBI: Fastmap: Simplify attach by fastmap
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:50     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger

No need to check for this corner cases anymore.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/fastmap.c |   43 -------------------------------------------
 1 files changed, 0 insertions(+), 43 deletions(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index ba69267..da303b6 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -707,49 +707,6 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
 	if (max_sqnum > ai->max_sqnum)
 		ai->max_sqnum = max_sqnum;
 
-	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list) {
-		list_del(&tmp_aeb->u.list);
-		ubi_msg("moving PEB from used to erase: %i", tmp_aeb->pnum);
-		add_aeb(ai, &ai->erase, tmp_aeb->pnum, tmp_aeb->ec, 0);
-		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
-	}
-
-	/*
-	 * Sort out dups. We are allowed to have duplicates here because
-	 * the fastmap can be written without refilling all pools.
-	 * E.g. If PEB X is in a pool fastmap may detect it as empty and
-	 * puts it into the free list. But ff PEB X is in the pool, get's
-	 * used and returned (e.g. by schedule_erase()) it remains in
-	 * the erase or free list too.
-	 * We could also sort out these dups while creating the fastmap.
-	 */
-	if (list_empty(&free))
-		goto out;
-
-	list_for_each_entry(aeb, &ai->free, u.list) {
-		list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
-			if (aeb->pnum == tmp_aeb->pnum) {
-				aeb->scrub = tmp_aeb->scrub;
-				aeb->ec = tmp_aeb->ec;
-				list_del(&tmp_aeb->u.list);
-				kfree(tmp_aeb);
-				continue;
-			}
-		}
-	}
-
-	list_for_each_entry(aeb, &ai->erase, u.list) {
-		list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
-			if (aeb->pnum == tmp_aeb->pnum) {
-				aeb->scrub = tmp_aeb->scrub;
-				aeb->ec = tmp_aeb->ec;
-				list_del(&tmp_aeb->u.list);
-				kfree(tmp_aeb);
-				continue;
-			}
-		}
-	}
-
 	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
 		list_del(&tmp_aeb->u.list);
 		list_add_tail(&tmp_aeb->u.list, &ai->free);
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 09/15] UBI: Fastmap: Simplify attach by fastmap
@ 2012-06-21 21:50     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird

No need to check for this corner cases anymore.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/fastmap.c |   43 -------------------------------------------
 1 files changed, 0 insertions(+), 43 deletions(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index ba69267..da303b6 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -707,49 +707,6 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
 	if (max_sqnum > ai->max_sqnum)
 		ai->max_sqnum = max_sqnum;
 
-	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list) {
-		list_del(&tmp_aeb->u.list);
-		ubi_msg("moving PEB from used to erase: %i", tmp_aeb->pnum);
-		add_aeb(ai, &ai->erase, tmp_aeb->pnum, tmp_aeb->ec, 0);
-		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
-	}
-
-	/*
-	 * Sort out dups. We are allowed to have duplicates here because
-	 * the fastmap can be written without refilling all pools.
-	 * E.g. If PEB X is in a pool fastmap may detect it as empty and
-	 * puts it into the free list. But ff PEB X is in the pool, get's
-	 * used and returned (e.g. by schedule_erase()) it remains in
-	 * the erase or free list too.
-	 * We could also sort out these dups while creating the fastmap.
-	 */
-	if (list_empty(&free))
-		goto out;
-
-	list_for_each_entry(aeb, &ai->free, u.list) {
-		list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
-			if (aeb->pnum == tmp_aeb->pnum) {
-				aeb->scrub = tmp_aeb->scrub;
-				aeb->ec = tmp_aeb->ec;
-				list_del(&tmp_aeb->u.list);
-				kfree(tmp_aeb);
-				continue;
-			}
-		}
-	}
-
-	list_for_each_entry(aeb, &ai->erase, u.list) {
-		list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
-			if (aeb->pnum == tmp_aeb->pnum) {
-				aeb->scrub = tmp_aeb->scrub;
-				aeb->ec = tmp_aeb->ec;
-				list_del(&tmp_aeb->u.list);
-				kfree(tmp_aeb);
-				continue;
-			}
-		}
-	}
-
 	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
 		list_del(&tmp_aeb->u.list);
 		list_add_tail(&tmp_aeb->u.list, &ai->free);
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 10/15] UBI: Fastmap: Remove unused variable Signed-off-by: Richard Weinberger <richard@nod.at>
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:50     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger


Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/attach.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 7f65166..7cf4711 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -1214,7 +1214,7 @@ out_ai:
  */
 int ubi_attach(struct ubi_device *ubi, int force_scan)
 {
-	int err, i;
+	int err;
 	struct ubi_attach_info *ai;
 
 	ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 10/15] UBI: Fastmap: Remove unused variable Signed-off-by: Richard Weinberger <richard@nod.at>
@ 2012-06-21 21:50     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird


Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/attach.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 7f65166..7cf4711 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -1214,7 +1214,7 @@ out_ai:
  */
 int ubi_attach(struct ubi_device *ubi, int force_scan)
 {
-	int err, i;
+	int err;
 	struct ubi_attach_info *ai;
 
 	ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 11/15] UBI: Fastmap: Remove unused label Signed-off-by: Richard Weinberger <richard@nod.at>
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:50     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger


Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/fastmap.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index da303b6..76b0d2f 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -711,7 +711,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
 		list_del(&tmp_aeb->u.list);
 		list_add_tail(&tmp_aeb->u.list, &ai->free);
 	}
-out:
+
 	return 0;
 
 fail_bad:
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 11/15] UBI: Fastmap: Remove unused label Signed-off-by: Richard Weinberger <richard@nod.at>
@ 2012-06-21 21:50     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird


Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/fastmap.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index da303b6..76b0d2f 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -711,7 +711,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
 		list_del(&tmp_aeb->u.list);
 		list_add_tail(&tmp_aeb->u.list, &ai->free);
 	}
-out:
+
 	return 0;
 
 fail_bad:
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 12/15] UBI: Fastmap: Fix ai handling
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:50     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger

If attaching by fastmap fails, we have to free ai and
create a new one.
Fixes also destroy_ai to be able to destroy an unsued ai.
It's also no longer needed to export it.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/attach.c |   52 +++++++++++++++++++++++++++++++--------------
 drivers/mtd/ubi/ubi.h    |    1 -
 2 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 7cf4711..b6f8e95 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -90,6 +90,8 @@
 #include "ubi.h"
 
 static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai);
+static void destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai);
+static struct ubi_attach_info *new_ai(void);
 
 /* Temporary variables used during scanning */
 static struct ubi_ec_hdr *ech;
@@ -1123,12 +1125,6 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	struct ubi_ainf_volume *av;
 	struct ubi_ainf_peb *aeb;
 
-	INIT_LIST_HEAD(&ai->corr);
-	INIT_LIST_HEAD(&ai->free);
-	INIT_LIST_HEAD(&ai->erase);
-	INIT_LIST_HEAD(&ai->alien);
-	ai->volumes = RB_ROOT;
-
 	err = -ENOMEM;
 	ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
 					       sizeof(struct ubi_ainf_peb),
@@ -1200,7 +1196,7 @@ out_vidh:
 out_ech:
 	kfree(ech);
 out_ai:
-	ubi_destroy_ai(ubi, ai);
+	destroy_ai(ubi, ai);
 	return err;
 }
 
@@ -1217,7 +1213,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
 	int err;
 	struct ubi_attach_info *ai;
 
-	ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
+	ai = new_ai();
 	if (!ai)
 		return -ENOMEM;
 
@@ -1225,12 +1221,18 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
 		err = scan_all(ubi, ai);
 	else {
 		err = ubi_scan_fastmap(ubi, ai);
-		if (err > 0)
+		if (err > 0) {
+			destroy_ai(ubi, ai);
+			ai = new_ai();
+			if (!ai)
+				return -ENOMEM;
+
 			err = scan_all(ubi, ai);
+		}
 	}
 
 	if (err)
-		return err;
+		goto out_ai;
 
 	/* TODO: currently the fastmap code assumes that the fastmap data
 	 * structures are created only by the kernel when the kernel attaches
@@ -1268,7 +1270,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
 
 	if (ubi->fm && ubi->dbg->chk_gen) {
 		struct ubi_attach_info *scan_ai;
-		scan_ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
+		scan_ai = new_ai();
 		if (!scan_ai)
 			goto out_ai;
 
@@ -1279,10 +1281,10 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
 		}
 
 		self_check_eba(ubi, ai, scan_ai);
-		ubi_destroy_ai(ubi, scan_ai);
+		destroy_ai(ubi, scan_ai);
 	}
 
-	ubi_destroy_ai(ubi, ai);
+	destroy_ai(ubi, ai);
 
 	/* TODO: UBI auto formats the flash if it is empty (see ubi->is_empty).
 	 * It is currently done so that every sub-system writes initializes its
@@ -1299,7 +1301,7 @@ out_vtbl:
 	ubi_free_internal_volumes(ubi);
 	vfree(ubi->vtbl);
 out_ai:
-	ubi_destroy_ai(ubi, ai);
+	destroy_ai(ubi, ai);
 	return err;
 }
 
@@ -1337,11 +1339,11 @@ static void destroy_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av)
 }
 
 /**
- * ubi_destroy_ai - destroy attaching information.
+ * destroy_ai - destroy attaching information.
  * @ubi: UBI device object
  * @ai: attaching information
  */
-void ubi_destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
+static void destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
 {
 	struct ubi_ainf_peb *aeb, *aeb_tmp;
 	struct ubi_ainf_volume *av;
@@ -1392,6 +1394,24 @@ void ubi_destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	kfree(ai);
 }
 
+static struct ubi_attach_info *new_ai(void)
+{
+	static struct ubi_attach_info *ai;
+
+	ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
+	if (!ai)
+		goto out;
+
+	INIT_LIST_HEAD(&ai->corr);
+	INIT_LIST_HEAD(&ai->free);
+	INIT_LIST_HEAD(&ai->erase);
+	INIT_LIST_HEAD(&ai->alien);
+	ai->volumes = RB_ROOT;
+
+out:
+	return ai;
+}
+
 /**
  * self_check_ai - check the attaching information.
  * @ubi: UBI device description object
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 7e0dfda..534e851 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -696,7 +696,6 @@ void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av);
 struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
 				       struct ubi_attach_info *ai);
 int ubi_attach(struct ubi_device *ubi, int force_scan);
-void ubi_destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai);
 
 /* vtbl.c */
 int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 12/15] UBI: Fastmap: Fix ai handling
@ 2012-06-21 21:50     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird

If attaching by fastmap fails, we have to free ai and
create a new one.
Fixes also destroy_ai to be able to destroy an unsued ai.
It's also no longer needed to export it.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/attach.c |   52 +++++++++++++++++++++++++++++++--------------
 drivers/mtd/ubi/ubi.h    |    1 -
 2 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 7cf4711..b6f8e95 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -90,6 +90,8 @@
 #include "ubi.h"
 
 static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai);
+static void destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai);
+static struct ubi_attach_info *new_ai(void);
 
 /* Temporary variables used during scanning */
 static struct ubi_ec_hdr *ech;
@@ -1123,12 +1125,6 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	struct ubi_ainf_volume *av;
 	struct ubi_ainf_peb *aeb;
 
-	INIT_LIST_HEAD(&ai->corr);
-	INIT_LIST_HEAD(&ai->free);
-	INIT_LIST_HEAD(&ai->erase);
-	INIT_LIST_HEAD(&ai->alien);
-	ai->volumes = RB_ROOT;
-
 	err = -ENOMEM;
 	ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
 					       sizeof(struct ubi_ainf_peb),
@@ -1200,7 +1196,7 @@ out_vidh:
 out_ech:
 	kfree(ech);
 out_ai:
-	ubi_destroy_ai(ubi, ai);
+	destroy_ai(ubi, ai);
 	return err;
 }
 
@@ -1217,7 +1213,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
 	int err;
 	struct ubi_attach_info *ai;
 
-	ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
+	ai = new_ai();
 	if (!ai)
 		return -ENOMEM;
 
@@ -1225,12 +1221,18 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
 		err = scan_all(ubi, ai);
 	else {
 		err = ubi_scan_fastmap(ubi, ai);
-		if (err > 0)
+		if (err > 0) {
+			destroy_ai(ubi, ai);
+			ai = new_ai();
+			if (!ai)
+				return -ENOMEM;
+
 			err = scan_all(ubi, ai);
+		}
 	}
 
 	if (err)
-		return err;
+		goto out_ai;
 
 	/* TODO: currently the fastmap code assumes that the fastmap data
 	 * structures are created only by the kernel when the kernel attaches
@@ -1268,7 +1270,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
 
 	if (ubi->fm && ubi->dbg->chk_gen) {
 		struct ubi_attach_info *scan_ai;
-		scan_ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
+		scan_ai = new_ai();
 		if (!scan_ai)
 			goto out_ai;
 
@@ -1279,10 +1281,10 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
 		}
 
 		self_check_eba(ubi, ai, scan_ai);
-		ubi_destroy_ai(ubi, scan_ai);
+		destroy_ai(ubi, scan_ai);
 	}
 
-	ubi_destroy_ai(ubi, ai);
+	destroy_ai(ubi, ai);
 
 	/* TODO: UBI auto formats the flash if it is empty (see ubi->is_empty).
 	 * It is currently done so that every sub-system writes initializes its
@@ -1299,7 +1301,7 @@ out_vtbl:
 	ubi_free_internal_volumes(ubi);
 	vfree(ubi->vtbl);
 out_ai:
-	ubi_destroy_ai(ubi, ai);
+	destroy_ai(ubi, ai);
 	return err;
 }
 
@@ -1337,11 +1339,11 @@ static void destroy_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av)
 }
 
 /**
- * ubi_destroy_ai - destroy attaching information.
+ * destroy_ai - destroy attaching information.
  * @ubi: UBI device object
  * @ai: attaching information
  */
-void ubi_destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
+static void destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
 {
 	struct ubi_ainf_peb *aeb, *aeb_tmp;
 	struct ubi_ainf_volume *av;
@@ -1392,6 +1394,24 @@ void ubi_destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	kfree(ai);
 }
 
+static struct ubi_attach_info *new_ai(void)
+{
+	static struct ubi_attach_info *ai;
+
+	ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
+	if (!ai)
+		goto out;
+
+	INIT_LIST_HEAD(&ai->corr);
+	INIT_LIST_HEAD(&ai->free);
+	INIT_LIST_HEAD(&ai->erase);
+	INIT_LIST_HEAD(&ai->alien);
+	ai->volumes = RB_ROOT;
+
+out:
+	return ai;
+}
+
 /**
  * self_check_ai - check the attaching information.
  * @ubi: UBI device description object
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 7e0dfda..534e851 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -696,7 +696,6 @@ void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av);
 struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
 				       struct ubi_attach_info *ai);
 int ubi_attach(struct ubi_device *ubi, int force_scan);
-void ubi_destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai);
 
 /* vtbl.c */
 int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 13/15] UBI: Fastmap: Add new self check
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:50     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger

If fastmap is able to detect that it's missing PEBs
fall back to scanning mode and print a fat warning.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/fastmap.c |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 76b0d2f..68be3d5 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -461,6 +461,26 @@ out:
 	return ret;
 }
 
+static int self_check_fastmap(struct ubi_attach_info *ai)
+{
+	struct ubi_ainf_peb *aeb;
+	struct ubi_ainf_volume *av;
+	struct rb_node *rb1, *rb2;
+	int n = 0;
+
+	list_for_each_entry(aeb, &ai->erase, u.list)
+		n++;
+
+	list_for_each_entry(aeb, &ai->free, u.list)
+		n++;
+
+	 ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb)
+		ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb)
+			n++;
+
+	return n;
+}
+
 /**
  * ubi_attach_fastmap - creates ubi_attach_info from a fastmap.
  * @ubi: UBI device object
@@ -978,6 +998,19 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 		goto free_hdr;
 	}
 
+	/*
+	 * If fastmap is leaking PEBs (must not happen), raise a
+	 * fat warning and fall back to scanning mode.
+	 * We do this here because in ubi_wl_init() it's too late
+	 * and we cannot fall back to scanning.
+	 */
+	if (WARN_ON(self_check_fastmap(ai) != ubi->peb_count -
+		    ubi->bad_peb_count - used_blocks)) {
+		ret = UBI_BAD_FASTMAP;
+		kfree(fm);
+		goto free_hdr;
+	}
+
 	fm->size = fm_size;
 	fm->used_blocks = used_blocks;
 
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 13/15] UBI: Fastmap: Add new self check
@ 2012-06-21 21:50     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird

If fastmap is able to detect that it's missing PEBs
fall back to scanning mode and print a fat warning.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/fastmap.c |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 76b0d2f..68be3d5 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -461,6 +461,26 @@ out:
 	return ret;
 }
 
+static int self_check_fastmap(struct ubi_attach_info *ai)
+{
+	struct ubi_ainf_peb *aeb;
+	struct ubi_ainf_volume *av;
+	struct rb_node *rb1, *rb2;
+	int n = 0;
+
+	list_for_each_entry(aeb, &ai->erase, u.list)
+		n++;
+
+	list_for_each_entry(aeb, &ai->free, u.list)
+		n++;
+
+	 ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb)
+		ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb)
+			n++;
+
+	return n;
+}
+
 /**
  * ubi_attach_fastmap - creates ubi_attach_info from a fastmap.
  * @ubi: UBI device object
@@ -978,6 +998,19 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 		goto free_hdr;
 	}
 
+	/*
+	 * If fastmap is leaking PEBs (must not happen), raise a
+	 * fat warning and fall back to scanning mode.
+	 * We do this here because in ubi_wl_init() it's too late
+	 * and we cannot fall back to scanning.
+	 */
+	if (WARN_ON(self_check_fastmap(ai) != ubi->peb_count -
+		    ubi->bad_peb_count - used_blocks)) {
+		ret = UBI_BAD_FASTMAP;
+		kfree(fm);
+		goto free_hdr;
+	}
+
 	fm->size = fm_size;
 	fm->used_blocks = used_blocks;
 
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 14/15] UBI: Fastmap: Improve invalidate_fastmap()
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:50     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/fastmap.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 68be3d5..582f5ee 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1332,8 +1332,21 @@ static int invalidate_fastmap(struct ubi_device *ubi,
 			      struct ubi_fastmap_layout *fm)
 {
 	int ret, i;
+	struct ubi_vid_hdr *vh;
 
 	ret = erase_block(ubi, fm->e[0]->pnum);
+	if (ret < 0)
+		return ret;
+
+	vh = new_fm_vhdr(ubi, UBI_FM_SB_VOLUME_ID);
+	if (!vh)
+		return -ENOMEM;
+
+	/* deleting the current fastmap SB is not enough, an old SB may exist,
+	 * so create a (corrupted) SB such that fastmap will find it and fall
+	 * back to scanning mode in any case */
+	vh->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
+	ret = ubi_io_write_vid_hdr(ubi, fm->e[0]->pnum, vh);
 
 	for (i = 0; i < fm->used_blocks; i++)
 		ubi_wl_put_fm_peb(ubi, fm->e[i], fm->to_be_tortured[i]);
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 14/15] UBI: Fastmap: Improve invalidate_fastmap()
@ 2012-06-21 21:50     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/fastmap.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 68be3d5..582f5ee 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1332,8 +1332,21 @@ static int invalidate_fastmap(struct ubi_device *ubi,
 			      struct ubi_fastmap_layout *fm)
 {
 	int ret, i;
+	struct ubi_vid_hdr *vh;
 
 	ret = erase_block(ubi, fm->e[0]->pnum);
+	if (ret < 0)
+		return ret;
+
+	vh = new_fm_vhdr(ubi, UBI_FM_SB_VOLUME_ID);
+	if (!vh)
+		return -ENOMEM;
+
+	/* deleting the current fastmap SB is not enough, an old SB may exist,
+	 * so create a (corrupted) SB such that fastmap will find it and fall
+	 * back to scanning mode in any case */
+	vh->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
+	ret = ubi_io_write_vid_hdr(ubi, fm->e[0]->pnum, vh);
 
 	for (i = 0; i < fm->used_blocks; i++)
 		ubi_wl_put_fm_peb(ubi, fm->e[i], fm->to_be_tortured[i]);
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 15/15] UBI: Fastmap: Write a fastmap also while detaching.
  2012-06-21 21:49 ` Richard Weinberger
@ 2012-06-21 21:50     ` Richard Weinberger
  2012-06-21 21:49     ` Richard Weinberger
                       ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
	shmulik.ladkani, tglx, tim.bird, Marius.Mazarel,
	artem.bityutskiy, Richard Weinberger

To ensure that fastmap knows all EC values we have to do this.
Otherwise fastmap my miss EC updates.
E.g: If the WL sub-system moves data from PEB A to PEB B.
It picks B from the WL pool, moves the data to it an eraes A.
If we detach now (or a power cut happens) the new EC value is lost.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/build.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 186bc19..611d0c4 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -1051,6 +1051,8 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
 	ubi_notify_all(ubi, UBI_VOLUME_REMOVED, NULL);
 	dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);
 
+	ubi_update_fastmap(ubi);
+
 	/*
 	 * Before freeing anything, we have to stop the background thread to
 	 * prevent it from doing anything on this device while we are freeing.
@@ -1058,10 +1060,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
 	if (ubi->bgt_thread)
 		kthread_stop(ubi->bgt_thread);
 
-	/* If no fastmap is present on the FLASH write one. */
-	if (!ubi->fm)
-		ubi_update_fastmap(ubi);
-
 	/*
 	 * Get a reference to the device in order to prevent 'dev_release()'
 	 * from freeing the @ubi object.
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 15/15] UBI: Fastmap: Write a fastmap also while detaching.
@ 2012-06-21 21:50     ` Richard Weinberger
  0 siblings, 0 replies; 31+ messages in thread
From: Richard Weinberger @ 2012-06-21 21:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: artem.bityutskiy, linux-kernel, adrian.hunter, Heinz.Egger,
	thomas.wucher, shmulik.ladkani, Richard Weinberger, tglx,
	Marius.Mazarel, tim.bird

To ensure that fastmap knows all EC values we have to do this.
Otherwise fastmap my miss EC updates.
E.g: If the WL sub-system moves data from PEB A to PEB B.
It picks B from the WL pool, moves the data to it an eraes A.
If we detach now (or a power cut happens) the new EC value is lost.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/build.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 186bc19..611d0c4 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -1051,6 +1051,8 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
 	ubi_notify_all(ubi, UBI_VOLUME_REMOVED, NULL);
 	dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);
 
+	ubi_update_fastmap(ubi);
+
 	/*
 	 * Before freeing anything, we have to stop the background thread to
 	 * prevent it from doing anything on this device while we are freeing.
@@ -1058,10 +1060,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
 	if (ubi->bgt_thread)
 		kthread_stop(ubi->bgt_thread);
 
-	/* If no fastmap is present on the FLASH write one. */
-	if (!ubi->fm)
-		ubi_update_fastmap(ubi);
-
 	/*
 	 * Get a reference to the device in order to prevent 'dev_release()'
 	 * from freeing the @ubi object.
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2012-06-21 21:54 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <UBI fastmap updates>
2012-06-21 21:49 ` Richard Weinberger
2012-06-21 21:49   ` [PATCH 01/15] UBI: Fastmap: Relax EBA selfcheck Richard Weinberger
2012-06-21 21:49     ` Richard Weinberger
2012-06-21 21:49   ` [PATCH 02/15] UBI: Fastmap: Coding style fix Richard Weinberger
2012-06-21 21:49     ` Richard Weinberger
2012-06-21 21:49   ` [PATCH 03/15] UBI: Fastmap: Modify ubi_attach() to force scanning if requested Richard Weinberger
2012-06-21 21:49     ` Richard Weinberger
2012-06-21 21:49   ` [PATCH 04/15] UBI: Fastmap: Always refill pools upon writing a new fastmap Richard Weinberger
2012-06-21 21:49     ` Richard Weinberger
2012-06-21 21:49   ` [PATCH 05/15] UBI: Fastmap: Amend locking Richard Weinberger
2012-06-21 21:49     ` Richard Weinberger
2012-06-21 21:49   ` [PATCH 06/15] UBI: Fastmap: Call ensure_wear_leveling() again in erase_worker() Richard Weinberger
2012-06-21 21:49     ` Richard Weinberger
2012-06-21 21:50   ` [PATCH 07/15] UBI: Fastmap: Add a workqueue to allow delayed fastmap update Richard Weinberger
2012-06-21 21:50     ` Richard Weinberger
2012-06-21 21:50   ` [PATCH 08/15] UBI: Fastmap: Fix lock inbalance Richard Weinberger
2012-06-21 21:50     ` Richard Weinberger
2012-06-21 21:50   ` [PATCH 09/15] UBI: Fastmap: Simplify attach by fastmap Richard Weinberger
2012-06-21 21:50     ` Richard Weinberger
2012-06-21 21:50   ` [PATCH 10/15] UBI: Fastmap: Remove unused variable Signed-off-by: Richard Weinberger <richard@nod.at> Richard Weinberger
2012-06-21 21:50     ` Richard Weinberger
2012-06-21 21:50   ` [PATCH 11/15] UBI: Fastmap: Remove unused label " Richard Weinberger
2012-06-21 21:50     ` Richard Weinberger
2012-06-21 21:50   ` [PATCH 12/15] UBI: Fastmap: Fix ai handling Richard Weinberger
2012-06-21 21:50     ` Richard Weinberger
2012-06-21 21:50   ` [PATCH 13/15] UBI: Fastmap: Add new self check Richard Weinberger
2012-06-21 21:50     ` Richard Weinberger
2012-06-21 21:50   ` [PATCH 14/15] UBI: Fastmap: Improve invalidate_fastmap() Richard Weinberger
2012-06-21 21:50     ` Richard Weinberger
2012-06-21 21:50   ` [PATCH 15/15] UBI: Fastmap: Write a fastmap also while detaching Richard Weinberger
2012-06-21 21:50     ` Richard Weinberger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.