summaryrefslogtreecommitdiff
path: root/device_mapper/ioctl
diff options
context:
space:
mode:
authorZdenek Kabelac <zkabelac@redhat.com>2021-12-15 11:34:50 +0100
committerZdenek Kabelac <zkabelac@redhat.com>2021-12-20 16:13:28 +0100
commit988ea0e94c79a496f2619eab878fd9db6168711d (patch)
treee7b9d05b0c0b38f281911481ea70a2443a7278ec /device_mapper/ioctl
parent90da953fd22437a8abfff02eb590a621efcc007c (diff)
downloadlvm2-988ea0e94c79a496f2619eab878fd9db6168711d.tar.gz
devicemapper: add dm_task_get_device_list
New API extension (internal ATM) for getting a list of active DM device with extra features like i.e. uuid. To easily lookout for existing UUID in device list, there is: dm_device_list_find_by_uuid() Once the returned structure is no longer usable call: dm_device_list_destroy() Struct dm_active_device {} holds all the info, but is always allocated and destroyed within library. TODO: once it's stable, copy to libdm
Diffstat (limited to 'device_mapper/ioctl')
-rw-r--r--device_mapper/ioctl/libdm-iface.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/device_mapper/ioctl/libdm-iface.c b/device_mapper/ioctl/libdm-iface.c
index acc0f557c..738807f8f 100644
--- a/device_mapper/ioctl/libdm-iface.c
+++ b/device_mapper/ioctl/libdm-iface.c
@@ -779,6 +779,134 @@ static int _check_has_event_nr(void) {
return _has_event_nr;
}
+struct dm_device_list {
+ struct dm_list list;
+ unsigned count;
+ unsigned features;
+ struct dm_hash_table *uuids;
+};
+
+int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
+ unsigned *devs_features)
+{
+ struct dm_names *names, *names1;
+ struct dm_active_device *dm_dev, *dm_new_dev;
+ struct dm_device_list *devs;
+ unsigned next = 0;
+ uint32_t *event_nr;
+ char *uuid_ptr;
+ size_t len;
+ int cnt = 0;
+
+ *devs_list = 0;
+ *devs_features = 0;
+
+ if ((names = dm_task_get_names(dmt)) && names->dev) {
+ names1 = names;
+ if (!names->name[0])
+ cnt = -1; /* -> cnt == 0 when no device is really present */
+ do {
+ names1 = (struct dm_names *)((char *) names1 + next);
+ next = names1->next;
+ ++cnt;
+ } while (next);
+ }
+
+ if (!(devs = malloc(sizeof(*devs) + (cnt ? cnt * sizeof(*dm_dev) + (char*)names1 - (char*)names + 256 : 0))))
+ return_0;
+
+ dm_list_init(&devs->list);
+ devs->count = cnt;
+ devs->uuids = NULL;
+
+ if (!cnt) {
+ /* nothing in the list -> mark all features present */
+ *devs_features |= (DM_DEVICE_LIST_HAS_EVENT_NR | DM_DEVICE_LIST_HAS_UUID);
+ goto out; /* nothing else to do */
+ }
+
+ dm_dev = (struct dm_active_device *) (devs + 1);
+
+ do {
+ names = (struct dm_names *)((char *) names + next);
+
+ dm_dev->major = MAJOR(names->dev);
+ dm_dev->minor = MINOR(names->dev);
+ dm_dev->name = (char*)(dm_dev + 1);
+ dm_dev->event_nr = 0;
+ dm_dev->uuid = NULL;
+
+ strcpy(dm_dev->name, names->name);
+ len = strlen(names->name) + 1;
+
+ dm_new_dev = _align_ptr((char*)(dm_dev + 1) + len);
+ if (_check_has_event_nr()) {
+ /* Hash for UUIDs with some more bits to reduce colision count */
+ if (!devs->uuids && !(devs->uuids = dm_hash_create(cnt * 8))) {
+ free(devs);
+ return_0;
+ }
+
+ *devs_features |= DM_DEVICE_LIST_HAS_EVENT_NR;
+ event_nr = _align_ptr(names->name + len);
+ dm_dev->event_nr = event_nr[0];
+
+ if ((event_nr[1] & DM_NAME_LIST_FLAG_HAS_UUID)) {
+ *devs_features |= DM_DEVICE_LIST_HAS_UUID;
+ uuid_ptr = _align_ptr(event_nr + 2);
+ dm_dev->uuid = (char*) dm_new_dev;
+ dm_new_dev = _align_ptr((char*)dm_new_dev + strlen(uuid_ptr) + 1);
+ strcpy(dm_dev->uuid, uuid_ptr);
+ if (!dm_hash_insert(devs->uuids, dm_dev->uuid, dm_dev))
+ return_0; // FIXME
+#if 0
+ log_debug("Active %s (%s) %d:%d event:%u",
+ dm_dev->name, dm_dev->uuid,
+ dm_dev->major, dm_dev->minor, dm_dev->event_nr);
+#endif
+ }
+ }
+
+ dm_list_add(&devs->list, &dm_dev->list);
+ dm_dev = dm_new_dev;
+ next = names->next;
+ } while (next);
+
+ out:
+ *devs_list = (struct dm_list *)devs;
+
+ return 1;
+}
+
+int dm_device_list_find_by_uuid(struct dm_list *devs_list, const char *uuid,
+ const struct dm_active_device **dev)
+{
+ struct dm_device_list *devs = (struct dm_device_list *) devs_list;
+ struct dm_active_device *dm_dev;
+
+ if (devs->uuids &&
+ (dm_dev = dm_hash_lookup(devs->uuids, uuid))) {
+ if (dev)
+ *dev = dm_dev;
+ return 1;
+ }
+
+ return 0;
+}
+
+void dm_device_list_destroy(struct dm_list **devs_list)
+{
+ struct dm_device_list *devs = (struct dm_device_list *) *devs_list;
+
+ if (devs) {
+ if (devs->uuids)
+ dm_hash_destroy(devs->uuids);
+
+ free(devs);
+ *devs_list = NULL;
+ }
+}
+
struct dm_names *dm_task_get_names(struct dm_task *dmt)
{
return (struct dm_names *) (((char *) dmt->dmi.v4) +