diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-07-13 14:47:47 -0400 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-07-24 06:34:46 -0400 |
commit | f40ac9cdf6991287f19bdafe9b0752ee40137908 (patch) | |
tree | a49120d5be3729feaa40880962f29e3679c1800e /drivers/mtd/ubi/vmt.c | |
parent | c8566350a3229ca505b84313c65d1403b4d0cbfc (diff) |
UBI: implement multiple volumes rename
Quite useful ioctl which allows to make atomic system upgrades.
The idea belongs to Richard Titmuss <richard_titmuss@logitech.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers/mtd/ubi/vmt.c')
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 2cd886a5adac..4be4014c70df 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c | |||
@@ -402,13 +402,14 @@ out_unlock: | |||
402 | /** | 402 | /** |
403 | * ubi_remove_volume - remove volume. | 403 | * ubi_remove_volume - remove volume. |
404 | * @desc: volume descriptor | 404 | * @desc: volume descriptor |
405 | * @no_vtbl: do not change volume table if not zero | ||
405 | * | 406 | * |
406 | * 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 |
407 | * 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 |
408 | * 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 |
409 | * locked. | 410 | * locked. |
410 | */ | 411 | */ |
411 | int ubi_remove_volume(struct ubi_volume_desc *desc) | 412 | int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl) |
412 | { | 413 | { |
413 | struct ubi_volume *vol = desc->vol; | 414 | struct ubi_volume *vol = desc->vol; |
414 | struct ubi_device *ubi = vol->ubi; | 415 | struct ubi_device *ubi = vol->ubi; |
@@ -437,9 +438,11 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) | |||
437 | if (err) | 438 | if (err) |
438 | goto out_err; | 439 | goto out_err; |
439 | 440 | ||
440 | err = ubi_change_vtbl_record(ubi, vol_id, NULL); | 441 | if (!no_vtbl) { |
441 | if (err) | 442 | err = ubi_change_vtbl_record(ubi, vol_id, NULL); |
442 | goto out_err; | 443 | if (err) |
444 | goto out_err; | ||
445 | } | ||
443 | 446 | ||
444 | for (i = 0; i < vol->reserved_pebs; i++) { | 447 | for (i = 0; i < vol->reserved_pebs; i++) { |
445 | err = ubi_eba_unmap_leb(ubi, vol, i); | 448 | err = ubi_eba_unmap_leb(ubi, vol, i); |
@@ -465,7 +468,8 @@ 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 | err = paranoid_check_volumes(ubi); | 471 | if (!no_vtbl) |
472 | err = paranoid_check_volumes(ubi); | ||
469 | return err; | 473 | return err; |
470 | 474 | ||
471 | out_err: | 475 | out_err: |
@@ -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 | * @renam_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 | 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 |
@@ -826,10 +868,9 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id) | |||
826 | 868 | ||
827 | fail: | 869 | fail: |
828 | ubi_err("paranoid check failed for volume %d", vol_id); | 870 | ubi_err("paranoid check failed for volume %d", vol_id); |
829 | if (vol) { | 871 | if (vol) |
830 | ubi_dbg_dump_vol_info(vol); | 872 | ubi_dbg_dump_vol_info(vol); |
831 | ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); | 873 | ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); |
832 | } | ||
833 | spin_unlock(&ubi->volumes_lock); | 874 | spin_unlock(&ubi->volumes_lock); |
834 | return -EINVAL; | 875 | return -EINVAL; |
835 | } | 876 | } |