[Devel] [PATCH vz9 v1 59/63] dm-ploop: resubmit enospc pios from dispatcher thread

Alexander Atanasov alexander.atanasov at virtuozzo.com
Fri Jan 24 18:36:33 MSK 2025


When running out of space pios are delayed and retried
from a timer. This timer is the only thing that runs in
interrupt context and brings requirement to use _irqsave
variants, since a complete request processing can be started
from the timer. To avoid this set a flag from the timer
and process delayed pios from the dispatcher thread.
Follow up patches will cleanup flags saving.

https://virtuozzo.atlassian.net/browse/VSTOR-98016
Signed-off-by: Alexander Atanasov <alexander.atanasov at virtuozzo.com>
---
 drivers/md/dm-ploop-map.c    | 31 ++++++++++++++++++-------------
 drivers/md/dm-ploop-target.c |  2 +-
 drivers/md/dm-ploop.h        |  2 ++
 3 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
index 00929455fcf5..98297fb46bb6 100644
--- a/drivers/md/dm-ploop-map.c
+++ b/drivers/md/dm-ploop-map.c
@@ -151,12 +151,7 @@ static void ploop_init_prq_and_embedded_pio(struct ploop *ploop,
 void ploop_enospc_timer(struct timer_list *timer)
 {
 	struct ploop *ploop = from_timer(ploop, timer, enospc_timer);
-	struct llist_node *enospc_pending = llist_del_all(&ploop->enospc_pios);
-
-	if (enospc_pending) {
-		enospc_pending = llist_reverse_order(enospc_pending);
-		ploop_submit_embedded_pios(ploop, enospc_pending);
-	}
+	ploop->submit_enospc = true;
 }
 
 void do_ploop_event_work(struct work_struct *ws)
@@ -169,12 +164,11 @@ void do_ploop_event_work(struct work_struct *ws)
 static bool ploop_try_delay_enospc(struct ploop_rq *prq, struct pio *pio)
 {
 	struct ploop *ploop = pio->ploop;
-	bool delayed = true;
 	unsigned long flags;
 
 	if (unlikely(ploop->wants_suspend)) {
-		delayed = false;
-		goto unlock;
+		PL_WARN("dropping pio enospc\n");
+		return false;
 	}
 
 	ploop_init_prq_and_embedded_pio(ploop, prq->rq, prq, pio);
@@ -185,13 +179,11 @@ static bool ploop_try_delay_enospc(struct ploop_rq *prq, struct pio *pio)
 	ploop->event_enospc = true;
 	spin_unlock_irqrestore(&ploop->deferred_lock, flags);
 	llist_add((struct llist_node *)(&pio->list), &ploop->enospc_pios);
-unlock:
 
-	if (delayed)
-		mod_timer(&ploop->enospc_timer, jiffies + PLOOP_ENOSPC_TIMEOUT);
+	mod_timer(&ploop->enospc_timer, jiffies + PLOOP_ENOSPC_TIMEOUT);
 	schedule_work(&ploop->event_work);
 
-	return delayed;
+	return true;
 }
 
 static void ploop_prq_endio(struct pio *pio, void *prq_ptr,
@@ -2165,6 +2157,14 @@ static inline int ploop_runners_add_work_list(struct ploop *ploop, struct llist_
 	return 0;
 }
 
+void ploop_resubmit_enospc_pios(struct ploop *ploop)
+{
+	struct llist_node *enospc_pending = llist_del_all(&ploop->enospc_pios);
+
+	if (enospc_pending)
+		ploop_submit_embedded_pios(ploop, llist_reverse_order(enospc_pending));
+}
+
 void do_ploop_run_work(struct ploop *ploop)
 {
 	LLIST_HEAD(deferred_pios);
@@ -2180,6 +2180,11 @@ void do_ploop_run_work(struct ploop *ploop)
 
 	current->flags |= PF_IO_THREAD|PF_LOCAL_THROTTLE|PF_MEMALLOC_NOIO;
 
+	if (ploop->submit_enospc) {
+		ploop->submit_enospc = false;
+		ploop_resubmit_enospc_pios(ploop);
+	}
+
 	llembedded_pios = llist_del_all(&ploop->pios[PLOOP_LIST_PREPARE]);
 
 	lldeferred_pios = llist_del_all(&ploop->pios[PLOOP_LIST_DEFERRED]);
diff --git a/drivers/md/dm-ploop-target.c b/drivers/md/dm-ploop-target.c
index 641950031fe3..f306f0c85ee5 100644
--- a/drivers/md/dm-ploop-target.c
+++ b/drivers/md/dm-ploop-target.c
@@ -695,7 +695,7 @@ static void ploop_presuspend(struct dm_target *ti)
 	wait_event_interruptible(ploop->dispatcher_wq_data,
 			(!atomic_read(&ploop->kt_worker->inflight_pios)));
 	vfs_fsync(ploop_top_delta(ploop)->file, 0);
-	ploop_enospc_timer(&ploop->enospc_timer);
+	ploop_resubmit_enospc_pios(ploop);
 }
 
 static void ploop_presuspend_undo(struct dm_target *ti)
diff --git a/drivers/md/dm-ploop.h b/drivers/md/dm-ploop.h
index edf9b1448887..43e65e841e4a 100644
--- a/drivers/md/dm-ploop.h
+++ b/drivers/md/dm-ploop.h
@@ -259,6 +259,7 @@ struct ploop {
 	bool nokblkcg;
 
 	struct timer_list enospc_timer;
+	bool submit_enospc; /* timer expired run pios from dispatcher */
 	bool event_enospc;
 
 	loff_t prealloc_size;
@@ -637,5 +638,6 @@ extern void ploop_disable_writeback_delay(struct ploop *ploop);
 extern void ploop_enable_writeback_delay(struct ploop *ploop);
 
 extern void ploop_should_prealloc(struct ploop *ploop, struct file *file);
+extern void ploop_resubmit_enospc_pios(struct ploop *ploop);
 
 #endif /* __DM_PLOOP_H */
-- 
2.43.0



More information about the Devel mailing list