aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-07-26 21:00:36 -0400
committerNeilBrown <neilb@suse.de>2011-07-26 21:00:36 -0400
commit5389042ffa36976caa45a79af16081d759001fa7 (patch)
treeeb303de141a50f41ccac438e734b65dbfe25825e
parenta478a069b6adf186373a6648c54fc5f1d3c2f8eb (diff)
md: change managed of recovery_disabled.
If we hit a read error while recovering a mirror, we want to abort the recovery without necessarily failing the disk - as having a disk this a read error is better than not having an array at all. Currently this is managed with a per-array flag "recovery_disabled" and is only implemented for RAID1. For RAID10 we will need finer grained control as we might want to disable recovery for individual devices separately. So push more of the decision making into the personality. 'recovery_disabled' is now a 'cookie' which is copied when the personality want to disable recovery and is changed when a device is added to the array as this is used as a trigger to 'try recovery again'. This will allow RAID10 to get the control that it needs. Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--drivers/md/md.c4
-rw-r--r--drivers/md/md.h9
-rw-r--r--drivers/md/raid1.c7
-rw-r--r--drivers/md/raid1.h6
4 files changed, 19 insertions, 7 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 77bd8d8708e4..c7d9c6af4634 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1922,7 +1922,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
1922 bd_link_disk_holder(rdev->bdev, mddev->gendisk); 1922 bd_link_disk_holder(rdev->bdev, mddev->gendisk);
1923 1923
1924 /* May as well allow recovery to be retried once */ 1924 /* May as well allow recovery to be retried once */
1925 mddev->recovery_disabled = 0; 1925 mddev->recovery_disabled++;
1926 1926
1927 return 0; 1927 return 0;
1928 1928
@@ -7070,7 +7070,7 @@ static int remove_and_add_spares(mddev_t *mddev)
7070 } 7070 }
7071 } 7071 }
7072 7072
7073 if (mddev->degraded && !mddev->recovery_disabled) { 7073 if (mddev->degraded) {
7074 list_for_each_entry(rdev, &mddev->disks, same_set) { 7074 list_for_each_entry(rdev, &mddev->disks, same_set) {
7075 if (rdev->raid_disk >= 0 && 7075 if (rdev->raid_disk >= 0 &&
7076 !test_bit(In_sync, &rdev->flags) && 7076 !test_bit(In_sync, &rdev->flags) &&
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 6863f722cd2a..de5455d30d41 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -239,9 +239,12 @@ struct mddev_s
239#define MD_RECOVERY_FROZEN 9 239#define MD_RECOVERY_FROZEN 9
240 240
241 unsigned long recovery; 241 unsigned long recovery;
242 int recovery_disabled; /* if we detect that recovery 242 /* If a RAID personality determines that recovery (of a particular
243 * will always fail, set this 243 * device) will fail due to a read error on the source device, it
244 * so we don't loop trying */ 244 * takes a copy of this number and does not attempt recovery again
245 * until this number changes.
246 */
247 int recovery_disabled;
245 248
246 int in_sync; /* know to not need resync */ 249 int in_sync; /* know to not need resync */
247 /* 'open_mutex' avoids races between 'md_open' and 'do_md_stop', so 250 /* 'open_mutex' avoids races between 'md_open' and 'do_md_stop', so
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 1d79a041db09..44069b38d6dd 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -956,7 +956,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
956 * However don't try a recovery from this drive as 956 * However don't try a recovery from this drive as
957 * it is very likely to fail. 957 * it is very likely to fail.
958 */ 958 */
959 mddev->recovery_disabled = 1; 959 conf->recovery_disabled = mddev->recovery_disabled;
960 return; 960 return;
961 } 961 }
962 if (test_and_clear_bit(In_sync, &rdev->flags)) { 962 if (test_and_clear_bit(In_sync, &rdev->flags)) {
@@ -1052,6 +1052,9 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
1052 int first = 0; 1052 int first = 0;
1053 int last = mddev->raid_disks - 1; 1053 int last = mddev->raid_disks - 1;
1054 1054
1055 if (mddev->recovery_disabled == conf->recovery_disabled)
1056 return -EBUSY;
1057
1055 if (rdev->raid_disk >= 0) 1058 if (rdev->raid_disk >= 0)
1056 first = last = rdev->raid_disk; 1059 first = last = rdev->raid_disk;
1057 1060
@@ -1107,7 +1110,7 @@ static int raid1_remove_disk(mddev_t *mddev, int number)
1107 * is not possible. 1110 * is not possible.
1108 */ 1111 */
1109 if (!test_bit(Faulty, &rdev->flags) && 1112 if (!test_bit(Faulty, &rdev->flags) &&
1110 !mddev->recovery_disabled && 1113 mddev->recovery_disabled != conf->recovery_disabled &&
1111 mddev->degraded < conf->raid_disks) { 1114 mddev->degraded < conf->raid_disks) {
1112 err = -EBUSY; 1115 err = -EBUSY;
1113 goto abort; 1116 goto abort;
diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h
index e743a64fac4f..3cd18cfda2ad 100644
--- a/drivers/md/raid1.h
+++ b/drivers/md/raid1.h
@@ -48,6 +48,12 @@ struct r1_private_data_s {
48 * (fresh device added). 48 * (fresh device added).
49 * Cleared when a sync completes. 49 * Cleared when a sync completes.
50 */ 50 */
51 int recovery_disabled; /* when the same as
52 * mddev->recovery_disabled
53 * we don't allow recovery
54 * to be attempted as we
55 * expect a read error
56 */
51 57
52 wait_queue_head_t wait_barrier; 58 wait_queue_head_t wait_barrier;
53 59