diff options
author | Heinz Mauelshagen <heinzm@redhat.com> | 2016-06-29 12:13:58 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2016-07-18 15:37:31 -0400 |
commit | 469b304b58c417874a68630c5f58cf076a34850c (patch) | |
tree | 2c4b5c36e71b2addd5fdb0e8cce1f5f25e631f5b /drivers/md/dm-raid.c | |
parent | 2a5556c2a86f77ff6085f2cae798728cda47e2c4 (diff) |
dm raid: enhance reshape check and factor out reshape setup
Enhance rs_reshape_requested() check function to be more transparent and
fix its raid10 check.
Streamline the constructor by factoring out reshaping preparation into
fucntion rs_prepare_reshape().
Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-raid.c')
-rw-r--r-- | drivers/md/dm-raid.c | 167 |
1 files changed, 106 insertions, 61 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 846c58d2bcf9..473c6d9765f0 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -1700,16 +1700,30 @@ static bool rs_takeover_requested(struct raid_set *rs) | |||
1700 | /* True if @rs is requested to reshape by ctr */ | 1700 | /* True if @rs is requested to reshape by ctr */ |
1701 | static bool rs_reshape_requested(struct raid_set *rs) | 1701 | static bool rs_reshape_requested(struct raid_set *rs) |
1702 | { | 1702 | { |
1703 | bool change; | ||
1703 | struct mddev *mddev = &rs->md; | 1704 | struct mddev *mddev = &rs->md; |
1704 | 1705 | ||
1706 | if (rs_takeover_requested(rs)) | ||
1707 | return false; | ||
1708 | |||
1705 | if (!mddev->level) | 1709 | if (!mddev->level) |
1706 | return false; | 1710 | return false; |
1707 | 1711 | ||
1708 | return !__is_raid10_far(mddev->new_layout) && | 1712 | change = mddev->new_layout != mddev->layout || |
1709 | mddev->new_level == mddev->level && | 1713 | mddev->new_chunk_sectors != mddev->chunk_sectors || |
1710 | (mddev->new_layout != mddev->layout || | 1714 | rs->delta_disks; |
1711 | mddev->new_chunk_sectors != mddev->chunk_sectors || | 1715 | |
1712 | rs->raid_disks + rs->delta_disks != mddev->raid_disks); | 1716 | /* Historical case to support raid1 reshape without delta disks */ |
1717 | if (mddev->level == 1) | ||
1718 | return !change && | ||
1719 | mddev->raid_disks != rs->raid_disks; | ||
1720 | |||
1721 | if (mddev->level == 10) | ||
1722 | return change && | ||
1723 | !__is_raid10_far(mddev->new_layout) && | ||
1724 | rs->delta_disks >= 0; | ||
1725 | |||
1726 | return change; | ||
1713 | } | 1727 | } |
1714 | 1728 | ||
1715 | /* Features */ | 1729 | /* Features */ |
@@ -1821,7 +1835,7 @@ static int rs_check_reshape(struct raid_set *rs) | |||
1821 | rs->ti->error = "Can't reshape degraded raid set"; | 1835 | rs->ti->error = "Can't reshape degraded raid set"; |
1822 | else if (rs_is_recovering(rs)) | 1836 | else if (rs_is_recovering(rs)) |
1823 | rs->ti->error = "Convert request on recovering raid set prohibited"; | 1837 | rs->ti->error = "Convert request on recovering raid set prohibited"; |
1824 | else if (mddev->reshape_position && rs_is_reshaping(rs)) | 1838 | else if (rs_is_reshaping(rs)) |
1825 | rs->ti->error = "raid set already reshaping!"; | 1839 | rs->ti->error = "raid set already reshaping!"; |
1826 | else if (!(rs_is_raid10(rs) || rs_is_raid456(rs))) | 1840 | else if (!(rs_is_raid10(rs) || rs_is_raid456(rs))) |
1827 | rs->ti->error = "Reshaping only supported for raid4/5/6/10"; | 1841 | rs->ti->error = "Reshaping only supported for raid4/5/6/10"; |
@@ -2518,6 +2532,69 @@ static int rs_setup_takeover(struct raid_set *rs) | |||
2518 | return 0; | 2532 | return 0; |
2519 | } | 2533 | } |
2520 | 2534 | ||
2535 | /* Prepare @rs for reshape */ | ||
2536 | static int rs_prepare_reshape(struct raid_set *rs) | ||
2537 | { | ||
2538 | bool reshape; | ||
2539 | struct mddev *mddev = &rs->md; | ||
2540 | |||
2541 | if (rs_is_raid10(rs)) { | ||
2542 | if (rs->raid_disks != mddev->raid_disks && | ||
2543 | __is_raid10_near(mddev->layout) && | ||
2544 | rs->raid10_copies && | ||
2545 | rs->raid10_copies != __raid10_near_copies(mddev->layout)) { | ||
2546 | /* | ||
2547 | * raid disk have to be multiple of data copies to allow this conversion, | ||
2548 | * | ||
2549 | * This is actually not a reshape it is a | ||
2550 | * rebuild of any additional mirrors per group | ||
2551 | */ | ||
2552 | if (rs->raid_disks % rs->raid10_copies) { | ||
2553 | rs->ti->error = "Can't reshape raid10 mirror groups"; | ||
2554 | return -EINVAL; | ||
2555 | } | ||
2556 | |||
2557 | /* Userpace reordered disks to add/remove mirrors -> adjust raid_disk indexes */ | ||
2558 | __reorder_raid_disk_indexes(rs); | ||
2559 | mddev->layout = raid10_format_to_md_layout(rs, ALGORITHM_RAID10_NEAR, | ||
2560 | rs->raid10_copies); | ||
2561 | mddev->new_layout = mddev->layout; | ||
2562 | reshape = false; | ||
2563 | } else | ||
2564 | reshape = true; | ||
2565 | |||
2566 | } else if (rs_is_raid456(rs)) | ||
2567 | reshape = true; | ||
2568 | |||
2569 | /* | ||
2570 | * HM FIXME: process raid1 via delta_disks as well? | ||
2571 | * Would cause allocations in raid1->check_reshape | ||
2572 | * though, thus more issues with potential failures | ||
2573 | */ | ||
2574 | else if (rs_is_raid1(rs)) { | ||
2575 | set_bit(RT_FLAG_KEEP_RS_FROZEN, &rs->runtime_flags); | ||
2576 | mddev->raid_disks = rs->raid_disks; | ||
2577 | reshape = false; | ||
2578 | |||
2579 | } else { | ||
2580 | rs->ti->error = "Called with bogus raid type"; | ||
2581 | return -EINVAL; | ||
2582 | } | ||
2583 | |||
2584 | if (reshape) { | ||
2585 | set_bit(RT_FLAG_RESHAPE_RS, &rs->runtime_flags); | ||
2586 | set_bit(RT_FLAG_UPDATE_SBS, &rs->runtime_flags); | ||
2587 | set_bit(RT_FLAG_KEEP_RS_FROZEN, &rs->runtime_flags); | ||
2588 | } | ||
2589 | /* Create new superblocks and bitmaps, if any */ | ||
2590 | if (mddev->raid_disks < rs->raid_disks) { | ||
2591 | set_bit(RT_FLAG_UPDATE_SBS, &rs->runtime_flags); | ||
2592 | rs_set_cur(rs); | ||
2593 | } | ||
2594 | |||
2595 | return 0; | ||
2596 | } | ||
2597 | |||
2521 | /* | 2598 | /* |
2522 | * | 2599 | * |
2523 | * - change raid layout | 2600 | * - change raid layout |
@@ -2682,7 +2759,7 @@ static void configure_discard_support(struct raid_set *rs) | |||
2682 | static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv) | 2759 | static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv) |
2683 | { | 2760 | { |
2684 | int r; | 2761 | int r; |
2685 | bool resize = false; | 2762 | bool resize; |
2686 | struct raid_type *rt; | 2763 | struct raid_type *rt; |
2687 | unsigned num_raid_params, num_raid_devs; | 2764 | unsigned num_raid_params, num_raid_devs; |
2688 | sector_t calculated_dev_sectors; | 2765 | sector_t calculated_dev_sectors; |
@@ -2770,6 +2847,12 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
2770 | /* Restore any requested new layout for conversion decision */ | 2847 | /* Restore any requested new layout for conversion decision */ |
2771 | rs_config_restore(rs, &rs_layout); | 2848 | rs_config_restore(rs, &rs_layout); |
2772 | 2849 | ||
2850 | /* | ||
2851 | * Now that we have any superblock metadata available, | ||
2852 | * check for new, recovering, reshaping, to be taken over, | ||
2853 | * to be reshaped or an existing, unchanged raid set to | ||
2854 | * run in sequence. | ||
2855 | */ | ||
2773 | if (test_bit(MD_ARRAY_FIRST_USE, &rs->md.flags)) { | 2856 | if (test_bit(MD_ARRAY_FIRST_USE, &rs->md.flags)) { |
2774 | /* A new raid6 set has to be recovered to ensure proper parity and Q-Syndrome */ | 2857 | /* A new raid6 set has to be recovered to ensure proper parity and Q-Syndrome */ |
2775 | if (rs_is_raid6(rs) && | 2858 | if (rs_is_raid6(rs) && |
@@ -2782,6 +2865,7 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
2782 | set_bit(RT_FLAG_UPDATE_SBS, &rs->runtime_flags); | 2865 | set_bit(RT_FLAG_UPDATE_SBS, &rs->runtime_flags); |
2783 | rs_set_new(rs); | 2866 | rs_set_new(rs); |
2784 | } else if (rs_is_recovering(rs)) { | 2867 | } else if (rs_is_recovering(rs)) { |
2868 | /* A recovering raid set may be resized */ | ||
2785 | ; /* skip setup rs */ | 2869 | ; /* skip setup rs */ |
2786 | } else if (rs_is_reshaping(rs)) { | 2870 | } else if (rs_is_reshaping(rs)) { |
2787 | /* Have to reject size change request during reshape */ | 2871 | /* Have to reject size change request during reshape */ |
@@ -2790,7 +2874,7 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
2790 | r = -EPERM; | 2874 | r = -EPERM; |
2791 | goto bad; | 2875 | goto bad; |
2792 | } | 2876 | } |
2793 | ; /* skip setup rs */ | 2877 | /* skip setup rs */ |
2794 | } else if (rs_takeover_requested(rs)) { | 2878 | } else if (rs_takeover_requested(rs)) { |
2795 | if (rs_is_reshaping(rs)) { | 2879 | if (rs_is_reshaping(rs)) { |
2796 | ti->error = "Can't takeover a reshaping raid set"; | 2880 | ti->error = "Can't takeover a reshaping raid set"; |
@@ -2800,7 +2884,9 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
2800 | 2884 | ||
2801 | /* | 2885 | /* |
2802 | * If a takeover is needed, userspace sets any additional | 2886 | * If a takeover is needed, userspace sets any additional |
2803 | * devices to rebuild, so set the level to the new requested | 2887 | * devices to rebuild and we can check for a valid request here. |
2888 | * | ||
2889 | * If acceptible, set the level to the new requested | ||
2804 | * one, prohibit requesting recovery, allow the raid | 2890 | * one, prohibit requesting recovery, allow the raid |
2805 | * set to run and store superblocks during resume. | 2891 | * set to run and store superblocks during resume. |
2806 | */ | 2892 | */ |
@@ -2814,63 +2900,22 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
2814 | 2900 | ||
2815 | set_bit(RT_FLAG_UPDATE_SBS, &rs->runtime_flags); | 2901 | set_bit(RT_FLAG_UPDATE_SBS, &rs->runtime_flags); |
2816 | set_bit(RT_FLAG_KEEP_RS_FROZEN, &rs->runtime_flags); | 2902 | set_bit(RT_FLAG_KEEP_RS_FROZEN, &rs->runtime_flags); |
2903 | /* Takeover ain't recovery, so disable recovery */ | ||
2817 | rs_setup_recovery(rs, MaxSector); | 2904 | rs_setup_recovery(rs, MaxSector); |
2818 | rs_set_new(rs); | 2905 | rs_set_new(rs); |
2819 | } else if (rs_reshape_requested(rs)) { | 2906 | } else if (rs_reshape_requested(rs)) { |
2820 | if (rs_is_reshaping(rs)) { | ||
2821 | ti->error = "raid set already reshaping!"; | ||
2822 | r = -EPERM; | ||
2823 | goto bad; | ||
2824 | } | ||
2825 | |||
2826 | if (rs_is_raid10(rs)) { | ||
2827 | if (rs->raid_disks != rs->md.raid_disks && | ||
2828 | __is_raid10_near(rs->md.layout) && | ||
2829 | rs->raid10_copies && | ||
2830 | rs->raid10_copies != __raid10_near_copies(rs->md.layout)) { | ||
2831 | /* | ||
2832 | * raid disk have to be multiple of data copies to allow this conversion, | ||
2833 | * | ||
2834 | * This is actually not a reshape it is a | ||
2835 | * rebuild of any additional mirrors per group | ||
2836 | */ | ||
2837 | if (rs->raid_disks % rs->raid10_copies) { | ||
2838 | ti->error = "Can't reshape raid10 mirror groups"; | ||
2839 | r = -EINVAL; | ||
2840 | goto bad; | ||
2841 | } | ||
2842 | |||
2843 | /* Userpace reordered disks to add/remove mirrors -> adjust raid_disk indexes */ | ||
2844 | __reorder_raid_disk_indexes(rs); | ||
2845 | rs->md.layout = raid10_format_to_md_layout(rs, ALGORITHM_RAID10_NEAR, | ||
2846 | rs->raid10_copies); | ||
2847 | rs->md.new_layout = rs->md.layout; | ||
2848 | |||
2849 | } else | ||
2850 | set_bit(RT_FLAG_RESHAPE_RS, &rs->runtime_flags); | ||
2851 | |||
2852 | } else if (rs_is_raid456(rs)) | ||
2853 | set_bit(RT_FLAG_RESHAPE_RS, &rs->runtime_flags); | ||
2854 | |||
2855 | /* | 2907 | /* |
2856 | * HM FIXME: process raid1 via delta_disks as well? | 2908 | * We can only prepare for a reshape here, because the |
2857 | * Would cause allocations in raid1->check_reshape | 2909 | * raid set needs to run to provide the repective reshape |
2858 | * though, thus more issues with potential failures | 2910 | * check functions via its MD personality instance. |
2859 | */ | 2911 | * |
2860 | else if (rs_is_raid1(rs)) { | 2912 | * So do the reshape check after md_run() succeeded. |
2861 | set_bit(RT_FLAG_KEEP_RS_FROZEN, &rs->runtime_flags); | 2913 | */ |
2862 | rs->md.raid_disks = rs->raid_disks; | 2914 | r = rs_prepare_reshape(rs); |
2863 | } | 2915 | if (r) |
2864 | 2916 | return r; | |
2865 | if (test_bit(RT_FLAG_RESHAPE_RS, &rs->runtime_flags)) { | ||
2866 | set_bit(RT_FLAG_UPDATE_SBS, &rs->runtime_flags); | ||
2867 | set_bit(RT_FLAG_KEEP_RS_FROZEN, &rs->runtime_flags); | ||
2868 | } | ||
2869 | |||
2870 | /* Create new superblocks and bitmaps, if any */ | ||
2871 | if (rs->md.raid_disks < rs->raid_disks) | ||
2872 | set_bit(RT_FLAG_UPDATE_SBS, &rs->runtime_flags); | ||
2873 | 2917 | ||
2918 | /* Reshaping ain't recovery, so disable recovery */ | ||
2874 | rs_setup_recovery(rs, MaxSector); | 2919 | rs_setup_recovery(rs, MaxSector); |
2875 | rs_set_cur(rs); | 2920 | rs_set_cur(rs); |
2876 | } else { | 2921 | } else { |