[Devel] [PATCH RHEL8 COMMIT] ploop: Handle ENOSPC in prq_endio()

Konstantin Khorenko khorenko at virtuozzo.com
Thu Aug 5 18:28:22 MSK 2021


The commit is pushed to "branch-rh8-4.18.0-305.3.1.vz8.7.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-305.3.1.vz8.7.2
------>
commit 02f2cfce786858a24b8be2a2034472897999ffd0
Author: Kirill Tkhai <ktkhai at virtuozzo.com>
Date:   Thu Aug 5 18:28:22 2021 +0300

    ploop: Handle ENOSPC in prq_endio()
    
    prq_endio() is final place for all handled requests.
    There are no splitted pios, there are only original
    requests came from upper level. So, it's a good place
    to handle any ENOSPC instead of doing this in many
    places of code.
    
    Next patch will make allocate_cluster() care about
    ENOSPC, and that will already picked by update in this
    patch.
    
    https://jira.sw.ru/browse/PSBM-131771
    
    Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
    
    ====================
    Patchset descrition:
    
    ploop: Handle falloc ENOSPC
    
     #PSBM-106554 added fallocation of whole cluster.
    This case also may fail with -ENOSPC. We need
    to resubmit pio after that in the same way as
    it's done in #PSBM-127225.
    
    https://jira.sw.ru/browse/PSBM-131771
    
    Kirill Tkhai (3):
          ploop: Introduce init_prq_and_embedded_pio()
          ploop: Handle ENOSPC in prq_endio()
          ploop: Pass actual error from allocate_cluster()
---
 drivers/md/dm-ploop-map.c | 107 +++++++++++++++++++++++++---------------------
 1 file changed, 59 insertions(+), 48 deletions(-)

diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
index 4ef07f2d3fbb..7d1e6538615d 100644
--- a/drivers/md/dm-ploop-map.c
+++ b/drivers/md/dm-ploop-map.c
@@ -128,6 +128,52 @@ static void init_prq_and_embedded_pio(struct ploop *ploop, struct request *rq,
 	pio->endio_cb_data = prq;
 }
 
+void ploop_enospc_timer(struct timer_list *timer)
+{
+	struct ploop *ploop = from_timer(ploop, timer, enospc_timer);
+	unsigned long flags;
+	LIST_HEAD(list);
+
+	spin_lock_irqsave(&ploop->deferred_lock, flags);
+	list_splice_init(&ploop->enospc_pios, &list);
+	spin_unlock_irqrestore(&ploop->deferred_lock, flags);
+
+	submit_embedded_pios(ploop, &list);
+}
+
+void ploop_event_work(struct work_struct *ws)
+{
+	struct ploop *ploop = container_of(ws, struct ploop, event_work);
+
+	dm_table_event(ploop->ti->table);
+}
+
+static bool ploop_try_delay_enospc(struct ploop_rq *prq, struct pio *pio)
+{
+	struct ploop *ploop = pio->ploop;
+	bool delayed = true;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ploop->deferred_lock, flags);
+	if (unlikely(ploop->wants_suspend)) {
+		delayed = false;
+		goto unlock;
+	}
+
+	init_prq_and_embedded_pio(ploop, prq->rq, prq, pio);
+
+	ploop->event_enospc = true;
+	list_add_tail(&pio->list, &ploop->enospc_pios);
+unlock:
+	spin_unlock_irqrestore(&ploop->deferred_lock, flags);
+
+	if (delayed)
+		mod_timer(&ploop->enospc_timer, jiffies + PLOOP_ENOSPC_TIMEOUT);
+	schedule_work(&ploop->event_work);
+
+	return delayed;
+}
+
 void prq_endio(struct pio *pio, void *prq_ptr, blk_status_t bi_status)
 {
         struct ploop_rq *prq = prq_ptr;
@@ -137,6 +183,19 @@ void prq_endio(struct pio *pio, void *prq_ptr, blk_status_t bi_status)
 		kfree(prq->bvec);
 	if (prq->css)
 		css_put(prq->css);
+	/*
+	 * Here is exit point for rq, and here we handle ENOSPC.
+	 * Embedded pios will be reinitialized like they've just
+	 * came from upper dm level, and later resubmitted after
+	 * timeout. Note, that we do not handle merge here: merge
+	 * callers receive -ENOSPC synchronous without intermediaries.
+	 */
+	if (unlikely(bi_status == BLK_STS_NOSPC)) {
+		WARN_ON_ONCE(!op_is_write(pio->bi_op));
+		if (ploop_try_delay_enospc(prq, pio))
+			return;
+	}
+
 	dm_complete_request(rq, bi_status);
 }
 
@@ -1119,49 +1178,6 @@ static void ploop_queue_resubmit(struct pio *pio)
 	queue_work(ploop->wq, &ploop->worker);
 }
 
-void ploop_enospc_timer(struct timer_list *timer)
-{
-	struct ploop *ploop = from_timer(ploop, timer, enospc_timer);
-	unsigned long flags;
-
-	spin_lock_irqsave(&ploop->deferred_lock, flags);
-	list_splice_init(&ploop->enospc_pios, &ploop->resubmit_pios);
-	spin_unlock_irqrestore(&ploop->deferred_lock, flags);
-
-	queue_work(ploop->wq, &ploop->worker);
-}
-
-void ploop_event_work(struct work_struct *ws)
-{
-	struct ploop *ploop = container_of(ws, struct ploop, event_work);
-
-	dm_table_event(ploop->ti->table);
-}
-
-static bool ploop_try_delay_enospc(struct pio *pio)
-{
-	struct ploop *ploop = pio->ploop;
-	bool delayed = true;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ploop->deferred_lock, flags);
-	if (unlikely(ploop->wants_suspend)) {
-		delayed = false;
-		goto unlock;
-	}
-
-	ploop->event_enospc = true;
-	list_add_tail(&pio->list, &ploop->enospc_pios);
-unlock:
-	spin_unlock_irqrestore(&ploop->deferred_lock, flags);
-
-	if (delayed)
-		mod_timer(&ploop->enospc_timer, jiffies + PLOOP_ENOSPC_TIMEOUT);
-	schedule_work(&ploop->event_work);
-
-	return delayed;
-}
-
 static void data_rw_complete(struct pio *pio)
 {
 	bool completed;
@@ -1174,11 +1190,6 @@ static void data_rw_complete(struct pio *pio)
 			ploop_queue_resubmit(pio);
 			return;
 		}
-		if (pio->ret == -ENOSPC) {
-			WARN_ON_ONCE(!op_is_write(pio->bi_op));
-			if (ploop_try_delay_enospc(pio))
-				return;
-		}
 		pio->bi_status = errno_to_blk_status(pio->ret);
 	}
 


More information about the Devel mailing list