[Devel] [PATCH 2/2] ploop: handle discard requests via fallocate
Andrei Vagin
avagin at openvz.org
Tue Feb 6 03:25:27 MSK 2018
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 | 19 +++++++++++++++----
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, 26 insertions(+), 5 deletions(-)
diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 12fde00..4519d14 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -517,7 +517,7 @@ 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 (plo->fbd && 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 +570,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 +1487,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 +2570,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;
@@ -3978,6 +3987,8 @@ static int ploop_start(struct ploop_device * plo, struct block_device *bdev)
blk_queue_max_discard_sectors(plo->queue, INT_MAX);
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, plo->queue);
+ plo->queue->limits.discard_granularity = 4096;
+ plo->queue->limits.discard_alignment = 4096;
set_capacity(plo->disk, plo->bd_size);
bd_set_size(bdev, (loff_t)plo->bd_size << 9);
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