diff options
Diffstat (limited to 'drivers/mtd/ubi/eba.c')
-rw-r--r-- | drivers/mtd/ubi/eba.c | 77 |
1 files changed, 22 insertions, 55 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 7ce91ca742b1..e04bcf1dff87 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -19,20 +19,20 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * The UBI Eraseblock Association (EBA) unit. | 22 | * The UBI Eraseblock Association (EBA) sub-system. |
23 | * | 23 | * |
24 | * This unit is responsible for I/O to/from logical eraseblock. | 24 | * This sub-system is responsible for I/O to/from logical eraseblock. |
25 | * | 25 | * |
26 | * Although in this implementation the EBA table is fully kept and managed in | 26 | * Although in this implementation the EBA table is fully kept and managed in |
27 | * RAM, which assumes poor scalability, it might be (partially) maintained on | 27 | * RAM, which assumes poor scalability, it might be (partially) maintained on |
28 | * flash in future implementations. | 28 | * flash in future implementations. |
29 | * | 29 | * |
30 | * The EBA unit implements per-logical eraseblock locking. Before accessing a | 30 | * The EBA sub-system implements per-logical eraseblock locking. Before |
31 | * logical eraseblock it is locked for reading or writing. The per-logical | 31 | * accessing a logical eraseblock it is locked for reading or writing. The |
32 | * eraseblock locking is implemented by means of the lock tree. The lock tree | 32 | * per-logical eraseblock locking is implemented by means of the lock tree. The |
33 | * is an RB-tree which refers all the currently locked logical eraseblocks. The | 33 | * lock tree is an RB-tree which refers all the currently locked logical |
34 | * lock tree elements are &struct ubi_ltree_entry objects. They are indexed by | 34 | * eraseblocks. The lock tree elements are &struct ubi_ltree_entry objects. |
35 | * (@vol_id, @lnum) pairs. | 35 | * They are indexed by (@vol_id, @lnum) pairs. |
36 | * | 36 | * |
37 | * EBA also maintains the global sequence counter which is incremented each | 37 | * EBA also maintains the global sequence counter which is incremented each |
38 | * time a logical eraseblock is mapped to a physical eraseblock and it is | 38 | * time a logical eraseblock is mapped to a physical eraseblock and it is |
@@ -189,9 +189,7 @@ static struct ubi_ltree_entry *ltree_add_entry(struct ubi_device *ubi, | |||
189 | le->users += 1; | 189 | le->users += 1; |
190 | spin_unlock(&ubi->ltree_lock); | 190 | spin_unlock(&ubi->ltree_lock); |
191 | 191 | ||
192 | if (le_free) | 192 | kfree(le_free); |
193 | kfree(le_free); | ||
194 | |||
195 | return le; | 193 | return le; |
196 | } | 194 | } |
197 | 195 | ||
@@ -223,22 +221,18 @@ static int leb_read_lock(struct ubi_device *ubi, int vol_id, int lnum) | |||
223 | */ | 221 | */ |
224 | static void leb_read_unlock(struct ubi_device *ubi, int vol_id, int lnum) | 222 | static void leb_read_unlock(struct ubi_device *ubi, int vol_id, int lnum) |
225 | { | 223 | { |
226 | int free = 0; | ||
227 | struct ubi_ltree_entry *le; | 224 | struct ubi_ltree_entry *le; |
228 | 225 | ||
229 | spin_lock(&ubi->ltree_lock); | 226 | spin_lock(&ubi->ltree_lock); |
230 | le = ltree_lookup(ubi, vol_id, lnum); | 227 | le = ltree_lookup(ubi, vol_id, lnum); |
231 | le->users -= 1; | 228 | le->users -= 1; |
232 | ubi_assert(le->users >= 0); | 229 | ubi_assert(le->users >= 0); |
230 | up_read(&le->mutex); | ||
233 | if (le->users == 0) { | 231 | if (le->users == 0) { |
234 | rb_erase(&le->rb, &ubi->ltree); | 232 | rb_erase(&le->rb, &ubi->ltree); |
235 | free = 1; | 233 | kfree(le); |
236 | } | 234 | } |
237 | spin_unlock(&ubi->ltree_lock); | 235 | spin_unlock(&ubi->ltree_lock); |
238 | |||
239 | up_read(&le->mutex); | ||
240 | if (free) | ||
241 | kfree(le); | ||
242 | } | 236 | } |
243 | 237 | ||
244 | /** | 238 | /** |
@@ -274,7 +268,6 @@ static int leb_write_lock(struct ubi_device *ubi, int vol_id, int lnum) | |||
274 | */ | 268 | */ |
275 | static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) | 269 | static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) |
276 | { | 270 | { |
277 | int free; | ||
278 | struct ubi_ltree_entry *le; | 271 | struct ubi_ltree_entry *le; |
279 | 272 | ||
280 | le = ltree_add_entry(ubi, vol_id, lnum); | 273 | le = ltree_add_entry(ubi, vol_id, lnum); |
@@ -289,12 +282,9 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) | |||
289 | ubi_assert(le->users >= 0); | 282 | ubi_assert(le->users >= 0); |
290 | if (le->users == 0) { | 283 | if (le->users == 0) { |
291 | rb_erase(&le->rb, &ubi->ltree); | 284 | rb_erase(&le->rb, &ubi->ltree); |
292 | free = 1; | ||
293 | } else | ||
294 | free = 0; | ||
295 | spin_unlock(&ubi->ltree_lock); | ||
296 | if (free) | ||
297 | kfree(le); | 285 | kfree(le); |
286 | } | ||
287 | spin_unlock(&ubi->ltree_lock); | ||
298 | 288 | ||
299 | return 1; | 289 | return 1; |
300 | } | 290 | } |
@@ -307,23 +297,18 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) | |||
307 | */ | 297 | */ |
308 | static void leb_write_unlock(struct ubi_device *ubi, int vol_id, int lnum) | 298 | static void leb_write_unlock(struct ubi_device *ubi, int vol_id, int lnum) |
309 | { | 299 | { |
310 | int free; | ||
311 | struct ubi_ltree_entry *le; | 300 | struct ubi_ltree_entry *le; |
312 | 301 | ||
313 | spin_lock(&ubi->ltree_lock); | 302 | spin_lock(&ubi->ltree_lock); |
314 | le = ltree_lookup(ubi, vol_id, lnum); | 303 | le = ltree_lookup(ubi, vol_id, lnum); |
315 | le->users -= 1; | 304 | le->users -= 1; |
316 | ubi_assert(le->users >= 0); | 305 | ubi_assert(le->users >= 0); |
306 | up_write(&le->mutex); | ||
317 | if (le->users == 0) { | 307 | if (le->users == 0) { |
318 | rb_erase(&le->rb, &ubi->ltree); | 308 | rb_erase(&le->rb, &ubi->ltree); |
319 | free = 1; | ||
320 | } else | ||
321 | free = 0; | ||
322 | spin_unlock(&ubi->ltree_lock); | ||
323 | |||
324 | up_write(&le->mutex); | ||
325 | if (free) | ||
326 | kfree(le); | 309 | kfree(le); |
310 | } | ||
311 | spin_unlock(&ubi->ltree_lock); | ||
327 | } | 312 | } |
328 | 313 | ||
329 | /** | 314 | /** |
@@ -516,9 +501,8 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, | |||
516 | struct ubi_vid_hdr *vid_hdr; | 501 | struct ubi_vid_hdr *vid_hdr; |
517 | 502 | ||
518 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); | 503 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); |
519 | if (!vid_hdr) { | 504 | if (!vid_hdr) |
520 | return -ENOMEM; | 505 | return -ENOMEM; |
521 | } | ||
522 | 506 | ||
523 | mutex_lock(&ubi->buf_mutex); | 507 | mutex_lock(&ubi->buf_mutex); |
524 | 508 | ||
@@ -752,7 +736,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, | |||
752 | /* If this is the last LEB @len may be unaligned */ | 736 | /* If this is the last LEB @len may be unaligned */ |
753 | len = ALIGN(data_size, ubi->min_io_size); | 737 | len = ALIGN(data_size, ubi->min_io_size); |
754 | else | 738 | else |
755 | ubi_assert(len % ubi->min_io_size == 0); | 739 | ubi_assert(!(len & (ubi->min_io_size - 1))); |
756 | 740 | ||
757 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); | 741 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); |
758 | if (!vid_hdr) | 742 | if (!vid_hdr) |
@@ -919,7 +903,7 @@ retry: | |||
919 | } | 903 | } |
920 | 904 | ||
921 | if (vol->eba_tbl[lnum] >= 0) { | 905 | if (vol->eba_tbl[lnum] >= 0) { |
922 | err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 1); | 906 | err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0); |
923 | if (err) | 907 | if (err) |
924 | goto out_leb_unlock; | 908 | goto out_leb_unlock; |
925 | } | 909 | } |
@@ -1141,7 +1125,7 @@ out_unlock_leb: | |||
1141 | } | 1125 | } |
1142 | 1126 | ||
1143 | /** | 1127 | /** |
1144 | * ubi_eba_init_scan - initialize the EBA unit using scanning information. | 1128 | * ubi_eba_init_scan - initialize the EBA sub-system using scanning information. |
1145 | * @ubi: UBI device description object | 1129 | * @ubi: UBI device description object |
1146 | * @si: scanning information | 1130 | * @si: scanning information |
1147 | * | 1131 | * |
@@ -1156,7 +1140,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) | |||
1156 | struct ubi_scan_leb *seb; | 1140 | struct ubi_scan_leb *seb; |
1157 | struct rb_node *rb; | 1141 | struct rb_node *rb; |
1158 | 1142 | ||
1159 | dbg_eba("initialize EBA unit"); | 1143 | dbg_eba("initialize EBA sub-system"); |
1160 | 1144 | ||
1161 | spin_lock_init(&ubi->ltree_lock); | 1145 | spin_lock_init(&ubi->ltree_lock); |
1162 | mutex_init(&ubi->alc_mutex); | 1146 | mutex_init(&ubi->alc_mutex); |
@@ -1222,7 +1206,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) | |||
1222 | ubi->rsvd_pebs += ubi->beb_rsvd_pebs; | 1206 | ubi->rsvd_pebs += ubi->beb_rsvd_pebs; |
1223 | } | 1207 | } |
1224 | 1208 | ||
1225 | dbg_eba("EBA unit is initialized"); | 1209 | dbg_eba("EBA sub-system is initialized"); |
1226 | return 0; | 1210 | return 0; |
1227 | 1211 | ||
1228 | out_free: | 1212 | out_free: |
@@ -1233,20 +1217,3 @@ out_free: | |||
1233 | } | 1217 | } |
1234 | return err; | 1218 | return err; |
1235 | } | 1219 | } |
1236 | |||
1237 | /** | ||
1238 | * ubi_eba_close - close EBA unit. | ||
1239 | * @ubi: UBI device description object | ||
1240 | */ | ||
1241 | void ubi_eba_close(const struct ubi_device *ubi) | ||
1242 | { | ||
1243 | int i, num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT; | ||
1244 | |||
1245 | dbg_eba("close EBA unit"); | ||
1246 | |||
1247 | for (i = 0; i < num_volumes; i++) { | ||
1248 | if (!ubi->volumes[i]) | ||
1249 | continue; | ||
1250 | kfree(ubi->volumes[i]->eba_tbl); | ||
1251 | } | ||
1252 | } | ||