The last step of processing of RELOC_A request is
nullifying BAT block. We smartly noticed, that flush
needed after that, but fsync is not enough:

>       /*
>        * Lately we think we does sync of nullified blocks at format
>        * driver by image fsync before header update.
>        * But we write this data directly into underlying device
>        * bypassing EXT4 by usage of extent map tree
>        * (see dio_submit()). So fsync of EXT4 image doesnt help us.
>        * We need to force sync of nullified blocks.
>        */
>       set_bit(PLOOP_REQ_FORCE_FUA, &preq->state);
>       top_delta->io.ops->submit(&top_delta->io, preq, preq->req_rw,
>                                 &sbl, preq->iblock, 1<<plo->cluster_log);

Unfortunately, the way how we handle FORCE_FUA in dio_submit
(sending last bio with REQ_FUA bit set) is not safe: firstly because
we decided that ploop shouldn't strongly rely on the assumption of
equivalence of REQ_FUA and post-FLUSH; and secondly because dio_submit
cannot ensure that that last bio marked as REQ_FUA won't be actually
processed before others.

To fix this problem the patch makes explicit ->issue_flush to flush
nullified block.

Signed-off-by: Maxim Patlasov <mpatla...@virtuozzo.com>
---
 drivers/block/ploop/dev.c       |   11 ++++++++++-
 drivers/block/ploop/io_direct.c |    3 ++-
 drivers/block/ploop/map.c       |    4 +++-
 include/linux/ploop/ploop.h     |    1 +
 4 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 557ddba..2b60dfa 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -1305,6 +1305,8 @@ static void ploop_complete_request(struct ploop_request * 
preq)
        }
        preq->bl.tail = NULL;
 
+       WARN_ON(!preq->error && test_bit(PLOOP_REQ_ISSUE_FLUSH, &preq->state));
+
        if (test_bit(PLOOP_REQ_RELOC_A, &preq->state) ||
            test_bit(PLOOP_REQ_RELOC_S, &preq->state)) {
                if (preq->error)
@@ -2429,6 +2431,13 @@ static void ploop_req_state_process(struct ploop_request 
* preq)
                preq->eng_io = NULL;
        }
 
+       if (test_bit(PLOOP_REQ_ISSUE_FLUSH, &preq->state)) {
+               preq->eng_io->ops->issue_flush(preq->eng_io, preq);
+               clear_bit(PLOOP_REQ_ISSUE_FLUSH, &preq->state);
+               preq->eng_io = NULL;
+               goto out;
+       }
+
 restart:
        BUG_ON(test_bit(PLOOP_REQ_POST_SUBMIT, &preq->state));
        __TRACE("ST %p %u %lu\n", preq, preq->req_cluster, preq->eng_state);
@@ -2705,7 +2714,7 @@ restart:
        default:
                BUG();
        }
-
+out:
        if (release_ioc) {
                struct io_context * ioc = current->io_context;
                current->io_context = saved_ioc;
diff --git a/drivers/block/ploop/io_direct.c b/drivers/block/ploop/io_direct.c
index 94936c7..c4d0f63 100644
--- a/drivers/block/ploop/io_direct.c
+++ b/drivers/block/ploop/io_direct.c
@@ -413,6 +413,7 @@ try_again:
 
                preq->iblock = iblk;
                preq->eng_io = io;
+               BUG_ON(test_bit(PLOOP_REQ_ISSUE_FLUSH, &preq->state));
                set_bit(PLOOP_REQ_POST_SUBMIT, &preq->state);
                dio_submit_pad(io, preq, sbl, size, em);
                err = 0;
@@ -1819,7 +1820,7 @@ static void dio_issue_flush(struct ploop_io * io, struct 
ploop_request *preq)
 
        atomic_inc(&preq->io_count);
        ploop_acc_ff_out(io->plo, preq->req_rw | bio->bi_rw);
-       submit_bio(preq->req_rw, bio);
+       submit_bio(WRITE_FLUSH, bio);
        ploop_complete_io_request(preq);
 }
 
diff --git a/drivers/block/ploop/map.c b/drivers/block/ploop/map.c
index f87fb08..915a216 100644
--- a/drivers/block/ploop/map.c
+++ b/drivers/block/ploop/map.c
@@ -1077,7 +1077,9 @@ static void map_wb_complete_post_process(struct ploop_map 
*map,
         * (see dio_submit()). So fsync of EXT4 image doesnt help us.
         * We need to force sync of nullified blocks.
         */
-       set_bit(PLOOP_REQ_FORCE_FUA, &preq->state);
+       preq->eng_io = &top_delta->io;
+       BUG_ON(test_bit(PLOOP_REQ_POST_SUBMIT, &preq->state));
+       set_bit(PLOOP_REQ_ISSUE_FLUSH, &preq->state);
        top_delta->io.ops->submit(&top_delta->io, preq, preq->req_rw,
                                  &sbl, preq->iblock, 1<<plo->cluster_log);
 }
diff --git a/include/linux/ploop/ploop.h b/include/linux/ploop/ploop.h
index af222f1..920daf7 100644
--- a/include/linux/ploop/ploop.h
+++ b/include/linux/ploop/ploop.h
@@ -479,6 +479,7 @@ enum
        PLOOP_REQ_POST_SUBMIT, /* preq needs post_submit processing */
        PLOOP_REQ_PUSH_BACKUP, /* preq was ACKed by userspace push_backup */
        PLOOP_REQ_FSYNC_DONE,  /* fsync_thread() performed f_op->fsync() */
+       PLOOP_REQ_ISSUE_FLUSH, /* preq needs ->issue_flush before completing */
 };
 
 #define PLOOP_REQ_MERGE_FL (1 << PLOOP_REQ_MERGE)

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to