From: NeilBrown See patch to md.txt for more details Signed-off-by: Neil Brown Signed-off-by: Andrew Morton --- Documentation/md.txt | 24 ++++++++++++++++++++++++ drivers/md/md.c | 4 ++++ drivers/md/raid5.c | 15 +++++++++++---- drivers/md/raid6main.c | 13 +++++++++---- include/linux/raid/md_k.h | 1 + 5 files changed, 49 insertions(+), 8 deletions(-) diff -puN Documentation/md.txt~md-allow-dirty-raid-arrays-to-be-started-at-boot Documentation/md.txt --- devel/Documentation/md.txt~md-allow-dirty-raid-arrays-to-be-started-at-boot 2005-12-22 05:10:10.000000000 -0800 +++ devel-akpm/Documentation/md.txt 2005-12-22 05:10:10.000000000 -0800 @@ -51,6 +51,30 @@ superblock can be autodetected and run a The kernel parameter "raid=partitionable" (or "raid=part") means that all auto-detected arrays are assembled as partitionable. +Boot time assembly of degraded/dirty arrays +------------------------------------------- + +If a raid5 or raid6 array is both dirty and degraded, it could have +undetectable data corruption. This is because the fact that it is +'dirty' means that the parity cannot be trusted, and the fact that it +is degraded means that some datablocks are missing and cannot reliably +be reconstructed (due to no parity). + +For this reason, md will normally refuse to start such an array. This +requires the sysadmin to take action to explicitly start the array +desipite possible corruption. This is normally done with + mdadm --assemble --force .... + +This option is not really available if the array has the root +filesystem on it. In order to support this booting from such an +array, md supports a module parameter "start_dirty_degraded" which, +when set to 1, bypassed the checks and will allows dirty degraded +arrays to be started. + +So, to boot with a root filesystem of a dirty degraded raid[56], use + + md-mod.start_dirty_degraded=1 + Superblock formats ------------------ diff -puN drivers/md/md.c~md-allow-dirty-raid-arrays-to-be-started-at-boot drivers/md/md.c --- devel/drivers/md/md.c~md-allow-dirty-raid-arrays-to-be-started-at-boot 2005-12-22 05:10:10.000000000 -0800 +++ devel-akpm/drivers/md/md.c 2005-12-22 05:10:10.000000000 -0800 @@ -1937,6 +1937,7 @@ static void md_safemode_timeout(unsigned md_wakeup_thread(mddev->thread); } +static int start_dirty_degraded; static int do_md_run(mddev_t * mddev) { @@ -2048,6 +2049,7 @@ static int do_md_run(mddev_t * mddev) mddev->recovery = 0; mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ mddev->barriers_work = 1; + mddev->ok_start_degraded = start_dirty_degraded; if (start_readonly) mddev->ro = 2; /* read-only, but switch on first write */ @@ -4501,6 +4503,8 @@ static int set_ro(const char *val, struc } module_param_call(start_ro, set_ro, get_ro, NULL, 0600); +module_param(start_dirty_degraded, int, 0644); + EXPORT_SYMBOL(register_md_personality); EXPORT_SYMBOL(unregister_md_personality); diff -puN drivers/md/raid5.c~md-allow-dirty-raid-arrays-to-be-started-at-boot drivers/md/raid5.c --- devel/drivers/md/raid5.c~md-allow-dirty-raid-arrays-to-be-started-at-boot 2005-12-22 05:10:10.000000000 -0800 +++ devel-akpm/drivers/md/raid5.c 2005-12-22 05:10:10.000000000 -0800 @@ -1904,10 +1904,17 @@ static int run(mddev_t *mddev) if (mddev->degraded == 1 && mddev->recovery_cp != MaxSector) { - printk(KERN_ERR - "raid5: cannot start dirty degraded array for %s\n", - mdname(mddev)); - goto abort; + if (mddev->ok_start_degraded) + printk(KERN_WARNING + "raid5: starting dirty degraded array: %s" + "- data corruption possible.\n", + mdname(mddev)); + else { + printk(KERN_ERR + "raid5: cannot start dirty degraded array for %s\n", + mdname(mddev)); + goto abort; + } } { diff -puN drivers/md/raid6main.c~md-allow-dirty-raid-arrays-to-be-started-at-boot drivers/md/raid6main.c --- devel/drivers/md/raid6main.c~md-allow-dirty-raid-arrays-to-be-started-at-boot 2005-12-22 05:10:10.000000000 -0800 +++ devel-akpm/drivers/md/raid6main.c 2005-12-22 05:10:10.000000000 -0800 @@ -1929,13 +1929,18 @@ static int run(mddev_t *mddev) goto abort; } -#if 0 /* FIX: For now */ if (mddev->degraded > 0 && mddev->recovery_cp != MaxSector) { - printk(KERN_ERR "raid6: cannot start dirty degraded array for %s\n", mdname(mddev)); - goto abort; + if (mddev->ok_start_degraded) + printk(KERN_WARNING "raid6: starting dirty degraded array:%s" + "- data corruption possible.\n", + mdname(mddev)); + else { + printk(KERN_ERR "raid6: cannot start dirty degraded array" + " for %s\n", mdname(mddev)); + goto abort; + } } -#endif { mddev->thread = md_register_thread(raid6d, mddev, "%s_raid6"); diff -puN include/linux/raid/md_k.h~md-allow-dirty-raid-arrays-to-be-started-at-boot include/linux/raid/md_k.h --- devel/include/linux/raid/md_k.h~md-allow-dirty-raid-arrays-to-be-started-at-boot 2005-12-22 05:10:10.000000000 -0800 +++ devel-akpm/include/linux/raid/md_k.h 2005-12-22 05:10:10.000000000 -0800 @@ -183,6 +183,7 @@ struct mddev_s sector_t resync_mismatches; /* count of sectors where * parity/replica mismatch found */ + int ok_start_degraded; /* recovery/resync flags * NEEDED: we might need to start a resync/recover * RUNNING: a thread is running, or about to be started _