Recheck that the exception hasn't entered the pending table by another thread. --- diff/drivers/md/dm-snapshot.c 2003-11-26 10:19:17.000000000 +0000 +++ source/drivers/md/dm-snapshot.c 2003-11-26 10:19:22.000000000 +0000 @@ -808,22 +808,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;