diff mbox

[05/35] UBI: Fastmap: Ensure that only one fastmap work is scheduled

Message ID 1414586758-9972-6-git-send-email-richard@nod.at
State Superseded
Headers show

Commit Message

Richard Weinberger Oct. 29, 2014, 12:45 p.m. UTC
If the WL pool runs out of PEBs we schedule a fastmap write
to refill it as soon as possible.
Ensure that only one at a time is scheduled otherwise we might end in
a fastmap write storm because writing the fastmap can schedule another
write if bitflips are detected.

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

Comments

Artem Bityutskiy Nov. 5, 2014, 3:42 p.m. UTC | #1
On Wed, 2014-10-29 at 13:45 +0100, Richard Weinberger wrote:
>  	struct ubi_device *ubi = container_of(wrk, struct ubi_device, fm_work);
>  	ubi_update_fastmap(ubi);
> +	spin_lock(&ubi->wl_lock);
> +	ubi->fm_work_scheduled = 0;
> +	spin_unlock(&ubi->wl_lock);
>  }

Why is the 'update_fastmap_work_fn()' function in wl.c? Can we move it
to fastmap.c?
Richard Weinberger Nov. 5, 2014, 3:47 p.m. UTC | #2
Am 05.11.2014 um 16:42 schrieb Artem Bityutskiy:
> On Wed, 2014-10-29 at 13:45 +0100, Richard Weinberger wrote:
>>  	struct ubi_device *ubi = container_of(wrk, struct ubi_device, fm_work);
>>  	ubi_update_fastmap(ubi);
>> +	spin_lock(&ubi->wl_lock);
>> +	ubi->fm_work_scheduled = 0;
>> +	spin_unlock(&ubi->wl_lock);
>>  }
> 
> Why is the 'update_fastmap_work_fn()' function in wl.c? Can we move it
> to fastmap.c?
> 

Please see "[PATCH 29/35] UBI: Move fastmap specific functions out of wl.c".

Thanks,
//richard
diff mbox

Patch

diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index f80a726..5d2e737 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -430,6 +430,7 @@  struct ubi_debug_info {
  * @fm_size: fastmap size in bytes
  * @fm_sem: allows ubi_update_fastmap() to block EBA table changes
  * @fm_work: fastmap work queue
+ * @fm_work_scheduled: non-zero if fastmap work was scheduled
  *
  * @used: RB-tree of used physical eraseblocks
  * @erroneous: RB-tree of erroneous used physical eraseblocks
@@ -536,6 +537,7 @@  struct ubi_device {
 	void *fm_buf;
 	size_t fm_size;
 	struct work_struct fm_work;
+	int fm_work_scheduled;
 
 	/* Wear-leveling sub-system's stuff */
 	struct rb_root used;
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index a12c54b..bd2e8d5 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -149,6 +149,9 @@  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);
+	spin_lock(&ubi->wl_lock);
+	ubi->fm_work_scheduled = 0;
+	spin_unlock(&ubi->wl_lock);
 }
 
 /**
@@ -657,7 +660,10 @@  static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
 		/* We cannot update the fastmap here because this
 		 * function is called in atomic context.
 		 * Let's fail here and refill/update it as soon as possible. */
-		schedule_work(&ubi->fm_work);
+		if (!ubi->fm_work_scheduled) {
+			ubi->fm_work_scheduled = 1;
+			schedule_work(&ubi->fm_work);
+		}
 		return NULL;
 	} else {
 		pnum = pool->pebs[pool->used++];