diff options
author | NeilBrown <neilb@suse.de> | 2009-03-30 23:39:39 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2009-03-30 23:39:39 -0400 |
commit | 245f46c2c221ef09c7db892f0e3fc2149be42052 (patch) | |
tree | be7e6f4b7b65b682c43e59ef17f7ed580bc8a82b /drivers/md/raid5.c | |
parent | 409c57f3801701dfee27a28103dda4831306cb20 (diff) |
md: add ->takeover method to support changing the personality managing an array
Implement this for RAID6 to be able to 'takeover' a RAID5 array. The
new RAID6 will use a layout which places Q on the last device, and
that device will be missing.
If there are any available spares, one will immediately have Q
recovered onto it.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 64 |
1 files changed, 59 insertions, 5 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 81789fa7a023..5b346b41e515 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -933,8 +933,10 @@ static int grow_stripes(raid5_conf_t *conf, int num) | |||
933 | struct kmem_cache *sc; | 933 | struct kmem_cache *sc; |
934 | int devs = conf->raid_disks; | 934 | int devs = conf->raid_disks; |
935 | 935 | ||
936 | sprintf(conf->cache_name[0], "raid5-%s", mdname(conf->mddev)); | 936 | sprintf(conf->cache_name[0], |
937 | sprintf(conf->cache_name[1], "raid5-%s-alt", mdname(conf->mddev)); | 937 | "raid%d-%s", conf->level, mdname(conf->mddev)); |
938 | sprintf(conf->cache_name[1], | ||
939 | "raid%d-%s-alt", conf->level, mdname(conf->mddev)); | ||
938 | conf->active_name = 0; | 940 | conf->active_name = 0; |
939 | sc = kmem_cache_create(conf->cache_name[conf->active_name], | 941 | sc = kmem_cache_create(conf->cache_name[conf->active_name], |
940 | sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), | 942 | sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), |
@@ -4361,10 +4363,12 @@ static int run(mddev_t *mddev) | |||
4361 | BUG_ON(mddev->chunk_size != mddev->new_chunk); | 4363 | BUG_ON(mddev->chunk_size != mddev->new_chunk); |
4362 | BUG_ON(mddev->delta_disks != 0); | 4364 | BUG_ON(mddev->delta_disks != 0); |
4363 | } | 4365 | } |
4364 | conf = setup_conf(mddev); | ||
4365 | 4366 | ||
4366 | if (conf == NULL) | 4367 | if (mddev->private == NULL) |
4367 | return -EIO; | 4368 | conf = setup_conf(mddev); |
4369 | else | ||
4370 | conf = mddev->private; | ||
4371 | |||
4368 | if (IS_ERR(conf)) | 4372 | if (IS_ERR(conf)) |
4369 | return PTR_ERR(conf); | 4373 | return PTR_ERR(conf); |
4370 | 4374 | ||
@@ -4880,6 +4884,55 @@ static void raid5_quiesce(mddev_t *mddev, int state) | |||
4880 | } | 4884 | } |
4881 | } | 4885 | } |
4882 | 4886 | ||
4887 | static struct mdk_personality raid5_personality; | ||
4888 | |||
4889 | static void *raid6_takeover(mddev_t *mddev) | ||
4890 | { | ||
4891 | /* Currently can only take over a raid5. We map the | ||
4892 | * personality to an equivalent raid6 personality | ||
4893 | * with the Q block at the end. | ||
4894 | */ | ||
4895 | int new_layout; | ||
4896 | |||
4897 | if (mddev->pers != &raid5_personality) | ||
4898 | return ERR_PTR(-EINVAL); | ||
4899 | if (mddev->degraded > 1) | ||
4900 | return ERR_PTR(-EINVAL); | ||
4901 | if (mddev->raid_disks > 253) | ||
4902 | return ERR_PTR(-EINVAL); | ||
4903 | if (mddev->raid_disks < 3) | ||
4904 | return ERR_PTR(-EINVAL); | ||
4905 | |||
4906 | switch (mddev->layout) { | ||
4907 | case ALGORITHM_LEFT_ASYMMETRIC: | ||
4908 | new_layout = ALGORITHM_LEFT_ASYMMETRIC_6; | ||
4909 | break; | ||
4910 | case ALGORITHM_RIGHT_ASYMMETRIC: | ||
4911 | new_layout = ALGORITHM_RIGHT_ASYMMETRIC_6; | ||
4912 | break; | ||
4913 | case ALGORITHM_LEFT_SYMMETRIC: | ||
4914 | new_layout = ALGORITHM_LEFT_SYMMETRIC_6; | ||
4915 | break; | ||
4916 | case ALGORITHM_RIGHT_SYMMETRIC: | ||
4917 | new_layout = ALGORITHM_RIGHT_SYMMETRIC_6; | ||
4918 | break; | ||
4919 | case ALGORITHM_PARITY_0: | ||
4920 | new_layout = ALGORITHM_PARITY_0_6; | ||
4921 | break; | ||
4922 | case ALGORITHM_PARITY_N: | ||
4923 | new_layout = ALGORITHM_PARITY_N; | ||
4924 | break; | ||
4925 | default: | ||
4926 | return ERR_PTR(-EINVAL); | ||
4927 | } | ||
4928 | mddev->new_level = 6; | ||
4929 | mddev->new_layout = new_layout; | ||
4930 | mddev->delta_disks = 1; | ||
4931 | mddev->raid_disks += 1; | ||
4932 | return setup_conf(mddev); | ||
4933 | } | ||
4934 | |||
4935 | |||
4883 | static struct mdk_personality raid6_personality = | 4936 | static struct mdk_personality raid6_personality = |
4884 | { | 4937 | { |
4885 | .name = "raid6", | 4938 | .name = "raid6", |
@@ -4900,6 +4953,7 @@ static struct mdk_personality raid6_personality = | |||
4900 | .start_reshape = raid5_start_reshape, | 4953 | .start_reshape = raid5_start_reshape, |
4901 | #endif | 4954 | #endif |
4902 | .quiesce = raid5_quiesce, | 4955 | .quiesce = raid5_quiesce, |
4956 | .takeover = raid6_takeover, | ||
4903 | }; | 4957 | }; |
4904 | static struct mdk_personality raid5_personality = | 4958 | static struct mdk_personality raid5_personality = |
4905 | { | 4959 | { |