[rh7,2/2] ploop: Disable fast path on in case of pending discard

Submitted by Kirill Tkhai on March 3, 2020, 3:13 p.m.

Details

Message ID 158324843460.1227740.9818394825816754122.stgit@localhost.localdomain
State New
Series "Series without cover letter"
Headers show

Commit Message

Kirill Tkhai March 3, 2020, 3:13 p.m.
Despite underlining fs should not send discard bios
in parallel with others, but we have to be safe
in case of raw access to device too.

This patch adds accounting of inflight discard requests
and disables fast path in case they are pending.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 drivers/block/ploop/dev.c   |   13 ++++++++++++-
 drivers/block/ploop/sysfs.c |    6 ++++++
 include/linux/ploop/ploop.h |    1 +
 3 files changed, 19 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 9e01866860bd..12f1a41dcfd7 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -988,7 +988,8 @@  static void ploop_make_request(struct request_queue *q, struct bio *bio)
 	/* No fast path, when maintenance is in progress.
 	 * (PLOOP_S_TRACK was checked immediately above) */
 	if (FAST_PATH_DISABLED(plo->maintenance_type) ||
-	    plo->fast_path_disabled_count)
+	    plo->fast_path_disabled_count ||
+	    plo->bio_discard_inflight_reqs)
 		goto queue;
 
 	/* Attention state, always queue */
@@ -1377,6 +1378,8 @@  static void ploop_complete_request(struct ploop_request * preq)
 	 */
 	spin_lock_irq(&plo->lock);
 	plo->active_reqs--;
+	if (preq->req_rw & REQ_DISCARD)
+		plo->bio_discard_inflight_reqs--;
 	spin_unlock_irq(&plo->lock);
 
 	while (preq->bl.head) {
@@ -3090,6 +3093,7 @@  static int ploop_thread(void * data)
 	struct ploop_device * plo = data;
 	struct blk_plug plug;
 	LIST_HEAD(drop_list);
+	bool wait_fast_path;
 
 	set_user_nice(current, -20);
 
@@ -3098,6 +3102,7 @@  static int ploop_thread(void * data)
 		/* Convert bios to preqs early (at least before processing
 		 * entry queue) to increase chances of bio merge
 		 */
+		wait_fast_path = false;
 		cond_resched();
 		spin_lock_irq(&plo->lock);
 		BUG_ON (!list_empty(&drop_list));
@@ -3157,6 +3162,9 @@  static int ploop_thread(void * data)
 			}
 
 			plo->active_reqs++;
+			if ((preq->req_rw & REQ_DISCARD) &&
+			    (plo->bio_discard_inflight_reqs++) == 0)
+				wait_fast_path = true;
 			ploop_entry_qlen_dec(preq);
 
 			if (test_bit(PLOOP_REQ_DISCARD, &preq->state)) {
@@ -3171,6 +3179,9 @@  static int ploop_thread(void * data)
 			preq->eng_state = PLOOP_E_ENTRY;
 			spin_unlock_irq(&plo->lock);
 
+			if (wait_fast_path)
+				wait_fast_path_reqs(plo);
+
 			ploop_req_state_process(preq);
 			continue;
 		}
diff --git a/drivers/block/ploop/sysfs.c b/drivers/block/ploop/sysfs.c
index ef7fffc9fd2f..292ed3c48990 100644
--- a/drivers/block/ploop/sysfs.c
+++ b/drivers/block/ploop/sysfs.c
@@ -296,6 +296,11 @@  static u32 show_discard_bios(struct ploop_device * plo)
 	return plo->bio_discard_qlen;
 }
 
+static u32 show_discard_inflight_bios(struct ploop_device * plo)
+{
+	return plo->bio_discard_inflight_reqs;
+}
+
 static u32 show_active_reqs(struct ploop_device * plo)
 {
 	return plo->active_reqs;
@@ -564,6 +569,7 @@  static struct attribute *state_attributes[] = {
 	_A(total_bios),
 	_A(queued_bios),
 	_A(discard_bios),
+	_A(discard_inflight_bios),
 	_A(active_reqs),
 	_A(entry_reqs),
 	_A(entry_read_sync_reqs),
diff --git a/include/linux/ploop/ploop.h b/include/linux/ploop/ploop.h
index 8495ca2145fd..50ee95ab623d 100644
--- a/include/linux/ploop/ploop.h
+++ b/include/linux/ploop/ploop.h
@@ -381,6 +381,7 @@  struct ploop_device
 	struct bio		*bio_sync;
 	struct bio_list		bio_discard_list;
 	int			bio_discard_qlen;
+	int			bio_discard_inflight_reqs;
 	int			bio_qlen;
 	int			bio_total;