The commit is pushed to "branch-rh10-6.12.0-55.13.1.2.x.vz10-ovz" and will 
appear at g...@bitbucket.org:openvz/vzkernel.git
after rh10-6.12.0-55.13.1.2.8.vz10
------>
commit 72eefbe763606a314db757b0d077a2bc013f6c7a
Author: Vasileios Almpanis <vasileios.almpa...@virtuozzo.com>
Date:   Thu Sep 18 13:20:15 2025 +0000

    dm-ploop: fix concurrent COW operations on same cluster
    
    When multiple threads attempt operations on the same cluster simultaneously,
    the current code logs warnings but continues with potentially conflicting
    operations, leading to WARN_ON triggers.
    
    Fix by implementing proper deferral when cluster locks fail:
    
     1. Change ploop_link_pio() to add identical pios to the lock holder's
        endio list instead of issuing warnings and continuing
     2. Rename ploop_add_cluster_lk() to ploop_try_add_cluster_lk() to reflect
        the new behavior
     3. Update COW and discard paths to abort operations when cluster locking
        fails, allowing proper deferral.
    
    This ensures that conflicting operations are serialized rather than
    corrupting shared data structures.
    
    Observed during snapshot creation where filesystem metadata updates
    trigger concurrent operations on the same clusters.
    
    https://virtuozzo.atlassian.net/browse/VSTOR-115446
    
    Signed-off-by: Vasileios Almpanis <vasileios.almpa...@virtuozzo.com>
    Reviewed-by: Pavel Tikhomirov <ptikhomi...@virtuozzo.com>
    
    Feature: dm-ploop: ploop target driver
---
 drivers/md/dm-ploop-map.c | 32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
index 56481d0f8323d..ddd0132e7270a 100644
--- a/drivers/md/dm-ploop-map.c
+++ b/drivers/md/dm-ploop-map.c
@@ -535,10 +535,10 @@ static int ploop_link_pio(struct hlist_head head[], 
struct pio *pio,
                if (pe == pio)
                        return 1;
 
-               WARN_ON_ONCE(pe != NULL);
-
-               if (pe)
-                       PL_ERR("clu:%u already exclusively locked\n", clu);
+               if (pe) {
+                       ploop_add_endio_pio(pe, pio);
+                       return 0;
+               }
        }
 
        if (!hlist_unhashed_lockless(&pio->hlist_node)) {
@@ -569,7 +569,7 @@ static int ploop_unlink_pio(struct ploop *ploop, struct pio 
*pio,
        return 1;
 }
 
-static int ploop_add_cluster_lk(struct ploop *ploop, struct pio *pio, u32 clu)
+static int ploop_try_add_cluster_lk(struct ploop *ploop, struct pio *pio, u32 
clu)
 {
        unsigned long flags;
        int ret;
@@ -753,9 +753,9 @@ static int ploop_handle_discard_pio(struct ploop *ploop, 
struct pio *pio,
                        ploop_device_name(ploop));
                return 0;
        }
+       if (!ploop_try_add_cluster_lk(ploop, pio, clu))
+               return 1;
 
-       if (!ploop_add_cluster_lk(ploop, pio, clu))
-               PL_ERR("dis clu %d already locked\n", clu);
        pio->wants_discard_index_cleanup = true;
 
 punch_hole:
@@ -1585,12 +1585,19 @@ static int ploop_submit_cluster_cow(struct ploop 
*ploop, unsigned int level,
 {
        struct ploop_cow *cow = NULL;
        struct pio *aux_pio = NULL;
+       int ret = 0;
 
        /* Prepare new delta read */
        aux_pio = ploop_alloc_pio_with_pages(ploop);
        cow = kmem_cache_alloc(cow_cache, GFP_ATOMIC);
-       if (!aux_pio || !cow)
-               goto err;
+       if (!aux_pio || !cow) {
+               ret = -ENOMEM;
+               goto cleanup;
+       }
+
+       if (!ploop_try_add_cluster_lk(ploop, cow_pio, clu))
+               goto cleanup;
+
        ploop_init_pio(ploop, REQ_OP_READ, aux_pio);
        ploop_pio_prepare_offsets(ploop, aux_pio, clu);
        aux_pio->css = cow_pio->css;
@@ -1602,17 +1609,14 @@ static int ploop_submit_cluster_cow(struct ploop 
*ploop, unsigned int level,
        cow->aux_pio = aux_pio;
        cow->cow_pio = cow_pio;
 
-       if (!ploop_add_cluster_lk(ploop, cow_pio, clu))
-               PL_ERR("cowclu %d already locked\n", clu);
-
        /* Stage #0: read secondary delta full clu */
        ploop_map_and_submit_rw(ploop, dst_clu, aux_pio, level);
        return 0;
-err:
+cleanup:
        if (aux_pio)
                ploop_free_pio_with_pages(ploop, aux_pio);
        kfree(cow);
-       return -ENOMEM;
+       return ret;
 }
 
 static int ploop_initiate_cluster_cow(struct ploop *ploop, unsigned int level,
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to