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: 808222b3f6b7 ("dm: add llseek_hole infrastructure")
https://virtuozzo.atlassian.net/browse/VSTOR-132310
Signed-off-by: Konstantin Khorenko <[email protected]>
---
 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);
 
-- 
2.47.1

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to