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.
This commit is contained in:
@@ -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)
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
} 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,
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
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,8 +2588,14 @@ static bool handle_stripe5(struct stripe_head *sh)
|
|||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (unlikely(blocked_rdev)) {
|
if (unlikely(blocked_rdev)) {
|
||||||
set_bit(STRIPE_HANDLE, &sh->state);
|
if (s.syncing || s.expanding || s.expanded ||
|
||||||
goto unlock;
|
s.to_write || s.written) {
|
||||||
|
set_bit(STRIPE_HANDLE, &sh->state);
|
||||||
|
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)) {
|
||||||
@@ -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)
|
|||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (unlikely(blocked_rdev)) {
|
if (unlikely(blocked_rdev)) {
|
||||||
set_bit(STRIPE_HANDLE, &sh->state);
|
if (s.syncing || s.expanding || s.expanded ||
|
||||||
goto unlock;
|
s.to_write || s.written) {
|
||||||
|
set_bit(STRIPE_HANDLE, &sh->state);
|
||||||
|
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)
|
|||||||
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
|
||||||
|
Reference in New Issue
Block a user