diff options
Diffstat (limited to 'drivers/mtd/ubi')
-rw-r--r-- | drivers/mtd/ubi/eba.c | 33 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 16 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 13 |
3 files changed, 36 insertions, 26 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 25def348e5ba..7ab79e247245 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -950,12 +950,7 @@ write_error: | |||
950 | * physical eraseblock @to. The @vid_hdr buffer may be changed by this | 950 | * physical eraseblock @to. The @vid_hdr buffer may be changed by this |
951 | * function. Returns: | 951 | * function. Returns: |
952 | * o %0 in case of success; | 952 | * o %0 in case of success; |
953 | * o %1 if the operation was canceled because the volume is being deleted | 953 | * o %MOVE_CANCEL_RACE, %MOVE_TARGET_WR_ERR, or %MOVE_CANCEL_BITFLIPS; |
954 | * or because the PEB was put meanwhile; | ||
955 | * o %2 if the operation was canceled because there was a write error to the | ||
956 | * target PEB; | ||
957 | * o %-EAGAIN if the operation was canceled because a bit-flip was detected | ||
958 | * in the target PEB; | ||
959 | * o a negative error code in case of failure. | 954 | * o a negative error code in case of failure. |
960 | */ | 955 | */ |
961 | int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | 956 | int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, |
@@ -986,13 +981,12 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
986 | * be locked in 'ubi_wl_put_peb()' and wait for the WL worker to finish. | 981 | * be locked in 'ubi_wl_put_peb()' and wait for the WL worker to finish. |
987 | */ | 982 | */ |
988 | vol = ubi->volumes[idx]; | 983 | vol = ubi->volumes[idx]; |
984 | spin_unlock(&ubi->volumes_lock); | ||
989 | if (!vol) { | 985 | if (!vol) { |
990 | /* No need to do further work, cancel */ | 986 | /* No need to do further work, cancel */ |
991 | dbg_eba("volume %d is being removed, cancel", vol_id); | 987 | dbg_eba("volume %d is being removed, cancel", vol_id); |
992 | spin_unlock(&ubi->volumes_lock); | 988 | return MOVE_CANCEL_RACE; |
993 | return 1; | ||
994 | } | 989 | } |
995 | spin_unlock(&ubi->volumes_lock); | ||
996 | 990 | ||
997 | /* | 991 | /* |
998 | * We do not want anybody to write to this logical eraseblock while we | 992 | * We do not want anybody to write to this logical eraseblock while we |
@@ -1004,12 +998,13 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1004 | * (@from). This task locks the LEB and goes sleep in the | 998 | * (@from). This task locks the LEB and goes sleep in the |
1005 | * 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are | 999 | * 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are |
1006 | * holding @ubi->move_mutex and go sleep on the LEB lock. So, if the | 1000 | * holding @ubi->move_mutex and go sleep on the LEB lock. So, if the |
1007 | * LEB is already locked, we just do not move it and return %1. | 1001 | * LEB is already locked, we just do not move it and return |
1002 | * %MOVE_CANCEL_RACE, which means that UBI will re-try, but later. | ||
1008 | */ | 1003 | */ |
1009 | err = leb_write_trylock(ubi, vol_id, lnum); | 1004 | err = leb_write_trylock(ubi, vol_id, lnum); |
1010 | if (err) { | 1005 | if (err) { |
1011 | dbg_eba("contention on LEB %d:%d, cancel", vol_id, lnum); | 1006 | dbg_eba("contention on LEB %d:%d, cancel", vol_id, lnum); |
1012 | return err; | 1007 | return MOVE_CANCEL_RACE; |
1013 | } | 1008 | } |
1014 | 1009 | ||
1015 | /* | 1010 | /* |
@@ -1021,14 +1016,14 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1021 | dbg_eba("LEB %d:%d is no longer mapped to PEB %d, mapped to " | 1016 | dbg_eba("LEB %d:%d is no longer mapped to PEB %d, mapped to " |
1022 | "PEB %d, cancel", vol_id, lnum, from, | 1017 | "PEB %d, cancel", vol_id, lnum, from, |
1023 | vol->eba_tbl[lnum]); | 1018 | vol->eba_tbl[lnum]); |
1024 | err = 1; | 1019 | err = MOVE_CANCEL_RACE; |
1025 | goto out_unlock_leb; | 1020 | goto out_unlock_leb; |
1026 | } | 1021 | } |
1027 | 1022 | ||
1028 | /* | 1023 | /* |
1029 | * OK, now the LEB is locked and we can safely start moving it. Since | 1024 | * OK, now the LEB is locked and we can safely start moving it. Since |
1030 | * this function utilizes the @ubi->peb1_buf buffer which is shared | 1025 | * this function utilizes the @ubi->peb_buf1 buffer which is shared |
1031 | * with some other functions, so lock the buffer by taking the | 1026 | * with some other functions - we lock the buffer by taking the |
1032 | * @ubi->buf_mutex. | 1027 | * @ubi->buf_mutex. |
1033 | */ | 1028 | */ |
1034 | mutex_lock(&ubi->buf_mutex); | 1029 | mutex_lock(&ubi->buf_mutex); |
@@ -1059,7 +1054,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1059 | cond_resched(); | 1054 | cond_resched(); |
1060 | 1055 | ||
1061 | /* | 1056 | /* |
1062 | * It may turn out to me that the whole @from physical eraseblock | 1057 | * It may turn out to be that the whole @from physical eraseblock |
1063 | * contains only 0xFF bytes. Then we have to only write the VID header | 1058 | * contains only 0xFF bytes. Then we have to only write the VID header |
1064 | * and do not write any data. This also means we should not set | 1059 | * and do not write any data. This also means we should not set |
1065 | * @vid_hdr->copy_flag, @vid_hdr->data_size, and @vid_hdr->data_crc. | 1060 | * @vid_hdr->copy_flag, @vid_hdr->data_size, and @vid_hdr->data_crc. |
@@ -1074,7 +1069,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1074 | err = ubi_io_write_vid_hdr(ubi, to, vid_hdr); | 1069 | err = ubi_io_write_vid_hdr(ubi, to, vid_hdr); |
1075 | if (err) { | 1070 | if (err) { |
1076 | if (err == -EIO) | 1071 | if (err == -EIO) |
1077 | err = 2; | 1072 | err = MOVE_TARGET_WR_ERR; |
1078 | goto out_unlock_buf; | 1073 | goto out_unlock_buf; |
1079 | } | 1074 | } |
1080 | 1075 | ||
@@ -1086,7 +1081,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1086 | if (err != UBI_IO_BITFLIPS) | 1081 | if (err != UBI_IO_BITFLIPS) |
1087 | ubi_warn("cannot read VID header back from PEB %d", to); | 1082 | ubi_warn("cannot read VID header back from PEB %d", to); |
1088 | else | 1083 | else |
1089 | err = -EAGAIN; | 1084 | err = MOVE_CANCEL_BITFLIPS; |
1090 | goto out_unlock_buf; | 1085 | goto out_unlock_buf; |
1091 | } | 1086 | } |
1092 | 1087 | ||
@@ -1094,7 +1089,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1094 | err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size); | 1089 | err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size); |
1095 | if (err) { | 1090 | if (err) { |
1096 | if (err == -EIO) | 1091 | if (err == -EIO) |
1097 | err = 2; | 1092 | err = MOVE_TARGET_WR_ERR; |
1098 | goto out_unlock_buf; | 1093 | goto out_unlock_buf; |
1099 | } | 1094 | } |
1100 | 1095 | ||
@@ -1111,7 +1106,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1111 | ubi_warn("cannot read data back from PEB %d", | 1106 | ubi_warn("cannot read data back from PEB %d", |
1112 | to); | 1107 | to); |
1113 | else | 1108 | else |
1114 | err = -EAGAIN; | 1109 | err = MOVE_CANCEL_BITFLIPS; |
1115 | goto out_unlock_buf; | 1110 | goto out_unlock_buf; |
1116 | } | 1111 | } |
1117 | 1112 | ||
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 749007e9f1aa..fd9b20da5b6b 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
@@ -100,6 +100,22 @@ enum { | |||
100 | UBI_IO_BITFLIPS | 100 | UBI_IO_BITFLIPS |
101 | }; | 101 | }; |
102 | 102 | ||
103 | /* | ||
104 | * Return codes of the 'ubi_eba_copy_leb()' function. | ||
105 | * | ||
106 | * MOVE_CANCEL_RACE: canceled because the volume is being deleted, the source | ||
107 | * PEB was put meanwhile, or there is I/O on the source PEB | ||
108 | * MOVE_TARGET_WR_ERR: canceled because there was a write error to the target | ||
109 | * PEB | ||
110 | * MOVE_CANCEL_BITFLIPS: canceled because a bit-flip was detected in the | ||
111 | * target PEB | ||
112 | */ | ||
113 | enum { | ||
114 | MOVE_CANCEL_RACE = 1, | ||
115 | MOVE_TARGET_WR_ERR, | ||
116 | MOVE_CANCEL_BITFLIPS, | ||
117 | }; | ||
118 | |||
103 | /** | 119 | /** |
104 | * struct ubi_wl_entry - wear-leveling entry. | 120 | * struct ubi_wl_entry - wear-leveling entry. |
105 | * @u.rb: link in the corresponding (free/used) RB-tree | 121 | * @u.rb: link in the corresponding (free/used) RB-tree |
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 891534f8210d..ec915c02301c 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c | |||
@@ -756,15 +756,14 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, | |||
756 | 756 | ||
757 | err = ubi_eba_copy_leb(ubi, e1->pnum, e2->pnum, vid_hdr); | 757 | err = ubi_eba_copy_leb(ubi, e1->pnum, e2->pnum, vid_hdr); |
758 | if (err) { | 758 | if (err) { |
759 | if (err == -EAGAIN) | 759 | if (err == MOVE_CANCEL_BITFLIPS || |
760 | goto out_not_moved; | 760 | err == MOVE_TARGET_WR_ERR) { |
761 | if (err < 0) | 761 | /* Target PEB bit-flips or write error, torture it */ |
762 | goto out_error; | ||
763 | if (err == 2) { | ||
764 | /* Target PEB write error, torture it */ | ||
765 | torture = 1; | 762 | torture = 1; |
766 | goto out_not_moved; | 763 | goto out_not_moved; |
767 | } | 764 | } |
765 | if (err < 0) | ||
766 | goto out_error; | ||
768 | 767 | ||
769 | /* | 768 | /* |
770 | * The LEB has not been moved because the volume is being | 769 | * The LEB has not been moved because the volume is being |
@@ -774,7 +773,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, | |||
774 | */ | 773 | */ |
775 | 774 | ||
776 | dbg_wl("canceled moving PEB %d", e1->pnum); | 775 | dbg_wl("canceled moving PEB %d", e1->pnum); |
777 | ubi_assert(err == 1); | 776 | ubi_assert(err == MOVE_CANCEL_RACE); |
778 | 777 | ||
779 | ubi_free_vid_hdr(ubi, vid_hdr); | 778 | ubi_free_vid_hdr(ubi, vid_hdr); |
780 | vid_hdr = NULL; | 779 | vid_hdr = NULL; |