a pio may complete after md page update, in that case we must not complete the update but wait for the last data pio and only then complete them all.
https://virtuozzo.atlassian.net/browse/VSTOR-91821 Signed-off-by: Alexander Atanasov <alexander.atana...@virtuozzo.com> --- drivers/md/dm-ploop-map.c | 57 ++++++++++++++++++++++++++------------- drivers/md/dm-ploop.h | 1 + 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c index 482022d6b60b..9da996935945 100644 --- a/drivers/md/dm-ploop-map.c +++ b/drivers/md/dm-ploop-map.c @@ -598,7 +598,6 @@ static void ploop_unlink_completed_pio(struct ploop *ploop, struct pio *pio) static bool ploop_md_make_dirty(struct ploop *ploop, struct md_page *md) { - unsigned long flags; bool new = false; /* @@ -896,6 +895,7 @@ static void ploop_advance_local_after_bat_wb(struct ploop *ploop, if (wait_llist_pending) { llist_for_each_safe(pos, t, wait_llist_pending) { pio = list_entry((struct list_head *)pos, typeof(*pio), list); + INIT_LIST_HEAD(&pio->list); list_add(&pio->list, &list); } } @@ -962,15 +962,22 @@ static void ploop_bat_write_complete(struct pio *pio, void *piwb_ptr, */ ploop_advance_local_after_bat_wb(ploop, piwb, true); } + } else { + PL_ERR("piwb not completed\n"); } spin_lock_irqsave(&piwb->lock, flags); - if (completed) + if (completed) { piwb->completed = completed; - piwb->bi_status = bi_status; - ll_ready_pios = llist_reverse_order(llist_del_all(&piwb->llready_data_pios)); + ll_ready_pios = llist_del_all(&piwb->llready_data_pios); + } else { + piwb->wait_for_last = 1; + } + if (bi_status) + piwb->bi_status = bi_status; spin_unlock_irqrestore(&piwb->lock, flags); - + if (!completed) + return; ll_cow_pios = llist_reverse_order(llist_del_all(&piwb->cow_llist)); /* @@ -978,8 +985,8 @@ static void ploop_bat_write_complete(struct pio *pio, void *piwb_ptr, */ llist_for_each_safe(pos, t, ll_ready_pios) { - pio = list_entry((struct list_head *)pos, typeof(*aux_pio), list); - INIT_LIST_HEAD(&pio->list); + data_pio = list_entry((struct list_head *)pos, typeof(*data_pio), list); + INIT_LIST_HEAD(&data_pio->list); if (bi_status) data_pio->bi_status = bi_status; ploop_pio_endio(data_pio); @@ -1026,9 +1033,10 @@ static int ploop_prepare_bat_update(struct ploop *ploop, struct md_page *md, piwb->pio = pio = ploop_alloc_pio(ploop, GFP_NOIO); if (!page || !pio) goto err; - piwb->kmpage = kmap(piwb->bat_page); ploop_init_pio(ploop, REQ_OP_WRITE, pio); - + piwb->kmpage = kmap(piwb->bat_page); + WARN_ON(!piwb->kmpage); + piwb->wait_for_last = 0; bat_entries = md->kmpage; spin_lock_irq(&md->md_lock); @@ -1251,6 +1259,7 @@ static bool ploop_data_pio_end(struct pio *pio) struct ploop_index_wb *piwb = pio->piwb; unsigned long flags; bool completed; + int last_pio = 0; spin_lock_irqsave(&piwb->lock, flags); completed = piwb->completed; @@ -1258,12 +1267,26 @@ static bool ploop_data_pio_end(struct pio *pio) llist_add((struct llist_node *)(&pio->list), &piwb->llready_data_pios); else if (!pio->bi_status) pio->bi_status = piwb->bi_status; - spin_unlock_irqrestore(&piwb->lock, flags); /* If pio is late then end it here. this can happen with flushes */ - if (completed) + if (atomic_read(&piwb->count) == 2) { + if (piwb->wait_for_last) + last_pio = 1; + } + spin_unlock_irqrestore(&piwb->lock, flags); + ploop_put_piwb(piwb); + if (completed) { + struct ploop *ploop = pio->ploop; + + PL_ERR("late pio already completed\n"); ploop_pio_endio(pio); + } else if (last_pio) { + /* + * Status is set from first call to ploop_bat_write_complete + * zero keeps it as is + */ + ploop_bat_write_complete(piwb->pio, piwb, piwb->bi_status); + } - ploop_put_piwb(piwb); return completed; } @@ -1309,8 +1332,6 @@ static void ploop_check_standby_mode(struct ploop *ploop, long res) static void ploop_data_rw_complete(struct pio *pio) { - bool completed; - if (pio->ret != pio->bi_iter.bi_size) { if (pio->ret >= 0 || pio->ret == -ENOTBLK) { /* Partial IO or request to retry in buffered mode */ @@ -1338,12 +1359,10 @@ static void ploop_data_rw_complete(struct pio *pio) pio->bi_status = errno_to_blk_status(pio->ret); } if (pio->is_data_alloc) { - completed = ploop_data_pio_end(pio); - if (!completed) - return; + ploop_data_pio_end(pio); + } else { + ploop_pio_endio(pio); } - - ploop_pio_endio(pio); } /* diff --git a/drivers/md/dm-ploop.h b/drivers/md/dm-ploop.h index 5ad2a5142521..cc66f9dcd27f 100644 --- a/drivers/md/dm-ploop.h +++ b/drivers/md/dm-ploop.h @@ -111,6 +111,7 @@ struct ploop_index_wb { u32 page_id; struct bio_vec aux_bvec; struct pio *flush_pio; + int wait_for_last; }; /* Metadata page */ -- 2.43.0 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel