Commit 6ff8d8ec authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds

[PATCH] md: allow dirty raid[456] arrays to be started at boot

See patch to md.txt for more details
Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 14f8d26b
...@@ -51,6 +51,30 @@ superblock can be autodetected and run at boot time. ...@@ -51,6 +51,30 @@ superblock can be autodetected and run at boot time.
The kernel parameter "raid=partitionable" (or "raid=part") means The kernel parameter "raid=partitionable" (or "raid=part") means
that all auto-detected arrays are assembled as partitionable. 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 Superblock formats
------------------ ------------------
......
...@@ -1937,6 +1937,7 @@ static void md_safemode_timeout(unsigned long data) ...@@ -1937,6 +1937,7 @@ static void md_safemode_timeout(unsigned long data)
md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->thread);
} }
static int start_dirty_degraded;
static int do_md_run(mddev_t * mddev) static int do_md_run(mddev_t * mddev)
{ {
...@@ -2048,6 +2049,7 @@ static int do_md_run(mddev_t * mddev) ...@@ -2048,6 +2049,7 @@ static int do_md_run(mddev_t * mddev)
mddev->recovery = 0; mddev->recovery = 0;
mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
mddev->barriers_work = 1; mddev->barriers_work = 1;
mddev->ok_start_degraded = start_dirty_degraded;
if (start_readonly) if (start_readonly)
mddev->ro = 2; /* read-only, but switch on first write */ mddev->ro = 2; /* read-only, but switch on first write */
...@@ -4509,6 +4511,8 @@ static int set_ro(const char *val, struct kernel_param *kp) ...@@ -4509,6 +4511,8 @@ static int set_ro(const char *val, struct kernel_param *kp)
} }
module_param_call(start_ro, set_ro, get_ro, NULL, 0600); 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(register_md_personality);
EXPORT_SYMBOL(unregister_md_personality); EXPORT_SYMBOL(unregister_md_personality);
......
...@@ -1904,11 +1904,18 @@ static int run(mddev_t *mddev) ...@@ -1904,11 +1904,18 @@ static int run(mddev_t *mddev)
if (mddev->degraded == 1 && if (mddev->degraded == 1 &&
mddev->recovery_cp != MaxSector) { mddev->recovery_cp != MaxSector) {
if (mddev->ok_start_degraded)
printk(KERN_WARNING
"raid5: starting dirty degraded array: %s"
"- data corruption possible.\n",
mdname(mddev));
else {
printk(KERN_ERR printk(KERN_ERR
"raid5: cannot start dirty degraded array for %s\n", "raid5: cannot start dirty degraded array for %s\n",
mdname(mddev)); mdname(mddev));
goto abort; goto abort;
} }
}
{ {
mddev->thread = md_register_thread(raid5d, mddev, "%s_raid5"); mddev->thread = md_register_thread(raid5d, mddev, "%s_raid5");
......
...@@ -1929,13 +1929,18 @@ static int run(mddev_t *mddev) ...@@ -1929,13 +1929,18 @@ static int run(mddev_t *mddev)
goto abort; goto abort;
} }
#if 0 /* FIX: For now */
if (mddev->degraded > 0 && if (mddev->degraded > 0 &&
mddev->recovery_cp != MaxSector) { mddev->recovery_cp != MaxSector) {
printk(KERN_ERR "raid6: cannot start dirty degraded array for %s\n", mdname(mddev)); 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; goto abort;
} }
#endif }
{ {
mddev->thread = md_register_thread(raid6d, mddev, "%s_raid6"); mddev->thread = md_register_thread(raid6d, mddev, "%s_raid6");
......
...@@ -183,6 +183,7 @@ struct mddev_s ...@@ -183,6 +183,7 @@ struct mddev_s
sector_t resync_mismatches; /* count of sectors where sector_t resync_mismatches; /* count of sectors where
* parity/replica mismatch found * parity/replica mismatch found
*/ */
int ok_start_degraded;
/* recovery/resync flags /* recovery/resync flags
* NEEDED: we might need to start a resync/recover * NEEDED: we might need to start a resync/recover
* RUNNING: a thread is running, or about to be started * RUNNING: a thread is running, or about to be started
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment