Commit 3141eb6c authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://neil.brown.name/md

* 'for-linus' of git://neil.brown.name/md:
  md: cancel check/repair requests when recovery is needed
  Allow raid10 resync to happening in larger chunks.
  Allow faulty devices to be removed from a readonly array.
  Don't let a blocked_rdev interfere with read request in raid5/6
  Fail safely when trying to grow an array with a write-intent bitmap.
  Restore force switch of md array to readonly at reboot time.
  Make writes to md/safe_mode_delay immediately effective.
parents 7db9cbb3 56ac36d7
...@@ -2393,6 +2393,8 @@ static void analyze_sbs(mddev_t * mddev) ...@@ -2393,6 +2393,8 @@ static void analyze_sbs(mddev_t * mddev)
} }
static void md_safemode_timeout(unsigned long data);
static ssize_t static ssize_t
safe_delay_show(mddev_t *mddev, char *page) safe_delay_show(mddev_t *mddev, char *page)
{ {
...@@ -2432,9 +2434,12 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len) ...@@ -2432,9 +2434,12 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
if (msec == 0) if (msec == 0)
mddev->safemode_delay = 0; mddev->safemode_delay = 0;
else { else {
unsigned long old_delay = mddev->safemode_delay;
mddev->safemode_delay = (msec*HZ)/1000; mddev->safemode_delay = (msec*HZ)/1000;
if (mddev->safemode_delay == 0) if (mddev->safemode_delay == 0)
mddev->safemode_delay = 1; mddev->safemode_delay = 1;
if (mddev->safemode_delay < old_delay)
md_safemode_timeout((unsigned long)mddev);
} }
return len; return len;
} }
...@@ -4634,6 +4639,11 @@ static int update_size(mddev_t *mddev, sector_t num_sectors) ...@@ -4634,6 +4639,11 @@ static int update_size(mddev_t *mddev, sector_t num_sectors)
*/ */
if (mddev->sync_thread) if (mddev->sync_thread)
return -EBUSY; return -EBUSY;
if (mddev->bitmap)
/* Sorry, cannot grow a bitmap yet, just remove it,
* grow, and re-add.
*/
return -EBUSY;
rdev_for_each(rdev, tmp, mddev) { rdev_for_each(rdev, tmp, mddev) {
sector_t avail; sector_t avail;
avail = rdev->size * 2; avail = rdev->size * 2;
...@@ -5993,7 +6003,7 @@ static int remove_and_add_spares(mddev_t *mddev) ...@@ -5993,7 +6003,7 @@ static int remove_and_add_spares(mddev_t *mddev)
} }
} }
if (mddev->degraded) { if (mddev->degraded && ! mddev->ro) {
rdev_for_each(rdev, rtmp, mddev) { rdev_for_each(rdev, rtmp, mddev) {
if (rdev->raid_disk >= 0 && if (rdev->raid_disk >= 0 &&
!test_bit(In_sync, &rdev->flags) && !test_bit(In_sync, &rdev->flags) &&
...@@ -6067,6 +6077,8 @@ void md_check_recovery(mddev_t *mddev) ...@@ -6067,6 +6077,8 @@ void md_check_recovery(mddev_t *mddev)
flush_signals(current); flush_signals(current);
} }
if (mddev->ro && !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
return;
if ( ! ( if ( ! (
(mddev->flags && !mddev->external) || (mddev->flags && !mddev->external) ||
test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
...@@ -6080,6 +6092,15 @@ void md_check_recovery(mddev_t *mddev) ...@@ -6080,6 +6092,15 @@ void md_check_recovery(mddev_t *mddev)
if (mddev_trylock(mddev)) { if (mddev_trylock(mddev)) {
int spares = 0; int spares = 0;
if (mddev->ro) {
/* Only thing we do on a ro array is remove
* failed devices.
*/
remove_and_add_spares(mddev);
clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
goto unlock;
}
if (!mddev->external) { if (!mddev->external) {
int did_change = 0; int did_change = 0;
spin_lock_irq(&mddev->write_lock); spin_lock_irq(&mddev->write_lock);
...@@ -6117,7 +6138,8 @@ void md_check_recovery(mddev_t *mddev) ...@@ -6117,7 +6138,8 @@ void md_check_recovery(mddev_t *mddev)
/* resync has finished, collect result */ /* resync has finished, collect result */
md_unregister_thread(mddev->sync_thread); md_unregister_thread(mddev->sync_thread);
mddev->sync_thread = NULL; mddev->sync_thread = NULL;
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
/* success...*/ /* success...*/
/* activate any spares */ /* activate any spares */
if (mddev->pers->spare_active(mddev)) if (mddev->pers->spare_active(mddev))
...@@ -6169,6 +6191,7 @@ void md_check_recovery(mddev_t *mddev) ...@@ -6169,6 +6191,7 @@ void md_check_recovery(mddev_t *mddev)
} else if ((spares = remove_and_add_spares(mddev))) { } else if ((spares = remove_and_add_spares(mddev))) {
clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
} else if (mddev->recovery_cp < MaxSector) { } else if (mddev->recovery_cp < MaxSector) {
set_bit(MD_RECOVERY_SYNC, &mddev->recovery); set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
...@@ -6232,7 +6255,11 @@ static int md_notify_reboot(struct notifier_block *this, ...@@ -6232,7 +6255,11 @@ static int md_notify_reboot(struct notifier_block *this,
for_each_mddev(mddev, tmp) for_each_mddev(mddev, tmp)
if (mddev_trylock(mddev)) { if (mddev_trylock(mddev)) {
do_md_stop (mddev, 1, 0); /* Force a switch to readonly even array
* appears to still be in use. Hence
* the '100'.
*/
do_md_stop (mddev, 1, 100);
mddev_unlock(mddev); mddev_unlock(mddev);
} }
/* /*
......
...@@ -76,11 +76,13 @@ static void r10bio_pool_free(void *r10_bio, void *data) ...@@ -76,11 +76,13 @@ static void r10bio_pool_free(void *r10_bio, void *data)
kfree(r10_bio); kfree(r10_bio);
} }
/* Maximum size of each resync request */
#define RESYNC_BLOCK_SIZE (64*1024) #define RESYNC_BLOCK_SIZE (64*1024)
//#define RESYNC_BLOCK_SIZE PAGE_SIZE
#define RESYNC_SECTORS (RESYNC_BLOCK_SIZE >> 9)
#define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE) #define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE)
#define RESYNC_WINDOW (2048*1024) /* amount of memory to reserve for resync requests */
#define RESYNC_WINDOW (1024*1024)
/* maximum number of concurrent requests, memory permitting */
#define RESYNC_DEPTH (32*1024*1024/RESYNC_BLOCK_SIZE)
/* /*
* When performing a resync, we need to read and compare, so * When performing a resync, we need to read and compare, so
...@@ -690,7 +692,6 @@ static int flush_pending_writes(conf_t *conf) ...@@ -690,7 +692,6 @@ static int flush_pending_writes(conf_t *conf)
* there is no normal IO happeing. It must arrange to call * there is no normal IO happeing. It must arrange to call
* lower_barrier when the particular background IO completes. * lower_barrier when the particular background IO completes.
*/ */
#define RESYNC_DEPTH 32
static void raise_barrier(conf_t *conf, int force) static void raise_barrier(conf_t *conf, int force)
{ {
......
...@@ -2568,10 +2568,10 @@ static bool handle_stripe5(struct stripe_head *sh) ...@@ -2568,10 +2568,10 @@ static bool handle_stripe5(struct stripe_head *sh)
if (dev->written) if (dev->written)
s.written++; s.written++;
rdev = rcu_dereference(conf->disks[i].rdev); rdev = rcu_dereference(conf->disks[i].rdev);
if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) { if (blocked_rdev == NULL &&
rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
blocked_rdev = rdev; blocked_rdev = rdev;
atomic_inc(&rdev->nr_pending); atomic_inc(&rdev->nr_pending);
break;
} }
if (!rdev || !test_bit(In_sync, &rdev->flags)) { if (!rdev || !test_bit(In_sync, &rdev->flags)) {
/* The ReadError flag will just be confusing now */ /* The ReadError flag will just be confusing now */
...@@ -2588,9 +2588,15 @@ static bool handle_stripe5(struct stripe_head *sh) ...@@ -2588,9 +2588,15 @@ static bool handle_stripe5(struct stripe_head *sh)
rcu_read_unlock(); rcu_read_unlock();
if (unlikely(blocked_rdev)) { if (unlikely(blocked_rdev)) {
if (s.syncing || s.expanding || s.expanded ||
s.to_write || s.written) {
set_bit(STRIPE_HANDLE, &sh->state); set_bit(STRIPE_HANDLE, &sh->state);
goto unlock; goto unlock;
} }
/* There is nothing for the blocked_rdev to block */
rdev_dec_pending(blocked_rdev, conf->mddev);
blocked_rdev = NULL;
}
if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) { if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) {
set_bit(STRIPE_OP_BIOFILL, &s.ops_request); set_bit(STRIPE_OP_BIOFILL, &s.ops_request);
...@@ -2832,10 +2838,10 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page) ...@@ -2832,10 +2838,10 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
if (dev->written) if (dev->written)
s.written++; s.written++;
rdev = rcu_dereference(conf->disks[i].rdev); rdev = rcu_dereference(conf->disks[i].rdev);
if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) { if (blocked_rdev == NULL &&
rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
blocked_rdev = rdev; blocked_rdev = rdev;
atomic_inc(&rdev->nr_pending); atomic_inc(&rdev->nr_pending);
break;
} }
if (!rdev || !test_bit(In_sync, &rdev->flags)) { if (!rdev || !test_bit(In_sync, &rdev->flags)) {
/* The ReadError flag will just be confusing now */ /* The ReadError flag will just be confusing now */
...@@ -2853,9 +2859,16 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page) ...@@ -2853,9 +2859,16 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
rcu_read_unlock(); rcu_read_unlock();
if (unlikely(blocked_rdev)) { if (unlikely(blocked_rdev)) {
if (s.syncing || s.expanding || s.expanded ||
s.to_write || s.written) {
set_bit(STRIPE_HANDLE, &sh->state); set_bit(STRIPE_HANDLE, &sh->state);
goto unlock; goto unlock;
} }
/* There is nothing for the blocked_rdev to block */
rdev_dec_pending(blocked_rdev, conf->mddev);
blocked_rdev = NULL;
}
pr_debug("locked=%d uptodate=%d to_read=%d" pr_debug("locked=%d uptodate=%d to_read=%d"
" to_write=%d failed=%d failed_num=%d,%d\n", " to_write=%d failed=%d failed_num=%d,%d\n",
s.locked, s.uptodate, s.to_read, s.to_write, s.failed, s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
...@@ -4446,6 +4459,9 @@ static int raid5_check_reshape(mddev_t *mddev) ...@@ -4446,6 +4459,9 @@ static int raid5_check_reshape(mddev_t *mddev)
return -EINVAL; /* Cannot shrink array or change level yet */ return -EINVAL; /* Cannot shrink array or change level yet */
if (mddev->delta_disks == 0) if (mddev->delta_disks == 0)
return 0; /* nothing to do */ return 0; /* nothing to do */
if (mddev->bitmap)
/* Cannot grow a bitmap yet */
return -EBUSY;
/* Can only proceed if there are plenty of stripe_heads. /* Can only proceed if there are plenty of stripe_heads.
* We need a minimum of one full stripe,, and for sensible progress * We need a minimum of one full stripe,, and for sensible progress
......
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