struct bio_list origin_bios;
        struct bio_list snapshot_bios;
 
+       /*
+        * Short-term queue of pending exceptions prior to submission.
+        */
+       struct list_head list;
+
        /*
         * Other pending_exceptions that are processing this
         * chunk.  When this list is empty, we know we can
        int r = 1, first = 1;
        struct dm_snapshot *snap;
        struct exception *e;
-       struct pending_exception *pe, *last = NULL;
+       struct pending_exception *pe, *next_pe, *last = NULL;
        chunk_t chunk;
+       LIST_HEAD(pe_queue);
 
        /* Do all the snapshots on this origin */
        list_for_each_entry (snap, snapshots, list) {
                                snap->valid = 0;
 
                        } else {
-                               if (last)
+                               if (first) {
+                                       bio_list_add(&pe->origin_bios, bio);
+                                       r = 0;
+                                       first = 0;
+                               }
+                               if (last && list_empty(&pe->siblings))
                                        list_merge(&pe->siblings,
                                                   &last->siblings);
-
+                               if (!pe->started) {
+                                       pe->started = 1;
+                                       list_add_tail(&pe->list, &pe_queue);
+                               }
                                last = pe;
-                               r = 0;
                        }
                }
 
        /*
         * Now that we have a complete pe list we can start the copying.
         */
-       if (last) {
-               pe = last;
-               do {
-                       down_write(&pe->snap->lock);
-                       if (first)
-                               bio_list_add(&pe->origin_bios, bio);
-                       if (!pe->started) {
-                               pe->started = 1;
-                               up_write(&pe->snap->lock);
-                               start_copy(pe);
-                       } else
-                               up_write(&pe->snap->lock);
-                       first = 0;
-                       pe = list_entry(pe->siblings.next,
-                                       struct pending_exception, siblings);
-
-               } while (pe != last);
-       }
+       list_for_each_entry_safe(pe, next_pe, &pe_queue, list)
+               start_copy(pe);
 
        return r;
 }