diff options
author | Zdenek Kabelac <zkabelac@redhat.com> | 2021-12-15 11:34:50 +0100 |
---|---|---|
committer | Zdenek Kabelac <zkabelac@redhat.com> | 2021-12-20 16:13:28 +0100 |
commit | 988ea0e94c79a496f2619eab878fd9db6168711d (patch) | |
tree | e7b9d05b0c0b38f281911481ea70a2443a7278ec /device_mapper/ioctl | |
parent | 90da953fd22437a8abfff02eb590a621efcc007c (diff) | |
download | lvm2-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.c | 128 |
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) + |