diff options
Diffstat (limited to 'drivers/mtd/ubi/eba.c')
-rw-r--r-- | drivers/mtd/ubi/eba.c | 145 |
1 files changed, 100 insertions, 45 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 84f7dc9fd3ac..c94f475758de 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -260,6 +260,44 @@ static int leb_write_lock(struct ubi_device *ubi, int vol_id, int lnum) | |||
260 | } | 260 | } |
261 | 261 | ||
262 | /** | 262 | /** |
263 | * leb_write_lock - lock logical eraseblock for writing. | ||
264 | * @ubi: UBI device description object | ||
265 | * @vol_id: volume ID | ||
266 | * @lnum: logical eraseblock number | ||
267 | * | ||
268 | * This function locks a logical eraseblock for writing if there is no | ||
269 | * contention and does nothing if there is contention. Returns %0 in case of | ||
270 | * success, %1 in case of contention, and and a negative error code in case of | ||
271 | * failure. | ||
272 | */ | ||
273 | static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) | ||
274 | { | ||
275 | int free; | ||
276 | struct ubi_ltree_entry *le; | ||
277 | |||
278 | le = ltree_add_entry(ubi, vol_id, lnum); | ||
279 | if (IS_ERR(le)) | ||
280 | return PTR_ERR(le); | ||
281 | if (down_write_trylock(&le->mutex)) | ||
282 | return 0; | ||
283 | |||
284 | /* Contention, cancel */ | ||
285 | spin_lock(&ubi->ltree_lock); | ||
286 | le->users -= 1; | ||
287 | ubi_assert(le->users >= 0); | ||
288 | if (le->users == 0) { | ||
289 | rb_erase(&le->rb, &ubi->ltree); | ||
290 | free = 1; | ||
291 | } else | ||
292 | free = 0; | ||
293 | spin_unlock(&ubi->ltree_lock); | ||
294 | if (free) | ||
295 | kmem_cache_free(ubi_ltree_slab, le); | ||
296 | |||
297 | return 1; | ||
298 | } | ||
299 | |||
300 | /** | ||
263 | * leb_write_unlock - unlock logical eraseblock. | 301 | * leb_write_unlock - unlock logical eraseblock. |
264 | * @ubi: UBI device description object | 302 | * @ubi: UBI device description object |
265 | * @vol_id: volume ID | 303 | * @vol_id: volume ID |
@@ -923,14 +961,16 @@ write_error: | |||
923 | * | 961 | * |
924 | * This function copies logical eraseblock from physical eraseblock @from to | 962 | * This function copies logical eraseblock from physical eraseblock @from to |
925 | * physical eraseblock @to. The @vid_hdr buffer may be changed by this | 963 | * physical eraseblock @to. The @vid_hdr buffer may be changed by this |
926 | * function. Returns zero in case of success, %UBI_IO_BITFLIPS if the operation | 964 | * function. Returns: |
927 | * was canceled because bit-flips were detected at the target PEB, and a | 965 | * o %0 in case of success; |
928 | * negative error code in case of failure. | 966 | * o %1 if the operation was canceled and should be tried later (e.g., |
967 | * because a bit-flip was detected at the target PEB); | ||
968 | * o %2 if the volume is being deleted and this LEB should not be moved. | ||
929 | */ | 969 | */ |
930 | int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | 970 | int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, |
931 | struct ubi_vid_hdr *vid_hdr) | 971 | struct ubi_vid_hdr *vid_hdr) |
932 | { | 972 | { |
933 | int err, vol_id, lnum, data_size, aldata_size, pnum, idx; | 973 | int err, vol_id, lnum, data_size, aldata_size, idx; |
934 | struct ubi_volume *vol; | 974 | struct ubi_volume *vol; |
935 | uint32_t crc; | 975 | uint32_t crc; |
936 | 976 | ||
@@ -946,57 +986,67 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
946 | data_size = aldata_size = | 986 | data_size = aldata_size = |
947 | ubi->leb_size - be32_to_cpu(vid_hdr->data_pad); | 987 | ubi->leb_size - be32_to_cpu(vid_hdr->data_pad); |
948 | 988 | ||
949 | /* | ||
950 | * We do not want anybody to write to this logical eraseblock while we | ||
951 | * are moving it, so we lock it. | ||
952 | */ | ||
953 | err = leb_write_lock(ubi, vol_id, lnum); | ||
954 | if (err) | ||
955 | return err; | ||
956 | |||
957 | mutex_lock(&ubi->buf_mutex); | ||
958 | |||
959 | /* | ||
960 | * But the logical eraseblock might have been put by this time. | ||
961 | * Cancel if it is true. | ||
962 | */ | ||
963 | idx = vol_id2idx(ubi, vol_id); | 989 | idx = vol_id2idx(ubi, vol_id); |
964 | 990 | spin_lock(&ubi->volumes_lock); | |
965 | /* | 991 | /* |
966 | * We may race with volume deletion/re-size, so we have to hold | 992 | * Note, we may race with volume deletion, which means that the volume |
967 | * @ubi->volumes_lock. | 993 | * this logical eraseblock belongs to might be being deleted. Since the |
968 | * | 994 | * volume deletion unmaps all the volume's logical eraseblocks, it will |
969 | * Note, it is not a problem if we race with volume deletion or re-size | 995 | * be locked in 'ubi_wl_put_peb()' and wait for the WL worker to finish. |
970 | * here. If the volume is deleted or re-sized while we are moving an | ||
971 | * eraseblock which belongs to this volume, we'll end up with finding | ||
972 | * out that this LEB was unmapped at the end (see WL), and drop this | ||
973 | * PEB. | ||
974 | */ | 996 | */ |
975 | spin_lock(&ubi->volumes_lock); | ||
976 | vol = ubi->volumes[idx]; | 997 | vol = ubi->volumes[idx]; |
977 | if (!vol) { | 998 | if (!vol) { |
978 | dbg_eba("volume %d was removed meanwhile", vol_id); | 999 | /* No need to do further work, cancel */ |
1000 | dbg_eba("volume %d is being removed, cancel", vol_id); | ||
979 | spin_unlock(&ubi->volumes_lock); | 1001 | spin_unlock(&ubi->volumes_lock); |
980 | goto out_unlock; | 1002 | return 2; |
981 | } | 1003 | } |
1004 | spin_unlock(&ubi->volumes_lock); | ||
982 | 1005 | ||
983 | pnum = vol->eba_tbl[lnum]; | 1006 | /* |
984 | if (pnum != from) { | 1007 | * We do not want anybody to write to this logical eraseblock while we |
985 | dbg_eba("LEB %d:%d is no longer mapped to PEB %d, mapped to " | 1008 | * are moving it, so lock it. |
986 | "PEB %d, cancel", vol_id, lnum, from, pnum); | 1009 | * |
987 | spin_unlock(&ubi->volumes_lock); | 1010 | * Note, we are using non-waiting locking here, because we cannot sleep |
988 | goto out_unlock; | 1011 | * on the LEB, since it may cause deadlocks. Indeed, imagine a task is |
1012 | * unmapping the LEB which is mapped to the PEB we are going to move | ||
1013 | * (@from). This task locks the LEB and goes sleep in the | ||
1014 | * 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are | ||
1015 | * holding @ubi->move_mutex and go sleep on the LEB lock. So, if the | ||
1016 | * LEB is already locked, we just do not move it and return %1. | ||
1017 | */ | ||
1018 | err = leb_write_trylock(ubi, vol_id, lnum); | ||
1019 | if (err) { | ||
1020 | dbg_eba("contention on LEB %d:%d, cancel", vol_id, lnum); | ||
1021 | return err; | ||
989 | } | 1022 | } |
990 | spin_unlock(&ubi->volumes_lock); | ||
991 | 1023 | ||
992 | /* OK, now the LEB is locked and we can safely start moving it */ | 1024 | /* |
1025 | * The LEB might have been put meanwhile, and the task which put it is | ||
1026 | * probably waiting on @ubi->move_mutex. No need to continue the work, | ||
1027 | * cancel it. | ||
1028 | */ | ||
1029 | if (vol->eba_tbl[lnum] != from) { | ||
1030 | dbg_eba("LEB %d:%d is no longer mapped to PEB %d, mapped to " | ||
1031 | "PEB %d, cancel", vol_id, lnum, from, | ||
1032 | vol->eba_tbl[lnum]); | ||
1033 | err = 1; | ||
1034 | goto out_unlock_leb; | ||
1035 | } | ||
993 | 1036 | ||
1037 | /* | ||
1038 | * OK, now the LEB is locked and we can safely start moving iy. Since | ||
1039 | * this function utilizes thie @ubi->peb1_buf buffer which is shared | ||
1040 | * with some other functions, so lock the buffer by taking the | ||
1041 | * @ubi->buf_mutex. | ||
1042 | */ | ||
1043 | mutex_lock(&ubi->buf_mutex); | ||
994 | dbg_eba("read %d bytes of data", aldata_size); | 1044 | dbg_eba("read %d bytes of data", aldata_size); |
995 | err = ubi_io_read_data(ubi, ubi->peb_buf1, from, 0, aldata_size); | 1045 | err = ubi_io_read_data(ubi, ubi->peb_buf1, from, 0, aldata_size); |
996 | if (err && err != UBI_IO_BITFLIPS) { | 1046 | if (err && err != UBI_IO_BITFLIPS) { |
997 | ubi_warn("error %d while reading data from PEB %d", | 1047 | ubi_warn("error %d while reading data from PEB %d", |
998 | err, from); | 1048 | err, from); |
999 | goto out_unlock; | 1049 | goto out_unlock_buf; |
1000 | } | 1050 | } |
1001 | 1051 | ||
1002 | /* | 1052 | /* |
@@ -1032,7 +1082,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1032 | 1082 | ||
1033 | err = ubi_io_write_vid_hdr(ubi, to, vid_hdr); | 1083 | err = ubi_io_write_vid_hdr(ubi, to, vid_hdr); |
1034 | if (err) | 1084 | if (err) |
1035 | goto out_unlock; | 1085 | goto out_unlock_buf; |
1036 | 1086 | ||
1037 | cond_resched(); | 1087 | cond_resched(); |
1038 | 1088 | ||
@@ -1041,13 +1091,15 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1041 | if (err) { | 1091 | if (err) { |
1042 | if (err != UBI_IO_BITFLIPS) | 1092 | if (err != UBI_IO_BITFLIPS) |
1043 | ubi_warn("cannot read VID header back from PEB %d", to); | 1093 | ubi_warn("cannot read VID header back from PEB %d", to); |
1044 | goto out_unlock; | 1094 | else |
1095 | err = 1; | ||
1096 | goto out_unlock_buf; | ||
1045 | } | 1097 | } |
1046 | 1098 | ||
1047 | if (data_size > 0) { | 1099 | if (data_size > 0) { |
1048 | err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size); | 1100 | err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size); |
1049 | if (err) | 1101 | if (err) |
1050 | goto out_unlock; | 1102 | goto out_unlock_buf; |
1051 | 1103 | ||
1052 | cond_resched(); | 1104 | cond_resched(); |
1053 | 1105 | ||
@@ -1061,7 +1113,9 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1061 | if (err != UBI_IO_BITFLIPS) | 1113 | if (err != UBI_IO_BITFLIPS) |
1062 | ubi_warn("cannot read data back from PEB %d", | 1114 | ubi_warn("cannot read data back from PEB %d", |
1063 | to); | 1115 | to); |
1064 | goto out_unlock; | 1116 | else |
1117 | err = 1; | ||
1118 | goto out_unlock_buf; | ||
1065 | } | 1119 | } |
1066 | 1120 | ||
1067 | cond_resched(); | 1121 | cond_resched(); |
@@ -1069,15 +1123,16 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1069 | if (memcmp(ubi->peb_buf1, ubi->peb_buf2, aldata_size)) { | 1123 | if (memcmp(ubi->peb_buf1, ubi->peb_buf2, aldata_size)) { |
1070 | ubi_warn("read data back from PEB %d - it is different", | 1124 | ubi_warn("read data back from PEB %d - it is different", |
1071 | to); | 1125 | to); |
1072 | goto out_unlock; | 1126 | goto out_unlock_buf; |
1073 | } | 1127 | } |
1074 | } | 1128 | } |
1075 | 1129 | ||
1076 | ubi_assert(vol->eba_tbl[lnum] == from); | 1130 | ubi_assert(vol->eba_tbl[lnum] == from); |
1077 | vol->eba_tbl[lnum] = to; | 1131 | vol->eba_tbl[lnum] = to; |
1078 | 1132 | ||
1079 | out_unlock: | 1133 | out_unlock_buf: |
1080 | mutex_unlock(&ubi->buf_mutex); | 1134 | mutex_unlock(&ubi->buf_mutex); |
1135 | out_unlock_leb: | ||
1081 | leb_write_unlock(ubi, vol_id, lnum); | 1136 | leb_write_unlock(ubi, vol_id, lnum); |
1082 | return err; | 1137 | return err; |
1083 | } | 1138 | } |