Commit 2d35e42d authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] md 19 of 22 - Improve serialisation of md syncing

If two md arrays which share real devices (i.e they each own a partition
on some device) need to sync/reconstruct at the same time, it is much
more efficient to have one wait while the other completes.

The current code uses interruptible_sleep_on which isn't SMP safe (without the BKL).
This patch re-does this code to make it more secure.  Even it two start simultaneously,
one will reliably get priority, and the other wont wait for ever.
parent 7145dd24
......@@ -3160,7 +3160,7 @@ int md_do_sync(mddev_t *mddev, mdp_disk_t *spare)
{
mddev_t *mddev2;
unsigned int max_sectors, currspeed = 0,
j, window, err, serialize;
j, window, err;
unsigned long mark[SYNC_MARKS];
unsigned long mark_cnt[SYNC_MARKS];
int last_mark,m;
......@@ -3168,30 +3168,36 @@ int md_do_sync(mddev_t *mddev, mdp_disk_t *spare)
unsigned long last_check;
recheck:
serialize = 0;
ITERATE_MDDEV(mddev2,tmp) {
if (mddev2 == mddev)
continue;
if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) {
printk(KERN_INFO "md: delaying resync of md%d until md%d "
"has finished resync (they share one or more physical units)\n",
mdidx(mddev), mdidx(mddev2));
serialize = 1;
break;
}
}
if (serialize) {
interruptible_sleep_on(&resync_wait);
if (signal_pending(current)) {
flush_curr_signals();
err = -EINTR;
goto out;
/* we overload curr_resync somewhat here.
* 0 == not engaged in resync at all
* 2 == checking that there is no conflict with another sync
* 1 == like 2, but have yielded to allow conflicting resync to
* commense
* other == active in resync - this many blocks
*/
do {
mddev->curr_resync = 2;
ITERATE_MDDEV(mddev2,tmp) {
if (mddev2 == mddev)
continue;
if (mddev2->curr_resync &&
match_mddev_units(mddev,mddev2)) {
printk(KERN_INFO "md: delaying resync of md%d until md%d "
"has finished resync (they share one or more physical units)\n",
mdidx(mddev), mdidx(mddev2));
if (mddev < mddev2) /* arbitrarily yield */
mddev->curr_resync = 1;
if (wait_event_interruptible(resync_wait,
mddev2->curr_resync < 2)) {
flush_curr_signals();
err = -EINTR;
goto out;
}
}
}
goto recheck;
}
} while (mddev->curr_resync < 2);
mddev->curr_resync = 1;
max_sectors = mddev->sb->size << 1;
printk(KERN_INFO "md: syncing RAID array md%d\n", mdidx(mddev));
......@@ -3229,7 +3235,7 @@ int md_do_sync(mddev_t *mddev, mdp_disk_t *spare)
}
atomic_add(sectors, &mddev->recovery_active);
j += sectors;
mddev->curr_resync = j;
if (j>1) mddev->curr_resync = j;
if (last_check + window > j)
continue;
......
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