md: allow parallel resync of md-devices.

In some configurations, a raid6 resync can be limited by CPU speed
(Calculating P and Q and moving data) rather than by device speed.  In
these cases there is nothing to be gained byt serialising resync of arrays
that share a device, and doing the resync in parallel can provide benefit.
 So add a sysfs tunable to flag an array as being allowed to resync in
parallel with other arrays that use (a different part of) the same device.

Signed-off-by: Bernd Schubert <bs@q-leap.de>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Bernd Schubert 2008-05-23 13:04:38 -07:00 committed by Linus Torvalds
parent 4f54b0e948
commit 90b08710e4
2 changed files with 39 additions and 4 deletions

View file

@ -74,6 +74,8 @@ static DEFINE_SPINLOCK(pers_lock);
static void md_print_devices(void); static void md_print_devices(void);
static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
#define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); } #define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); }
/* /*
@ -3012,6 +3014,36 @@ degraded_show(mddev_t *mddev, char *page)
} }
static struct md_sysfs_entry md_degraded = __ATTR_RO(degraded); static struct md_sysfs_entry md_degraded = __ATTR_RO(degraded);
static ssize_t
sync_force_parallel_show(mddev_t *mddev, char *page)
{
return sprintf(page, "%d\n", mddev->parallel_resync);
}
static ssize_t
sync_force_parallel_store(mddev_t *mddev, const char *buf, size_t len)
{
long n;
if (strict_strtol(buf, 10, &n))
return -EINVAL;
if (n != 0 && n != 1)
return -EINVAL;
mddev->parallel_resync = n;
if (mddev->sync_thread)
wake_up(&resync_wait);
return len;
}
/* force parallel resync, even with shared block devices */
static struct md_sysfs_entry md_sync_force_parallel =
__ATTR(sync_force_parallel, S_IRUGO|S_IWUSR,
sync_force_parallel_show, sync_force_parallel_store);
static ssize_t static ssize_t
sync_speed_show(mddev_t *mddev, char *page) sync_speed_show(mddev_t *mddev, char *page)
{ {
@ -3187,6 +3219,7 @@ static struct attribute *md_redundancy_attrs[] = {
&md_sync_min.attr, &md_sync_min.attr,
&md_sync_max.attr, &md_sync_max.attr,
&md_sync_speed.attr, &md_sync_speed.attr,
&md_sync_force_parallel.attr,
&md_sync_completed.attr, &md_sync_completed.attr,
&md_max_sync.attr, &md_max_sync.attr,
&md_suspend_lo.attr, &md_suspend_lo.attr,
@ -5487,8 +5520,6 @@ void md_allow_write(mddev_t *mddev)
} }
EXPORT_SYMBOL_GPL(md_allow_write); EXPORT_SYMBOL_GPL(md_allow_write);
static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
#define SYNC_MARKS 10 #define SYNC_MARKS 10
#define SYNC_MARK_STEP (3*HZ) #define SYNC_MARK_STEP (3*HZ)
void md_do_sync(mddev_t *mddev) void md_do_sync(mddev_t *mddev)
@ -5552,8 +5583,9 @@ void md_do_sync(mddev_t *mddev)
for_each_mddev(mddev2, tmp) { for_each_mddev(mddev2, tmp) {
if (mddev2 == mddev) if (mddev2 == mddev)
continue; continue;
if (mddev2->curr_resync && if (!mddev->parallel_resync
match_mddev_units(mddev,mddev2)) { && mddev2->curr_resync
&& match_mddev_units(mddev, mddev2)) {
DEFINE_WAIT(wq); DEFINE_WAIT(wq);
if (mddev < mddev2 && mddev->curr_resync == 2) { if (mddev < mddev2 && mddev->curr_resync == 2) {
/* arbitrarily yield */ /* arbitrarily yield */

View file

@ -180,6 +180,9 @@ struct mddev_s
int sync_speed_min; int sync_speed_min;
int sync_speed_max; int sync_speed_max;
/* resync even though the same disks are shared among md-devices */
int parallel_resync;
int ok_start_degraded; int ok_start_degraded;
/* recovery/resync flags /* recovery/resync flags
* NEEDED: we might need to start a resync/recover * NEEDED: we might need to start a resync/recover