+
+ clear_bit(DMF_BLOCK_IO, &md->flags);
+}
+
+static void __merge_pushback_list(struct mapped_device *md)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&md->pushback_lock, flags);
+ clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
+ bio_list_merge_head(&md->deferred, &md->pushback);
+ bio_list_init(&md->pushback);
+ spin_unlock_irqrestore(&md->pushback_lock, flags);
+}
+
+static void dm_wq_work(struct work_struct *work)
+{
+ struct dm_wq_req *req = container_of(work, struct dm_wq_req, work);
+ struct mapped_device *md = req->md;
+
+ down_write(&md->io_lock);
+ switch (req->type) {
+ case DM_WQ_FLUSH_ALL:
+ __merge_pushback_list(md);
+ /* pass through */
+ case DM_WQ_FLUSH_DEFERRED:
+ __flush_deferred_io(md);
+ break;
+ default:
+ DMERR("dm_wq_work: unrecognised work type %d", req->type);
+ BUG();
+ }
+ up_write(&md->io_lock);
+}
+
+static void dm_wq_queue(struct mapped_device *md, int type, void *context,
+ struct dm_wq_req *req)
+{
+ req->type = type;
+ req->md = md;
+ req->context = context;
+ INIT_WORK(&req->work, dm_wq_work);
+ queue_work(md->wq, &req->work);
+}
+
+static void dm_queue_flush(struct mapped_device *md, int type, void *context)
+{
+ struct dm_wq_req req;
+
+ dm_wq_queue(md, type, context, &req);
+ flush_workqueue(md->wq);