aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
commitd562b0c4313e3ddea402a400371afa47ddf679f9 (patch)
treee895c3f1688493f6587ad61d9824e96994ca38d6 /drivers
parent245f46c2c221ef09c7db892f0e3fc2149be42052 (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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/raid5.c48
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
4888static 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
4916static 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
4887static struct mdk_personality raid5_personality; 4934static struct mdk_personality raid5_personality;
4888 4935
4889static void *raid6_takeover(mddev_t *mddev) 4936static 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
4980static struct mdk_personality raid4_personality = 5028static struct mdk_personality raid4_personality =