[Devel] [PATCH RHEL10 COMMIT] dm: fix SRCU read-lock leak on dm_llseek_hole() early error paths

Konstantin Khorenko khorenko at virtuozzo.com
Mon Jun 15 13:55:44 MSK 2026


The commit is pushed to "branch-rh10-6.12.0-211.16.1.12.x.vz10-ovz" and will appear at git at bitbucket.org:openvz/vzkernel.git
after rh10-6.12.0-211.16.1.el10
------>
commit a356ccb8cc8a3b257288f2b6b0077b6f46bec5c6
Author: Konstantin Khorenko <khorenko at virtuozzo.com>
Date:   Wed Jun 3 23:54:38 2026 +0200

    dm: fix SRCU read-lock leak on dm_llseek_hole() early error paths
    
    dm_get_live_table() always takes the io_barrier SRCU read lock (storing
    the index in *srcu_idx) and returns the live map. dm_llseek_hole() left
    two early-return paths that skipped the matching dm_put_live_table():
    
            table = dm_get_live_table(md, &srcu_idx);
            if (!table || !dm_table_get_size(table))
                    return -ENOTTY;          /* leaks SRCU read lock */
            ...
            if (table->num_targets != 1)
                    return -EOPNOTSUPP;      /* leaks SRCU read lock */
    
    So a SEEK_HOLE/SEEK_DATA on a dm device with no live table, an empty
    table, or more than one target leaked an SRCU reader. A leaked reader
    stalls any later synchronize_srcu() (device suspend / table reload) and
    unbalances the per-CPU SRCU counter. The remaining error paths already
    use "goto out".
    
    Convert the two early returns to the "ret = ...; goto out;" pattern so
    they release the lock via the out: label like the rest of the function.
    
    Fixes: f6dc73be5d35 ("dm: add llseek_hole infrastructure")
    https://virtuozzo.atlassian.net/browse/VSTOR-132310
    Feature: dm: implement SEEK_HOLE for dm-qcow2 and dm-ploop
    Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
 drivers/md/dm.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index b5e28553824d..130eec93fa10 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -493,16 +493,20 @@ static loff_t dm_llseek_hole(struct block_device *bdev, loff_t offset, int whenc
 	loff_t ret;
 
 	table = dm_get_live_table(md, &srcu_idx);
-	if (!table || !dm_table_get_size(table))
-		return -ENOTTY;
+	if (!table || !dm_table_get_size(table)) {
+		ret = -ENOTTY;
+		goto out;
+	}
 
 	/*
 	 * For now we only support devices that have a single target.
 	 * But probably it is not hard to break it to a few requests to a different
 	 * targets
 	 */
-	if (table->num_targets != 1)
-		return -EOPNOTSUPP;
+	if (table->num_targets != 1) {
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
 
 	ti = dm_table_get_target(table, 0);
 


More information about the Devel mailing list