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 | d562b0c4313e3ddea402a400371afa47ddf679f9 (patch) | |
tree | e895c3f1688493f6587ad61d9824e96994ca38d6 | |
parent | 245f46c2c221ef09c7db892f0e3fc2149be42052 (diff) |
md: add ->takeover method for raid5 to be able to take over raid1
The RAID1 must have two drives and be a suitable size to
be a multiple of a chunksize that isn't too small.
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | drivers/md/raid5.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 5b346b41e515..611ea7bbf474 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -4884,6 +4884,53 @@ static void raid5_quiesce(mddev_t *mddev, int state) | |||
4884 | } | 4884 | } |
4885 | } | 4885 | } |
4886 | 4886 | ||
4887 | |||
4888 | static void *raid5_takeover_raid1(mddev_t *mddev) | ||
4889 | { | ||
4890 | int chunksect; | ||
4891 | |||
4892 | if (mddev->raid_disks != 2 || | ||
4893 | mddev->degraded > 1) | ||
4894 | return ERR_PTR(-EINVAL); | ||
4895 | |||
4896 | /* Should check if there are write-behind devices? */ | ||
4897 | |||
4898 | chunksect = 64*2; /* 64K by default */ | ||
4899 | |||
4900 | /* The array must be an exact multiple of chunksize */ | ||
4901 | while (chunksect && (mddev->array_sectors & (chunksect-1))) | ||
4902 | chunksect >>= 1; | ||
4903 | |||
4904 | if ((chunksect<<9) < STRIPE_SIZE) | ||
4905 | /* array size does not allow a suitable chunk size */ | ||
4906 | return ERR_PTR(-EINVAL); | ||
4907 | |||
4908 | mddev->new_level = 5; | ||
4909 | mddev->new_layout = ALGORITHM_LEFT_SYMMETRIC; | ||
4910 | mddev->new_chunk = chunksect << 9; | ||
4911 | |||
4912 | return setup_conf(mddev); | ||
4913 | } | ||
4914 | |||
4915 | |||
4916 | static void *raid5_takeover(mddev_t *mddev) | ||
4917 | { | ||
4918 | /* raid5 can take over: | ||
4919 | * raid0 - if all devices are the same - make it a raid4 layout | ||
4920 | * raid1 - if there are two drives. We need to know the chunk size | ||
4921 | * raid4 - trivial - just use a raid4 layout. | ||
4922 | * raid6 - Providing it is a *_6 layout | ||
4923 | * | ||
4924 | * For now, just do raid1 | ||
4925 | */ | ||
4926 | |||
4927 | if (mddev->level == 1) | ||
4928 | return raid5_takeover_raid1(mddev); | ||
4929 | |||
4930 | return ERR_PTR(-EINVAL); | ||
4931 | } | ||
4932 | |||
4933 | |||
4887 | static struct mdk_personality raid5_personality; | 4934 | static struct mdk_personality raid5_personality; |
4888 | 4935 | ||
4889 | static void *raid6_takeover(mddev_t *mddev) | 4936 | static void *raid6_takeover(mddev_t *mddev) |
@@ -4975,6 +5022,7 @@ static struct mdk_personality raid5_personality = | |||
4975 | .start_reshape = raid5_start_reshape, | 5022 | .start_reshape = raid5_start_reshape, |
4976 | #endif | 5023 | #endif |
4977 | .quiesce = raid5_quiesce, | 5024 | .quiesce = raid5_quiesce, |
5025 | .takeover = raid5_takeover, | ||
4978 | }; | 5026 | }; |
4979 | 5027 | ||
4980 | static struct mdk_personality raid4_personality = | 5028 | static struct mdk_personality raid4_personality = |