diff options
author | Boris Brezillon <boris.brezillon@free-electrons.com> | 2016-09-16 10:59:25 -0400 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2016-10-02 16:48:14 -0400 |
commit | 799dca34ac543485f581bd8464ec9b1c4f0f852a (patch) | |
tree | 8db04c7fe6e12e4964ea09e095c3eb21547b2065 | |
parent | 1f81a5ccaba51c8884db8f060b9f606c29db931d (diff) |
UBI: hide EBA internals
Create a private ubi_eba_table struct to hide EBA internals and provide
helpers to allocate, destroy, copy and assing an EBA table to a volume.
Now that external EBA users are using helpers to query/modify the EBA
state we can safely change the internal representation, which will be
needed to support the LEB consolidation concept.
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
-rw-r--r-- | drivers/mtd/ubi/build.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/eba.c | 166 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 8 | ||||
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 40 |
4 files changed, 165 insertions, 51 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 0680516bb472..85d54f37e28f 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
@@ -574,7 +574,7 @@ void ubi_free_internal_volumes(struct ubi_device *ubi) | |||
574 | 574 | ||
575 | for (i = ubi->vtbl_slots; | 575 | for (i = ubi->vtbl_slots; |
576 | i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { | 576 | i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { |
577 | kfree(ubi->volumes[i]->eba_tbl); | 577 | ubi_eba_replace_table(ubi->volumes[i], NULL); |
578 | kfree(ubi->volumes[i]); | 578 | kfree(ubi->volumes[i]); |
579 | } | 579 | } |
580 | } | 580 | } |
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index f3ff8604b5e5..884c91ffe7ba 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -50,6 +50,30 @@ | |||
50 | #define EBA_RESERVED_PEBS 1 | 50 | #define EBA_RESERVED_PEBS 1 |
51 | 51 | ||
52 | /** | 52 | /** |
53 | * struct ubi_eba_entry - structure encoding a single LEB -> PEB association | ||
54 | * @pnum: the physical eraseblock number attached to the LEB | ||
55 | * | ||
56 | * This structure is encoding a LEB -> PEB association. Note that the LEB | ||
57 | * number is not stored here, because it is the index used to access the | ||
58 | * entries table. | ||
59 | */ | ||
60 | struct ubi_eba_entry { | ||
61 | int pnum; | ||
62 | }; | ||
63 | |||
64 | /** | ||
65 | * struct ubi_eba_table - LEB -> PEB association information | ||
66 | * @entries: the LEB to PEB mapping (one entry per LEB). | ||
67 | * | ||
68 | * This structure is private to the EBA logic and should be kept here. | ||
69 | * It is encoding the LEB to PEB association table, and is subject to | ||
70 | * changes. | ||
71 | */ | ||
72 | struct ubi_eba_table { | ||
73 | struct ubi_eba_entry *entries; | ||
74 | }; | ||
75 | |||
76 | /** | ||
53 | * next_sqnum - get next sequence number. | 77 | * next_sqnum - get next sequence number. |
54 | * @ubi: UBI device description object | 78 | * @ubi: UBI device description object |
55 | * | 79 | * |
@@ -97,7 +121,94 @@ void ubi_eba_get_ldesc(struct ubi_volume *vol, int lnum, | |||
97 | struct ubi_eba_leb_desc *ldesc) | 121 | struct ubi_eba_leb_desc *ldesc) |
98 | { | 122 | { |
99 | ldesc->lnum = lnum; | 123 | ldesc->lnum = lnum; |
100 | ldesc->pnum = vol->eba_tbl[lnum]; | 124 | ldesc->pnum = vol->eba_tbl->entries[lnum].pnum; |
125 | } | ||
126 | |||
127 | /** | ||
128 | * ubi_eba_create_table - allocate a new EBA table and initialize it with all | ||
129 | * LEBs unmapped | ||
130 | * @vol: volume containing the EBA table to copy | ||
131 | * @nentries: number of entries in the table | ||
132 | * | ||
133 | * Allocate a new EBA table and initialize it with all LEBs unmapped. | ||
134 | * Returns a valid pointer if it succeed, an ERR_PTR() otherwise. | ||
135 | */ | ||
136 | struct ubi_eba_table *ubi_eba_create_table(struct ubi_volume *vol, | ||
137 | int nentries) | ||
138 | { | ||
139 | struct ubi_eba_table *tbl; | ||
140 | int err = -ENOMEM; | ||
141 | int i; | ||
142 | |||
143 | tbl = kzalloc(sizeof(*tbl), GFP_KERNEL); | ||
144 | if (!tbl) | ||
145 | return ERR_PTR(-ENOMEM); | ||
146 | |||
147 | tbl->entries = kmalloc_array(nentries, sizeof(*tbl->entries), | ||
148 | GFP_KERNEL); | ||
149 | if (!tbl->entries) | ||
150 | goto err; | ||
151 | |||
152 | for (i = 0; i < nentries; i++) | ||
153 | tbl->entries[i].pnum = UBI_LEB_UNMAPPED; | ||
154 | |||
155 | return tbl; | ||
156 | |||
157 | err: | ||
158 | kfree(tbl->entries); | ||
159 | kfree(tbl); | ||
160 | |||
161 | return ERR_PTR(err); | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * ubi_eba_destroy_table - destroy an EBA table | ||
166 | * @tbl: the table to destroy | ||
167 | * | ||
168 | * Destroy an EBA table. | ||
169 | */ | ||
170 | void ubi_eba_destroy_table(struct ubi_eba_table *tbl) | ||
171 | { | ||
172 | if (!tbl) | ||
173 | return; | ||
174 | |||
175 | kfree(tbl->entries); | ||
176 | kfree(tbl); | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * ubi_eba_copy_table - copy the EBA table attached to vol into another table | ||
181 | * @vol: volume containing the EBA table to copy | ||
182 | * @dst: destination | ||
183 | * @nentries: number of entries to copy | ||
184 | * | ||
185 | * Copy the EBA table stored in vol into the one pointed by dst. | ||
186 | */ | ||
187 | void ubi_eba_copy_table(struct ubi_volume *vol, struct ubi_eba_table *dst, | ||
188 | int nentries) | ||
189 | { | ||
190 | struct ubi_eba_table *src; | ||
191 | int i; | ||
192 | |||
193 | ubi_assert(dst && vol && vol->eba_tbl); | ||
194 | |||
195 | src = vol->eba_tbl; | ||
196 | |||
197 | for (i = 0; i < nentries; i++) | ||
198 | dst->entries[i].pnum = src->entries[i].pnum; | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * ubi_eba_replace_table - assign a new EBA table to a volume | ||
203 | * @vol: volume containing the EBA table to copy | ||
204 | * @tbl: new EBA table | ||
205 | * | ||
206 | * Assign a new EBA table to the volume and release the old one. | ||
207 | */ | ||
208 | void ubi_eba_replace_table(struct ubi_volume *vol, struct ubi_eba_table *tbl) | ||
209 | { | ||
210 | ubi_eba_destroy_table(vol->eba_tbl); | ||
211 | vol->eba_tbl = tbl; | ||
101 | } | 212 | } |
102 | 213 | ||
103 | /** | 214 | /** |
@@ -337,7 +448,7 @@ static void leb_write_unlock(struct ubi_device *ubi, int vol_id, int lnum) | |||
337 | */ | 448 | */ |
338 | bool ubi_eba_is_mapped(struct ubi_volume *vol, int lnum) | 449 | bool ubi_eba_is_mapped(struct ubi_volume *vol, int lnum) |
339 | { | 450 | { |
340 | return vol->eba_tbl[lnum] >= 0; | 451 | return vol->eba_tbl->entries[lnum].pnum >= 0; |
341 | } | 452 | } |
342 | 453 | ||
343 | /** | 454 | /** |
@@ -362,7 +473,7 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, | |||
362 | if (err) | 473 | if (err) |
363 | return err; | 474 | return err; |
364 | 475 | ||
365 | pnum = vol->eba_tbl[lnum]; | 476 | pnum = vol->eba_tbl->entries[lnum].pnum; |
366 | if (pnum < 0) | 477 | if (pnum < 0) |
367 | /* This logical eraseblock is already unmapped */ | 478 | /* This logical eraseblock is already unmapped */ |
368 | goto out_unlock; | 479 | goto out_unlock; |
@@ -370,7 +481,7 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, | |||
370 | dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum); | 481 | dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum); |
371 | 482 | ||
372 | down_read(&ubi->fm_eba_sem); | 483 | down_read(&ubi->fm_eba_sem); |
373 | vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED; | 484 | vol->eba_tbl->entries[lnum].pnum = UBI_LEB_UNMAPPED; |
374 | up_read(&ubi->fm_eba_sem); | 485 | up_read(&ubi->fm_eba_sem); |
375 | err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 0); | 486 | err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 0); |
376 | 487 | ||
@@ -409,7 +520,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | |||
409 | if (err) | 520 | if (err) |
410 | return err; | 521 | return err; |
411 | 522 | ||
412 | pnum = vol->eba_tbl[lnum]; | 523 | pnum = vol->eba_tbl->entries[lnum].pnum; |
413 | if (pnum < 0) { | 524 | if (pnum < 0) { |
414 | /* | 525 | /* |
415 | * The logical eraseblock is not mapped, fill the whole buffer | 526 | * The logical eraseblock is not mapped, fill the whole buffer |
@@ -658,7 +769,7 @@ out_unlock: | |||
658 | mutex_unlock(&ubi->buf_mutex); | 769 | mutex_unlock(&ubi->buf_mutex); |
659 | 770 | ||
660 | if (!err) | 771 | if (!err) |
661 | vol->eba_tbl[lnum] = new_pnum; | 772 | vol->eba_tbl->entries[lnum].pnum = new_pnum; |
662 | 773 | ||
663 | out_put: | 774 | out_put: |
664 | up_read(&ubi->fm_eba_sem); | 775 | up_read(&ubi->fm_eba_sem); |
@@ -749,7 +860,7 @@ static int try_write_vid_and_data(struct ubi_volume *vol, int lnum, | |||
749 | goto out_put; | 860 | goto out_put; |
750 | } | 861 | } |
751 | 862 | ||
752 | opnum = vol->eba_tbl[lnum]; | 863 | opnum = vol->eba_tbl->entries[lnum].pnum; |
753 | 864 | ||
754 | dbg_eba("write VID hdr and %d bytes at offset %d of LEB %d:%d, PEB %d", | 865 | dbg_eba("write VID hdr and %d bytes at offset %d of LEB %d:%d, PEB %d", |
755 | len, offset, vol_id, lnum, pnum); | 866 | len, offset, vol_id, lnum, pnum); |
@@ -771,7 +882,7 @@ static int try_write_vid_and_data(struct ubi_volume *vol, int lnum, | |||
771 | } | 882 | } |
772 | } | 883 | } |
773 | 884 | ||
774 | vol->eba_tbl[lnum] = pnum; | 885 | vol->eba_tbl->entries[lnum].pnum = pnum; |
775 | 886 | ||
776 | out_put: | 887 | out_put: |
777 | up_read(&ubi->fm_eba_sem); | 888 | up_read(&ubi->fm_eba_sem); |
@@ -812,7 +923,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | |||
812 | if (err) | 923 | if (err) |
813 | return err; | 924 | return err; |
814 | 925 | ||
815 | pnum = vol->eba_tbl[lnum]; | 926 | pnum = vol->eba_tbl->entries[lnum].pnum; |
816 | if (pnum >= 0) { | 927 | if (pnum >= 0) { |
817 | dbg_eba("write %d bytes at offset %d of LEB %d:%d, PEB %d", | 928 | dbg_eba("write %d bytes at offset %d of LEB %d:%d, PEB %d", |
818 | len, offset, vol_id, lnum, pnum); | 929 | len, offset, vol_id, lnum, pnum); |
@@ -930,7 +1041,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, | |||
930 | vid_hdr->used_ebs = cpu_to_be32(used_ebs); | 1041 | vid_hdr->used_ebs = cpu_to_be32(used_ebs); |
931 | vid_hdr->data_crc = cpu_to_be32(crc); | 1042 | vid_hdr->data_crc = cpu_to_be32(crc); |
932 | 1043 | ||
933 | ubi_assert(vol->eba_tbl[lnum] < 0); | 1044 | ubi_assert(vol->eba_tbl->entries[lnum].pnum < 0); |
934 | 1045 | ||
935 | for (tries = 0; tries <= UBI_IO_RETRIES; tries++) { | 1046 | for (tries = 0; tries <= UBI_IO_RETRIES; tries++) { |
936 | err = try_write_vid_and_data(vol, lnum, vid_hdr, buf, 0, len); | 1047 | err = try_write_vid_and_data(vol, lnum, vid_hdr, buf, 0, len); |
@@ -1140,9 +1251,9 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1140 | * probably waiting on @ubi->move_mutex. No need to continue the work, | 1251 | * probably waiting on @ubi->move_mutex. No need to continue the work, |
1141 | * cancel it. | 1252 | * cancel it. |
1142 | */ | 1253 | */ |
1143 | if (vol->eba_tbl[lnum] != from) { | 1254 | if (vol->eba_tbl->entries[lnum].pnum != from) { |
1144 | dbg_wl("LEB %d:%d is no longer mapped to PEB %d, mapped to PEB %d, cancel", | 1255 | dbg_wl("LEB %d:%d is no longer mapped to PEB %d, mapped to PEB %d, cancel", |
1145 | vol_id, lnum, from, vol->eba_tbl[lnum]); | 1256 | vol_id, lnum, from, vol->eba_tbl->entries[lnum].pnum); |
1146 | err = MOVE_CANCEL_RACE; | 1257 | err = MOVE_CANCEL_RACE; |
1147 | goto out_unlock_leb; | 1258 | goto out_unlock_leb; |
1148 | } | 1259 | } |
@@ -1227,9 +1338,9 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1227 | cond_resched(); | 1338 | cond_resched(); |
1228 | } | 1339 | } |
1229 | 1340 | ||
1230 | ubi_assert(vol->eba_tbl[lnum] == from); | 1341 | ubi_assert(vol->eba_tbl->entries[lnum].pnum == from); |
1231 | down_read(&ubi->fm_eba_sem); | 1342 | down_read(&ubi->fm_eba_sem); |
1232 | vol->eba_tbl[lnum] = to; | 1343 | vol->eba_tbl->entries[lnum].pnum = to; |
1233 | up_read(&ubi->fm_eba_sem); | 1344 | up_read(&ubi->fm_eba_sem); |
1234 | 1345 | ||
1235 | out_unlock_buf: | 1346 | out_unlock_buf: |
@@ -1386,7 +1497,7 @@ out_free: | |||
1386 | */ | 1497 | */ |
1387 | int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai) | 1498 | int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai) |
1388 | { | 1499 | { |
1389 | int i, j, err, num_volumes; | 1500 | int i, err, num_volumes; |
1390 | struct ubi_ainf_volume *av; | 1501 | struct ubi_ainf_volume *av; |
1391 | struct ubi_volume *vol; | 1502 | struct ubi_volume *vol; |
1392 | struct ubi_ainf_peb *aeb; | 1503 | struct ubi_ainf_peb *aeb; |
@@ -1402,35 +1513,39 @@ int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai) | |||
1402 | num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT; | 1513 | num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT; |
1403 | 1514 | ||
1404 | for (i = 0; i < num_volumes; i++) { | 1515 | for (i = 0; i < num_volumes; i++) { |
1516 | struct ubi_eba_table *tbl; | ||
1517 | |||
1405 | vol = ubi->volumes[i]; | 1518 | vol = ubi->volumes[i]; |
1406 | if (!vol) | 1519 | if (!vol) |
1407 | continue; | 1520 | continue; |
1408 | 1521 | ||
1409 | cond_resched(); | 1522 | cond_resched(); |
1410 | 1523 | ||
1411 | vol->eba_tbl = kmalloc(vol->reserved_pebs * sizeof(int), | 1524 | tbl = ubi_eba_create_table(vol, vol->reserved_pebs); |
1412 | GFP_KERNEL); | 1525 | if (IS_ERR(tbl)) { |
1413 | if (!vol->eba_tbl) { | 1526 | err = PTR_ERR(tbl); |
1414 | err = -ENOMEM; | ||
1415 | goto out_free; | 1527 | goto out_free; |
1416 | } | 1528 | } |
1417 | 1529 | ||
1418 | for (j = 0; j < vol->reserved_pebs; j++) | 1530 | ubi_eba_replace_table(vol, tbl); |
1419 | vol->eba_tbl[j] = UBI_LEB_UNMAPPED; | ||
1420 | 1531 | ||
1421 | av = ubi_find_av(ai, idx2vol_id(ubi, i)); | 1532 | av = ubi_find_av(ai, idx2vol_id(ubi, i)); |
1422 | if (!av) | 1533 | if (!av) |
1423 | continue; | 1534 | continue; |
1424 | 1535 | ||
1425 | ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) { | 1536 | ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) { |
1426 | if (aeb->lnum >= vol->reserved_pebs) | 1537 | if (aeb->lnum >= vol->reserved_pebs) { |
1427 | /* | 1538 | /* |
1428 | * This may happen in case of an unclean reboot | 1539 | * This may happen in case of an unclean reboot |
1429 | * during re-size. | 1540 | * during re-size. |
1430 | */ | 1541 | */ |
1431 | ubi_move_aeb_to_list(av, aeb, &ai->erase); | 1542 | ubi_move_aeb_to_list(av, aeb, &ai->erase); |
1432 | else | 1543 | } else { |
1433 | vol->eba_tbl[aeb->lnum] = aeb->pnum; | 1544 | struct ubi_eba_entry *entry; |
1545 | |||
1546 | entry = &vol->eba_tbl->entries[aeb->lnum]; | ||
1547 | entry->pnum = aeb->pnum; | ||
1548 | } | ||
1434 | } | 1549 | } |
1435 | } | 1550 | } |
1436 | 1551 | ||
@@ -1467,8 +1582,7 @@ out_free: | |||
1467 | for (i = 0; i < num_volumes; i++) { | 1582 | for (i = 0; i < num_volumes; i++) { |
1468 | if (!ubi->volumes[i]) | 1583 | if (!ubi->volumes[i]) |
1469 | continue; | 1584 | continue; |
1470 | kfree(ubi->volumes[i]->eba_tbl); | 1585 | ubi_eba_replace_table(ubi->volumes[i], NULL); |
1471 | ubi->volumes[i]->eba_tbl = NULL; | ||
1472 | } | 1586 | } |
1473 | return err; | 1587 | return err; |
1474 | } | 1588 | } |
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 98e5dac677ee..bc145229a53c 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
@@ -359,7 +359,7 @@ struct ubi_volume { | |||
359 | long long upd_received; | 359 | long long upd_received; |
360 | void *upd_buf; | 360 | void *upd_buf; |
361 | 361 | ||
362 | int *eba_tbl; | 362 | struct ubi_eba_table *eba_tbl; |
363 | unsigned int checked:1; | 363 | unsigned int checked:1; |
364 | unsigned int corrupted:1; | 364 | unsigned int corrupted:1; |
365 | unsigned int upd_marker:1; | 365 | unsigned int upd_marker:1; |
@@ -864,6 +864,12 @@ static inline bool ubi_leb_valid(struct ubi_volume *vol, int lnum) | |||
864 | } | 864 | } |
865 | 865 | ||
866 | /* eba.c */ | 866 | /* eba.c */ |
867 | struct ubi_eba_table *ubi_eba_create_table(struct ubi_volume *vol, | ||
868 | int nentries); | ||
869 | void ubi_eba_destroy_table(struct ubi_eba_table *tbl); | ||
870 | void ubi_eba_copy_table(struct ubi_volume *vol, struct ubi_eba_table *dst, | ||
871 | int nentries); | ||
872 | void ubi_eba_replace_table(struct ubi_volume *vol, struct ubi_eba_table *tbl); | ||
867 | void ubi_eba_get_ldesc(struct ubi_volume *vol, int lnum, | 873 | void ubi_eba_get_ldesc(struct ubi_volume *vol, int lnum, |
868 | struct ubi_eba_leb_desc *ldesc); | 874 | struct ubi_eba_leb_desc *ldesc); |
869 | bool ubi_eba_is_mapped(struct ubi_volume *vol, int lnum); | 875 | bool ubi_eba_is_mapped(struct ubi_volume *vol, int lnum); |
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 0138f526474a..7ac78c13dd1c 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c | |||
@@ -138,7 +138,7 @@ static void vol_release(struct device *dev) | |||
138 | { | 138 | { |
139 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); | 139 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); |
140 | 140 | ||
141 | kfree(vol->eba_tbl); | 141 | ubi_eba_replace_table(vol, NULL); |
142 | kfree(vol); | 142 | kfree(vol); |
143 | } | 143 | } |
144 | 144 | ||
@@ -158,6 +158,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
158 | int i, err, vol_id = req->vol_id, do_free = 1; | 158 | int i, err, vol_id = req->vol_id, do_free = 1; |
159 | struct ubi_volume *vol; | 159 | struct ubi_volume *vol; |
160 | struct ubi_vtbl_record vtbl_rec; | 160 | struct ubi_vtbl_record vtbl_rec; |
161 | struct ubi_eba_table *eba_tbl = NULL; | ||
161 | dev_t dev; | 162 | dev_t dev; |
162 | 163 | ||
163 | if (ubi->ro_mode) | 164 | if (ubi->ro_mode) |
@@ -241,14 +242,13 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
241 | if (err) | 242 | if (err) |
242 | goto out_acc; | 243 | goto out_acc; |
243 | 244 | ||
244 | vol->eba_tbl = kmalloc(vol->reserved_pebs * sizeof(int), GFP_KERNEL); | 245 | eba_tbl = ubi_eba_create_table(vol, vol->reserved_pebs); |
245 | if (!vol->eba_tbl) { | 246 | if (IS_ERR(eba_tbl)) { |
246 | err = -ENOMEM; | 247 | err = PTR_ERR(eba_tbl); |
247 | goto out_acc; | 248 | goto out_acc; |
248 | } | 249 | } |
249 | 250 | ||
250 | for (i = 0; i < vol->reserved_pebs; i++) | 251 | ubi_eba_replace_table(vol, eba_tbl); |
251 | vol->eba_tbl[i] = UBI_LEB_UNMAPPED; | ||
252 | 252 | ||
253 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { | 253 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { |
254 | vol->used_ebs = vol->reserved_pebs; | 254 | vol->used_ebs = vol->reserved_pebs; |
@@ -329,7 +329,7 @@ out_cdev: | |||
329 | cdev_del(&vol->cdev); | 329 | cdev_del(&vol->cdev); |
330 | out_mapping: | 330 | out_mapping: |
331 | if (do_free) | 331 | if (do_free) |
332 | kfree(vol->eba_tbl); | 332 | ubi_eba_destroy_table(eba_tbl); |
333 | out_acc: | 333 | out_acc: |
334 | spin_lock(&ubi->volumes_lock); | 334 | spin_lock(&ubi->volumes_lock); |
335 | ubi->rsvd_pebs -= vol->reserved_pebs; | 335 | ubi->rsvd_pebs -= vol->reserved_pebs; |
@@ -427,10 +427,11 @@ out_unlock: | |||
427 | */ | 427 | */ |
428 | int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | 428 | int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) |
429 | { | 429 | { |
430 | int i, err, pebs, *new_mapping; | 430 | int i, err, pebs; |
431 | struct ubi_volume *vol = desc->vol; | 431 | struct ubi_volume *vol = desc->vol; |
432 | struct ubi_device *ubi = vol->ubi; | 432 | struct ubi_device *ubi = vol->ubi; |
433 | struct ubi_vtbl_record vtbl_rec; | 433 | struct ubi_vtbl_record vtbl_rec; |
434 | struct ubi_eba_table *new_eba_tbl = NULL; | ||
434 | int vol_id = vol->vol_id; | 435 | int vol_id = vol->vol_id; |
435 | 436 | ||
436 | if (ubi->ro_mode) | 437 | if (ubi->ro_mode) |
@@ -450,12 +451,9 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
450 | if (reserved_pebs == vol->reserved_pebs) | 451 | if (reserved_pebs == vol->reserved_pebs) |
451 | return 0; | 452 | return 0; |
452 | 453 | ||
453 | new_mapping = kmalloc(reserved_pebs * sizeof(int), GFP_KERNEL); | 454 | new_eba_tbl = ubi_eba_create_table(vol, reserved_pebs); |
454 | if (!new_mapping) | 455 | if (IS_ERR(new_eba_tbl)) |
455 | return -ENOMEM; | 456 | return PTR_ERR(new_eba_tbl); |
456 | |||
457 | for (i = 0; i < reserved_pebs; i++) | ||
458 | new_mapping[i] = UBI_LEB_UNMAPPED; | ||
459 | 457 | ||
460 | spin_lock(&ubi->volumes_lock); | 458 | spin_lock(&ubi->volumes_lock); |
461 | if (vol->ref_count > 1) { | 459 | if (vol->ref_count > 1) { |
@@ -481,10 +479,8 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
481 | } | 479 | } |
482 | ubi->avail_pebs -= pebs; | 480 | ubi->avail_pebs -= pebs; |
483 | ubi->rsvd_pebs += pebs; | 481 | ubi->rsvd_pebs += pebs; |
484 | for (i = 0; i < vol->reserved_pebs; i++) | 482 | ubi_eba_copy_table(vol, new_eba_tbl, vol->reserved_pebs); |
485 | new_mapping[i] = vol->eba_tbl[i]; | 483 | ubi_eba_replace_table(vol, new_eba_tbl); |
486 | kfree(vol->eba_tbl); | ||
487 | vol->eba_tbl = new_mapping; | ||
488 | spin_unlock(&ubi->volumes_lock); | 484 | spin_unlock(&ubi->volumes_lock); |
489 | } | 485 | } |
490 | 486 | ||
@@ -498,10 +494,8 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
498 | ubi->rsvd_pebs += pebs; | 494 | ubi->rsvd_pebs += pebs; |
499 | ubi->avail_pebs -= pebs; | 495 | ubi->avail_pebs -= pebs; |
500 | ubi_update_reserved(ubi); | 496 | ubi_update_reserved(ubi); |
501 | for (i = 0; i < reserved_pebs; i++) | 497 | ubi_eba_copy_table(vol, new_eba_tbl, reserved_pebs); |
502 | new_mapping[i] = vol->eba_tbl[i]; | 498 | ubi_eba_replace_table(vol, new_eba_tbl); |
503 | kfree(vol->eba_tbl); | ||
504 | vol->eba_tbl = new_mapping; | ||
505 | spin_unlock(&ubi->volumes_lock); | 499 | spin_unlock(&ubi->volumes_lock); |
506 | } | 500 | } |
507 | 501 | ||
@@ -543,7 +537,7 @@ out_acc: | |||
543 | spin_unlock(&ubi->volumes_lock); | 537 | spin_unlock(&ubi->volumes_lock); |
544 | } | 538 | } |
545 | out_free: | 539 | out_free: |
546 | kfree(new_mapping); | 540 | kfree(new_eba_tbl); |
547 | return err; | 541 | return err; |
548 | } | 542 | } |
549 | 543 | ||