summaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-ioctl.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2021-03-12 15:07:30 +0100
committerMike Snitzer <snitzer@redhat.com>2021-03-26 19:53:41 +0100
commit8b638081bd4520f63db1defc660666ec5f65bc15 (patch)
treeaf1a56b4acdcff94e679306f6b0ce8177a13a935 /drivers/md/dm-ioctl.c
parentdm ioctl: replace device hash with red-black tree (diff)
downloadlinux-8b638081bd4520f63db1defc660666ec5f65bc15.tar.xz
linux-8b638081bd4520f63db1defc660666ec5f65bc15.zip
dm ioctl: return UUID in DM_LIST_DEVICES_CMD result
When LVM needs to find a device with a particular UUID it needs to ask for UUID for each device. This patch returns UUID directly in the list of devices, so that LVM doesn't have to query all the devices with an ioctl. The UUID is returned if the flag DM_UUID_FLAG is set in the parameters. Returning UUID is done in backward-compatible way. There's one unused 32-bit word value after the event number. This patch sets the bit DM_NAME_LIST_FLAG_HAS_UUID if UUID is present and DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID if it isn't (if none of these bits is set, then we have an old kernel that doesn't support returning UUIDs). The UUID is stored after this word. The 'next' value is updated to point after the UUID, so that old version of libdevmapper will skip the UUID without attempting to interpret it. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-ioctl.c')
-rw-r--r--drivers/md/dm-ioctl.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 272de8772d52..0812ac6e9d70 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -558,7 +558,9 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_
for (n = rb_first(&name_rb_tree); n; n = rb_next(n)) {
hc = container_of(n, struct hash_cell, name_node);
needed += align_val(offsetof(struct dm_name_list, name) + strlen(hc->name) + 1);
- needed += align_val(sizeof(uint32_t));
+ needed += align_val(sizeof(uint32_t) * 2);
+ if (param->flags & DM_UUID_FLAG && hc->uuid)
+ needed += align_val(strlen(hc->uuid) + 1);
}
/*
@@ -577,6 +579,7 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_
* Now loop through filling out the names.
*/
for (n = rb_first(&name_rb_tree); n; n = rb_next(n)) {
+ void *uuid_ptr;
hc = container_of(n, struct hash_cell, name_node);
if (old_nl)
old_nl->next = (uint32_t) ((void *) nl -
@@ -588,8 +591,19 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_
old_nl = nl;
event_nr = align_ptr(nl->name + strlen(hc->name) + 1);
- *event_nr = dm_get_event_nr(hc->md);
- nl = align_ptr(event_nr + 1);
+ event_nr[0] = dm_get_event_nr(hc->md);
+ event_nr[1] = 0;
+ uuid_ptr = align_ptr(event_nr + 2);
+ if (param->flags & DM_UUID_FLAG) {
+ if (hc->uuid) {
+ event_nr[1] |= DM_NAME_LIST_FLAG_HAS_UUID;
+ strcpy(uuid_ptr, hc->uuid);
+ uuid_ptr = align_ptr(uuid_ptr + strlen(hc->uuid) + 1);
+ } else {
+ event_nr[1] |= DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID;
+ }
+ }
+ nl = uuid_ptr;
}
/*
* If mismatch happens, security may be compromised due to buffer