ubi: Fix producing anchor PEBs
[linux-2.6-microblaze.git] / drivers / mtd / ubi / wl.c
index 3fcdefe..5d77a38 100644 (file)
@@ -339,13 +339,6 @@ static struct ubi_wl_entry *find_wl_entry(struct ubi_device *ubi,
                }
        }
 
-       /* If no fastmap has been written and this WL entry can be used
-        * as anchor PEB, hold it back and return the second best WL entry
-        * such that fastmap can use the anchor PEB later. */
-       if (prev_e && !ubi->fm_disabled &&
-           !ubi->fm && e->pnum < UBI_FM_MAX_START)
-               return prev_e;
-
        return e;
 }
 
@@ -656,9 +649,6 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
 {
        int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0;
        int erase = 0, keep = 0, vol_id = -1, lnum = -1;
-#ifdef CONFIG_MTD_UBI_FASTMAP
-       int anchor = wrk->anchor;
-#endif
        struct ubi_wl_entry *e1, *e2;
        struct ubi_vid_io_buf *vidb;
        struct ubi_vid_hdr *vid_hdr;
@@ -698,11 +688,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
        }
 
 #ifdef CONFIG_MTD_UBI_FASTMAP
-       /* Check whether we need to produce an anchor PEB */
-       if (!anchor)
-               anchor = !anchor_pebs_available(&ubi->free);
-
-       if (anchor) {
+       if (ubi->fm_do_produce_anchor) {
                e1 = find_anchor_wl_entry(&ubi->used);
                if (!e1)
                        goto out_cancel;
@@ -719,6 +705,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
                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);
+               ubi->fm_do_produce_anchor = 0;
        } else if (!ubi->scrub.rb_node) {
 #else
        if (!ubi->scrub.rb_node) {
@@ -1051,7 +1038,6 @@ 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);
@@ -1093,8 +1079,15 @@ static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk)
        err = sync_erase(ubi, e, wl_wrk->torture);
        if (!err) {
                spin_lock(&ubi->wl_lock);
-               wl_tree_add(e, &ubi->free);
-               ubi->free_count++;
+
+               if (!ubi->fm_anchor && e->pnum < UBI_FM_MAX_START) {
+                       ubi->fm_anchor = e;
+                       ubi->fm_do_produce_anchor = 0;
+               } else {
+                       wl_tree_add(e, &ubi->free);
+                       ubi->free_count++;
+               }
+
                spin_unlock(&ubi->wl_lock);
 
                /*
@@ -1882,6 +1875,9 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
        if (err)
                goto out_free;
 
+#ifdef CONFIG_MTD_UBI_FASTMAP
+       ubi_ensure_anchor_pebs(ubi);
+#endif
        return 0;
 
 out_free: