diff options
Diffstat (limited to 'drivers/mtd/ubi/vmt.c')
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 148 |
1 files changed, 95 insertions, 53 deletions
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 5be58d85c639..3531ca9a1e24 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c | |||
@@ -28,9 +28,9 @@ | |||
28 | #include "ubi.h" | 28 | #include "ubi.h" |
29 | 29 | ||
30 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | 30 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID |
31 | static void paranoid_check_volumes(struct ubi_device *ubi); | 31 | static int paranoid_check_volumes(struct ubi_device *ubi); |
32 | #else | 32 | #else |
33 | #define paranoid_check_volumes(ubi) | 33 | #define paranoid_check_volumes(ubi) 0 |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | static ssize_t vol_attribute_show(struct device *dev, | 36 | static ssize_t vol_attribute_show(struct device *dev, |
@@ -127,6 +127,7 @@ static void vol_release(struct device *dev) | |||
127 | { | 127 | { |
128 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); | 128 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); |
129 | 129 | ||
130 | kfree(vol->eba_tbl); | ||
130 | kfree(vol); | 131 | kfree(vol); |
131 | } | 132 | } |
132 | 133 | ||
@@ -201,7 +202,7 @@ static void volume_sysfs_close(struct ubi_volume *vol) | |||
201 | */ | 202 | */ |
202 | int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | 203 | int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) |
203 | { | 204 | { |
204 | int i, err, vol_id = req->vol_id, dont_free = 0; | 205 | int i, err, vol_id = req->vol_id, do_free = 1; |
205 | struct ubi_volume *vol; | 206 | struct ubi_volume *vol; |
206 | struct ubi_vtbl_record vtbl_rec; | 207 | struct ubi_vtbl_record vtbl_rec; |
207 | uint64_t bytes; | 208 | uint64_t bytes; |
@@ -217,7 +218,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
217 | spin_lock(&ubi->volumes_lock); | 218 | spin_lock(&ubi->volumes_lock); |
218 | if (vol_id == UBI_VOL_NUM_AUTO) { | 219 | if (vol_id == UBI_VOL_NUM_AUTO) { |
219 | /* Find unused volume ID */ | 220 | /* Find unused volume ID */ |
220 | dbg_msg("search for vacant volume ID"); | 221 | dbg_gen("search for vacant volume ID"); |
221 | for (i = 0; i < ubi->vtbl_slots; i++) | 222 | for (i = 0; i < ubi->vtbl_slots; i++) |
222 | if (!ubi->volumes[i]) { | 223 | if (!ubi->volumes[i]) { |
223 | vol_id = i; | 224 | vol_id = i; |
@@ -232,7 +233,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
232 | req->vol_id = vol_id; | 233 | req->vol_id = vol_id; |
233 | } | 234 | } |
234 | 235 | ||
235 | dbg_msg("volume ID %d, %llu bytes, type %d, name %s", | 236 | dbg_gen("volume ID %d, %llu bytes, type %d, name %s", |
236 | vol_id, (unsigned long long)req->bytes, | 237 | vol_id, (unsigned long long)req->bytes, |
237 | (int)req->vol_type, req->name); | 238 | (int)req->vol_type, req->name); |
238 | 239 | ||
@@ -252,7 +253,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
252 | goto out_unlock; | 253 | goto out_unlock; |
253 | } | 254 | } |
254 | 255 | ||
255 | /* Calculate how many eraseblocks are requested */ | 256 | /* Calculate how many eraseblocks are requested */ |
256 | vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment; | 257 | vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment; |
257 | bytes = req->bytes; | 258 | bytes = req->bytes; |
258 | if (do_div(bytes, vol->usable_leb_size)) | 259 | if (do_div(bytes, vol->usable_leb_size)) |
@@ -274,7 +275,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
274 | vol->data_pad = ubi->leb_size % vol->alignment; | 275 | vol->data_pad = ubi->leb_size % vol->alignment; |
275 | vol->vol_type = req->vol_type; | 276 | vol->vol_type = req->vol_type; |
276 | vol->name_len = req->name_len; | 277 | vol->name_len = req->name_len; |
277 | memcpy(vol->name, req->name, vol->name_len + 1); | 278 | memcpy(vol->name, req->name, vol->name_len); |
278 | vol->ubi = ubi; | 279 | vol->ubi = ubi; |
279 | 280 | ||
280 | /* | 281 | /* |
@@ -349,7 +350,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
349 | vtbl_rec.vol_type = UBI_VID_DYNAMIC; | 350 | vtbl_rec.vol_type = UBI_VID_DYNAMIC; |
350 | else | 351 | else |
351 | vtbl_rec.vol_type = UBI_VID_STATIC; | 352 | vtbl_rec.vol_type = UBI_VID_STATIC; |
352 | memcpy(vtbl_rec.name, vol->name, vol->name_len + 1); | 353 | memcpy(vtbl_rec.name, vol->name, vol->name_len); |
353 | 354 | ||
354 | err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); | 355 | err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); |
355 | if (err) | 356 | if (err) |
@@ -360,19 +361,19 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
360 | ubi->vol_count += 1; | 361 | ubi->vol_count += 1; |
361 | spin_unlock(&ubi->volumes_lock); | 362 | spin_unlock(&ubi->volumes_lock); |
362 | 363 | ||
363 | paranoid_check_volumes(ubi); | 364 | err = paranoid_check_volumes(ubi); |
364 | return 0; | 365 | return err; |
365 | 366 | ||
366 | out_sysfs: | 367 | out_sysfs: |
367 | /* | 368 | /* |
368 | * We have registered our device, we should not free the volume* | 369 | * We have registered our device, we should not free the volume |
369 | * description object in this function in case of an error - it is | 370 | * description object in this function in case of an error - it is |
370 | * freed by the release function. | 371 | * freed by the release function. |
371 | * | 372 | * |
372 | * Get device reference to prevent the release function from being | 373 | * Get device reference to prevent the release function from being |
373 | * called just after sysfs has been closed. | 374 | * called just after sysfs has been closed. |
374 | */ | 375 | */ |
375 | dont_free = 1; | 376 | do_free = 0; |
376 | get_device(&vol->dev); | 377 | get_device(&vol->dev); |
377 | volume_sysfs_close(vol); | 378 | volume_sysfs_close(vol); |
378 | out_gluebi: | 379 | out_gluebi: |
@@ -382,17 +383,18 @@ out_gluebi: | |||
382 | out_cdev: | 383 | out_cdev: |
383 | cdev_del(&vol->cdev); | 384 | cdev_del(&vol->cdev); |
384 | out_mapping: | 385 | out_mapping: |
385 | kfree(vol->eba_tbl); | 386 | if (do_free) |
387 | kfree(vol->eba_tbl); | ||
386 | out_acc: | 388 | out_acc: |
387 | spin_lock(&ubi->volumes_lock); | 389 | spin_lock(&ubi->volumes_lock); |
388 | ubi->rsvd_pebs -= vol->reserved_pebs; | 390 | ubi->rsvd_pebs -= vol->reserved_pebs; |
389 | ubi->avail_pebs += vol->reserved_pebs; | 391 | ubi->avail_pebs += vol->reserved_pebs; |
390 | out_unlock: | 392 | out_unlock: |
391 | spin_unlock(&ubi->volumes_lock); | 393 | spin_unlock(&ubi->volumes_lock); |
392 | if (dont_free) | 394 | if (do_free) |
393 | put_device(&vol->dev); | ||
394 | else | ||
395 | kfree(vol); | 395 | kfree(vol); |
396 | else | ||
397 | put_device(&vol->dev); | ||
396 | ubi_err("cannot create volume %d, error %d", vol_id, err); | 398 | ubi_err("cannot create volume %d, error %d", vol_id, err); |
397 | return err; | 399 | return err; |
398 | } | 400 | } |
@@ -400,19 +402,20 @@ out_unlock: | |||
400 | /** | 402 | /** |
401 | * ubi_remove_volume - remove volume. | 403 | * ubi_remove_volume - remove volume. |
402 | * @desc: volume descriptor | 404 | * @desc: volume descriptor |
405 | * @no_vtbl: do not change volume table if not zero | ||
403 | * | 406 | * |
404 | * This function removes volume described by @desc. The volume has to be opened | 407 | * This function removes volume described by @desc. The volume has to be opened |
405 | * in "exclusive" mode. Returns zero in case of success and a negative error | 408 | * in "exclusive" mode. Returns zero in case of success and a negative error |
406 | * code in case of failure. The caller has to have the @ubi->volumes_mutex | 409 | * code in case of failure. The caller has to have the @ubi->volumes_mutex |
407 | * locked. | 410 | * locked. |
408 | */ | 411 | */ |
409 | int ubi_remove_volume(struct ubi_volume_desc *desc) | 412 | int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl) |
410 | { | 413 | { |
411 | struct ubi_volume *vol = desc->vol; | 414 | struct ubi_volume *vol = desc->vol; |
412 | struct ubi_device *ubi = vol->ubi; | 415 | struct ubi_device *ubi = vol->ubi; |
413 | int i, err, vol_id = vol->vol_id, reserved_pebs = vol->reserved_pebs; | 416 | int i, err, vol_id = vol->vol_id, reserved_pebs = vol->reserved_pebs; |
414 | 417 | ||
415 | dbg_msg("remove UBI volume %d", vol_id); | 418 | dbg_gen("remove UBI volume %d", vol_id); |
416 | ubi_assert(desc->mode == UBI_EXCLUSIVE); | 419 | ubi_assert(desc->mode == UBI_EXCLUSIVE); |
417 | ubi_assert(vol == ubi->volumes[vol_id]); | 420 | ubi_assert(vol == ubi->volumes[vol_id]); |
418 | 421 | ||
@@ -435,9 +438,11 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) | |||
435 | if (err) | 438 | if (err) |
436 | goto out_err; | 439 | goto out_err; |
437 | 440 | ||
438 | err = ubi_change_vtbl_record(ubi, vol_id, NULL); | 441 | if (!no_vtbl) { |
439 | if (err) | 442 | err = ubi_change_vtbl_record(ubi, vol_id, NULL); |
440 | goto out_err; | 443 | if (err) |
444 | goto out_err; | ||
445 | } | ||
441 | 446 | ||
442 | for (i = 0; i < vol->reserved_pebs; i++) { | 447 | for (i = 0; i < vol->reserved_pebs; i++) { |
443 | err = ubi_eba_unmap_leb(ubi, vol, i); | 448 | err = ubi_eba_unmap_leb(ubi, vol, i); |
@@ -445,8 +450,6 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) | |||
445 | goto out_err; | 450 | goto out_err; |
446 | } | 451 | } |
447 | 452 | ||
448 | kfree(vol->eba_tbl); | ||
449 | vol->eba_tbl = NULL; | ||
450 | cdev_del(&vol->cdev); | 453 | cdev_del(&vol->cdev); |
451 | volume_sysfs_close(vol); | 454 | volume_sysfs_close(vol); |
452 | 455 | ||
@@ -465,8 +468,9 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) | |||
465 | ubi->vol_count -= 1; | 468 | ubi->vol_count -= 1; |
466 | spin_unlock(&ubi->volumes_lock); | 469 | spin_unlock(&ubi->volumes_lock); |
467 | 470 | ||
468 | paranoid_check_volumes(ubi); | 471 | if (!no_vtbl) |
469 | return 0; | 472 | err = paranoid_check_volumes(ubi); |
473 | return err; | ||
470 | 474 | ||
471 | out_err: | 475 | out_err: |
472 | ubi_err("cannot remove volume %d, error %d", vol_id, err); | 476 | ubi_err("cannot remove volume %d, error %d", vol_id, err); |
@@ -497,7 +501,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
497 | if (ubi->ro_mode) | 501 | if (ubi->ro_mode) |
498 | return -EROFS; | 502 | return -EROFS; |
499 | 503 | ||
500 | dbg_msg("re-size volume %d to from %d to %d PEBs", | 504 | dbg_gen("re-size volume %d to from %d to %d PEBs", |
501 | vol_id, vol->reserved_pebs, reserved_pebs); | 505 | vol_id, vol->reserved_pebs, reserved_pebs); |
502 | 506 | ||
503 | if (vol->vol_type == UBI_STATIC_VOLUME && | 507 | if (vol->vol_type == UBI_STATIC_VOLUME && |
@@ -586,8 +590,8 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
586 | (long long)vol->used_ebs * vol->usable_leb_size; | 590 | (long long)vol->used_ebs * vol->usable_leb_size; |
587 | } | 591 | } |
588 | 592 | ||
589 | paranoid_check_volumes(ubi); | 593 | err = paranoid_check_volumes(ubi); |
590 | return 0; | 594 | return err; |
591 | 595 | ||
592 | out_acc: | 596 | out_acc: |
593 | if (pebs > 0) { | 597 | if (pebs > 0) { |
@@ -602,6 +606,44 @@ out_free: | |||
602 | } | 606 | } |
603 | 607 | ||
604 | /** | 608 | /** |
609 | * ubi_rename_volumes - re-name UBI volumes. | ||
610 | * @ubi: UBI device description object | ||
611 | * @rename_list: list of &struct ubi_rename_entry objects | ||
612 | * | ||
613 | * This function re-names or removes volumes specified in the re-name list. | ||
614 | * Returns zero in case of success and a negative error code in case of | ||
615 | * failure. | ||
616 | */ | ||
617 | int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list) | ||
618 | { | ||
619 | int err; | ||
620 | struct ubi_rename_entry *re; | ||
621 | |||
622 | err = ubi_vtbl_rename_volumes(ubi, rename_list); | ||
623 | if (err) | ||
624 | return err; | ||
625 | |||
626 | list_for_each_entry(re, rename_list, list) { | ||
627 | if (re->remove) { | ||
628 | err = ubi_remove_volume(re->desc, 1); | ||
629 | if (err) | ||
630 | break; | ||
631 | } else { | ||
632 | struct ubi_volume *vol = re->desc->vol; | ||
633 | |||
634 | spin_lock(&ubi->volumes_lock); | ||
635 | vol->name_len = re->new_name_len; | ||
636 | memcpy(vol->name, re->new_name, re->new_name_len + 1); | ||
637 | spin_unlock(&ubi->volumes_lock); | ||
638 | } | ||
639 | } | ||
640 | |||
641 | if (!err) | ||
642 | err = paranoid_check_volumes(ubi); | ||
643 | return err; | ||
644 | } | ||
645 | |||
646 | /** | ||
605 | * ubi_add_volume - add volume. | 647 | * ubi_add_volume - add volume. |
606 | * @ubi: UBI device description object | 648 | * @ubi: UBI device description object |
607 | * @vol: volume description object | 649 | * @vol: volume description object |
@@ -615,8 +657,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) | |||
615 | int err, vol_id = vol->vol_id; | 657 | int err, vol_id = vol->vol_id; |
616 | dev_t dev; | 658 | dev_t dev; |
617 | 659 | ||
618 | dbg_msg("add volume %d", vol_id); | 660 | dbg_gen("add volume %d", vol_id); |
619 | ubi_dbg_dump_vol_info(vol); | ||
620 | 661 | ||
621 | /* Register character device for the volume */ | 662 | /* Register character device for the volume */ |
622 | cdev_init(&vol->cdev, &ubi_vol_cdev_operations); | 663 | cdev_init(&vol->cdev, &ubi_vol_cdev_operations); |
@@ -650,8 +691,8 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) | |||
650 | return err; | 691 | return err; |
651 | } | 692 | } |
652 | 693 | ||
653 | paranoid_check_volumes(ubi); | 694 | err = paranoid_check_volumes(ubi); |
654 | return 0; | 695 | return err; |
655 | 696 | ||
656 | out_gluebi: | 697 | out_gluebi: |
657 | err = ubi_destroy_gluebi(vol); | 698 | err = ubi_destroy_gluebi(vol); |
@@ -672,7 +713,7 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) | |||
672 | { | 713 | { |
673 | int err; | 714 | int err; |
674 | 715 | ||
675 | dbg_msg("free volume %d", vol->vol_id); | 716 | dbg_gen("free volume %d", vol->vol_id); |
676 | 717 | ||
677 | ubi->volumes[vol->vol_id] = NULL; | 718 | ubi->volumes[vol->vol_id] = NULL; |
678 | err = ubi_destroy_gluebi(vol); | 719 | err = ubi_destroy_gluebi(vol); |
@@ -686,8 +727,10 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) | |||
686 | * paranoid_check_volume - check volume information. | 727 | * paranoid_check_volume - check volume information. |
687 | * @ubi: UBI device description object | 728 | * @ubi: UBI device description object |
688 | * @vol_id: volume ID | 729 | * @vol_id: volume ID |
730 | * | ||
731 | * Returns zero if volume is all right and a a negative error code if not. | ||
689 | */ | 732 | */ |
690 | static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | 733 | static int paranoid_check_volume(struct ubi_device *ubi, int vol_id) |
691 | { | 734 | { |
692 | int idx = vol_id2idx(ubi, vol_id); | 735 | int idx = vol_id2idx(ubi, vol_id); |
693 | int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker; | 736 | int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker; |
@@ -705,16 +748,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | |||
705 | goto fail; | 748 | goto fail; |
706 | } | 749 | } |
707 | spin_unlock(&ubi->volumes_lock); | 750 | spin_unlock(&ubi->volumes_lock); |
708 | return; | 751 | return 0; |
709 | } | ||
710 | |||
711 | if (vol->exclusive) { | ||
712 | /* | ||
713 | * The volume may be being created at the moment, do not check | ||
714 | * it (e.g., it may be in the middle of ubi_create_volume(). | ||
715 | */ | ||
716 | spin_unlock(&ubi->volumes_lock); | ||
717 | return; | ||
718 | } | 752 | } |
719 | 753 | ||
720 | if (vol->reserved_pebs < 0 || vol->alignment < 0 || vol->data_pad < 0 || | 754 | if (vol->reserved_pebs < 0 || vol->alignment < 0 || vol->data_pad < 0 || |
@@ -727,7 +761,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | |||
727 | goto fail; | 761 | goto fail; |
728 | } | 762 | } |
729 | 763 | ||
730 | n = vol->alignment % ubi->min_io_size; | 764 | n = vol->alignment & (ubi->min_io_size - 1); |
731 | if (vol->alignment != 1 && n) { | 765 | if (vol->alignment != 1 && n) { |
732 | ubi_err("alignment is not multiple of min I/O unit"); | 766 | ubi_err("alignment is not multiple of min I/O unit"); |
733 | goto fail; | 767 | goto fail; |
@@ -824,31 +858,39 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | |||
824 | 858 | ||
825 | if (alignment != vol->alignment || data_pad != vol->data_pad || | 859 | if (alignment != vol->alignment || data_pad != vol->data_pad || |
826 | upd_marker != vol->upd_marker || vol_type != vol->vol_type || | 860 | upd_marker != vol->upd_marker || vol_type != vol->vol_type || |
827 | name_len!= vol->name_len || strncmp(name, vol->name, name_len)) { | 861 | name_len != vol->name_len || strncmp(name, vol->name, name_len)) { |
828 | ubi_err("volume info is different"); | 862 | ubi_err("volume info is different"); |
829 | goto fail; | 863 | goto fail; |
830 | } | 864 | } |
831 | 865 | ||
832 | spin_unlock(&ubi->volumes_lock); | 866 | spin_unlock(&ubi->volumes_lock); |
833 | return; | 867 | return 0; |
834 | 868 | ||
835 | fail: | 869 | fail: |
836 | ubi_err("paranoid check failed for volume %d", vol_id); | 870 | ubi_err("paranoid check failed for volume %d", vol_id); |
837 | ubi_dbg_dump_vol_info(vol); | 871 | if (vol) |
872 | ubi_dbg_dump_vol_info(vol); | ||
838 | ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); | 873 | ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); |
839 | spin_unlock(&ubi->volumes_lock); | 874 | spin_unlock(&ubi->volumes_lock); |
840 | BUG(); | 875 | return -EINVAL; |
841 | } | 876 | } |
842 | 877 | ||
843 | /** | 878 | /** |
844 | * paranoid_check_volumes - check information about all volumes. | 879 | * paranoid_check_volumes - check information about all volumes. |
845 | * @ubi: UBI device description object | 880 | * @ubi: UBI device description object |
881 | * | ||
882 | * Returns zero if volumes are all right and a a negative error code if not. | ||
846 | */ | 883 | */ |
847 | static void paranoid_check_volumes(struct ubi_device *ubi) | 884 | static int paranoid_check_volumes(struct ubi_device *ubi) |
848 | { | 885 | { |
849 | int i; | 886 | int i, err = 0; |
850 | 887 | ||
851 | for (i = 0; i < ubi->vtbl_slots; i++) | 888 | for (i = 0; i < ubi->vtbl_slots; i++) { |
852 | paranoid_check_volume(ubi, i); | 889 | err = paranoid_check_volume(ubi, i); |
890 | if (err) | ||
891 | break; | ||
892 | } | ||
893 | |||
894 | return err; | ||
853 | } | 895 | } |
854 | #endif | 896 | #endif |