Dropping and retaking the snapshot lock around the allocation of the pending- exception means we need to check again for a pending exception before adding this new one to the snapshot map. --- a/drivers/md/dm-snapshot.c 2003-10-20 12:21:30.000000000 -0500 +++ b/drivers/md/dm-snapshot.c 2003-10-20 12:10:36.000000000 -0500 @@ -807,22 +807,28 @@ * to hold the lock while we do this. */ up_write(&s->lock); - pe = alloc_pending_exception(); - pe->e.old_chunk = chunk; - pe->origin_bios = pe->snapshot_bios = NULL; - INIT_LIST_HEAD(&pe->siblings); - pe->snap = s; - pe->started = 0; - down_write(&s->lock); - if (s->store.prepare_exception(&s->store, &pe->e)) { + + e = lookup_exception(&s->pending, chunk); + if (e) { free_pending_exception(pe); - s->valid = 0; - return NULL; - } + pe = list_entry(e, struct pending_exception, e); + } else { + pe->e.old_chunk = chunk; + pe->origin_bios = pe->snapshot_bios = NULL; + INIT_LIST_HEAD(&pe->siblings); + pe->snap = s; + pe->started = 0; - insert_exception(&s->pending, &pe->e); + if (s->store.prepare_exception(&s->store, &pe->e)) { + free_pending_exception(pe); + s->valid = 0; + return NULL; + } + + insert_exception(&s->pending, &pe->e); + } } return pe;