Move the sync count from the mirror set to the log.

Newly synced regions weren't being marked clean.

[AJ Lewis]
--- diff/drivers/md/dm-log.c	2004-01-14 14:42:18.000000000 +0000
+++ source/drivers/md/dm-log.c	2004-01-27 14:57:58.000000000 +0000
@@ -133,6 +133,7 @@
 	int touched;
 	sector_t region_size;
 	unsigned int region_count;
+	region_t sync_count;
 
 	unsigned bitset_uint32_count;
 	uint32_t *clean_bits;
@@ -334,6 +335,7 @@
 		return -ENOMEM;
 	}
 	memset(lc->sync_bits, 0, bitset_size);
+        lc->sync_count = 0;
 
 	lc->recovering_bits = vmalloc(bitset_size);
 	if (!lc->recovering_bits) {
@@ -430,6 +432,27 @@
 	core_dtr(log);
 }
 
+static int count_bits(const unsigned long *addr, unsigned size)
+{
+	/* FIXME: test this */
+#if 1
+	int n, count = 0;
+
+	n = find_first_bit(addr, size);
+	while (n < size) {
+		count++;
+		find_next_bit(addr, size, n + 1);
+	}
+
+	return count;
+#else
+	int count = 0;
+        for (i = 0; i < lc->region_count; i++)
+                count += log_test_bit(lc->sync_bits, i);
+	return count;
+#endif
+}
+
 static int disk_resume(struct dirty_log *log)
 {
 	int r;
@@ -454,6 +477,7 @@
 
 	/* copy clean across to sync */
 	memcpy(lc->sync_bits, lc->clean_bits, size);
+	lc->sync_count = count_bits((const unsigned long *) lc->clean_bits, size);
 
 	/* write the bits */
 	r = write_bits(lc);
@@ -547,8 +571,17 @@
 	struct log_c *lc = (struct log_c *) log->context;
 
 	log_clear_bit(lc, lc->recovering_bits, region);
-	if (success)
+	if (success) {
 		log_set_bit(lc, lc->sync_bits, region);
+                lc->sync_count++;
+        }
+}
+
+static region_t core_get_sync_count(struct dirty_log *log)
+{
+        struct log_c *lc = (struct log_c *) log->context;
+
+        return lc->sync_count;
 }
 
 static struct dirty_log_type _core_type = {
@@ -562,7 +595,8 @@
 	.mark_region = core_mark_region,
 	.clear_region = core_clear_region,
 	.get_resync_work = core_get_resync_work,
-	.complete_resync_work = core_complete_resync_work
+	.complete_resync_work = core_complete_resync_work,
+        .get_sync_count = core_get_sync_count
 };
 
 static struct dirty_log_type _disk_type = {
@@ -578,7 +612,8 @@
 	.mark_region = core_mark_region,
 	.clear_region = core_clear_region,
 	.get_resync_work = core_get_resync_work,
-	.complete_resync_work = core_complete_resync_work
+	.complete_resync_work = core_complete_resync_work,
+        .get_sync_count = core_get_sync_count
 };
 
 __init int dm_dirty_log_init(void)
--- diff/drivers/md/dm-log.h	2003-12-29 10:17:03.000000000 +0000
+++ source/drivers/md/dm-log.h	2004-01-27 15:01:29.000000000 +0000
@@ -96,6 +96,11 @@
 	 */
 	void (*complete_resync_work)(struct dirty_log *log,
 				     region_t region, int success);
+
+        /*
+	 * Returns the number of regions that are in sync.
+         */
+        region_t (*get_sync_count)(struct dirty_log *log);
 };
 
 int dm_register_dirty_log_type(struct dirty_log_type *type);
--- diff/drivers/md/dm-raid1.c	2004-01-16 13:57:42.000000000 +0000
+++ source/drivers/md/dm-raid1.c	2004-01-27 15:40:17.000000000 +0000
@@ -356,6 +356,7 @@
 	list_for_each_safe (tmp, tmp2, &recovered) {
 		reg = list_entry(tmp, struct region, list);
 
+		rh->log->type->clear_region(rh->log, reg->key);
 		rh->log->type->complete_resync_work(rh->log, reg->key, 1);
 		dispatch_bios(rh->ms, reg->delayed_bios);
 		up(&rh->recovery_count);
@@ -556,7 +557,7 @@
 
 	/* recovery */
 	region_t nr_regions;
-	region_t sync_count;
+	int in_sync;
 
 	unsigned int nr_mirrors;
 	struct mirror mirror[0];
@@ -593,15 +594,11 @@
 			      void *context)
 {
 	struct region *reg = (struct region *) context;
-	struct mirror_set *ms = reg->rh->ms;
 
 	/* FIXME: we need to flush the log */
 
 	/* FIXME: better error handling */
 	rh_recovery_end(reg, read_err || write_err);
-	if (++ms->sync_count == ms->nr_regions)
-		/* the sync is complete */
-		dm_table_event(ms->ti->table);
 }
 
 static int recover(struct mirror_set *ms, struct region *reg)
@@ -651,6 +648,7 @@
 {
 	int r;
 	struct region *reg;
+	struct dirty_log *log = ms->rh.log;
 
 	/*
 	 * Start quiescing some regions.
@@ -665,6 +663,16 @@
 		if (r)
 			rh_recovery_end(reg, 0);
 	}
+
+	/*
+	 * Update the in sync flag.
+	 */
+	if (!ms->in_sync &&
+	    (log->type->get_sync_count(log) == ms->nr_regions)) {
+		/* the sync is complete */
+		dm_table_event(ms->ti->table);
+		ms->in_sync = 1;
+	}
 }
 
 /*-----------------------------------------------------------------
@@ -893,6 +901,7 @@
 	ms->ti = ti;
 	ms->nr_mirrors = nr_mirrors;
 	ms->nr_regions = dm_div_up(ti->len, region_size);
+	ms->in_sync = 0;
 
 	if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) {
 		ti->error = "dm-mirror: Error creating dirty region hash";
@@ -1193,7 +1202,8 @@
 
 		sz += snprintf(result + sz, maxlen - sz,
 			       SECTOR_FORMAT "/" SECTOR_FORMAT,
-			       ms->sync_count, ms->nr_regions);
+			       ms->rh.log->type->get_sync_count(ms->rh.log),
+			       ms->nr_regions);
 		break;
 
 	case STATUSTYPE_TABLE:
