|
@@ -580,7 +580,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
|
|
|
* failure.
|
|
|
*/
|
|
|
static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
|
|
|
- int vol_id, int lnum, int torture)
|
|
|
+ int vol_id, int lnum, int torture, bool nested)
|
|
|
{
|
|
|
struct ubi_work *wl_wrk;
|
|
|
|
|
@@ -599,7 +599,10 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
|
|
|
wl_wrk->lnum = lnum;
|
|
|
wl_wrk->torture = torture;
|
|
|
|
|
|
- schedule_ubi_work(ubi, wl_wrk);
|
|
|
+ if (nested)
|
|
|
+ __schedule_ubi_work(ubi, wl_wrk);
|
|
|
+ else
|
|
|
+ schedule_ubi_work(ubi, wl_wrk);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -663,6 +666,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
|
|
|
|
|
|
vid_hdr = ubi_get_vid_hdr(vidb);
|
|
|
|
|
|
+ down_read(&ubi->fm_eba_sem);
|
|
|
mutex_lock(&ubi->move_mutex);
|
|
|
spin_lock(&ubi->wl_lock);
|
|
|
ubi_assert(!ubi->move_from && !ubi->move_to);
|
|
@@ -893,6 +897,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
|
|
|
|
|
|
dbg_wl("done");
|
|
|
mutex_unlock(&ubi->move_mutex);
|
|
|
+ up_read(&ubi->fm_eba_sem);
|
|
|
return 0;
|
|
|
|
|
|
/*
|
|
@@ -943,6 +948,7 @@ out_not_moved:
|
|
|
}
|
|
|
|
|
|
mutex_unlock(&ubi->move_mutex);
|
|
|
+ up_read(&ubi->fm_eba_sem);
|
|
|
return 0;
|
|
|
|
|
|
out_error:
|
|
@@ -964,6 +970,7 @@ out_error:
|
|
|
out_ro:
|
|
|
ubi_ro_mode(ubi);
|
|
|
mutex_unlock(&ubi->move_mutex);
|
|
|
+ up_read(&ubi->fm_eba_sem);
|
|
|
ubi_assert(err != 0);
|
|
|
return err < 0 ? err : -EIO;
|
|
|
|
|
@@ -971,6 +978,7 @@ out_cancel:
|
|
|
ubi->wl_scheduled = 0;
|
|
|
spin_unlock(&ubi->wl_lock);
|
|
|
mutex_unlock(&ubi->move_mutex);
|
|
|
+ up_read(&ubi->fm_eba_sem);
|
|
|
ubi_free_vid_buf(vidb);
|
|
|
return 0;
|
|
|
}
|
|
@@ -1093,7 +1101,7 @@ static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk)
|
|
|
int err1;
|
|
|
|
|
|
/* Re-schedule the LEB for erasure */
|
|
|
- err1 = schedule_erase(ubi, e, vol_id, lnum, 0);
|
|
|
+ err1 = schedule_erase(ubi, e, vol_id, lnum, 0, false);
|
|
|
if (err1) {
|
|
|
wl_entry_destroy(ubi, e);
|
|
|
err = err1;
|
|
@@ -1274,7 +1282,7 @@ retry:
|
|
|
}
|
|
|
spin_unlock(&ubi->wl_lock);
|
|
|
|
|
|
- err = schedule_erase(ubi, e, vol_id, lnum, torture);
|
|
|
+ err = schedule_erase(ubi, e, vol_id, lnum, torture, false);
|
|
|
if (err) {
|
|
|
spin_lock(&ubi->wl_lock);
|
|
|
wl_tree_add(e, &ubi->used);
|
|
@@ -1565,7 +1573,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
|
|
|
e->pnum = aeb->pnum;
|
|
|
e->ec = aeb->ec;
|
|
|
ubi->lookuptbl[e->pnum] = e;
|
|
|
- if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0)) {
|
|
|
+ if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false)) {
|
|
|
wl_entry_destroy(ubi, e);
|
|
|
goto out_free;
|
|
|
}
|
|
@@ -1644,7 +1652,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
|
|
|
e->ec = aeb->ec;
|
|
|
ubi_assert(!ubi->lookuptbl[e->pnum]);
|
|
|
ubi->lookuptbl[e->pnum] = e;
|
|
|
- if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0)) {
|
|
|
+ if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false)) {
|
|
|
wl_entry_destroy(ubi, e);
|
|
|
goto out_free;
|
|
|
}
|