aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorJoel Reardon <joel@clambassador.com>2012-05-18 09:40:24 -0400
committerArtem Bityutskiy <artem.bityutskiy@linux.intel.com>2012-05-21 04:34:41 -0400
commitd36e59e69b8be536c55d6118630f0221cee5ccee (patch)
tree8ffa8feec4ddbfeca391278c449c5ba1b3e78d2e /drivers/mtd
parent6dd3bc7e6032ffb392477fadca77172c1c9e346b (diff)
UBI: add lnum and vol_id to struct ubi_work
This is part of a multipart patch to allow UBI to force the erasure of particular logical eraseblock numbers. In this patch, the volume id and LEB number are added to ubi_work data structure, and both are also passed as a parameter to schedule erase to set it appropriately. Whenever ubi_wl_put_peb is called, the lnum is also passed to be forwarded to schedule erase. Later, a new ubi_sync_lnum will be added to execute immediately all work related to that lnum. This was tested by outputting the vol_id and lnum during the schedule of erasure. The ubi thread was disabled and two ubifs drives on separate partitions repeated changed a small number of LEBs. The ubi module was readded, and all the erased LEBs, corresponding to the volumes, were added to the schedule erase queue. Artem: minor tweaks Signed-off-by: Joel Reardon <reardonj@inf.ethz.ch> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/ubi/eba.c16
-rw-r--r--drivers/mtd/ubi/ubi.h3
-rw-r--r--drivers/mtd/ubi/wl.c32
3 files changed, 33 insertions, 18 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 5fa726f9c1f..b703ac7729c 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -341,7 +341,7 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
341 dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum); 341 dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum);
342 342
343 vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED; 343 vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED;
344 err = ubi_wl_put_peb(ubi, pnum, 0); 344 err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 0);
345 345
346out_unlock: 346out_unlock:
347 leb_write_unlock(ubi, vol_id, lnum); 347 leb_write_unlock(ubi, vol_id, lnum);
@@ -550,7 +550,7 @@ retry:
550 ubi_free_vid_hdr(ubi, vid_hdr); 550 ubi_free_vid_hdr(ubi, vid_hdr);
551 551
552 vol->eba_tbl[lnum] = new_pnum; 552 vol->eba_tbl[lnum] = new_pnum;
553 ubi_wl_put_peb(ubi, pnum, 1); 553 ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
554 554
555 ubi_msg("data was successfully recovered"); 555 ubi_msg("data was successfully recovered");
556 return 0; 556 return 0;
@@ -558,7 +558,7 @@ retry:
558out_unlock: 558out_unlock:
559 mutex_unlock(&ubi->buf_mutex); 559 mutex_unlock(&ubi->buf_mutex);
560out_put: 560out_put:
561 ubi_wl_put_peb(ubi, new_pnum, 1); 561 ubi_wl_put_peb(ubi, vol_id, lnum, new_pnum, 1);
562 ubi_free_vid_hdr(ubi, vid_hdr); 562 ubi_free_vid_hdr(ubi, vid_hdr);
563 return err; 563 return err;
564 564
@@ -568,7 +568,7 @@ write_error:
568 * get another one. 568 * get another one.
569 */ 569 */
570 ubi_warn("failed to write to PEB %d", new_pnum); 570 ubi_warn("failed to write to PEB %d", new_pnum);
571 ubi_wl_put_peb(ubi, new_pnum, 1); 571 ubi_wl_put_peb(ubi, vol_id, lnum, new_pnum, 1);
572 if (++tries > UBI_IO_RETRIES) { 572 if (++tries > UBI_IO_RETRIES) {
573 ubi_free_vid_hdr(ubi, vid_hdr); 573 ubi_free_vid_hdr(ubi, vid_hdr);
574 return err; 574 return err;
@@ -686,7 +686,7 @@ write_error:
686 * eraseblock, so just put it and request a new one. We assume that if 686 * eraseblock, so just put it and request a new one. We assume that if
687 * this physical eraseblock went bad, the erase code will handle that. 687 * this physical eraseblock went bad, the erase code will handle that.
688 */ 688 */
689 err = ubi_wl_put_peb(ubi, pnum, 1); 689 err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
690 if (err || ++tries > UBI_IO_RETRIES) { 690 if (err || ++tries > UBI_IO_RETRIES) {
691 ubi_ro_mode(ubi); 691 ubi_ro_mode(ubi);
692 leb_write_unlock(ubi, vol_id, lnum); 692 leb_write_unlock(ubi, vol_id, lnum);
@@ -804,7 +804,7 @@ write_error:
804 return err; 804 return err;
805 } 805 }
806 806
807 err = ubi_wl_put_peb(ubi, pnum, 1); 807 err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
808 if (err || ++tries > UBI_IO_RETRIES) { 808 if (err || ++tries > UBI_IO_RETRIES) {
809 ubi_ro_mode(ubi); 809 ubi_ro_mode(ubi);
810 leb_write_unlock(ubi, vol_id, lnum); 810 leb_write_unlock(ubi, vol_id, lnum);
@@ -901,7 +901,7 @@ retry:
901 } 901 }
902 902
903 if (vol->eba_tbl[lnum] >= 0) { 903 if (vol->eba_tbl[lnum] >= 0) {
904 err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0); 904 err = ubi_wl_put_peb(ubi, vol_id, lnum, vol->eba_tbl[lnum], 0);
905 if (err) 905 if (err)
906 goto out_leb_unlock; 906 goto out_leb_unlock;
907 } 907 }
@@ -926,7 +926,7 @@ write_error:
926 goto out_leb_unlock; 926 goto out_leb_unlock;
927 } 927 }
928 928
929 err = ubi_wl_put_peb(ubi, pnum, 1); 929 err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
930 if (err || ++tries > UBI_IO_RETRIES) { 930 if (err || ++tries > UBI_IO_RETRIES) {
931 ubi_ro_mode(ubi); 931 ubi_ro_mode(ubi);
932 goto out_leb_unlock; 932 goto out_leb_unlock;
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index b4b3913f1df..5e1182ca289 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -667,7 +667,8 @@ int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai);
667 667
668/* wl.c */ 668/* wl.c */
669int ubi_wl_get_peb(struct ubi_device *ubi); 669int ubi_wl_get_peb(struct ubi_device *ubi);
670int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture); 670int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum,
671 int pnum, int torture);
671int ubi_wl_flush(struct ubi_device *ubi); 672int ubi_wl_flush(struct ubi_device *ubi);
672int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum); 673int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum);
673int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai); 674int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai);
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index c143e611235..70ebfa7bc38 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -140,6 +140,8 @@
140 * @list: a link in the list of pending works 140 * @list: a link in the list of pending works
141 * @func: worker function 141 * @func: worker function
142 * @e: physical eraseblock to erase 142 * @e: physical eraseblock to erase
143 * @vol_id: the volume ID on which this erasure is being performed
144 * @lnum: the logical eraseblock number
143 * @torture: if the physical eraseblock has to be tortured 145 * @torture: if the physical eraseblock has to be tortured
144 * 146 *
145 * The @func pointer points to the worker function. If the @cancel argument is 147 * The @func pointer points to the worker function. If the @cancel argument is
@@ -152,6 +154,8 @@ struct ubi_work {
152 int (*func)(struct ubi_device *ubi, struct ubi_work *wrk, int cancel); 154 int (*func)(struct ubi_device *ubi, struct ubi_work *wrk, int cancel);
153 /* The below fields are only relevant to erasure works */ 155 /* The below fields are only relevant to erasure works */
154 struct ubi_wl_entry *e; 156 struct ubi_wl_entry *e;
157 int vol_id;
158 int lnum;
155 int torture; 159 int torture;
156}; 160};
157 161
@@ -579,13 +583,15 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
579 * schedule_erase - schedule an erase work. 583 * schedule_erase - schedule an erase work.
580 * @ubi: UBI device description object 584 * @ubi: UBI device description object
581 * @e: the WL entry of the physical eraseblock to erase 585 * @e: the WL entry of the physical eraseblock to erase
586 * @vol_id: the volume ID that last used this PEB
587 * @lnum: the last used logical eraseblock number for the PEB
582 * @torture: if the physical eraseblock has to be tortured 588 * @torture: if the physical eraseblock has to be tortured
583 * 589 *
584 * This function returns zero in case of success and a %-ENOMEM in case of 590 * This function returns zero in case of success and a %-ENOMEM in case of
585 * failure. 591 * failure.
586 */ 592 */
587static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, 593static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
588 int torture) 594 int vol_id, int lnum, int torture)
589{ 595{
590 struct ubi_work *wl_wrk; 596 struct ubi_work *wl_wrk;
591 597
@@ -598,6 +604,8 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
598 604
599 wl_wrk->func = &erase_worker; 605 wl_wrk->func = &erase_worker;
600 wl_wrk->e = e; 606 wl_wrk->e = e;
607 wl_wrk->vol_id = vol_id;
608 wl_wrk->lnum = lnum;
601 wl_wrk->torture = torture; 609 wl_wrk->torture = torture;
602 610
603 schedule_ubi_work(ubi, wl_wrk); 611 schedule_ubi_work(ubi, wl_wrk);
@@ -798,7 +806,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
798 ubi->move_to_put = ubi->wl_scheduled = 0; 806 ubi->move_to_put = ubi->wl_scheduled = 0;
799 spin_unlock(&ubi->wl_lock); 807 spin_unlock(&ubi->wl_lock);
800 808
801 err = schedule_erase(ubi, e1, 0); 809 err = schedule_erase(ubi, e1, vol_id, lnum, 0);
802 if (err) { 810 if (err) {
803 kmem_cache_free(ubi_wl_entry_slab, e1); 811 kmem_cache_free(ubi_wl_entry_slab, e1);
804 if (e2) 812 if (e2)
@@ -813,7 +821,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
813 */ 821 */
814 dbg_wl("PEB %d (LEB %d:%d) was put meanwhile, erase", 822 dbg_wl("PEB %d (LEB %d:%d) was put meanwhile, erase",
815 e2->pnum, vol_id, lnum); 823 e2->pnum, vol_id, lnum);
816 err = schedule_erase(ubi, e2, 0); 824 err = schedule_erase(ubi, e2, vol_id, lnum, 0);
817 if (err) { 825 if (err) {
818 kmem_cache_free(ubi_wl_entry_slab, e2); 826 kmem_cache_free(ubi_wl_entry_slab, e2);
819 goto out_ro; 827 goto out_ro;
@@ -852,7 +860,7 @@ out_not_moved:
852 spin_unlock(&ubi->wl_lock); 860 spin_unlock(&ubi->wl_lock);
853 861
854 ubi_free_vid_hdr(ubi, vid_hdr); 862 ubi_free_vid_hdr(ubi, vid_hdr);
855 err = schedule_erase(ubi, e2, torture); 863 err = schedule_erase(ubi, e2, vol_id, lnum, torture);
856 if (err) { 864 if (err) {
857 kmem_cache_free(ubi_wl_entry_slab, e2); 865 kmem_cache_free(ubi_wl_entry_slab, e2);
858 goto out_ro; 866 goto out_ro;
@@ -971,6 +979,8 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
971{ 979{
972 struct ubi_wl_entry *e = wl_wrk->e; 980 struct ubi_wl_entry *e = wl_wrk->e;
973 int pnum = e->pnum, err, need; 981 int pnum = e->pnum, err, need;
982 int vol_id = wl_wrk->vol_id;
983 int lnum = wl_wrk->lnum;
974 984
975 if (cancel) { 985 if (cancel) {
976 dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec); 986 dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec);
@@ -979,7 +989,8 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
979 return 0; 989 return 0;
980 } 990 }
981 991
982 dbg_wl("erase PEB %d EC %d", pnum, e->ec); 992 dbg_wl("erase PEB %d EC %d LEB %d:%d",
993 pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum);
983 994
984 err = sync_erase(ubi, e, wl_wrk->torture); 995 err = sync_erase(ubi, e, wl_wrk->torture);
985 if (!err) { 996 if (!err) {
@@ -1009,7 +1020,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
1009 int err1; 1020 int err1;
1010 1021
1011 /* Re-schedule the LEB for erasure */ 1022 /* Re-schedule the LEB for erasure */
1012 err1 = schedule_erase(ubi, e, 0); 1023 err1 = schedule_erase(ubi, e, vol_id, lnum, 0);
1013 if (err1) { 1024 if (err1) {
1014 err = err1; 1025 err = err1;
1015 goto out_ro; 1026 goto out_ro;
@@ -1077,6 +1088,8 @@ out_ro:
1077/** 1088/**
1078 * ubi_wl_put_peb - return a PEB to the wear-leveling sub-system. 1089 * ubi_wl_put_peb - return a PEB to the wear-leveling sub-system.
1079 * @ubi: UBI device description object 1090 * @ubi: UBI device description object
1091 * @vol_id: the volume ID that last used this PEB
1092 * @lnum: the last used logical eraseblock number for the PEB
1080 * @pnum: physical eraseblock to return 1093 * @pnum: physical eraseblock to return
1081 * @torture: if this physical eraseblock has to be tortured 1094 * @torture: if this physical eraseblock has to be tortured
1082 * 1095 *
@@ -1085,7 +1098,8 @@ out_ro:
1085 * occurred to this @pnum and it has to be tested. This function returns zero 1098 * occurred to this @pnum and it has to be tested. This function returns zero
1086 * in case of success, and a negative error code in case of failure. 1099 * in case of success, and a negative error code in case of failure.
1087 */ 1100 */
1088int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture) 1101int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum,
1102 int pnum, int torture)
1089{ 1103{
1090 int err; 1104 int err;
1091 struct ubi_wl_entry *e; 1105 struct ubi_wl_entry *e;
@@ -1151,7 +1165,7 @@ retry:
1151 } 1165 }
1152 spin_unlock(&ubi->wl_lock); 1166 spin_unlock(&ubi->wl_lock);
1153 1167
1154 err = schedule_erase(ubi, e, torture); 1168 err = schedule_erase(ubi, e, vol_id, lnum, torture);
1155 if (err) { 1169 if (err) {
1156 spin_lock(&ubi->wl_lock); 1170 spin_lock(&ubi->wl_lock);
1157 wl_tree_add(e, &ubi->used); 1171 wl_tree_add(e, &ubi->used);
@@ -1416,7 +1430,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
1416 e->pnum = aeb->pnum; 1430 e->pnum = aeb->pnum;
1417 e->ec = aeb->ec; 1431 e->ec = aeb->ec;
1418 ubi->lookuptbl[e->pnum] = e; 1432 ubi->lookuptbl[e->pnum] = e;
1419 if (schedule_erase(ubi, e, 0)) { 1433 if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0)) {
1420 kmem_cache_free(ubi_wl_entry_slab, e); 1434 kmem_cache_free(ubi_wl_entry_slab, e);
1421 goto out_free; 1435 goto out_free;
1422 } 1436 }