[Devel] [PATCH 2/4] ploop: handle discard requests via fallocate

Andrei Vagin avagin at openvz.org
Thu Feb 15 04:36:05 MSK 2018


[This sender failed our fraud detection checks and may not be who they appear to be. Learn about spoofing at http://aka.ms/LearnAboutSpoofing]

Currently ploop can be compacted, but in this case discard requests are
hanled with help of a userspace tool.

This patch adds a native support for discard requests with a few
restrictions.

Currrenty this works only for raw images on a fuse file system due to
these reasons:
* Only the fuse file system allows to execute fallocate asynchroniously.
* pio_direct (ext4) requires that all blocks in image were allocated
  and initalized.
* The ploop1 format requires more changes to hanlde an index table.

Signed-off-by: Andrei Vagin <avagin at openvz.org>
---
 drivers/block/ploop/dev.c        | 18 ++++++++++++++----
 drivers/block/ploop/fmt_ploop1.c |  2 ++
 drivers/block/ploop/io_direct.c  |  1 +
 drivers/block/ploop/io_kaio.c    |  8 +++++++-
 include/linux/ploop/ploop.h      |  1 +
 5 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 12fde00..6c0b3c0 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -517,7 +517,8 @@ ploop_bio_queue(struct ploop_device * plo, struct bio * bio,
            ploop_pb_check_and_clear_bit(plo->pbd, preq->req_cluster))
                ploop_set_blockable(plo, preq);

-       if (unlikely(bio->bi_rw & REQ_DISCARD)) {
+       if (test_bit(PLOOP_S_DISCARD, &plo->state) &&
+           unlikely(bio->bi_rw & REQ_DISCARD)) {
                int clu_size = 1 << plo->cluster_log;
                int i = (clu_size - 1) & bio->bi_sector;
                int err = 0;
@@ -570,13 +571,13 @@ ploop_bio_queue(struct ploop_device * plo, struct bio * bio,

        __TRACE("A %p %u\n", preq, preq->req_cluster);

-       if (unlikely(bio->bi_rw & REQ_DISCARD))
+       if (unlikely(preq->state & (1 << PLOOP_REQ_DISCARD)))
                plo->bio_discard_qlen--;
        else
                plo->bio_qlen--;
        ploop_entry_add(plo, preq);

-       if (bio->bi_size && !(bio->bi_rw & REQ_DISCARD))
+       if (bio->bi_size && !(preq->state & (1 << PLOOP_REQ_DISCARD)))
                insert_entry_tree(plo, preq, drop_list);

        trace_bio_queue(preq);
@@ -1487,7 +1488,7 @@ void ploop_complete_io_state(struct ploop_request * preq)

        spin_lock_irqsave(&plo->lock, flags);
        __TRACE("C %p %u\n", preq, preq->req_cluster);
-       if (preq->error)
+       if (preq->error && !(preq->req_rw & REQ_DISCARD))
                set_bit(PLOOP_S_ABORT, &plo->state);

        list_add_tail(&preq->list, &plo->ready_queue);
@@ -2570,6 +2571,15 @@ restart:
                        break;
                }

+               if ((preq->req_rw & REQ_DISCARD) &&
+                   !test_bit(PLOOP_REQ_DISCARD, &preq->state) &&
+                   test_bit(PLOOP_S_NO_FALLOC_DISCARD, &plo->state)) {
+                       preq->eng_state = PLOOP_E_COMPLETE;
+                       preq->error = -EOPNOTSUPP;
+                       ploop_complete_io_state(preq);
+                       return;
+               }
+
                ploop_entry_request(preq);
                break;

diff --git a/drivers/block/ploop/fmt_ploop1.c b/drivers/block/ploop/fmt_ploop1.c
index 0034216..c2be627 100644
--- a/drivers/block/ploop/fmt_ploop1.c
+++ b/drivers/block/ploop/fmt_ploop1.c
@@ -189,6 +189,8 @@ ploop1_open(struct ploop_delta * delta)
            ((u64)ph->bd_size + ph->l1_off) << 9)
                delta->flags |= PLOOP_FMT_PREALLOCATED;

+       set_bit(PLOOP_S_NO_FALLOC_DISCARD, &delta->plo->state);
+
        return 0;

 out_err:
diff --git a/drivers/block/ploop/io_direct.c b/drivers/block/ploop/io_direct.c
index d6b1118..3c57aca 100644
--- a/drivers/block/ploop/io_direct.c
+++ b/drivers/block/ploop/io_direct.c
@@ -1032,6 +1032,7 @@ dio_init(struct ploop_io * io)
        init_timer(&io->fsync_timer);
        io->fsync_timer.function = fsync_timeout;
        io->fsync_timer.data = (unsigned long)io;
+       set_bit(PLOOP_S_NO_FALLOC_DISCARD, &io->plo->state);

        return 0;
 }
diff --git a/drivers/block/ploop/io_kaio.c b/drivers/block/ploop/io_kaio.c
index ee9ba26..543f98b 100644
--- a/drivers/block/ploop/io_kaio.c
+++ b/drivers/block/ploop/io_kaio.c
@@ -167,7 +167,9 @@ static int kaio_kernel_submit(struct file *file, struct kaio_req *kreq,
        if (!iocb)
                return -ENOMEM;

-       if (rw & REQ_WRITE)
+       if (rw & REQ_DISCARD)
+               op = IOCB_CMD_UNMAP_ITER;
+       else if (rw & REQ_WRITE)
                op = IOCB_CMD_WRITE_ITER;
        else
                op = IOCB_CMD_READ_ITER;
@@ -207,6 +209,10 @@ static size_t kaio_kreq_pack(struct kaio_req *kreq, int *nr_segs,

        BUG_ON(b->bi_idx);

+       if (b->bi_vcnt == 0) { /* REQ_DISCARD */
+               *nr_segs = 0;
+               return size;
+       }
        while (1) {
                int nr = min_t(int, kreq_nr_max, b->bi_vcnt - idx);
                BUG_ON(!nr);
diff --git a/include/linux/ploop/ploop.h b/include/linux/ploop/ploop.h
index f13b7ca..fd683f7 100644
--- a/include/linux/ploop/ploop.h
+++ b/include/linux/ploop/ploop.h
@@ -53,6 +53,7 @@ enum {
        PLOOP_S_ENOSPC_EVENT,   /* ENOSPC event happened but but was not
                                 * consumed by userspace yet */
        PLOOP_S_CONGESTED,      /* Too many bios submitted to us */
+       PLOOP_S_NO_FALLOC_DISCARD, /* Unable to handle discard requests by fallocate */
        PLOOP_S_DISCARD,        /* ploop is ready to handle discard request */
        PLOOP_S_DISCARD_LOADED, /* A discard request was handled and
                                   free blocks loaded */
--
1.8.3.1




More information about the Devel mailing list