Resubmit partially completed IO.

Signed-off-by: Kirill Tkhai <[email protected]>
---
 drivers/md/dm-qcow2-map.c    |   37 ++++++++++++++++++++++++++++++++++---
 drivers/md/dm-qcow2-target.c |    1 +
 drivers/md/dm-qcow2.h        |    1 +
 3 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c
index c3706705c465..9d0649a54e2b 100644
--- a/drivers/md/dm-qcow2-map.c
+++ b/drivers/md/dm-qcow2-map.c
@@ -2698,6 +2698,19 @@ static int prepare_backward_merge(struct qcow2 *qcow2, 
struct qio **qio,
        return 0;
 }
 
+static void qcow2_queue_resubmit(struct qio *qio)
+{
+       struct qcow2 *qcow2 = qio->qcow2;
+       unsigned long flags;
+
+       qio->queue_list_id = QLIST_INVALID;
+
+       spin_lock_irqsave(&qcow2->deferred_lock, flags);
+       list_add_tail(&qio->link, &qcow2->resubmit_qios);
+       spin_unlock_irqrestore(&qcow2->deferred_lock, flags);
+       queue_work(qcow2->tgt->wq, &qcow2->worker);
+}
+
 static void data_rw_complete(struct qio *qio)
 {
        bool finalize_wbd = false, call_endio = true;
@@ -2707,9 +2720,15 @@ static void data_rw_complete(struct qio *qio)
        struct wb_desc *wbd;
        unsigned long flags;
 
-       /* FIXME: short read/write */
-       if (qio->ret != qio->bi_iter.bi_size)
-               bi_status = BLK_STS_IOERR;
+       if (unlikely(qio->ret != qio->bi_iter.bi_size)) {
+               if (qio->ret >= 0) {
+                       WARN_ON_ONCE(qio->ret == 0);
+                       qio_advance(qio, qio->ret);
+                       qcow2_queue_resubmit(qio);
+                       return;
+               }
+               bi_status = errno_to_blk_status(qio->ret);
+       }
 
        wbd = qio->data;
        if (wbd) {
@@ -3898,6 +3917,15 @@ next:            qio = qio_list_pop(qio_list);
                }
        }
 }
+static void process_resubmit_qios(struct qcow2 *qcow2, struct list_head *qios)
+{
+       struct qio *qio;
+
+       while ((qio = qio_list_pop(qios)) != NULL) {
+               qio->queue_list_id = QLIST_INVALID;
+               submit_rw_mapped(qcow2, qio);
+       }
+}
 
 void do_qcow2_work(struct work_struct *ws)
 {
@@ -3909,6 +3937,7 @@ void do_qcow2_work(struct work_struct *ws)
        LIST_HEAD(cow_data_qios);
        LIST_HEAD(cow_indexes_qios);
        LIST_HEAD(cow_end_qios);
+       LIST_HEAD(resubmit_qios);
        unsigned int pflags = current->flags;
 
        current->flags |= PF_LESS_THROTTLE|PF_MEMALLOC_NOIO;
@@ -3920,6 +3949,7 @@ void do_qcow2_work(struct work_struct *ws)
        list_splice_init(&qcow2->qios[QLIST_COW_DATA], &cow_data_qios);
        list_splice_init(&qcow2->qios[QLIST_COW_INDEXES], &cow_indexes_qios);
        list_splice_init(&qcow2->qios[QLIST_COW_END], &cow_end_qios);
+       list_splice_init(&qcow2->resubmit_qios, &resubmit_qios);
        spin_unlock_irq(&qcow2->deferred_lock);
 
        process_embedded_qios(qcow2, &embedded_qios, &deferred_qios);
@@ -3929,6 +3959,7 @@ void do_qcow2_work(struct work_struct *ws)
        process_cow_data_write(qcow2, &cow_data_qios);
        process_cow_indexes_write(qcow2, &cow_indexes_qios);
        process_cow_end(qcow2, &cow_end_qios);
+       process_resubmit_qios(qcow2, &resubmit_qios);
 
        /* This actually submits batch of md writeback, initiated above */
        submit_metadata_writeback(qcow2);
diff --git a/drivers/md/dm-qcow2-target.c b/drivers/md/dm-qcow2-target.c
index 895b69f0a767..8c878073ac55 100644
--- a/drivers/md/dm-qcow2-target.c
+++ b/drivers/md/dm-qcow2-target.c
@@ -580,6 +580,7 @@ static struct qcow2 *qcow2_alloc_delta(struct qcow2_target 
*tgt, struct qcow2 *u
 
        for (i = 0; i < QLIST_COUNT; i++)
                INIT_LIST_HEAD(&qcow2->qios[i]);
+       INIT_LIST_HEAD(&qcow2->resubmit_qios);
        INIT_LIST_HEAD(&qcow2->paused_qios);
        INIT_LIST_HEAD(&qcow2->wb_batch_list);
        INIT_LIST_HEAD(&qcow2->slow_wb_batch_list);
diff --git a/drivers/md/dm-qcow2.h b/drivers/md/dm-qcow2.h
index 58c6fe48fef0..4fa02eac0e2a 100644
--- a/drivers/md/dm-qcow2.h
+++ b/drivers/md/dm-qcow2.h
@@ -178,6 +178,7 @@ struct qcow2 {
        spinlock_t md_pages_lock;
 
        struct list_head qios[QLIST_COUNT];
+       struct list_head resubmit_qios;
        struct list_head paused_qios; /* For pause_submitting_qios */
 
        /* For batching md update: */


_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to