aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid5.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-03-30 23:39:39 -0400
committerNeilBrown <neilb@suse.de>2009-03-30 23:39:39 -0400
commit245f46c2c221ef09c7db892f0e3fc2149be42052 (patch)
treebe7e6f4b7b65b682c43e59ef17f7ed580bc8a82b /drivers/md/raid5.c
parent409c57f3801701dfee27a28103dda4831306cb20 (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.c64
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
4887static struct mdk_personality raid5_personality;
4888
4889static 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
4883static struct mdk_personality raid6_personality = 4936static 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};
4904static struct mdk_personality raid5_personality = 4958static struct mdk_personality raid5_personality =
4905{ 4959{