[2/2] ploop: handle discard requests via fallocate

Submitted by Andrei Vagin on Feb. 6, 2018, 12:25 a.m.

Details

Message ID 1517876727-8078-2-git-send-email-avagin@openvz.org
State New
Series "Series without cover letter"
Headers show

Commit Message

Andrei Vagin Feb. 6, 2018, 12:25 a.m.
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@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(-)

Patch hide | download patch | download mbox

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 */