diff options
-rw-r--r-- | Documentation/md.txt | 24 | ||||
-rw-r--r-- | drivers/md/md.c | 4 | ||||
-rw-r--r-- | drivers/md/raid5.c | 15 | ||||
-rw-r--r-- | drivers/md/raid6main.c | 13 | ||||
-rw-r--r-- | include/linux/raid/md_k.h | 1 |
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. | |||
51 | The kernel parameter "raid=partitionable" (or "raid=part") means | 51 | The kernel parameter "raid=partitionable" (or "raid=part") means |
52 | that all auto-detected arrays are assembled as partitionable. | 52 | that all auto-detected arrays are assembled as partitionable. |
53 | 53 | ||
54 | Boot time assembly of degraded/dirty arrays | ||
55 | ------------------------------------------- | ||
56 | |||
57 | If a raid5 or raid6 array is both dirty and degraded, it could have | ||
58 | undetectable data corruption. This is because the fact that it is | ||
59 | 'dirty' means that the parity cannot be trusted, and the fact that it | ||
60 | is degraded means that some datablocks are missing and cannot reliably | ||
61 | be reconstructed (due to no parity). | ||
62 | |||
63 | For this reason, md will normally refuse to start such an array. This | ||
64 | requires the sysadmin to take action to explicitly start the array | ||
65 | desipite possible corruption. This is normally done with | ||
66 | mdadm --assemble --force .... | ||
67 | |||
68 | This option is not really available if the array has the root | ||
69 | filesystem on it. In order to support this booting from such an | ||
70 | array, md supports a module parameter "start_dirty_degraded" which, | ||
71 | when set to 1, bypassed the checks and will allows dirty degraded | ||
72 | arrays to be started. | ||
73 | |||
74 | So, to boot with a root filesystem of a dirty degraded raid[56], use | ||
75 | |||
76 | md-mod.start_dirty_degraded=1 | ||
77 | |||
54 | 78 | ||
55 | Superblock formats | 79 | Superblock 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 | ||
1940 | static int start_dirty_degraded; | ||
1940 | 1941 | ||
1941 | static int do_md_run(mddev_t * mddev) | 1942 | static 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 | ||
4511 | module_param_call(start_ro, set_ro, get_ro, NULL, 0600); | 4513 | module_param_call(start_ro, set_ro, get_ro, NULL, 0600); |
4514 | module_param(start_dirty_degraded, int, 0644); | ||
4515 | |||
4512 | 4516 | ||
4513 | EXPORT_SYMBOL(register_md_personality); | 4517 | EXPORT_SYMBOL(register_md_personality); |
4514 | EXPORT_SYMBOL(unregister_md_personality); | 4518 | EXPORT_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 |