summaryrefslogtreecommitdiffstats
path: root/drivers/md/raid5.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-03-31 14:39:39 +1100
committerNeilBrown <neilb@suse.de>2009-03-31 14:39:39 +1100
commitd562b0c4313e3ddea402a400371afa47ddf679f9 (patch)
treee895c3f1688493f6587ad61d9824e96994ca38d6 /drivers/md/raid5.c
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/md/raid5.c')
-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 5b346b41e51..611ea7bbf47 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -4884,6 +4884,53 @@ static void raid5_quiesce(mddev_t *mddev, int state)
}
}
+
+static void *raid5_takeover_raid1(mddev_t *mddev)
+{
+ int chunksect;
+
+ if (mddev->raid_disks != 2 ||
+ mddev->degraded > 1)
+ return ERR_PTR(-EINVAL);
+
+ /* Should check if there are write-behind devices? */
+
+ chunksect = 64*2; /* 64K by default */
+
+ /* The array must be an exact multiple of chunksize */
+ while (chunksect && (mddev->array_sectors & (chunksect-1)))
+ chunksect >>= 1;
+
+ if ((chunksect<<9) < STRIPE_SIZE)
+ /* array size does not allow a suitable chunk size */
+ return ERR_PTR(-EINVAL);
+
+ mddev->new_level = 5;
+ mddev->new_layout = ALGORITHM_LEFT_SYMMETRIC;
+ mddev->new_chunk = chunksect << 9;
+
+ return setup_conf(mddev);
+}
+
+
+static void *raid5_takeover(mddev_t *mddev)
+{
+ /* raid5 can take over:
+ * raid0 - if all devices are the same - make it a raid4 layout
+ * raid1 - if there are two drives. We need to know the chunk size
+ * raid4 - trivial - just use a raid4 layout.
+ * raid6 - Providing it is a *_6 layout
+ *
+ * For now, just do raid1
+ */
+
+ if (mddev->level == 1)
+ return raid5_takeover_raid1(mddev);
+
+ return ERR_PTR(-EINVAL);
+}
+
+
static struct mdk_personality raid5_personality;
static void *raid6_takeover(mddev_t *mddev)
@@ -4975,6 +5022,7 @@ static struct mdk_personality raid5_personality =
.start_reshape = raid5_start_reshape,
#endif
.quiesce = raid5_quiesce,
+ .takeover = raid5_takeover,
};
static struct mdk_personality raid4_personality =