]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
Revert "dm: fix a race condition in retrieve_deps"
authorBenjamin Marzinski <bmarzins@redhat.com>
Wed, 28 Jan 2026 00:12:23 +0000 (19:12 -0500)
committerMikulas Patocka <mpatocka@redhat.com>
Wed, 28 Jan 2026 14:44:02 +0000 (15:44 +0100)
This reverts commit f6007dce0cd35d634d9be91ef3515a6385dcee16.

Commit f6007dce0cd3 ("dm: fix a race condition in retrieve_deps") was
added to fix a race between retrieving the list of dm table devices and
multipath_message() modifying the list of table devices. But Commit
a48f6b82c5c4 ("dm mpath: don't call dm_get_device in multipath_message")
removed the call to dm_get_device() from multipath_message(). After that
commit, the only calls to dm_get_device() and dm_put_device() are in
target constructors and destructors, so the race with retrieve_deps() is
no longer possible.

Suggested-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
drivers/md/dm-core.h
drivers/md/dm-ioctl.c
drivers/md/dm-table.c

index 1cda8618d74d2c2c9ce6023f6ae95d978add42c0..a3b8ad6e1c42def591694cb304994c2b8d5ca301 100644 (file)
@@ -215,7 +215,6 @@ struct dm_table {
 
        /* a list of devices used by this table */
        struct list_head devices;
-       struct rw_semaphore devices_lock;
 
        /* events get handed up using this callback */
        void (*event_fn)(void *data);
index 4165fef4c17074758b5ba3de410038aa613d63f0..fd4bf8e1d73eb22539d63c8cc38dbb56d9fa93f3 100644 (file)
@@ -1648,8 +1648,6 @@ static void retrieve_deps(struct dm_table *table,
        struct dm_dev_internal *dd;
        struct dm_target_deps *deps;
 
-       down_read(&table->devices_lock);
-
        deps = get_result_buffer(param, param_size, &len);
 
        /*
@@ -1664,7 +1662,7 @@ static void retrieve_deps(struct dm_table *table,
        needed = struct_size(deps, dev, count);
        if (len < needed) {
                param->flags |= DM_BUFFER_FULL_FLAG;
-               goto out;
+               return;
        }
 
        /*
@@ -1676,9 +1674,6 @@ static void retrieve_deps(struct dm_table *table,
                deps->dev[count++] = huge_encode_dev(dd->dm_dev->bdev->bd_dev);
 
        param->data_size = param->data_start + needed;
-
-out:
-       up_read(&table->devices_lock);
 }
 
 static int table_deps(struct file *filp, struct dm_ioctl *param, size_t param_size)
index 4b70872725d043acc02a814decf3b5ecac78f85a..7be1d8dc8bdd2fabf0f36cdfeaaf2861899d1705 100644 (file)
@@ -139,7 +139,6 @@ int dm_table_create(struct dm_table **result, blk_mode_t mode,
                return -ENOMEM;
 
        INIT_LIST_HEAD(&t->devices);
-       init_rwsem(&t->devices_lock);
 
        if (!num_targets)
                num_targets = KEYS_PER_NODE;
@@ -380,20 +379,16 @@ int dm_get_device(struct dm_target *ti, const char *path, blk_mode_t mode,
        if (dev == disk_devt(t->md->disk))
                return -EINVAL;
 
-       down_write(&t->devices_lock);
-
        dd = find_device(&t->devices, dev);
        if (!dd) {
                dd = kmalloc(sizeof(*dd), GFP_KERNEL);
-               if (!dd) {
-                       r = -ENOMEM;
-                       goto unlock_ret_r;
-               }
+               if (!dd)
+                       return -ENOMEM;
 
                r = dm_get_table_device(t->md, dev, mode, &dd->dm_dev);
                if (r) {
                        kfree(dd);
-                       goto unlock_ret_r;
+                       return r;
                }
 
                refcount_set(&dd->count, 1);
@@ -403,17 +398,12 @@ int dm_get_device(struct dm_target *ti, const char *path, blk_mode_t mode,
        } else if (dd->dm_dev->mode != (mode | dd->dm_dev->mode)) {
                r = upgrade_mode(dd, mode, t->md);
                if (r)
-                       goto unlock_ret_r;
+                       return r;
        }
        refcount_inc(&dd->count);
 out:
-       up_write(&t->devices_lock);
        *result = dd->dm_dev;
        return 0;
-
-unlock_ret_r:
-       up_write(&t->devices_lock);
-       return r;
 }
 EXPORT_SYMBOL(dm_get_device);
 
@@ -464,12 +454,9 @@ static int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
 void dm_put_device(struct dm_target *ti, struct dm_dev *d)
 {
        int found = 0;
-       struct dm_table *t = ti->table;
-       struct list_head *devices = &t->devices;
+       struct list_head *devices = &ti->table->devices;
        struct dm_dev_internal *dd;
 
-       down_write(&t->devices_lock);
-
        list_for_each_entry(dd, devices, list) {
                if (dd->dm_dev == d) {
                        found = 1;
@@ -478,17 +465,14 @@ void dm_put_device(struct dm_target *ti, struct dm_dev *d)
        }
        if (!found) {
                DMERR("%s: device %s not in table devices list",
-                     dm_device_name(t->md), d->name);
-               goto unlock_ret;
+                     dm_device_name(ti->table->md), d->name);
+               return;
        }
        if (refcount_dec_and_test(&dd->count)) {
-               dm_put_table_device(t->md, d);
+               dm_put_table_device(ti->table->md, d);
                list_del(&dd->list);
                kfree(dd);
        }
-
-unlock_ret:
-       up_write(&t->devices_lock);
 }
 EXPORT_SYMBOL(dm_put_device);