[Libguestfs] [PATCH libldm 11/12] New API: ldm_volume_dm_get_device

Mykola Ivanets stenavin at gmail.com
Tue May 15 20:38:18 UTC 2018


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




More information about the Libguestfs mailing list