diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index f150f5c5492b..d701fe53bc96 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -4,6 +4,7 @@
  * This file is released under the GPL.
  */
 
+#include <linux/bio.h>
 #include <linux/blkdev.h>
 #include <linux/device-mapper.h>
 #include <linux/delay.h>
@@ -19,6 +20,7 @@
 #include <linux/log2.h>
 #include <linux/dm-kcopyd.h>
 #include <linux/semaphore.h>
+#include <linux/workqueue.h>
 
 #include "dm.h"
 
@@ -94,11 +96,12 @@ struct dm_snapshot {
 	struct dm_exception_table pending;
 	struct dm_exception_table complete;
 
-	/*
-	 * pe_lock protects all pending_exception operations and access
-	 * as well as the snapshot_bios list.
-	 */
-	spinlock_t pe_lock;
+	/* Origin bios queued for resubmission to the origin device. */
+	spinlock_t deferred_bios_lock;
+	struct bio_list deferred_origin_bios;
+
+	struct workqueue_struct *wq;
+	struct work_struct deferred_bios_work;
 
 	/* Chunks with outstanding reads */
 	spinlock_t tracked_chunk_lock;
@@ -1224,6 +1227,8 @@ static int parse_snapshot_features(struct dm_arg_set *as, struct dm_snapshot *s,
 	return r;
 }
 
+static void process_deferred_bios(struct work_struct *work);
+
 /*
  * Construct a snapshot mapping:
  * <origin_dev> <COW-dev> <p|po|n> <chunk-size> [<# feature args> [<arg>]*]
@@ -1313,7 +1318,8 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 	s->out_of_order_tree = RB_ROOT;
 	init_rwsem(&s->lock);
 	INIT_LIST_HEAD(&s->list);
-	spin_lock_init(&s->pe_lock);
+	spin_lock_init(&s->deferred_bios_lock);
+	bio_list_init(&s->deferred_origin_bios);
 	s->state_bits = 0;
 	s->merge_failed = 0;
 	s->first_merging_chunk = 0;
@@ -1336,6 +1342,15 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 		goto bad_kcopyd;
 	}
 
+	s->wq = alloc_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM, 0);
+	if (!s->wq) {
+		ti->error = "Could not allocate workqueue";
+		r = -ENOMEM;
+		goto bad_workqueue;
+	}
+
+	INIT_WORK(&s->deferred_bios_work, process_deferred_bios);
+
 	r = mempool_init_slab_pool(&s->pending_pool, MIN_IOS, pending_cache);
 	if (r) {
 		ti->error = "Could not allocate mempool for pending exceptions";
@@ -1401,6 +1416,8 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 bad_load_and_register:
 	mempool_exit(&s->pending_pool);
 bad_pending_pool:
+	destroy_workqueue(s->wq);
+bad_workqueue:
 	dm_kcopyd_client_destroy(s->kcopyd_client);
 bad_kcopyd:
 	dm_exception_table_exit(&s->pending, pending_cache);
@@ -1423,6 +1440,12 @@ static void __free_exceptions(struct dm_snapshot *s)
 	dm_kcopyd_client_destroy(s->kcopyd_client);
 	s->kcopyd_client = NULL;
 
+	/*
+	 * destroy_workqueue() drains the workqueue so any pending origin bios
+	 * will be sumbitted before it returns.
+	 */
+	destroy_workqueue(s->wq);
+
 	dm_exception_table_exit(&s->pending, pending_cache);
 	dm_exception_table_exit(&s->complete, exception_cache);
 }
@@ -1534,9 +1557,11 @@ static int do_origin(struct dm_dev *origin, struct bio *bio);
  */
 static void retry_origin_bios(struct dm_snapshot *s, struct bio *bio)
 {
+	struct blk_plug plug;
 	struct bio *n;
 	int r;
 
+	blk_start_plug(&plug);
 	while (bio) {
 		n = bio->bi_next;
 		bio->bi_next = NULL;
@@ -1545,6 +1570,28 @@ static void retry_origin_bios(struct dm_snapshot *s, struct bio *bio)
 			generic_make_request(bio);
 		bio = n;
 	}
+	blk_finish_plug(&plug);
+}
+
+static void process_deferred_bios(struct work_struct *work)
+{
+	struct dm_snapshot *s = container_of(work, typeof(*s), deferred_bios_work);
+	struct bio *origin_bios;
+
+	spin_lock(&s->deferred_bios_lock);
+	origin_bios = bio_list_get(&s->deferred_origin_bios);
+	spin_unlock(&s->deferred_bios_lock);
+
+	retry_origin_bios(s, origin_bios);
+}
+
+static void issue_origin_bios(struct dm_snapshot *s, struct bio_list *origin_bios)
+{
+	spin_lock(&s->deferred_bios_lock);
+	bio_list_merge(&s->deferred_origin_bios, origin_bios);
+	spin_unlock(&s->deferred_bios_lock);
+
+	queue_work(s->wq, &s->deferred_bios_work);
 }
 
 /*
@@ -1592,7 +1639,6 @@ static void pending_complete(void *context, int success)
 	struct dm_snap_pending_exception *pe = context;
 	struct dm_exception *e;
 	struct dm_snapshot *s = pe->snap;
-	struct bio *origin_bios = NULL;
 	struct bio *snapshot_bios = NULL;
 	struct bio *full_bio = NULL;
 	struct dm_exception_table_lock lock;
@@ -1653,7 +1699,6 @@ static void pending_complete(void *context, int success)
 	dm_exception_table_unlock(&lock);
 
 	snapshot_bios = bio_list_get(&pe->snapshot_bios);
-	origin_bios = bio_list_get(&pe->origin_bios);
 	full_bio = pe->full_bio;
 	if (full_bio)
 		full_bio->bi_end_io = pe->full_bio_end_io;
@@ -1670,7 +1715,43 @@ static void pending_complete(void *context, int success)
 		flush_bios(snapshot_bios);
 	}
 
-	retry_origin_bios(s, origin_bios);
+	/*
+	 * In order to retry the origin bios we have to acquire a read lock on
+	 * _origins_lock. This could lead to a deadlock:
+	 *
+	 * 1. One or more threads write to the origin device causing COW, which
+	 *    is performed by kcopyd.
+	 *
+	 * 2. At some point some of these threads might reach the s->cow_count
+	 *    semaphore limit and block in down(&s->cow_count), holding a read
+	 *    lock on _origins_lock.
+	 *
+	 * 3. Someone tries to acquire a write lock on _origins_lock, e.g.,
+	 *    snapshot_ctr(), which blocks because the threads at step (2)
+	 *    already hold a read lock on it.
+	 *
+	 * 4. A COW operation completes and kcopyd runs our completion
+	 *    callback, which ends up calling pending_complete(). If we
+	 *    resubmit the origin bios from pending_complete(), which runs in
+	 *    the kcopyd thread, it will block trying to acquire a read lock on
+	 *    _origins_lock.
+	 *
+	 *    This happens because the read-write semaphore implementation
+	 *    gives priority to writers, meaning that as soon as a writer tries
+	 *    to enter the critical section, no readers will be allowed in,
+	 *    until all writers have completed their work.
+	 *
+	 *    So, we wait for the writer at step (3) to acquire and release the
+	 *    lock. This writer waits for the readers at step (2) to release
+	 *    the read lock and those readers wait for us (the kcopyd thread)
+	 *    to signal the s->cow_count semaphore: DEADLOCK.
+	 *
+	 * To avoid this we delegate the resubmission of the origin bios to
+	 * another thread, so the kcopyd thread never tries to acquire
+	 * _origins_lock and it's free to continue its work and signal the
+	 * s->cow_count semaphore.
+	 */
+	issue_origin_bios(s, &pe->origin_bios);
 
 	free_pending_exception(pe);
 }
