@@ -790,17 +790,25 @@ static void merge_callback(int read_err, unsigned long write_err, void *context)
* so that dm_consecutive_chunk_count_dec() accounting works
*/
for (i = s->merge_write_interlock_n - 1; i >= 0; i--) {
- e = lookup_exception(&s->complete,
- s->merge_write_interlock + i);
+ chunk_t old_chunk = s->merge_write_interlock + i;
+ e = lookup_exception(&s->complete, old_chunk);
if (!e) {
DMERR("exception for block %llu is on "
"disk but not in memory",
- (unsigned long long)
- s->merge_write_interlock + i);
+ (unsigned long long)old_chunk);
up_write(&s->lock);
goto shut;
}
if (dm_consecutive_chunk_count(e)) {
+ if (old_chunk == e->old_chunk) {
+ e->old_chunk++;
+ e->new_chunk++;
+ } else if (old_chunk != e->old_chunk +
+ dm_consecutive_chunk_count(e)) {
+ DMERR("merge from the middle of a chunk range");
+ up_write(&s->lock);
+ goto shut;
+ }
dm_consecutive_chunk_count_dec(e);
} else {
remove_exception(e);