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

Kirill Tkhai ktkhai at virtuozzo.com
Tue Mar 3 18:19:06 MSK 2020


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 at virtuozzo.com>
---
diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 9e01866860bd..5f68353875d2 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -672,7 +672,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);
 
@@ -988,7 +989,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 +1379,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 +3094,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 +3103,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 +3163,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 +3180,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;
 


More information about the Devel mailing list