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: