[RHEL7,COMMIT] ploop: Disable fast path on in case of pending discard

Submitted by Konstantin Khorenko on March 6, 2020, 9:55 a.m.

Details

Message ID 202003060955.0269twCW031679@finist-ce7.sw.ru
State New
Series "Series without cover letter"
Headers show

Commit Message

Konstantin Khorenko March 6, 2020, 9:55 a.m.
The commit is pushed to "branch-rh7-3.10.0-1062.12.1.vz7.145.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1062.12.1.vz7.131.8
------>
commit 7dda2e22c800dd36959fd0cb6946c9c1dc4ec9ab
Author: Kirill Tkhai <ktkhai@virtuozzo.com>
Date:   Fri Mar 6 12:55:58 2020 +0300

    ploop: Disable fast path on in case of pending discard
    
    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   | 16 ++++++++++++++--
 drivers/block/ploop/sysfs.c |  6 ++++++
 include/linux/ploop/ploop.h |  1 +
 3 files changed, 21 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 7410e2e5dc4e0..0d291df2af80d 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -673,7 +673,8 @@  DEFINE_BIO_CB(ploop_fast_end_io)
 	    (test_bit(PLOOP_S_EXITING, &plo->state) ||
 	     !list_empty(&plo->entry_queue)))
 		wake_up_interruptible(&plo->waitq);
-	if (plo->fast_path_disabled_count && !plo->fastpath_reqs)
+	if ((plo->fast_path_disabled_count || plo->bio_discard_inflight_reqs) &&
+	    !plo->fastpath_reqs)
 		wake_up(&plo->fast_path_waitq);
 	spin_unlock_irqrestore(&plo->lock, flags);
 
@@ -989,7 +990,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 */
@@ -1378,6 +1380,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) {
@@ -3091,6 +3095,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);
 
@@ -3099,6 +3104,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));
@@ -3158,6 +3164,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)) {
@@ -3172,6 +3181,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 ef7fffc9fd2f1..292ed3c48990e 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 8495ca2145fd4..50ee95ab623d3 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;