===================================================================
@@ -57,6 +57,7 @@ struct mirror_set {
struct bio_list reads;
struct bio_list writes;
struct bio_list failures;
+ struct bio_list hold; /* bios are waiting until suspend */
struct dm_region_hash *rh;
struct dm_kcopyd_client *kcopyd_client;
@@ -415,6 +416,20 @@ static void map_region(struct dm_io_regi
io->count = bio->bi_size >> 9;
}
+static void hold_bio(struct mirror_set *ms, struct bio *bio)
+{
+ if (atomic_read(&ms->suspend)) {
+ if (dm_noflush_suspending(ms->ti))
+ bio_endio(bio, DM_ENDIO_REQUEUE);
+ else
+ bio_endio(bio, -EIO);
+ } else {
+ spin_lock_irq(&ms->lock);
+ bio_list_add(&ms->hold, bio);
+ spin_unlock_irq(&ms->lock);
+ }
+}
+
/*-----------------------------------------------------------------
* Reads
*---------------------------------------------------------------*/
@@ -760,6 +775,7 @@ static void do_mirror(struct work_struct
bio_list_init(&ms->reads);
bio_list_init(&ms->writes);
bio_list_init(&ms->failures);
+ bio_list_init(&ms->hold);
spin_unlock_irqrestore(&ms->lock, flags);
dm_rh_update_states(ms->rh, errors_handled(ms));
@@ -1192,6 +1208,9 @@ static void mirror_presuspend(struct dm_
struct mirror_set *ms = (struct mirror_set *) ti->private;
struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh);
+ struct bio_list hold;
+ struct bio *bio;
+
atomic_set(&ms->suspend, 1);
/*
@@ -1214,6 +1233,23 @@ static void mirror_presuspend(struct dm_
* we know that all of our I/O has been pushed.
*/
flush_workqueue(ms->kmirrord_wq);
+
+ /*
+ * Once we set ms->suspend and flush the workqueue,
+ * no more entries are being added to ms->hold list.
+ * Process the list now.
+ *
+ * (note that bios can still arive concurrently with
+ * or after presuspend, but they are never put to
+ * hold list because of ms->suspend != 0).
+ */
+ spin_lock_irq(&ms->lock);
+ hold = ms->hold;
+ bio_list_init(&ms->hold);
+ spin_unlock_irq(&ms->lock);
+
+ while ((bio = bio_list_pop(&hold)))
+ hold_bio(ms, bio);
}
static void mirror_postsuspend(struct dm_target *ti)