aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2007-05-05 04:24:02 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2007-07-18 09:52:32 -0400
commit78d87c95b89ccf86c142494beada3082810ed368 (patch)
treebb2bc3d2b11e2990376d25e13c94aeb50380a0c4 /drivers/mtd
parentc4e90ec0134d7bedebbe3fe58ed5d431293886d4 (diff)
UBI: fix error path in create_vtbl()
There were several bugs in volume table creation error path. Thanks to Satyam Sharma <satyam.sharma@gmail.com> and Florin Malita <fmalita@gmail.com> for finding and analysing them: http://lkml.org/lkml/2007/5/3/274 This patch makes ubi_scan_add_to_list() static and renames it to add_to_list(), just because it is not needed outside scan.c anymore. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/ubi/scan.c46
-rw-r--r--drivers/mtd/ubi/scan.h2
-rw-r--r--drivers/mtd/ubi/vtbl.c14
3 files changed, 35 insertions, 27 deletions
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index e4456869e753..30d536ee10fc 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -24,7 +24,7 @@
24 * This unit is responsible for scanning the flash media, checking UBI 24 * This unit is responsible for scanning the flash media, checking UBI
25 * headers and providing complete information about the UBI flash image. 25 * headers and providing complete information about the UBI flash image.
26 * 26 *
27 * The scanning information is reoresented by a &struct ubi_scan_info' object. 27 * The scanning information is represented by a &struct ubi_scan_info' object.
28 * Information about found volumes is represented by &struct ubi_scan_volume 28 * Information about found volumes is represented by &struct ubi_scan_volume
29 * objects which are kept in volume RB-tree with root at the @volumes field. 29 * objects which are kept in volume RB-tree with root at the @volumes field.
30 * The RB-tree is indexed by the volume ID. 30 * The RB-tree is indexed by the volume ID.
@@ -55,8 +55,19 @@ static int paranoid_check_si(const struct ubi_device *ubi,
55static struct ubi_ec_hdr *ech; 55static struct ubi_ec_hdr *ech;
56static struct ubi_vid_hdr *vidh; 56static struct ubi_vid_hdr *vidh;
57 57
58int ubi_scan_add_to_list(struct ubi_scan_info *si, int pnum, int ec, 58/*
59 struct list_head *list) 59 * add_to_list - add physical eraseblock to a list.
60 * @si: scanning information
61 * @pnum: physical eraseblock number to add
62 * @ec: erase counter of the physical eraseblock
63 * @list: the list to add to
64 *
65 * This function adds physical eraseblock @pnum to free, erase, corrupted or
66 * alien lists. Returns zero in case of success and a negative error code in
67 * case of failure.
68 */
69static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
70 struct list_head *list)
60{ 71{
61 struct ubi_scan_leb *seb; 72 struct ubi_scan_leb *seb;
62 73
@@ -492,11 +503,11 @@ int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
492 return err; 503 return err;
493 504
494 if (cmp_res & 4) 505 if (cmp_res & 4)
495 err = ubi_scan_add_to_list(si, seb->pnum, 506 err = add_to_list(si, seb->pnum, seb->ec,
496 seb->ec, &si->corr); 507 &si->corr);
497 else 508 else
498 err = ubi_scan_add_to_list(si, seb->pnum, 509 err = add_to_list(si, seb->pnum, seb->ec,
499 seb->ec, &si->erase); 510 &si->erase);
500 if (err) 511 if (err)
501 return err; 512 return err;
502 513
@@ -517,11 +528,9 @@ int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
517 * previously. 528 * previously.
518 */ 529 */
519 if (cmp_res & 4) 530 if (cmp_res & 4)
520 return ubi_scan_add_to_list(si, pnum, ec, 531 return add_to_list(si, pnum, ec, &si->corr);
521 &si->corr);
522 else 532 else
523 return ubi_scan_add_to_list(si, pnum, ec, 533 return add_to_list(si, pnum, ec, &si->erase);
524 &si->erase);
525 } 534 }
526 } 535 }
527 536
@@ -754,7 +763,7 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(const struct ubi_device *ubi,
754 * @si: scanning information 763 * @si: scanning information
755 * @pnum: the physical eraseblock number 764 * @pnum: the physical eraseblock number
756 * 765 *
757 * This function returns a zero if the physical eraseblock was succesfully 766 * This function returns a zero if the physical eraseblock was successfully
758 * handled and a negative error code in case of failure. 767 * handled and a negative error code in case of failure.
759 */ 768 */
760static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum) 769static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum)
@@ -783,8 +792,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
783 else if (err == UBI_IO_BITFLIPS) 792 else if (err == UBI_IO_BITFLIPS)
784 bitflips = 1; 793 bitflips = 1;
785 else if (err == UBI_IO_PEB_EMPTY) 794 else if (err == UBI_IO_PEB_EMPTY)
786 return ubi_scan_add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 795 return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase);
787 &si->erase);
788 else if (err == UBI_IO_BAD_EC_HDR) { 796 else if (err == UBI_IO_BAD_EC_HDR) {
789 /* 797 /*
790 * We have to also look at the VID header, possibly it is not 798 * We have to also look at the VID header, possibly it is not
@@ -832,13 +840,13 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
832 else if (err == UBI_IO_BAD_VID_HDR || 840 else if (err == UBI_IO_BAD_VID_HDR ||
833 (err == UBI_IO_PEB_FREE && ec_corr)) { 841 (err == UBI_IO_PEB_FREE && ec_corr)) {
834 /* VID header is corrupted */ 842 /* VID header is corrupted */
835 err = ubi_scan_add_to_list(si, pnum, ec, &si->corr); 843 err = add_to_list(si, pnum, ec, &si->corr);
836 if (err) 844 if (err)
837 return err; 845 return err;
838 goto adjust_mean_ec; 846 goto adjust_mean_ec;
839 } else if (err == UBI_IO_PEB_FREE) { 847 } else if (err == UBI_IO_PEB_FREE) {
840 /* No VID header - the physical eraseblock is free */ 848 /* No VID header - the physical eraseblock is free */
841 err = ubi_scan_add_to_list(si, pnum, ec, &si->free); 849 err = add_to_list(si, pnum, ec, &si->free);
842 if (err) 850 if (err)
843 return err; 851 return err;
844 goto adjust_mean_ec; 852 goto adjust_mean_ec;
@@ -853,7 +861,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
853 case UBI_COMPAT_DELETE: 861 case UBI_COMPAT_DELETE:
854 ubi_msg("\"delete\" compatible internal volume %d:%d" 862 ubi_msg("\"delete\" compatible internal volume %d:%d"
855 " found, remove it", vol_id, lnum); 863 " found, remove it", vol_id, lnum);
856 err = ubi_scan_add_to_list(si, pnum, ec, &si->corr); 864 err = add_to_list(si, pnum, ec, &si->corr);
857 if (err) 865 if (err)
858 return err; 866 return err;
859 break; 867 break;
@@ -868,7 +876,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
868 case UBI_COMPAT_PRESERVE: 876 case UBI_COMPAT_PRESERVE:
869 ubi_msg("\"preserve\" compatible internal volume %d:%d" 877 ubi_msg("\"preserve\" compatible internal volume %d:%d"
870 " found", vol_id, lnum); 878 " found", vol_id, lnum);
871 err = ubi_scan_add_to_list(si, pnum, ec, &si->alien); 879 err = add_to_list(si, pnum, ec, &si->alien);
872 if (err) 880 if (err)
873 return err; 881 return err;
874 si->alien_peb_count += 1; 882 si->alien_peb_count += 1;
@@ -1109,7 +1117,7 @@ static int paranoid_check_si(const struct ubi_device *ubi,
1109 uint8_t *buf; 1117 uint8_t *buf;
1110 1118
1111 /* 1119 /*
1112 * At first, check that scanning information is ok. 1120 * At first, check that scanning information is OK.
1113 */ 1121 */
1114 ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) { 1122 ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
1115 int leb_count = 0; 1123 int leb_count = 0;
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
index 3949f6192c76..140e82e26534 100644
--- a/drivers/mtd/ubi/scan.h
+++ b/drivers/mtd/ubi/scan.h
@@ -147,8 +147,6 @@ static inline void ubi_scan_move_to_list(struct ubi_scan_volume *sv,
147 list_add_tail(&seb->u.list, list); 147 list_add_tail(&seb->u.list, list);
148} 148}
149 149
150int ubi_scan_add_to_list(struct ubi_scan_info *si, int pnum, int ec,
151 struct list_head *list);
152int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si, 150int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
153 int pnum, int ec, const struct ubi_vid_hdr *vid_hdr, 151 int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
154 int bitflips); 152 int bitflips);
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 83236c31c892..9926f1f9aad8 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -317,13 +317,15 @@ retry:
317 return err; 317 return err;
318 318
319write_error: 319write_error:
320 /* Maybe this physical eraseblock went bad, try to pick another one */ 320 if (err == -EIO && ++tries <= 5) {
321 if (++tries <= 5) 321 /*
322 err = ubi_scan_add_to_list(si, new_seb->pnum, new_seb->ec, 322 * Probably this physical eraseblock went bad, try to pick
323 &si->corr); 323 * another one.
324 kfree(new_seb); 324 */
325 if (!err) 325 list_add_tail(&new_seb->u.list, &si->corr);
326 goto retry; 326 goto retry;
327 }
328 kfree(new_seb);
327out_free: 329out_free:
328 ubi_free_vid_hdr(ubi, vid_hdr); 330 ubi_free_vid_hdr(ubi, vid_hdr);
329 return err; 331 return err;