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 <[email protected]> --- 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 98e3e46d0223..4b72783e8a7e 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); } _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
