[lvm-devel] [PATCH] libdm: _dm_task_set_name_from_path: always use major/minor
Lidong Zhong
lidong.zhong at suse.com
Thu Jul 25 03:21:20 UTC 2019
Hi guys,
Martin asked me to send this patch for him since he is on vacation. And
this patch did fix a real problem. Could you help to review this patch
please?
Thanks,
Lidong
On 7/22/19 10:59 AM, Lidong Zhong wrote:
> From: Martin Wilck <mwilck at suse.com>
>
> libdm assumes that names of symlinks under /dev/mapper uniquely correspond
> to device-mapper names. If this is not the case (e.g. if additional symlinks
> under /dev/mapper have been created by custom udev rules), this algorithm
> may fail, as the names of the extra symlinks don't match the dm name of the
> device. The error message is then a rather misleading "Device does not
> exist" (the device _does_ actually exist, it just has a different dm
> name). Because the algorithm takes the first match in /dev/mapper, depending
> on sort order, this first match may be the "wrong" one of multiple symlinks,
> and thus this error can occur for an innocent "dmsetup info /dev/dm-1"
> command.
>
> The current algorithm checks the major/minor number anyway. Therefore, the
> assumption about symlink names under /dev/mapper can be easily dropped by
> always using the major/minor number rather than the name for device lookup.
> In theory, this approach might even be used if there were no symlinks under
> /dev/mapper at all matching a given device, but this patch refrains from doing
> so for compatibility reasons.
>
> This patch changes the user-visible behavior only where multiple symlinks are
> present. Under normal conditions (unique names under /dev/mapper), it yields
> the same results as before even for pathological invocations such as "dmsetup
> info -j 254 -m 7 /dev/dm-6".
>
> Signed-off-by: Martin Wilck <mwilck at suse.com>
> ---
> libdm/libdm-common.c | 27 +++++++++++++--------------
> 1 file changed, 13 insertions(+), 14 deletions(-)
>
> diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c
> index 40b366b..cbc454a 100644
> --- a/libdm/libdm-common.c
> +++ b/libdm/libdm-common.c
> @@ -343,7 +343,7 @@ struct dm_task *dm_task_create(int type)
> /*
> * Find the name associated with a given device number by scanning _dm_dir.
> */
> -static int _find_dm_name_of_device(dev_t st_rdev, char *buf, size_t buf_len)
> +static int _find_dm_name_of_device(dev_t st_rdev)
> {
> const char *name;
> char path[PATH_MAX];
> @@ -373,7 +373,6 @@ static int _find_dm_name_of_device(dev_t st_rdev, char *buf, size_t buf_len)
> continue;
>
> if (st.st_rdev == st_rdev) {
> - strncpy(buf, name, buf_len);
> r = 1;
> break;
> }
> @@ -605,7 +604,7 @@ static int _dm_task_set_name_from_path(struct dm_task *dmt, const char *path,
> {
> char buf[PATH_MAX];
> struct stat st1, st2;
> - const char *final_name = NULL;
> + int found = 0;
> size_t len;
>
> if (dmt->type == DM_DEVICE_CREATE) {
> @@ -625,7 +624,7 @@ static int _dm_task_set_name_from_path(struct dm_task *dmt, const char *path,
> }
>
> if (!stat(buf, &st2) && (st1.st_rdev == st2.st_rdev))
> - final_name = name;
> + found = 1;
> } else {
> /* Not found. */
> /* If there is exactly one '/' try a prefix of /dev */
> @@ -642,24 +641,24 @@ static int _dm_task_set_name_from_path(struct dm_task *dmt, const char *path,
> log_error("Device %s not found", path);
> return 0;
> }
> - /* Found */
> + found = 1;
> }
>
> /*
> * If we don't have the dm name yet, Call _find_dm_name_of_device() to
> * scan _dm_dir for a match.
> */
> - if (!final_name) {
> - if (_find_dm_name_of_device(st1.st_rdev, buf, sizeof(buf)))
> - final_name = buf;
> - else {
> - log_error("Device %s not found", name);
> - return 0;
> - }
> + if (!found)
> + found = _find_dm_name_of_device(st1.st_rdev);
> +
> + if (!found) {
> + log_error("Device %s not found", name);
> + return 0;
> }
>
> - /* This is an already existing path - do not mangle! */
> - return _dm_task_set_name(dmt, final_name, DM_STRING_MANGLING_NONE);
> + /* Don't allow fallback here - input major / minor should fit */
> + return dm_task_set_major_minor(dmt, MAJOR(st1.st_rdev),
> + MINOR(st1.st_rdev), 0);
> }
>
> int dm_task_set_name(struct dm_task *dmt, const char *name)
>
More information about the lvm-devel
mailing list