summaryrefslogtreecommitdiff
path: root/libdm
diff options
context:
space:
mode:
authorZdenek Kabelac <zkabelac@redhat.com>2021-12-08 10:45:13 +0100
committerZdenek Kabelac <zkabelac@redhat.com>2021-12-20 16:13:28 +0100
commit90da953fd22437a8abfff02eb590a621efcc007c (patch)
tree6e52b109d2908c9d779ad6c062fed4e7d941096b /libdm
parent65236ee7226930bcbabac0d2dc1979a90bcf2d19 (diff)
downloadlvm2-90da953fd22437a8abfff02eb590a621efcc007c.tar.gz
libdm: unmangling UUID for DM_DEVICE_LIST
Properly unmangle UUID if they are provided as result of DM_DEVICE_LIST ioctl on newer linux kernels.
Diffstat (limited to 'libdm')
-rw-r--r--libdm/ioctl/libdm-iface.c51
1 files changed, 43 insertions, 8 deletions
diff --git a/libdm/ioctl/libdm-iface.c b/libdm/ioctl/libdm-iface.c
index a3a1bdc66..0fba79ce4 100644
--- a/libdm/ioctl/libdm-iface.c
+++ b/libdm/ioctl/libdm-iface.c
@@ -762,6 +762,30 @@ struct dm_deps *dm_task_get_deps(struct dm_task *dmt)
dmt->dmi.v4->data_start);
}
+/*
+ * Round up the ptr to an 8-byte boundary.
+ * Follow kernel pattern.
+ */
+#define ALIGN_MASK 7
+static size_t _align_val(size_t val)
+{
+ return (val + ALIGN_MASK) & ~ALIGN_MASK;
+}
+static void *_align_ptr(void *ptr)
+{
+ return (void *)_align_val((size_t)ptr);
+}
+
+static int _check_has_event_nr(void) {
+ static int _has_event_nr = -1;
+
+ if (_has_event_nr < 0)
+ _has_event_nr = dm_check_version() &&
+ ((_dm_version == 4) ? _dm_version_minor >= 38 : _dm_version > 4);
+
+ return _has_event_nr;
+}
+
struct dm_names *dm_task_get_names(struct dm_task *dmt)
{
return (struct dm_names *) (((char *) dmt->dmi.v4) +
@@ -1782,23 +1806,34 @@ static int _do_dm_ioctl_unmangle_string(char *str, const char *str_name,
static int _dm_ioctl_unmangle_names(int type, struct dm_ioctl *dmi)
{
char buf[DM_NAME_LEN];
- struct dm_names *names;
+ char buf_uuid[DM_UUID_LEN];
+ struct dm_name_list *names;
unsigned next = 0;
char *name;
int r = 1;
+ uint32_t *event_nr;
+ char *uuid_ptr;
+ dm_string_mangling_t mangling_mode = dm_get_name_mangling_mode();
if ((name = dmi->name))
- r = _do_dm_ioctl_unmangle_string(name, "name", buf, sizeof(buf),
- dm_get_name_mangling_mode());
+ r &= _do_dm_ioctl_unmangle_string(name, "name", buf, sizeof(buf),
+ mangling_mode);
if (type == DM_DEVICE_LIST &&
- ((names = ((struct dm_names *) ((char *)dmi + dmi->data_start)))) &&
+ ((names = ((struct dm_name_list *) ((char *)dmi + dmi->data_start)))) &&
names->dev) {
do {
- names = (struct dm_names *)((char *) names + next);
- r = _do_dm_ioctl_unmangle_string(names->name, "name",
- buf, sizeof(buf),
- dm_get_name_mangling_mode());
+ names = (struct dm_name_list *)((char *) names + next);
+ event_nr = _align_ptr(names->name + strlen(names->name) + 1);
+ r &= _do_dm_ioctl_unmangle_string(names->name, "name",
+ buf, sizeof(buf), mangling_mode);
+ /* Unmangle also UUID within same loop */
+ if (_check_has_event_nr() &&
+ (event_nr[1] & DM_NAME_LIST_FLAG_HAS_UUID)) {
+ uuid_ptr = _align_ptr(event_nr + 2);
+ r &= _do_dm_ioctl_unmangle_string(uuid_ptr, "UUID", buf_uuid,
+ sizeof(buf_uuid), mangling_mode);
+ }
next = names->next;
} while (next);
}