Here is possible scenario of double-unlock of bat_lock:

On 12/6/24 05:56, Alexander Atanasov wrote:
@@ -1758,23 +1789,29 @@ static void ploop_process_one_discard_pio(struct ploop 
*ploop, struct pio *pio)
        struct ploop_index_wb *piwb;
        struct md_page *md;
        map_index_t *to;
+       unsigned long flags;
WARN_ON(ploop->nr_deltas != 1 ||
                pio->queue_list_id != PLOOP_LIST_DISCARD);
page_id = ploop_bat_clu_to_page_nr(clu);
        md = ploop_md_page_find(ploop, page_id);
-       if (ploop_delay_if_md_busy(ploop, md, PIWB_TYPE_DISCARD, pio))

take bat_lock:

+       spin_lock_irqsave(&ploop->bat_lock, flags);
+       if (ploop_delay_if_md_busy(ploop, md, PIWB_TYPE_DISCARD, pio)) {
+               spin_unlock_irqrestore(&ploop->bat_lock, flags);
                goto out;
+       }
+
if (!test_bit(MD_DIRTY, &md->status)) {
-                /* Unlocked since MD_DIRTY is set and cleared from this work */
                if (ploop_prepare_bat_update(ploop, md, PIWB_TYPE_DISCARD) < 0) 
{
                        pio->bi_status = BLK_STS_RESOURCE;
                        goto err;
                }
                bat_update_prepared = true;
+               ploop_md_make_dirty(ploop, md);
        }

release bat_lock:

+       spin_unlock_irqrestore(&ploop->bat_lock, flags);
piwb = md->piwb; @@ -1784,18 +1821,20 @@ static void ploop_process_one_discard_pio(struct ploop *ploop, struct pio *pio)
        to = piwb->kmpage;
        if (WARN_ON_ONCE(!to[clu])) {
                pio->bi_status = BLK_STS_IOERR;
+               clear_bit(MD_DIRTY, &md->status);

goto err:

                goto err;
        } else {
                WRITE_ONCE(to[clu], 0);
+               spin_lock_irqsave(&piwb->lock, flags);
                list_add_tail(&pio->list, &piwb->ready_data_pios);
+               spin_unlock_irqrestore(&piwb->lock, flags);
        }
- if (bat_update_prepared)
-               ploop_md_make_dirty(ploop, md);
        ploop_md_up_prio(ploop, md);
  out:
        return;
  err:

release bat lock again:

+       spin_unlock_irqrestore(&ploop->bat_lock, flags);
        if (bat_update_prepared)
                ploop_break_bat_update(ploop, md);
        ploop_pio_endio(pio);

--
Best regards, Tikhomirov Pavel
Senior Software Developer, Virtuozzo.

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to