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) ...@@ -3160,7 +3160,7 @@ int md_do_sync(mddev_t *mddev, mdp_disk_t *spare)
{ {
mddev_t *mddev2; mddev_t *mddev2;
unsigned int max_sectors, currspeed = 0, unsigned int max_sectors, currspeed = 0,
j, window, err, serialize; j, window, err;
unsigned long mark[SYNC_MARKS]; unsigned long mark[SYNC_MARKS];
unsigned long mark_cnt[SYNC_MARKS]; unsigned long mark_cnt[SYNC_MARKS];
int last_mark,m; int last_mark,m;
...@@ -3168,30 +3168,36 @@ int md_do_sync(mddev_t *mddev, mdp_disk_t *spare) ...@@ -3168,30 +3168,36 @@ int md_do_sync(mddev_t *mddev, mdp_disk_t *spare)
unsigned long last_check; unsigned long last_check;
recheck: /* we overload curr_resync somewhat here.
serialize = 0; * 0 == not engaged in resync at all
ITERATE_MDDEV(mddev2,tmp) { * 2 == checking that there is no conflict with another sync
if (mddev2 == mddev) * 1 == like 2, but have yielded to allow conflicting resync to
continue; * commense
if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) { * other == active in resync - this many blocks
printk(KERN_INFO "md: delaying resync of md%d until md%d " */
"has finished resync (they share one or more physical units)\n", do {
mdidx(mddev), mdidx(mddev2)); mddev->curr_resync = 2;
serialize = 1;
break; ITERATE_MDDEV(mddev2,tmp) {
} if (mddev2 == mddev)
} continue;
if (serialize) { if (mddev2->curr_resync &&
interruptible_sleep_on(&resync_wait); match_mddev_units(mddev,mddev2)) {
if (signal_pending(current)) { printk(KERN_INFO "md: delaying resync of md%d until md%d "
flush_curr_signals(); "has finished resync (they share one or more physical units)\n",
err = -EINTR; mdidx(mddev), mdidx(mddev2));
goto out; 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; max_sectors = mddev->sb->size << 1;
printk(KERN_INFO "md: syncing RAID array md%d\n", mdidx(mddev)); 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) ...@@ -3229,7 +3235,7 @@ int md_do_sync(mddev_t *mddev, mdp_disk_t *spare)
} }
atomic_add(sectors, &mddev->recovery_active); atomic_add(sectors, &mddev->recovery_active);
j += sectors; j += sectors;
mddev->curr_resync = j; if (j>1) mddev->curr_resync = j;
if (last_check + window > j) if (last_check + window > j)
continue; 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