Mykola Ivanets
2018-May-15 20:38 UTC
[Libguestfs] [PATCH libldm 00/12] New API: an ability to retrieve created device-mapper devices back after they have been created.
The main goal of these patch series is to implement a new API that allows to retrieve created device-mapper devices for volumes and partitions back after they have been created. As part of this patch: - required libdevmapper version was bumped to 1.02. I think it is safe because it was released more then 10 years ago; - newer version of libdevmapper allowed to simplify code base a little bit; - libdevmapper (and a good practice) suggest using UUID for device-mapper devices. It is get implemented as well. Presence of device UUID allows to use libevmapper API function to find device node easier; - misc fixes and improvements. IMPORTANT: These patch series depends on this one: https://www.redhat.com/archives/libguestfs/2018-May/msg00059.html. NOTE: I tried to look around and follow project code style but it seems inconsistent or I simply was unable to recognize used code style. Any comments re welcomed. -- Mykola Ivanets Mykola Ivanets (12): Requires libdevmapper v1.02. Change the way we sanitise LDM partition name. Clarify ldm_volume_dm_get_name function documentation. Set UUID for device mapper devices (partitions and volumes). Fix potential memory leak. Use device mapper device UUID instead of name to find device in a tree. refactoring: search for device-mapper node in tree. Don't use hard-coded path to a device mapper directory. Move devmapper logging functionality into a single place. misc: don't make unnecessary functions calls, return correct result. New API: ldm_volume_dm_get_device New API: ldm_partition_dm_get_device configure.ac | 2 +- docs/reference/ldmtool/ldmtool.xml | 20 ++ ldm-1.0.pc.in | 2 +- libldm.spec.in | 2 +- src/ldm.c | 379 ++++++++++++++++++++--------- src/ldm.h | 31 ++- src/ldmtool.c | 74 ++++-- test/ldmread.c | 34 ++- 8 files changed, 392 insertions(+), 152 deletions(-) -- 2.17.0
Mykola Ivanets
2018-May-15 20:38 UTC
[Libguestfs] [PATCH libldm 01/12] Requires libdevmapper v1.02.
libdevmapper v1.02 is available for more then 13 years already and it provides newer API which will allow to simplify code base. --- configure.ac | 2 +- ldm-1.0.pc.in | 2 +- libldm.spec.in | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 6f49f71..d1ac3af 100644 --- a/configure.ac +++ b/configure.ac @@ -99,7 +99,7 @@ PKG_CHECK_MODULES([UUID], [uuid], ] ) -PKG_CHECK_MODULES([DEVMAPPER], [devmapper >= 1.0], +PKG_CHECK_MODULES([DEVMAPPER], [devmapper >= 1.02], [ AC_SUBST([DEVMAPPER_CFLAGS]) AC_SUBST([DEVMAPPER_LIBS]) diff --git a/ldm-1.0.pc.in b/ldm-1.0.pc.in index 952f0f0..350546c 100644 --- a/ldm-1.0.pc.in +++ b/ldm-1.0.pc.in @@ -6,7 +6,7 @@ includedir=@includedir@ Name: LDM Description: Microsoft Windows LDM device management library Requires: gobject-2.0 >= 2.26.0 glib-2.0 -Requires.private: json-glib-1.0 >= 0.14.0 gio-unix-2.0 >= 2.32.0 devmapper >= 1.0 +Requires.private: json-glib-1.0 >= 0.14.0 gio-unix-2.0 >= 2.32.0 devmapper >= 1.02 Version: @VERSION@ Libs: -L${libdir} -lldm-1.0 Libs.private: -lz -luuid diff --git a/libldm.spec.in b/libldm.spec.in index 28cf160..bd8fe60 100644 --- a/libldm.spec.in +++ b/libldm.spec.in @@ -9,7 +9,7 @@ Source0: %{url}/downloads/%{name}-%{version}.tar.gz BuildRequires: glib2-devel >= 2.26.0 BuildRequires: json-glib-devel >= 0.14.0 -BuildRequires: device-mapper-devel >= 1.0 +BuildRequires: device-mapper-devel >= 1.02 BuildRequires: zlib-devel libuuid-devel readline-devel -- 2.17.0
Mykola Ivanets
2018-May-15 20:38 UTC
[Libguestfs] [PATCH libldm 02/12] Change the way we sanitise LDM partition name.
libdevmapper limits allowed characters for device name. Character whitelist: 0-9, A-Z, a-z, #+-.:=@_. LDM partition name is composed of disk group name and partition name. Disk group is named after the machine, with a "DgN" suffix; partition name is a disk name with a numerical suffix - partition number within a disk. So, the only variable part which might contain invalid characters is Windows machine name. Therefore g_uri_escape_string function was used to sanitise partition name. However its usage looks artificial because it is unclear either g_uri_escape_string will sanitise invalid characters defined by libdevmapper. Most likely libdevmapper v1.0 didn't provide any way to do that job on its own. Now when we switched to v1.02 of the library we can offload this work. First of all explicitly set mangling mode for devmapper library to DM_STRING_MANGLING_AUTO (mangle only if not already mangled with hex). So, we can set device name as is and the library will mangle name for us. After that we can retrieve mangled name back. --- src/ldm.c | 59 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/src/ldm.c b/src/ldm.c index 5c570a5..c701cbd 100644 --- a/src/ldm.c +++ b/src/ldm.c @@ -292,6 +292,8 @@ ldm_init(LDM * const o) { o->priv = LDM_GET_PRIVATE(o); bzero(o->priv, sizeof(*o->priv)); + + dm_set_name_mangling_mode(DM_STRING_MANGLING_AUTO); } static void @@ -2378,6 +2380,17 @@ ldm_partition_get_disk(LDMPartition * const o) return o->priv->disk; } +static GString * +_dm_part_name(const LDMPartitionPrivate * const part) +{ + const LDMDiskPrivate * const disk = part->disk->priv; + + GString * name = g_string_new(""); + g_string_printf(name, "ldm_part_%s_%s", disk->dgname, part->name); + + return name; +} + static GString * _dm_vol_name(const LDMVolumePrivate * const vol) { @@ -2492,10 +2505,12 @@ _find_device_tree_node(struct dm_tree * const tree, gboolean _dm_create(const gchar * const name, uint32_t udev_cookie, const guint n_targets, const struct dm_target * const targets, - GError ** const err) + GString **mangled_name, GError ** const err) { gboolean r = TRUE; + if (mangled_name) *mangled_name = NULL; + struct dm_task * const task = dm_task_create(DM_DEVICE_CREATE); if (!task) { g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL, @@ -2540,6 +2555,12 @@ _dm_create(const gchar * const name, uint32_t udev_cookie, r = FALSE; goto out; } + if (mangled_name) { + char *tmp = dm_task_get_name_mangled(task); + *mangled_name = g_string_new(tmp); + dm_free(tmp); + } + out: dm_task_destroy(task); return r; @@ -2613,28 +2634,16 @@ _dm_create_part(const LDMPartitionPrivate * const part, uint32_t cookie, g_string_printf(target.params, "%s %" PRIu64, disk->device, disk->data_start + part->start); - /* Ensure we sanitise table names */ - char * dgname_esc - g_uri_escape_string(disk->dgname, - G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT, - FALSE); - char * partname_esc - g_uri_escape_string(part->name, - G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT, - FALSE); - - GString *name = g_string_new(""); - g_string_printf(name, "ldm_part_%s_%s", dgname_esc, partname_esc); - g_free(dgname_esc); - g_free(partname_esc); - - if (!_dm_create(name->str, cookie, 1, &target, err)) { - g_string_free(name, TRUE); - name = NULL; + GString *name = _dm_part_name(part); + GString *mangled_name = NULL; + + if (!_dm_create(name->str, cookie, 1, &target, &mangled_name, err)) { + mangled_name = NULL; } + g_string_free(name, TRUE); g_string_free(target.params, TRUE); - return name; + return mangled_name; } static GString * @@ -2687,7 +2696,7 @@ _dm_create_spanned(const LDMVolumePrivate * const vol, GError ** const err) name = _dm_vol_name(vol); - if (!_dm_create(name->str, cookie, vol->parts->len, targets, err)) { + if (!_dm_create(name->str, cookie, vol->parts->len, targets, NULL, err)) { g_string_free(name, TRUE); name = NULL; } @@ -2744,7 +2753,7 @@ _dm_create_striped(const LDMVolumePrivate * const vol, GError ** const err) name = _dm_vol_name(vol); - if (!_dm_create(name->str, cookie, 1, &target, err)) { + if (!_dm_create(name->str, cookie, 1, &target, NULL, err)) { g_string_free(name, TRUE); name = NULL; } @@ -2818,7 +2827,7 @@ _dm_create_mirrored(const LDMVolumePrivate * const vol, GError ** const err) name = _dm_vol_name(vol); - if (!_dm_create(name->str, cookie, 1, &target, err)) { + if (!_dm_create(name->str, cookie, 1, &target, NULL, err)) { g_string_free(name, TRUE); name = NULL; } @@ -2906,7 +2915,7 @@ _dm_create_raid5(const LDMVolumePrivate * const vol, GError ** const err) name = _dm_vol_name(vol); - if (!_dm_create(name->str, cookie, 1, &target, err)) { + if (!_dm_create(name->str, cookie, 1, &target, NULL, err)) { g_string_free(name, TRUE); name = NULL; goto out; } @@ -2986,7 +2995,7 @@ ldm_volume_dm_create(const LDMVolume * const o, GString **created, return TRUE; } dm_tree_free(tree); tree = NULL; - g_string_free(name, TRUE); + g_string_free(name, TRUE); name = NULL; switch (vol->type) { case LDM_VOLUME_TYPE_SIMPLE: -- 2.17.0
Mykola Ivanets
2018-May-15 20:38 UTC
[Libguestfs] [PATCH libldm 03/12] Clarify ldm_volume_dm_get_name function documentation.
Emphasis that returned name is unmangled. --- src/ldm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ldm.h b/src/ldm.h index 280fbfb..cdc5817 100644 --- a/src/ldm.h +++ b/src/ldm.h @@ -443,7 +443,8 @@ guint64 ldm_volume_get_chunk_size(const LDMVolume *o); * @o: An #LDMVolume * * Get the name of the device mapper device which will be created for this - * volume. + * volume. Note that returned name is unmangled. Device mapper will mangle + * actual device name if it contains invalid characters. * * Returns: (transfer full): The device mapper name */ -- 2.17.0
Mykola Ivanets
2018-May-15 20:38 UTC
[Libguestfs] [PATCH libldm 04/12] Set UUID for device mapper devices (partitions and volumes).
Device mapper device UUID (alongside with device name) is an unique characteristic of device. However libldm didn't set device UUID. Also "dmsetup" user space tool has "mangle" command which issue a warning if device doesn't have UUID. Let's set UUID for created devices to be consistent with DM devices created by other subsystems. Device mapper device UUID is an arbitrary string conventionally prefixed with UUID prefix which is a short capitalised prefix indicating the subsystem that is managing the devices, e.g. "LVM-" or "MPATH-". "LDM-" prefix is used for device created by libldm. Partition UUID is composed in a form "LDM-<partition_name>-<disk_guid>". Disk GUID should be unique a cross disks and LDM partition name is unique within a disk. So, overall generated UUID should be unique. Volume UUID is composed in a form "LDM-<volume_name>-<volume_guid>". Volume GUID should be unique a cross all LDM volumes. So, overall generated UUID should be unique (despite LDM volume name). --- src/ldm.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 7 deletions(-) diff --git a/src/ldm.c b/src/ldm.c index c701cbd..02378f8 100644 --- a/src/ldm.c +++ b/src/ldm.c @@ -39,6 +39,8 @@ #include "gpt.h" #include "ldm.h" +#define DM_UUID_PREFIX "LDM-" + #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-" \ "%02x%02x-%02x%02x%02x%02x%02x%02x" #define UUID_VALS(uuid) (uuid)[0], (uuid)[1], (uuid)[2], (uuid)[3], \ @@ -294,6 +296,7 @@ ldm_init(LDM * const o) bzero(o->priv, sizeof(*o->priv)); dm_set_name_mangling_mode(DM_STRING_MANGLING_AUTO); + dm_set_uuid_prefix(DM_UUID_PREFIX); } static void @@ -2391,6 +2394,21 @@ _dm_part_name(const LDMPartitionPrivate * const part) return name; } +static GString * +_dm_part_uuid(const LDMPartitionPrivate * const part) +{ + const LDMDiskPrivate * const disk = part->disk->priv; + + char ldm_disk_guid[37]; + uuid_unparse_lower(disk->guid, ldm_disk_guid); + + GString * dm_uuid = g_string_new(""); + g_string_printf(dm_uuid, "%s%s-%s", + DM_UUID_PREFIX, part->name, ldm_disk_guid); + + return dm_uuid; +} + static GString * _dm_vol_name(const LDMVolumePrivate * const vol) { @@ -2399,6 +2417,19 @@ _dm_vol_name(const LDMVolumePrivate * const vol) return r; } +static GString * +_dm_vol_uuid(const LDMVolumePrivate * const vol) +{ + char ldm_vol_uuid[37]; + uuid_unparse_lower(vol->guid, ldm_vol_uuid); + + GString * dm_uuid = g_string_new(""); + g_string_printf(dm_uuid, "%s%s-%s", + DM_UUID_PREFIX, vol->name, ldm_vol_uuid); + + return dm_uuid; +} + /* We catch log messages generated by device mapper with errno != 0 and store * them here */ static int _dm_err_last_level = 0; @@ -2503,8 +2534,9 @@ _find_device_tree_node(struct dm_tree * const tree, } gboolean -_dm_create(const gchar * const name, uint32_t udev_cookie, - const guint n_targets, const struct dm_target * const targets, +_dm_create(const gchar * const name, const gchar * const uuid, + uint32_t udev_cookie, const guint n_targets, + const struct dm_target * const targets, GString **mangled_name, GError ** const err) { gboolean r = TRUE; @@ -2526,6 +2558,13 @@ _dm_create(const gchar * const name, uint32_t udev_cookie, r = FALSE; goto out; } + if (!dm_task_set_uuid(task, uuid)) { + g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL, + "DM_DEVICE_CREATE: dm_task_set_uuid(%s) failed: %s", + uuid, _dm_err_last_msg); + r = FALSE; goto out; + } + for (guint i = 0; i < n_targets; i++) { const struct dm_target * const target = &targets[i]; @@ -2635,14 +2674,18 @@ _dm_create_part(const LDMPartitionPrivate * const part, uint32_t cookie, disk->device, disk->data_start + part->start); GString *name = _dm_part_name(part); + GString *uuid = _dm_part_uuid(part); GString *mangled_name = NULL; - if (!_dm_create(name->str, cookie, 1, &target, &mangled_name, err)) { + if (!_dm_create(name->str, uuid->str, cookie, 1, &target, + &mangled_name, err)) { mangled_name = NULL; } g_string_free(name, TRUE); + g_string_free(uuid, TRUE); g_string_free(target.params, TRUE); + return mangled_name; } @@ -2695,12 +2738,15 @@ _dm_create_spanned(const LDMVolumePrivate * const vol, GError ** const err) } name = _dm_vol_name(vol); + GString *uuid = _dm_vol_uuid(vol); - if (!_dm_create(name->str, cookie, vol->parts->len, targets, NULL, err)) { + if (!_dm_create(name->str, uuid->str, cookie, vol->parts->len, targets, + NULL, err)) { g_string_free(name, TRUE); name = NULL; } + g_string_free(uuid, TRUE); dm_udev_wait(cookie); out: @@ -2752,12 +2798,14 @@ _dm_create_striped(const LDMVolumePrivate * const vol, GError ** const err) } name = _dm_vol_name(vol); + GString *uuid = _dm_vol_uuid(vol); - if (!_dm_create(name->str, cookie, 1, &target, NULL, err)) { + if (!_dm_create(name->str, uuid->str, cookie, 1, &target, NULL, err)) { g_string_free(name, TRUE); name = NULL; } + g_string_free(uuid, TRUE); dm_udev_wait(cookie); out: @@ -2826,12 +2874,14 @@ _dm_create_mirrored(const LDMVolumePrivate * const vol, GError ** const err) } name = _dm_vol_name(vol); + GString *uuid = _dm_vol_uuid(vol); - if (!_dm_create(name->str, cookie, 1, &target, NULL, err)) { + if (!_dm_create(name->str, uuid->str, cookie, 1, &target, NULL, err)) { g_string_free(name, TRUE); name = NULL; } + g_string_free(uuid, TRUE); dm_udev_wait(cookie); g_array_unref(devices); devices = NULL; @@ -2857,6 +2907,7 @@ static GString * _dm_create_raid5(const LDMVolumePrivate * const vol, GError ** const err) { GString *name = NULL; + GString *uuid = NULL; struct dm_target target; target.start = 0; @@ -2914,12 +2965,15 @@ _dm_create_raid5(const LDMVolumePrivate * const vol, GError ** const err) } name = _dm_vol_name(vol); + uuid = _dm_vol_uuid(vol); - if (!_dm_create(name->str, cookie, 1, &target, NULL, err)) { + if (!_dm_create(name->str, uuid->str, cookie, 1, &target, NULL, err)) { g_string_free(name, TRUE); name = NULL; + g_string_free(uuid, TRUE); goto out; } + g_string_free(uuid, TRUE); dm_udev_wait(cookie); g_array_unref(devices); devices = NULL; @@ -2938,6 +2992,7 @@ out: } g_string_free(target.params, TRUE); + return name; } -- 2.17.0
Mykola Ivanets
2018-May-15 20:38 UTC
[Libguestfs] [PATCH libldm 05/12] Fix potential memory leak.
Potential memory leak in ldm_volume_dm_create and ldm_volume_dm_remove functions is fixed. Leak was possible if the caller doesn't want to get back created or remove device name, passing NULL as a second argument. --- src/ldm.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/ldm.c b/src/ldm.c index 02378f8..65606cc 100644 --- a/src/ldm.c +++ b/src/ldm.c @@ -3033,6 +3033,8 @@ gboolean ldm_volume_dm_create(const LDMVolume * const o, GString **created, GError ** const err) { + if (created) *created = NULL; + const LDMVolumePrivate * const vol = o->priv; /* We should really store the previous logging function and restore it @@ -3077,14 +3079,22 @@ ldm_volume_dm_create(const LDMVolume * const o, GString **created, dm_log_with_errno_init(NULL); - if (created && name) *created = name; - return name == NULL ? FALSE : TRUE; + gboolean r = name != NULL; + + if (created) + *created = name; + else if (name) + g_string_free(name, TRUE); + + return r; } gboolean ldm_volume_dm_remove(const LDMVolume * const o, GString **removed, GError ** const err) { + if (removed) *removed = NULL; + const LDMVolumePrivate * const vol = o->priv; /* We should really store the previous logging function and restore it @@ -3129,7 +3139,11 @@ ldm_volume_dm_remove(const LDMVolume * const o, GString **removed, out: dm_tree_free(tree); - if (removed && name) *removed = name; + + if (removed) + *removed = name; + else if (name) + g_string_free(name, TRUE); dm_log_with_errno_init(NULL); -- 2.17.0
Mykola Ivanets
2018-May-15 20:38 UTC
[Libguestfs] [PATCH libldm 06/12] Use device mapper device UUID instead of name to find device in a tree.
libdevmapper provides dm_tree_find_node_by_uuid function which we can use to find device in a tree and get rid of our own implementation. --- src/ldm.c | 52 ++++++++++++---------------------------------------- 1 file changed, 12 insertions(+), 40 deletions(-) diff --git a/src/ldm.c b/src/ldm.c index 65606cc..1be6736 100644 --- a/src/ldm.c +++ b/src/ldm.c @@ -2501,38 +2501,6 @@ error: return NULL; } -static struct dm_tree_node * -_walk_tree(const struct dm_tree * const tree, - const struct dm_tree_node * const node, - const char * const search) -{ - void *handle = NULL; - struct dm_tree_node *child; - for (;;) { - child = dm_tree_next_child(&handle, node, 0); - if (!child) return NULL; - - const char * const name = dm_tree_node_get_name(child); - if (!name || *name == '\0') continue; - - if (g_strcmp0(search, name) == 0) return child; - - if (dm_tree_node_num_children(child, 0) > 0) { - struct dm_tree_node * const r_search - _walk_tree(tree, child, search); - if (r_search) return r_search; - } - } -} - -static struct dm_tree_node * -_find_device_tree_node(struct dm_tree * const tree, - const char * const name) -{ - const struct dm_tree_node * const root = dm_tree_find_node(tree, 0, 0); - return _walk_tree(tree, root, name); -} - gboolean _dm_create(const gchar * const name, const gchar * const uuid, uint32_t udev_cookie, const guint n_targets, @@ -2900,6 +2868,7 @@ out: } g_string_free(target.params, TRUE); + return name; } @@ -3045,15 +3014,17 @@ ldm_volume_dm_create(const LDMVolume * const o, GString **created, struct dm_tree *tree = _get_device_tree(err); if (!tree) return FALSE; - GString *name = _dm_vol_name(vol); - struct dm_tree_node *node = _find_device_tree_node(tree, name->str); + GString *uuid = _dm_vol_uuid(vol); + struct dm_tree_node *node = dm_tree_find_node_by_uuid(tree, uuid->str); + g_string_free(uuid, TRUE); + if (node) { dm_tree_free(tree); tree = NULL; return TRUE; } dm_tree_free(tree); tree = NULL; - g_string_free(name, TRUE); name = NULL; + GString *name = NULL; switch (vol->type) { case LDM_VOLUME_TYPE_SIMPLE: case LDM_VOLUME_TYPE_SPANNED: @@ -3106,17 +3077,20 @@ ldm_volume_dm_remove(const LDMVolume * const o, GString **removed, gboolean r = FALSE; - GString *name = _dm_vol_name(vol); - struct dm_tree_node *node = _find_device_tree_node(tree, name->str); + GString *uuid = _dm_vol_uuid(vol); + struct dm_tree_node *node = dm_tree_find_node_by_uuid(tree, uuid->str); + g_string_free(uuid, TRUE); + + GString *name = NULL; if (node) { uint32_t cookie; if (!dm_udev_create_cookie(&cookie)) { g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL, "dm_udev_create_cookie: %s", _dm_err_last_msg); - g_string_free(name, TRUE); name = NULL; goto out; } + name = _dm_vol_name(vol); if (!_dm_remove(name->str, cookie, err)) { g_string_free(name, TRUE); name = NULL; goto out; @@ -3131,8 +3105,6 @@ ldm_volume_dm_remove(const LDMVolume * const o, GString **removed, } dm_udev_wait(cookie); - } else { - g_string_free(name, TRUE); name = NULL; } r = TRUE; -- 2.17.0
Mykola Ivanets
2018-May-15 20:38 UTC
[Libguestfs] [PATCH libldm 07/12] refactoring: search for device-mapper node in tree.
Searching for device node in device mapper tree is used twice. So let's extract this functionality into a separate reusable function. --- src/ldm.c | 62 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/src/ldm.c b/src/ldm.c index 1be6736..ac6bae8 100644 --- a/src/ldm.c +++ b/src/ldm.c @@ -2446,7 +2446,7 @@ struct dm_target { }; static struct dm_tree * -_get_device_tree(GError **err) +_dm_get_device_tree(GError **err) { struct dm_tree *tree; tree = dm_tree_create(); @@ -2501,6 +2501,42 @@ error: return NULL; } +/* Returns TRUE if device with specified UUID is found or FALSE otherwise. + * + * Found device node is returned if dm_node is not NULL. In this case dm_tree + * MUST not be NULL as well. And the caller is responsible to free device tree + * by calling dm_tree_free function. + */ +gboolean +_dm_find_tree_node_by_uuid(const gchar * const uuid, + struct dm_tree_node ** dm_node, + struct dm_tree ** dm_tree, + GError ** const err) +{ + gboolean r = FALSE; + + if (dm_node) { + g_assert(dm_tree != NULL); + *dm_node = NULL; + } + if (dm_tree) *dm_tree = NULL; + + struct dm_tree *tree = _dm_get_device_tree(err); + if (tree) { + struct dm_tree_node *node = dm_tree_find_node_by_uuid(tree, uuid); + if (node) r = TRUE; + + if (dm_tree) + *dm_tree = tree; + else + dm_tree_free(tree); + + if (dm_node) *dm_node = node; + } + + return r; +} + gboolean _dm_create(const gchar * const name, const gchar * const uuid, uint32_t udev_cookie, const guint n_targets, @@ -3011,18 +3047,12 @@ ldm_volume_dm_create(const LDMVolume * const o, GString **created, dm_log_with_errno_init(_dm_log_fn); /* Check if the device already exists */ - struct dm_tree *tree = _get_device_tree(err); - if (!tree) return FALSE; - GString *uuid = _dm_vol_uuid(vol); - struct dm_tree_node *node = dm_tree_find_node_by_uuid(tree, uuid->str); - g_string_free(uuid, TRUE); - - if (node) { - dm_tree_free(tree); tree = NULL; + if (_dm_find_tree_node_by_uuid(uuid->str, NULL, NULL, err)) { + g_string_free(uuid, TRUE); return TRUE; } - dm_tree_free(tree); tree = NULL; + g_string_free(uuid, TRUE); GString *name = NULL; switch (vol->type) { @@ -3072,17 +3102,17 @@ ldm_volume_dm_remove(const LDMVolume * const o, GString **removed, * afterwards, but the API doesn't allow this. */ dm_log_with_errno_init(_dm_log_fn); - struct dm_tree *tree = _get_device_tree(err); - if (!tree) return FALSE; - gboolean r = FALSE; + struct dm_tree *tree = NULL; + struct dm_tree_node *node = NULL; + GString *uuid = _dm_vol_uuid(vol); - struct dm_tree_node *node = dm_tree_find_node_by_uuid(tree, uuid->str); + gboolean found = _dm_find_tree_node_by_uuid(uuid->str, &node, &tree, err); g_string_free(uuid, TRUE); GString *name = NULL; - if (node) { + if (found) { uint32_t cookie; if (!dm_udev_create_cookie(&cookie)) { g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL, @@ -3110,7 +3140,7 @@ ldm_volume_dm_remove(const LDMVolume * const o, GString **removed, r = TRUE; out: - dm_tree_free(tree); + if (tree) dm_tree_free(tree); if (removed) *removed = name; -- 2.17.0
Mykola Ivanets
2018-May-15 20:38 UTC
[Libguestfs] [PATCH libldm 08/12] Don't use hard-coded path to a device mapper directory.
Get path to a device mapper directory calling "dm_dir" function from devmapper library instead of using hard-coded value "/dev/mapper". --- src/ldm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ldm.c b/src/ldm.c index ac6bae8..f31a0aa 100644 --- a/src/ldm.c +++ b/src/ldm.c @@ -2840,6 +2840,8 @@ _dm_create_mirrored(const LDMVolumePrivate * const vol, GError ** const err) goto out; } + const char *dir = dm_dir(); + int found = 0; for (guint i = 0; i < vol->parts->len; i++) { const LDMPartition * const part_o @@ -2860,7 +2862,7 @@ _dm_create_mirrored(const LDMVolumePrivate * const vol, GError ** const err) found++; g_array_append_val(devices, chunk); - g_string_append_printf(target.params, " - /dev/mapper/%s", chunk->str); + g_string_append_printf(target.params, " - %s/%s", dir, chunk->str); } if (found == 0) { @@ -2932,6 +2934,8 @@ _dm_create_raid5(const LDMVolumePrivate * const vol, GError ** const err) goto out; } + const char *dir = dm_dir(); + guint n_found = 0; for (guint i = 0; i < vol->parts->len; i++) { const LDMPartition * const part_o @@ -2952,7 +2956,7 @@ _dm_create_raid5(const LDMVolumePrivate * const vol, GError ** const err) n_found++; g_array_append_val(devices, chunk); - g_string_append_printf(target.params, " - /dev/mapper/%s", chunk->str); + g_string_append_printf(target.params, " - %s/%s", dir, chunk->str); } if (n_found < vol->parts->len - 1) { -- 2.17.0
Mykola Ivanets
2018-May-15 20:38 UTC
[Libguestfs] [PATCH libldm 09/12] Move devmapper logging functionality into a single place.
Custom device mapper logging is initialized during libdm library initialization in one place. --- src/ldm.c | 87 +++++++++++++++++++++++++------------------------------ 1 file changed, 40 insertions(+), 47 deletions(-) diff --git a/src/ldm.c b/src/ldm.c index f31a0aa..16934d6 100644 --- a/src/ldm.c +++ b/src/ldm.c @@ -236,6 +236,41 @@ ldm_error_get_type(void) return etype; } +/* We catch log messages generated by device mapper with errno != 0 and store + * them here */ +static int _dm_err_last_level = 0; +static const char *_dm_err_last_file = NULL; +static int _dm_err_last_line = 0; +static int _dm_err_last_errno = 0; +static char *_dm_err_last_msg = NULL; + +static void +_dm_log_fn(const int level, const char * const file, const int line, + const int dm_errno, const char *f, ...) +{ + if (dm_errno == 0) return; + + _dm_err_last_level = level; + _dm_err_last_file = file; + _dm_err_last_line = line; + + /* device-mapper doesn't set dm_errno usefully (it only seems to use + * EUNCLASSIFIED), so we capture errno directly and cross our fingers */ + _dm_err_last_errno = errno; + + if (_dm_err_last_msg) { + free(_dm_err_last_msg); + _dm_err_last_msg = NULL; + } + + va_list ap; + va_start(ap, f); + if (vasprintf(&_dm_err_last_msg, f, ap) == -1) { + g_error("vasprintf"); + } + va_end(ap); +} + /* Macros for exporting object properties */ #define EXPORT_PROP_STRING(object, klass, property) \ @@ -287,6 +322,9 @@ ldm_dispose(GObject * const object) if (ldm->priv->disk_groups) { g_array_unref(ldm->priv->disk_groups); ldm->priv->disk_groups = NULL; } + + /* Restore default logging function. */ + dm_log_with_errno_init(NULL); } static void @@ -295,6 +333,8 @@ ldm_init(LDM * const o) o->priv = LDM_GET_PRIVATE(o); bzero(o->priv, sizeof(*o->priv)); + /* Provide our logging function. */ + dm_log_with_errno_init(_dm_log_fn); dm_set_name_mangling_mode(DM_STRING_MANGLING_AUTO); dm_set_uuid_prefix(DM_UUID_PREFIX); } @@ -2430,14 +2470,6 @@ _dm_vol_uuid(const LDMVolumePrivate * const vol) return dm_uuid; } -/* We catch log messages generated by device mapper with errno != 0 and store - * them here */ -static int _dm_err_last_level = 0; -static const char *_dm_err_last_file = NULL; -static int _dm_err_last_line = 0; -static int _dm_err_last_errno = 0; -static char *_dm_err_last_msg = NULL; - struct dm_target { guint64 start; guint64 size; @@ -3005,33 +3037,6 @@ out: return name; } -static void -_dm_log_fn(const int level, const char * const file, const int line, - const int dm_errno, const char *f, ...) -{ - if (dm_errno == 0) return; - - _dm_err_last_level = level; - _dm_err_last_file = file; - _dm_err_last_line = line; - - /* device-mapper doesn't set dm_errno usefully (it only seems to use - * EUNCLASSIFIED), so we capture errno directly and cross our fingers */ - _dm_err_last_errno = errno; - - if (_dm_err_last_msg) { - free(_dm_err_last_msg); - _dm_err_last_msg = NULL; - } - - va_list ap; - va_start(ap, f); - if (vasprintf(&_dm_err_last_msg, f, ap) == -1) { - g_error("vasprintf"); - } - va_end(ap); -} - GString * ldm_volume_dm_get_name(const LDMVolume * const o) { @@ -3046,10 +3051,6 @@ ldm_volume_dm_create(const LDMVolume * const o, GString **created, const LDMVolumePrivate * const vol = o->priv; - /* We should really store the previous logging function and restore it - * afterwards, but the API doesn't allow this. */ - dm_log_with_errno_init(_dm_log_fn); - /* Check if the device already exists */ GString *uuid = _dm_vol_uuid(vol); if (_dm_find_tree_node_by_uuid(uuid->str, NULL, NULL, err)) { @@ -3082,8 +3083,6 @@ ldm_volume_dm_create(const LDMVolume * const o, GString **created, g_error("Unexpected volume type: %u", vol->type); } - dm_log_with_errno_init(NULL); - gboolean r = name != NULL; if (created) @@ -3102,10 +3101,6 @@ ldm_volume_dm_remove(const LDMVolume * const o, GString **removed, const LDMVolumePrivate * const vol = o->priv; - /* We should really store the previous logging function and restore it - * afterwards, but the API doesn't allow this. */ - dm_log_with_errno_init(_dm_log_fn); - gboolean r = FALSE; struct dm_tree *tree = NULL; @@ -3151,7 +3146,5 @@ out: else if (name) g_string_free(name, TRUE); - dm_log_with_errno_init(NULL); - return r; } -- 2.17.0
Mykola Ivanets
2018-May-15 20:38 UTC
[Libguestfs] [PATCH libldm 10/12] misc: don't make unnecessary functions calls, return correct result.
Don't make unnecessary function calls in show_<object> functions family until we find requested object (volume, partition etc.). Also make sure the functions return correct result. --- src/ldmtool.c | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/ldmtool.c b/src/ldmtool.c index 9686778..6ae5c0b 100644 --- a/src/ldmtool.c +++ b/src/ldmtool.c @@ -279,15 +279,15 @@ show_volume(LDM *const ldm, const gint argc, gchar ** const argv, LDMVolume * const vol = g_array_index(volumes, LDMVolume *, i); gchar *name = ldm_volume_get_name(vol); - gchar* guid = ldm_volume_get_guid(vol); - LDMVolumeType type = ldm_volume_get_voltype(vol); - guint64 size = ldm_volume_get_size(vol); - guint64 chunk_size = ldm_volume_get_chunk_size(vol); - gchar *hint = ldm_volume_get_hint(vol); - if (g_strcmp0(name, argv[1]) == 0) { found = TRUE; + gchar* guid = ldm_volume_get_guid(vol); + LDMVolumeType type = ldm_volume_get_voltype(vol); + guint64 size = ldm_volume_get_size(vol); + guint64 chunk_size = ldm_volume_get_chunk_size(vol); + gchar *hint = ldm_volume_get_hint(vol); + json_builder_begin_object(jb); GEnumValue * const type_v @@ -323,11 +323,12 @@ show_volume(LDM *const ldm, const gint argc, gchar ** const argv, json_builder_end_array(jb); json_builder_end_object(jb); + + g_free(guid); + g_free(hint); } g_free(name); - g_free(guid); - g_free(hint); if (found) break; } @@ -347,17 +348,17 @@ show_partition(LDM *const ldm, const gint argc, gchar ** const argv, GArray * const parts = ldm_disk_group_get_partitions(dg); g_object_unref(dg); + gboolean found = FALSE; for (guint i = 0; i < parts->len; i++) { LDMPartition * const part = g_array_index(parts, LDMPartition *, i); gchar *name = ldm_partition_get_name(part); - guint64 start = ldm_partition_get_start(part); - guint64 size = ldm_partition_get_size(part); - - gboolean found = FALSE; if (g_strcmp0(name, argv[1]) == 0) { found = TRUE; + guint64 start = ldm_partition_get_start(part); + guint64 size = ldm_partition_get_size(part); + LDMDisk * const disk = ldm_partition_get_disk(part); gchar *diskname = ldm_disk_get_name(disk); g_object_unref(disk); @@ -384,7 +385,7 @@ show_partition(LDM *const ldm, const gint argc, gchar ** const argv, } g_array_unref(parts); - return TRUE; + return found; } gboolean @@ -403,16 +404,16 @@ show_disk(LDM *const ldm, const gint argc, gchar ** const argv, LDMDisk * const disk = g_array_index(disks, LDMDisk *, i); gchar *name = ldm_disk_get_name(disk); - gchar *guid = ldm_disk_get_guid(disk); - gchar *device = ldm_disk_get_device(disk); - guint64 data_start = ldm_disk_get_data_start(disk); - guint64 data_size = ldm_disk_get_data_size(disk); - guint64 metadata_start = ldm_disk_get_metadata_start(disk); - guint64 metadata_size = ldm_disk_get_metadata_size(disk); - if (g_strcmp0(name, argv[1]) == 0) { found = TRUE; + gchar *guid = ldm_disk_get_guid(disk); + gchar *device = ldm_disk_get_device(disk); + guint64 data_start = ldm_disk_get_data_start(disk); + guint64 data_size = ldm_disk_get_data_size(disk); + guint64 metadata_start = ldm_disk_get_metadata_start(disk); + guint64 metadata_size = ldm_disk_get_metadata_size(disk); + json_builder_begin_object(jb); json_builder_set_member_name(jb, "name"); @@ -435,17 +436,18 @@ show_disk(LDM *const ldm, const gint argc, gchar ** const argv, } json_builder_end_object(jb); + + g_free(guid); + g_free(device); } g_free(name); - g_free(guid); - g_free(device); if (found) break; } g_array_unref(disks); - return TRUE; + return found; } gboolean -- 2.17.0
Mykola Ivanets
2018-May-15 20:38 UTC
[Libguestfs] [PATCH libldm 11/12] New API: ldm_volume_dm_get_device
New API method is introduced - ldm_volume_dm_get_device(...) which returns device mapper device after it have been created or NULL otherwise. ldmtool "show volume" command displays "device" field if corresponding device mapper device have been created for the specified volume. Field is omitted otherwise. e.g. /dev/mapper/ldm_vol_Red-nzv8x6obywgDg0_Volume3 --- docs/reference/ldmtool/ldmtool.xml | 20 +++++++++++ src/ldm.c | 56 ++++++++++++++++++++++++++++++ src/ldm.h | 14 ++++++++ src/ldmtool.c | 15 +++++++- test/ldmread.c | 6 ++++ 5 files changed, 110 insertions(+), 1 deletion(-) diff --git a/docs/reference/ldmtool/ldmtool.xml b/docs/reference/ldmtool/ldmtool.xml index ec52633..3d1631b 100644 --- a/docs/reference/ldmtool/ldmtool.xml +++ b/docs/reference/ldmtool/ldmtool.xml @@ -312,6 +312,15 @@ </para> </listitem> </varlistentry> + <varlistentry> + <term>device</term> + <listitem> + <para> + The host device-mapper device which was created for this + volume if any (e.g. /dev/mapper/ldm_vol_Machine-Dg0_Volume1) + </para> + </listitem> + </varlistentry> <varlistentry> <term>partitions</term> <listitem> @@ -579,6 +588,7 @@ ldm> show volume 06495a84-fbfd-11e1-8cf9-52540061f5db Volume1 "size" : 129024, "chunk-size" : 0, "hint" : "E:", + "device" : "ldm_vol_WIN-ERRDJSBDAVF-Dg0_Volume1", "partitions" : [ "Disk1-01", "Disk2-01" @@ -643,6 +653,16 @@ ldm> create volume 06495a84-fbfd-11e1-8cf9-52540061f5db Volume1 <literal>/dev/mapper/ldm_vol_WIN-ERRDJSBDAVF-Dg0_Volume1</literal>. </para> + <para> + Note that returned name of the created device-mapper device is unmangled + and thus can contains not-whitelisted characters. User-space + device-mapper tools (like <literal>dmsetup</literal>) and + <literal>libdevmapper</literal> library accept unmangled names (if + properly configured) but take extra care composing path to a created + device yourself. Consider using <literal>"device"</literal> field of the + <command>show volume</command> command output. + </para> + <para> Create device-mapper devices for all volumes in both disk groups: </para> diff --git a/src/ldm.c b/src/ldm.c index 16934d6..75f6d5b 100644 --- a/src/ldm.c +++ b/src/ldm.c @@ -3043,6 +3043,62 @@ ldm_volume_dm_get_name(const LDMVolume * const o) return _dm_vol_name(o->priv); } +gchar * +ldm_volume_dm_get_device(const LDMVolume * const o, GError ** const err) +{ + GString *r = NULL; + + GString *uuid = _dm_vol_uuid(o->priv); + struct dm_tree_node *node = NULL; + struct dm_tree *tree = NULL; + struct dm_task *task = NULL; + + if (_dm_find_tree_node_by_uuid(uuid->str, &node, &tree, err)) { + const struct dm_info *info = dm_tree_node_get_info(node); + + task = dm_task_create(DM_DEVICE_INFO); + if (!task) { + g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL, + "dm_task_create: %s", _dm_err_last_msg); + goto error; + } + + if (!dm_task_set_major(task, info->major)) { + g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL, + "DM_DEVICE_INFO: dm_task_set_major(%d) failed: %s", + info->major, _dm_err_last_msg); + goto error; + } + + if (!dm_task_set_minor(task, info->minor)) { + g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL, + "DM_DEVICE_INFO: dm_task_set_major(%d) failed: %s", + info->minor, _dm_err_last_msg); + goto error; + } + + if (!dm_task_run(task)) { + g_set_error_literal(err, LDM_ERROR, LDM_ERROR_EXTERNAL, + _dm_err_last_msg); + goto error; + } + + const char *dir = dm_dir(); + char *mangled_name = dm_task_get_name_mangled(task); + r = g_string_new(""); + g_string_printf(r, "%s/%s", dir, mangled_name); + dm_free(mangled_name); + } + +error: + if (tree) dm_tree_free(tree); + if (task) dm_task_destroy(task); + g_string_free(uuid, TRUE); + + /* Really FALSE here - don't free but return the character data. */ + return r ? g_string_free(r, FALSE) : NULL; +} + gboolean ldm_volume_dm_create(const LDMVolume * const o, GString **created, GError ** const err) diff --git a/src/ldm.h b/src/ldm.h index cdc5817..de1552a 100644 --- a/src/ldm.h +++ b/src/ldm.h @@ -450,6 +450,20 @@ guint64 ldm_volume_get_chunk_size(const LDMVolume *o); */ GString *ldm_volume_dm_get_name(const LDMVolume *o); +/** + * ldm_volume_dm_get_device: + * @o: An #LDMVolume + * @err: A #GError to receive any generated errors + * + * Get the host device mapper device which was created for this volume + * (e.g. /dev/mapper/ldm_vol_Red-nzv8x6obywgDg0_Volume3). It is dynamic + * runtime property and it will be NULL if device mapper device is absent. + * + * Returns: (transfer full): The host device mapper device if present, + * or NULL otherwise + */ +gchar *ldm_volume_dm_get_device(const LDMVolume * const o, GError **err); + /** * ldm_volume_dm_create: * @o: An #LDMVolume diff --git a/src/ldmtool.c b/src/ldmtool.c index 6ae5c0b..bc58601 100644 --- a/src/ldmtool.c +++ b/src/ldmtool.c @@ -282,12 +282,20 @@ show_volume(LDM *const ldm, const gint argc, gchar ** const argv, if (g_strcmp0(name, argv[1]) == 0) { found = TRUE; - gchar* guid = ldm_volume_get_guid(vol); + gchar *guid = ldm_volume_get_guid(vol); LDMVolumeType type = ldm_volume_get_voltype(vol); guint64 size = ldm_volume_get_size(vol); guint64 chunk_size = ldm_volume_get_chunk_size(vol); gchar *hint = ldm_volume_get_hint(vol); + GError *err = NULL; + gchar *device = ldm_volume_dm_get_device(vol, &err); + if (err) { + g_warning("Unable to get device for volume %s with GUID %s: %s", + name, guid, err->message); + g_error_free(err); + } + json_builder_begin_object(jb); GEnumValue * const type_v @@ -307,6 +315,10 @@ show_volume(LDM *const ldm, const gint argc, gchar ** const argv, json_builder_set_member_name(jb, "hint"); json_builder_add_string_value(jb, hint); } + if (device != NULL) { + json_builder_set_member_name(jb, "device"); + json_builder_add_string_value(jb, device); + } json_builder_set_member_name(jb, "partitions"); json_builder_begin_array(jb); @@ -326,6 +338,7 @@ show_volume(LDM *const ldm, const gint argc, gchar ** const argv, g_free(guid); g_free(hint); + g_free(device); } g_free(name); diff --git a/test/ldmread.c b/test/ldmread.c index bc4d0c5..fd40670 100644 --- a/test/ldmread.c +++ b/test/ldmread.c @@ -89,6 +89,9 @@ int main(int argc, const char *argv[]) g_enum_get_value(g_type_class_peek(LDM_TYPE_VOLUME_TYPE), type); + GError *err = NULL; + gchar *device = ldm_volume_dm_get_device(vol, &err); + printf(" Volume: %s\n", name); printf(" GUID: %s\n", guid); printf(" Type: %s\n", type_v->value_nick); @@ -96,10 +99,13 @@ int main(int argc, const char *argv[]) printf(" Part Type: %hhu\n", part_type); printf(" Hint: %s\n", hint); printf(" Chunk Size: %lu\n", chunk_size); + printf(" Device: %s\n", device); g_free(name); g_free(guid); g_free(hint); + g_free(device); + if (err) g_error_free(err); } GArray *parts = ldm_volume_get_partitions(vol); -- 2.17.0
Mykola Ivanets
2018-May-15 20:38 UTC
[Libguestfs] [PATCH libldm 12/12] New API: ldm_partition_dm_get_device
New API method is introduced - ldm_partition_dm_get_device(...) which returns device mapper device after it have been created or NULL otherwise. ldmtool "show partition" command displays "device" field if corresponding device mapper device have been created for the specified partition. Field is omitted otherwise. e.g. /dev/mapper/ldm_part_Red-nzv8x6obywgDg0_Disk6-01 --- src/ldm.c | 114 ++++++++++++++++++++++++++++--------------------- src/ldm.h | 14 ++++++ src/ldmtool.c | 13 ++++++ test/ldmread.c | 30 +++++++------ 4 files changed, 111 insertions(+), 60 deletions(-) diff --git a/src/ldm.c b/src/ldm.c index 75f6d5b..20ec1b0 100644 --- a/src/ldm.c +++ b/src/ldm.c @@ -2569,6 +2569,60 @@ _dm_find_tree_node_by_uuid(const gchar * const uuid, return r; } +gchar * +_dm_get_device(const gchar * const uuid, GError ** const err) +{ + GString *r = NULL; + + struct dm_tree_node *node = NULL; + struct dm_tree *tree = NULL; + struct dm_task *task = NULL; + + if (_dm_find_tree_node_by_uuid(uuid, &node, &tree, err)) { + const struct dm_info *info = dm_tree_node_get_info(node); + + task = dm_task_create(DM_DEVICE_INFO); + if (!task) { + g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL, + "dm_task_create: %s", _dm_err_last_msg); + goto error; + } + + if (!dm_task_set_major(task, info->major)) { + g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL, + "DM_DEVICE_INFO: dm_task_set_major(%d) failed: %s", + info->major, _dm_err_last_msg); + goto error; + } + + if (!dm_task_set_minor(task, info->minor)) { + g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL, + "DM_DEVICE_INFO: dm_task_set_major(%d) failed: %s", + info->minor, _dm_err_last_msg); + goto error; + } + + if (!dm_task_run(task)) { + g_set_error_literal(err, LDM_ERROR, LDM_ERROR_EXTERNAL, + _dm_err_last_msg); + goto error; + } + + const char *dir = dm_dir(); + char *mangled_name = dm_task_get_name_mangled(task); + r = g_string_new(""); + g_string_printf(r, "%s/%s", dir, mangled_name); + dm_free(mangled_name); + } + +error: + if (tree) dm_tree_free(tree); + if (task) dm_task_destroy(task); + + /* Really FALSE here - don't free but return the character data. */ + return r ? g_string_free(r, FALSE) : NULL; +} + gboolean _dm_create(const gchar * const name, const gchar * const uuid, uint32_t udev_cookie, const guint n_targets, @@ -3044,59 +3098,23 @@ ldm_volume_dm_get_name(const LDMVolume * const o) } gchar * -ldm_volume_dm_get_device(const LDMVolume * const o, GError ** const err) +ldm_partition_dm_get_device(const LDMPartition * const o, GError ** const err) { - GString *r = NULL; - - GString *uuid = _dm_vol_uuid(o->priv); - struct dm_tree_node *node = NULL; - struct dm_tree *tree = NULL; - struct dm_task *task = NULL; - - if (_dm_find_tree_node_by_uuid(uuid->str, &node, &tree, err)) { - const struct dm_info *info = dm_tree_node_get_info(node); - - task = dm_task_create(DM_DEVICE_INFO); - if (!task) { - g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL, - "dm_task_create: %s", _dm_err_last_msg); - goto error; - } - - if (!dm_task_set_major(task, info->major)) { - g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL, - "DM_DEVICE_INFO: dm_task_set_major(%d) failed: %s", - info->major, _dm_err_last_msg); - goto error; - } - - if (!dm_task_set_minor(task, info->minor)) { - g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL, - "DM_DEVICE_INFO: dm_task_set_major(%d) failed: %s", - info->minor, _dm_err_last_msg); - goto error; - } - - if (!dm_task_run(task)) { - g_set_error_literal(err, LDM_ERROR, LDM_ERROR_EXTERNAL, - _dm_err_last_msg); - goto error; - } + GString *uuid = _dm_part_uuid(o->priv); + gchar* r = _dm_get_device(uuid->str, err); + g_string_free(uuid, TRUE); - const char *dir = dm_dir(); - char *mangled_name = dm_task_get_name_mangled(task); - r = g_string_new(""); - g_string_printf(r, "%s/%s", dir, mangled_name); - dm_free(mangled_name); - } + return r; +} -error: - if (tree) dm_tree_free(tree); - if (task) dm_task_destroy(task); +gchar * +ldm_volume_dm_get_device(const LDMVolume * const o, GError ** const err) +{ + GString *uuid = _dm_vol_uuid(o->priv); + gchar* r = _dm_get_device(uuid->str, err); g_string_free(uuid, TRUE); - /* Really FALSE here - don't free but return the character data. */ - return r ? g_string_free(r, FALSE) : NULL; + return r; } gboolean diff --git a/src/ldm.h b/src/ldm.h index de1552a..fd615b4 100644 --- a/src/ldm.h +++ b/src/ldm.h @@ -538,6 +538,20 @@ guint64 ldm_partition_get_start(const LDMPartition *o); */ guint64 ldm_partition_get_size(const LDMPartition *o); +/** + * ldm_partition_dm_get_device: + * @o: An #LDMPartition + * @err: A #GError to receive any generated errors + * + * Get the host device mapper device which was created for this partition + * (e.g. /dev/mapper/ldm_part_Red-nzv8x6obywgDg0_Disk1-01). It is dynamic + * runtime property and it will be NULL if device mapper device is absent. + * + * Returns: (transfer full): The host device mapper device if present, + * or NULL otherwise + */ +gchar *ldm_partition_dm_get_device(const LDMPartition * const o, GError **err); + /** * ldm_disk_get_name * @o: An #LDMDisk diff --git a/src/ldmtool.c b/src/ldmtool.c index bc58601..6957c1a 100644 --- a/src/ldmtool.c +++ b/src/ldmtool.c @@ -376,6 +376,14 @@ show_partition(LDM *const ldm, const gint argc, gchar ** const argv, gchar *diskname = ldm_disk_get_name(disk); g_object_unref(disk); + GError *err = NULL; + gchar *device = ldm_partition_dm_get_device(part, &err); + if (err) { + g_warning("Unable to get device for partition %s on disk %s: %s", + name, diskname, err->message); + g_error_free(err); + } + json_builder_begin_object(jb); json_builder_set_member_name(jb, "name"); @@ -386,10 +394,15 @@ show_partition(LDM *const ldm, const gint argc, gchar ** const argv, json_builder_add_int_value(jb, size); json_builder_set_member_name(jb, "disk"); json_builder_add_string_value(jb, diskname); + if (device != NULL) { + json_builder_set_member_name(jb, "device"); + json_builder_add_string_value(jb, device); + } json_builder_end_object(jb); g_free(diskname); + g_free(device); } g_free(name); diff --git a/test/ldmread.c b/test/ldmread.c index fd40670..a01ac67 100644 --- a/test/ldmread.c +++ b/test/ldmread.c @@ -61,7 +61,7 @@ int main(int argc, const char *argv[]) g_object_get(dg, "guid", &guid, "name", &name, NULL); printf("Disk Group: %s\n", name); - printf(" GUID: %s\n", guid); + printf(" GUID: %s\n", guid); g_free(guid); g_free(name); @@ -93,13 +93,13 @@ int main(int argc, const char *argv[]) gchar *device = ldm_volume_dm_get_device(vol, &err); printf(" Volume: %s\n", name); - printf(" GUID: %s\n", guid); + printf(" GUID: %s\n", guid); printf(" Type: %s\n", type_v->value_nick); printf(" Size: %lu\n", size); printf(" Part Type: %hhu\n", part_type); printf(" Hint: %s\n", hint); printf(" Chunk Size: %lu\n", chunk_size); - printf(" Device: %s\n", device); + printf(" Device: %s\n", device); g_free(name); g_free(guid); @@ -121,11 +121,17 @@ int main(int argc, const char *argv[]) g_object_get(part, "name", &name, "start", &start, "size", &size, NULL); + GError *err = NULL; + gchar *device = ldm_partition_dm_get_device(part, &err); + printf(" Partition: %s\n", name); - printf(" Start: %lu\n", start); - printf(" Size: %lu\n", size); + printf(" Start: %lu\n", start); + printf(" Size: %lu\n", size); + printf(" Device: %s\n", device); g_free(name); + g_free(device); + if (err) g_error_free(err); } LDMDisk * const disk = ldm_partition_get_disk(part); @@ -147,13 +153,13 @@ int main(int argc, const char *argv[]) "metadata-size", &metadata_size, NULL); - printf(" Disk: %s\n", name); - printf(" GUID: %s\n", guid); - printf(" Device: %s\n", device); - printf(" Data Start: %lu\n", data_start); - printf(" Data Size: %lu\n", data_size); - printf(" Metadata Start: %lu\n", metadata_start); - printf(" Metadata Size: %lu\n", metadata_size); + printf(" Disk: %s\n", name); + printf(" GUID: %s\n", guid); + printf(" Device: %s\n", device); + printf(" Data Start: %lu\n", data_start); + printf(" Data Size: %lu\n", data_size); + printf(" Metadata Start: %lu\n", metadata_start); + printf(" Metadata Size: %lu\n", metadata_size); g_free(name); g_free(guid); -- 2.17.0
Apparently Analagous Threads
- [PATCH libldm v2 0/1] Fix crash while creating mapper for a volume which lacks of partitions.
- [libldm 1/3] relax uuid, zlib version requirements
- [PATCH 0/1] libldm: Make libldm to parse and return volume GUID.
- [PATCH libldm v3 0/2] Make libldm to parse and return volume GUID.
- [PATCH libldm v2 0/1] Make libldm to parse and return volume GUID.