diff options
Diffstat (limited to 'drivers/mtd/ubi/vmt.c')
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 622d0d18952c..ea0d5c825ab4 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c | |||
@@ -228,7 +228,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
228 | for (i = 0; i < ubi->vtbl_slots; i++) | 228 | for (i = 0; i < ubi->vtbl_slots; i++) |
229 | if (ubi->volumes[i] && | 229 | if (ubi->volumes[i] && |
230 | ubi->volumes[i]->name_len == req->name_len && | 230 | ubi->volumes[i]->name_len == req->name_len && |
231 | strcmp(ubi->volumes[i]->name, req->name) == 0) { | 231 | !strcmp(ubi->volumes[i]->name, req->name)) { |
232 | dbg_err("volume \"%s\" exists (ID %d)", req->name, i); | 232 | dbg_err("volume \"%s\" exists (ID %d)", req->name, i); |
233 | goto out_unlock; | 233 | goto out_unlock; |
234 | } | 234 | } |
@@ -243,7 +243,6 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
243 | /* Reserve physical eraseblocks */ | 243 | /* Reserve physical eraseblocks */ |
244 | if (vol->reserved_pebs > ubi->avail_pebs) { | 244 | if (vol->reserved_pebs > ubi->avail_pebs) { |
245 | dbg_err("not enough PEBs, only %d available", ubi->avail_pebs); | 245 | dbg_err("not enough PEBs, only %d available", ubi->avail_pebs); |
246 | spin_unlock(&ubi->volumes_lock); | ||
247 | err = -ENOSPC; | 246 | err = -ENOSPC; |
248 | goto out_unlock; | 247 | goto out_unlock; |
249 | } | 248 | } |
@@ -281,7 +280,8 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
281 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { | 280 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { |
282 | vol->used_ebs = vol->reserved_pebs; | 281 | vol->used_ebs = vol->reserved_pebs; |
283 | vol->last_eb_bytes = vol->usable_leb_size; | 282 | vol->last_eb_bytes = vol->usable_leb_size; |
284 | vol->used_bytes = vol->used_ebs * vol->usable_leb_size; | 283 | vol->used_bytes = |
284 | (long long)vol->used_ebs * vol->usable_leb_size; | ||
285 | } else { | 285 | } else { |
286 | bytes = vol->used_bytes; | 286 | bytes = vol->used_bytes; |
287 | vol->last_eb_bytes = do_div(bytes, vol->usable_leb_size); | 287 | vol->last_eb_bytes = do_div(bytes, vol->usable_leb_size); |
@@ -320,10 +320,10 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
320 | 320 | ||
321 | /* Fill volume table record */ | 321 | /* Fill volume table record */ |
322 | memset(&vtbl_rec, 0, sizeof(struct ubi_vtbl_record)); | 322 | memset(&vtbl_rec, 0, sizeof(struct ubi_vtbl_record)); |
323 | vtbl_rec.reserved_pebs = cpu_to_ubi32(vol->reserved_pebs); | 323 | vtbl_rec.reserved_pebs = cpu_to_be32(vol->reserved_pebs); |
324 | vtbl_rec.alignment = cpu_to_ubi32(vol->alignment); | 324 | vtbl_rec.alignment = cpu_to_be32(vol->alignment); |
325 | vtbl_rec.data_pad = cpu_to_ubi32(vol->data_pad); | 325 | vtbl_rec.data_pad = cpu_to_be32(vol->data_pad); |
326 | vtbl_rec.name_len = cpu_to_ubi16(vol->name_len); | 326 | vtbl_rec.name_len = cpu_to_be16(vol->name_len); |
327 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) | 327 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) |
328 | vtbl_rec.vol_type = UBI_VID_DYNAMIC; | 328 | vtbl_rec.vol_type = UBI_VID_DYNAMIC; |
329 | else | 329 | else |
@@ -352,6 +352,7 @@ out_acc: | |||
352 | spin_lock(&ubi->volumes_lock); | 352 | spin_lock(&ubi->volumes_lock); |
353 | ubi->rsvd_pebs -= vol->reserved_pebs; | 353 | ubi->rsvd_pebs -= vol->reserved_pebs; |
354 | ubi->avail_pebs += vol->reserved_pebs; | 354 | ubi->avail_pebs += vol->reserved_pebs; |
355 | ubi->volumes[vol_id] = NULL; | ||
355 | out_unlock: | 356 | out_unlock: |
356 | spin_unlock(&ubi->volumes_lock); | 357 | spin_unlock(&ubi->volumes_lock); |
357 | kfree(vol); | 358 | kfree(vol); |
@@ -368,6 +369,7 @@ out_sysfs: | |||
368 | spin_lock(&ubi->volumes_lock); | 369 | spin_lock(&ubi->volumes_lock); |
369 | ubi->rsvd_pebs -= vol->reserved_pebs; | 370 | ubi->rsvd_pebs -= vol->reserved_pebs; |
370 | ubi->avail_pebs += vol->reserved_pebs; | 371 | ubi->avail_pebs += vol->reserved_pebs; |
372 | ubi->volumes[vol_id] = NULL; | ||
371 | spin_unlock(&ubi->volumes_lock); | 373 | spin_unlock(&ubi->volumes_lock); |
372 | volume_sysfs_close(vol); | 374 | volume_sysfs_close(vol); |
373 | return err; | 375 | return err; |
@@ -503,7 +505,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
503 | 505 | ||
504 | /* Change volume table record */ | 506 | /* Change volume table record */ |
505 | memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record)); | 507 | memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record)); |
506 | vtbl_rec.reserved_pebs = cpu_to_ubi32(reserved_pebs); | 508 | vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs); |
507 | err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); | 509 | err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); |
508 | if (err) | 510 | if (err) |
509 | goto out_acc; | 511 | goto out_acc; |
@@ -537,7 +539,8 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
537 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { | 539 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { |
538 | vol->used_ebs = reserved_pebs; | 540 | vol->used_ebs = reserved_pebs; |
539 | vol->last_eb_bytes = vol->usable_leb_size; | 541 | vol->last_eb_bytes = vol->usable_leb_size; |
540 | vol->used_bytes = vol->used_ebs * vol->usable_leb_size; | 542 | vol->used_bytes = |
543 | (long long)vol->used_ebs * vol->usable_leb_size; | ||
541 | } | 544 | } |
542 | 545 | ||
543 | paranoid_check_volumes(ubi); | 546 | paranoid_check_volumes(ubi); |
@@ -643,21 +646,33 @@ void ubi_free_volume(struct ubi_device *ubi, int vol_id) | |||
643 | * @ubi: UBI device description object | 646 | * @ubi: UBI device description object |
644 | * @vol_id: volume ID | 647 | * @vol_id: volume ID |
645 | */ | 648 | */ |
646 | static void paranoid_check_volume(const struct ubi_device *ubi, int vol_id) | 649 | static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) |
647 | { | 650 | { |
648 | int idx = vol_id2idx(ubi, vol_id); | 651 | int idx = vol_id2idx(ubi, vol_id); |
649 | int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker; | 652 | int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker; |
650 | const struct ubi_volume *vol = ubi->volumes[idx]; | 653 | const struct ubi_volume *vol; |
651 | long long n; | 654 | long long n; |
652 | const char *name; | 655 | const char *name; |
653 | 656 | ||
654 | reserved_pebs = ubi32_to_cpu(ubi->vtbl[vol_id].reserved_pebs); | 657 | spin_lock(&ubi->volumes_lock); |
658 | reserved_pebs = be32_to_cpu(ubi->vtbl[vol_id].reserved_pebs); | ||
659 | vol = ubi->volumes[idx]; | ||
655 | 660 | ||
656 | if (!vol) { | 661 | if (!vol) { |
657 | if (reserved_pebs) { | 662 | if (reserved_pebs) { |
658 | ubi_err("no volume info, but volume exists"); | 663 | ubi_err("no volume info, but volume exists"); |
659 | goto fail; | 664 | goto fail; |
660 | } | 665 | } |
666 | spin_unlock(&ubi->volumes_lock); | ||
667 | return; | ||
668 | } | ||
669 | |||
670 | if (vol->exclusive) { | ||
671 | /* | ||
672 | * The volume may be being created at the moment, do not check | ||
673 | * it (e.g., it may be in the middle of ubi_create_volume(). | ||
674 | */ | ||
675 | spin_unlock(&ubi->volumes_lock); | ||
661 | return; | 676 | return; |
662 | } | 677 | } |
663 | 678 | ||
@@ -726,7 +741,7 @@ static void paranoid_check_volume(const struct ubi_device *ubi, int vol_id) | |||
726 | goto fail; | 741 | goto fail; |
727 | } | 742 | } |
728 | 743 | ||
729 | n = vol->used_ebs * vol->usable_leb_size; | 744 | n = (long long)vol->used_ebs * vol->usable_leb_size; |
730 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { | 745 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { |
731 | if (vol->corrupted != 0) { | 746 | if (vol->corrupted != 0) { |
732 | ubi_err("corrupted dynamic volume"); | 747 | ubi_err("corrupted dynamic volume"); |
@@ -765,9 +780,9 @@ static void paranoid_check_volume(const struct ubi_device *ubi, int vol_id) | |||
765 | } | 780 | } |
766 | } | 781 | } |
767 | 782 | ||
768 | alignment = ubi32_to_cpu(ubi->vtbl[vol_id].alignment); | 783 | alignment = be32_to_cpu(ubi->vtbl[vol_id].alignment); |
769 | data_pad = ubi32_to_cpu(ubi->vtbl[vol_id].data_pad); | 784 | data_pad = be32_to_cpu(ubi->vtbl[vol_id].data_pad); |
770 | name_len = ubi16_to_cpu(ubi->vtbl[vol_id].name_len); | 785 | name_len = be16_to_cpu(ubi->vtbl[vol_id].name_len); |
771 | upd_marker = ubi->vtbl[vol_id].upd_marker; | 786 | upd_marker = ubi->vtbl[vol_id].upd_marker; |
772 | name = &ubi->vtbl[vol_id].name[0]; | 787 | name = &ubi->vtbl[vol_id].name[0]; |
773 | if (ubi->vtbl[vol_id].vol_type == UBI_VID_DYNAMIC) | 788 | if (ubi->vtbl[vol_id].vol_type == UBI_VID_DYNAMIC) |
@@ -782,12 +797,14 @@ static void paranoid_check_volume(const struct ubi_device *ubi, int vol_id) | |||
782 | goto fail; | 797 | goto fail; |
783 | } | 798 | } |
784 | 799 | ||
800 | spin_unlock(&ubi->volumes_lock); | ||
785 | return; | 801 | return; |
786 | 802 | ||
787 | fail: | 803 | fail: |
788 | ubi_err("paranoid check failed"); | 804 | ubi_err("paranoid check failed for volume %d", vol_id); |
789 | ubi_dbg_dump_vol_info(vol); | 805 | ubi_dbg_dump_vol_info(vol); |
790 | ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); | 806 | ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); |
807 | spin_unlock(&ubi->volumes_lock); | ||
791 | BUG(); | 808 | BUG(); |
792 | } | 809 | } |
793 | 810 | ||
@@ -800,10 +817,8 @@ static void paranoid_check_volumes(struct ubi_device *ubi) | |||
800 | int i; | 817 | int i; |
801 | 818 | ||
802 | mutex_lock(&ubi->vtbl_mutex); | 819 | mutex_lock(&ubi->vtbl_mutex); |
803 | spin_lock(&ubi->volumes_lock); | ||
804 | for (i = 0; i < ubi->vtbl_slots; i++) | 820 | for (i = 0; i < ubi->vtbl_slots; i++) |
805 | paranoid_check_volume(ubi, i); | 821 | paranoid_check_volume(ubi, i); |
806 | spin_unlock(&ubi->volumes_lock); | ||
807 | mutex_unlock(&ubi->vtbl_mutex); | 822 | mutex_unlock(&ubi->vtbl_mutex); |
808 | } | 823 | } |
809 | #endif | 824 | #endif |