diff options
author | Hannes Reinecke <hare@suse.de> | 2021-01-21 18:50:56 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-01-27 11:05:35 +0100 |
commit | 97c5846e04532a0651da7016b4d35862993ea56d (patch) | |
tree | 1311be0a725bb5ddb0d6e7bb669b064d54ef14ee /drivers/md/dm-table.c | |
parent | bcf374506f46795d85cd9183f00b43af9d44c7db (diff) | |
download | linux-stable-97c5846e04532a0651da7016b4d35862993ea56d.tar.gz linux-stable-97c5846e04532a0651da7016b4d35862993ea56d.tar.bz2 linux-stable-97c5846e04532a0651da7016b4d35862993ea56d.zip |
dm: avoid filesystem lookup in dm_get_dev_t()
commit 809b1e4945774c9ec5619a8f4e2189b7b3833c0c upstream.
This reverts commit
644bda6f3460 ("dm table: fall back to getting device using name_to_dev_t()")
dm_get_dev_t() is just used to convert an arbitrary 'path' string
into a dev_t. It doesn't presume that the device is present; that
check will be done later, as the only caller is dm_get_device(),
which does a dm_get_table_device() later on, which will properly
open the device.
So if the path string already _is_ in major:minor representation
we can convert it directly, avoiding a recursion into the filesystem
to lookup the block device.
This avoids a hang in multipath_message() when the filesystem is
inaccessible.
Fixes: 644bda6f3460 ("dm table: fall back to getting device using name_to_dev_t()")
Cc: stable@vger.kernel.org
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/md/dm-table.c')
-rw-r--r-- | drivers/md/dm-table.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index f849db3035a0..916433742485 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -431,14 +431,23 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode, { int r; dev_t dev; + unsigned int major, minor; + char dummy; struct dm_dev_internal *dd; struct dm_table *t = ti->table; BUG_ON(!t); - dev = dm_get_dev_t(path); - if (!dev) - return -ENODEV; + if (sscanf(path, "%u:%u%c", &major, &minor, &dummy) == 2) { + /* Extract the major/minor numbers */ + dev = MKDEV(major, minor); + if (MAJOR(dev) != major || MINOR(dev) != minor) + return -EOVERFLOW; + } else { + dev = dm_get_dev_t(path); + if (!dev) + return -ENODEV; + } dd = find_device(&t->devices, dev); if (!dd) { |