aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/eba.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/eba.c')
-rw-r--r--drivers/mtd/ubi/eba.c77
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 */
224static void leb_read_unlock(struct ubi_device *ubi, int vol_id, int lnum) 222static 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 */
275static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) 269static 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 */
308static void leb_write_unlock(struct ubi_device *ubi, int vol_id, int lnum) 298static 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
1228out_free: 1212out_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 */
1241void 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}