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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





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.



 ----------- Diffstat output ------------
 ./drivers/md/md.c |   54 ++++++++++++++++++++++++++++++------------------------
 1 files changed, 30 insertions(+), 24 deletions(-)

--- ./drivers/md/md.c	2002/06/18 05:29:05	1.18
+++ ./drivers/md/md.c	2002/06/18 05:33:38	1.19
@@ -3160,7 +3160,7 @@
 {
 	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 @@
 	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 @@
 		}
 		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;
-
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux