aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/md.txt24
-rw-r--r--drivers/md/md.c4
-rw-r--r--drivers/md/raid5.c15
-rw-r--r--drivers/md/raid6main.c13
-rw-r--r--include/linux/raid/md_k.h1
5 files changed, 49 insertions, 8 deletions
diff --git a/Documentation/md.txt b/Documentation/md.txt
index 23e6cce40f9c..1dd0fb6021cf 100644
--- a/Documentation/md.txt
+++ b/Documentation/md.txt
@@ -51,6 +51,30 @@ superblock can be autodetected and run at boot time.
51The kernel parameter "raid=partitionable" (or "raid=part") means 51The kernel parameter "raid=partitionable" (or "raid=part") means
52that all auto-detected arrays are assembled as partitionable. 52that all auto-detected arrays are assembled as partitionable.
53 53
54Boot time assembly of degraded/dirty arrays
55-------------------------------------------
56
57If a raid5 or raid6 array is both dirty and degraded, it could have
58undetectable data corruption. This is because the fact that it is
59'dirty' means that the parity cannot be trusted, and the fact that it
60is degraded means that some datablocks are missing and cannot reliably
61be reconstructed (due to no parity).
62
63For this reason, md will normally refuse to start such an array. This
64requires the sysadmin to take action to explicitly start the array
65desipite possible corruption. This is normally done with
66 mdadm --assemble --force ....
67
68This option is not really available if the array has the root
69filesystem on it. In order to support this booting from such an
70array, md supports a module parameter "start_dirty_degraded" which,
71when set to 1, bypassed the checks and will allows dirty degraded
72arrays to be started.
73
74So, to boot with a root filesystem of a dirty degraded raid[56], use
75
76 md-mod.start_dirty_degraded=1
77
54 78
55Superblock formats 79Superblock formats
56------------------ 80------------------
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 8175a2a222da..b4fb7247b3ed 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1937,6 +1937,7 @@ static void md_safemode_timeout(unsigned long data)
1937 md_wakeup_thread(mddev->thread); 1937 md_wakeup_thread(mddev->thread);
1938} 1938}
1939 1939
1940static int start_dirty_degraded;
1940 1941
1941static int do_md_run(mddev_t * mddev) 1942static int do_md_run(mddev_t * mddev)
1942{ 1943{
@@ -2048,6 +2049,7 @@ static int do_md_run(mddev_t * mddev)
2048 mddev->recovery = 0; 2049 mddev->recovery = 0;
2049 mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ 2050 mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
2050 mddev->barriers_work = 1; 2051 mddev->barriers_work = 1;
2052 mddev->ok_start_degraded = start_dirty_degraded;
2051 2053
2052 if (start_readonly) 2054 if (start_readonly)
2053 mddev->ro = 2; /* read-only, but switch on first write */ 2055 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} 4511}
4510 4512
4511module_param_call(start_ro, set_ro, get_ro, NULL, 0600); 4513module_param_call(start_ro, set_ro, get_ro, NULL, 0600);
4514module_param(start_dirty_degraded, int, 0644);
4515
4512 4516
4513EXPORT_SYMBOL(register_md_personality); 4517EXPORT_SYMBOL(register_md_personality);
4514EXPORT_SYMBOL(unregister_md_personality); 4518EXPORT_SYMBOL(unregister_md_personality);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 334ff7a07283..53a0f2ce76c8 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1904,10 +1904,17 @@ static int run(mddev_t *mddev)
1904 1904
1905 if (mddev->degraded == 1 && 1905 if (mddev->degraded == 1 &&
1906 mddev->recovery_cp != MaxSector) { 1906 mddev->recovery_cp != MaxSector) {
1907 printk(KERN_ERR 1907 if (mddev->ok_start_degraded)
1908 "raid5: cannot start dirty degraded array for %s\n", 1908 printk(KERN_WARNING
1909 mdname(mddev)); 1909 "raid5: starting dirty degraded array: %s"
1910 goto abort; 1910 "- data corruption possible.\n",
1911 mdname(mddev));
1912 else {
1913 printk(KERN_ERR
1914 "raid5: cannot start dirty degraded array for %s\n",
1915 mdname(mddev));
1916 goto abort;
1917 }
1911 } 1918 }
1912 1919
1913 { 1920 {
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 0000d162d198..9ac6dcd55127 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -1929,13 +1929,18 @@ static int run(mddev_t *mddev)
1929 goto abort; 1929 goto abort;
1930 } 1930 }
1931 1931
1932#if 0 /* FIX: For now */
1933 if (mddev->degraded > 0 && 1932 if (mddev->degraded > 0 &&
1934 mddev->recovery_cp != MaxSector) { 1933 mddev->recovery_cp != MaxSector) {
1935 printk(KERN_ERR "raid6: cannot start dirty degraded array for %s\n", mdname(mddev)); 1934 if (mddev->ok_start_degraded)
1936 goto abort; 1935 printk(KERN_WARNING "raid6: starting dirty degraded array:%s"
1936 "- data corruption possible.\n",
1937 mdname(mddev));
1938 else {
1939 printk(KERN_ERR "raid6: cannot start dirty degraded array"
1940 " for %s\n", mdname(mddev));
1941 goto abort;
1942 }
1937 } 1943 }
1938#endif
1939 1944
1940 { 1945 {
1941 mddev->thread = md_register_thread(raid6d, mddev, "%s_raid6"); 1946 mddev->thread = md_register_thread(raid6d, mddev, "%s_raid6");
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index 46629a275ba9..1dd587b5975a 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -183,6 +183,7 @@ struct mddev_s
183 sector_t resync_mismatches; /* count of sectors where 183 sector_t resync_mismatches; /* count of sectors where
184 * parity/replica mismatch found 184 * parity/replica mismatch found
185 */ 185 */
186 int ok_start_degraded;
186 /* recovery/resync flags 187 /* recovery/resync flags
187 * NEEDED: we might need to start a resync/recover 188 * NEEDED: we might need to start a resync/recover
188 * RUNNING: a thread is running, or about to be started 189 * RUNNING: a thread is running, or about to be started