File 003-Add-ability-to-override-device-mapper-UUID.patch of Package ldmtool
From 8023f57e851d6ef42368fa8f5e1f95f40adec57a Mon Sep 17 00:00:00 2001
From: Takeshi Suzuki <takeshi.suzuki@rubrik.com>
Date: Thu, 30 May 2024 01:25:39 +0000
Subject: [PATCH 3/5] Add ability to override device mapper UUID
---
docs/reference/ldmtool/ldmtool.xml | 13 ++++-
src/Makefile.am | 2 +-
src/ldm.c | 17 +++++-
src/ldm.h | 16 +++++-
src/ldmtool.c | 91 +++++++++++++++++++++---------
test/Makefile.am | 2 +-
6 files changed, 108 insertions(+), 33 deletions(-)
diff --git a/docs/reference/ldmtool/ldmtool.xml b/docs/reference/ldmtool/ldmtool.xml
index 3d1631b..89049c9 100644
--- a/docs/reference/ldmtool/ldmtool.xml
+++ b/docs/reference/ldmtool/ldmtool.xml
@@ -94,6 +94,17 @@
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>
+ <option>--uuid_override</option> <replaceable>uuid</replaceable>
+ </term>
+ <listitem>
+ <para>
+ User specified UUID for use with device mapper. This can only be
+ used in single action mode for a single volume.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
@@ -151,7 +162,7 @@
<refsect2>
<title>Single action mode</title>
-
+
<para>
When invoked to run a single action all block devices will be scanned by
default. In this case, if any block devices are specified with the
diff --git a/src/Makefile.am b/src/Makefile.am
index 06a5d44..2e21b15 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,7 +32,7 @@ bin_PROGRAMS = ldmtool
ldmtool_CFLAGS = $(AM_CFLAGS) $(GOBJECT_CFLAGS) $(JSON_CFLAGS) \
$(GIO_UNIX_CFLAGS)
ldmtool_LDADD = -lreadline $(builddir)/$(libname) $(GOBJECT_LIBS) \
- $(JSON_LIBS) $(GIO_UNIX_LIBS)
+ $(JSON_LIBS) $(GIO_UNIX_LIBS) $(UUID_LIBS)
# GObject introspection fails. This seems to be because g-ir-scanner incorrectly
# guesses the symbol prefix as 'l_dm', although explicitly passing in the
diff --git a/src/ldm.c b/src/ldm.c
index 4766bb0..47f393f 100644
--- a/src/ldm.c
+++ b/src/ldm.c
@@ -524,6 +524,9 @@ struct _LDMVolumePrivate
_int_volume_type _int_type;
guint32 _n_comps;
guint32 _n_comps_i;
+
+ /* User specified UUID for device mapper */
+ uuid_t uuid_override;
};
G_DEFINE_TYPE_WITH_PRIVATE(LDMVolume, ldm_volume, G_TYPE_OBJECT)
@@ -2441,7 +2444,11 @@ static GString *
_dm_vol_uuid(const LDMVolumePrivate * const vol)
{
char ldm_vol_uuid[37];
- uuid_unparse_lower(vol->guid, ldm_vol_uuid);
+ if (!uuid_is_null(vol->uuid_override)) {
+ uuid_unparse_lower(vol->uuid_override, ldm_vol_uuid);
+ } else {
+ uuid_unparse_lower(vol->guid, ldm_vol_uuid);
+ }
GString * dm_uuid = g_string_new("");
g_string_printf(dm_uuid, "%s%s-%s",
@@ -3154,7 +3161,7 @@ ldm_volume_dm_create(const LDMVolume * const o, GString **created,
}
gboolean r = name != NULL;
-
+
if (created)
*created = name;
else if (name)
@@ -3218,3 +3225,9 @@ out:
return r;
}
+
+void ldm_volume_override_uuid(LDMVolume * const o,
+ const uuid_t uuid_override) {
+ LDMVolumePrivate * const vol = o->priv;
+ uuid_copy(vol->uuid_override, uuid_override);
+}
diff --git a/src/ldm.h b/src/ldm.h
index fd615b4..87fff7b 100644
--- a/src/ldm.h
+++ b/src/ldm.h
@@ -18,6 +18,8 @@
#ifndef LIBLDM_LDM_H__
#define LIBLDM_LDM_H__
+#include <uuid/uuid.h>
+
#include <glib-object.h>
G_BEGIN_DECLS
@@ -259,7 +261,7 @@ LDM *ldm_new();
/**
* ldm_add:
* @o: An #LDM object
- * @path: The path of the device
+ * @path: The path of the device
* @err: A #GError to receive any generated errors
*
* Scan device @path and add its metadata to LDM object @o.
@@ -303,7 +305,7 @@ GArray *ldm_get_disk_groups(LDM *o);
*
* Returns: (element-type LDMVolume)(transfer container):
* An array of volumes
- */
+ */
GArray *ldm_disk_group_get_volumes(LDMDiskGroup *o);
/**
@@ -497,6 +499,16 @@ gboolean ldm_volume_dm_create(const LDMVolume *o, GString **created,
gboolean ldm_volume_dm_remove(const LDMVolume *o, GString **removed,
GError **err);
+/**
+ * ldm_volume_override_uuid:
+ * @o: An #LDMVolume
+ * @uuid_override: User specified UUID for device mapper
+ *
+ * Set the UUID used for device mapper. If no override is set, the volume's
+ * GUID will be used.
+ */
+void ldm_volume_override_uuid(LDMVolume * const o, const uuid_t uuid_override);
+
/**
* ldm_partition_get_disk:
* @o: An #LDMPartition
diff --git a/src/ldmtool.c b/src/ldmtool.c
index dbe2c8c..7ccd072 100644
--- a/src/ldmtool.c
+++ b/src/ldmtool.c
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <uuid/uuid.h>
#include <wordexp.h>
#include <glib-object.h>
@@ -74,13 +75,22 @@ gboolean usage_remove(void)
return FALSE;
}
-typedef gboolean (*_action_t) (LDM *ldm, gint argc, gchar **argv,
- JsonBuilder *jb);
+typedef struct {
+ /* User specified UUID for device mapper */
+ uuid_t uuid_override;
+} _options_t;
-gboolean ldm_scan(LDM *ldm, gint argc, gchar **argv, JsonBuilder *jb);
-gboolean ldm_show(LDM *ldm, gint argc, gchar **argv, JsonBuilder *jb);
-gboolean ldm_create(LDM *ldm, gint argc, gchar **argv, JsonBuilder *jb);
-gboolean ldm_remove(LDM *ldm, gint argc, gchar **argv, JsonBuilder *jb);
+typedef gboolean (*_action_t) (LDM *ldm, const _options_t * const opts,
+ gint argc, gchar **argv, JsonBuilder *jb);
+
+gboolean ldm_scan(LDM *ldm, const _options_t * const opts, gint argc,
+ gchar **argv, JsonBuilder *jb);
+gboolean ldm_show(LDM *ldm, const _options_t * const opts, gint argc,
+ gchar **argv, JsonBuilder *jb);
+gboolean ldm_create(LDM *ldm, const _options_t * const opts, gint argc,
+ gchar **argv, JsonBuilder *jb);
+gboolean ldm_remove(LDM *ldm, const _options_t * const opts, gint argc,
+ gchar **argv, JsonBuilder *jb);
typedef struct {
const char * name;
@@ -96,14 +106,15 @@ static const _command_t commands[] = {
};
gboolean
-do_command(LDM * const ldm, const int argc, char *argv[], gboolean *result,
+do_command(LDM * const ldm, const _options_t * const opts,
+ const int argc, char *argv[], gboolean *result,
GOutputStream * const out,
JsonGenerator * const jg, JsonBuilder * const jb)
{
const _command_t *i = commands;
while (i->name) {
if (g_strcmp0(i->name, argv[0]) == 0) {
- if ((i->action)(ldm, argc - 1, argv + 1, jb)) {
+ if ((i->action)(ldm, opts, argc - 1, argv + 1, jb)) {
GError *err = NULL;
json_generator_set_root(jg, json_builder_get_root(jb));
if (!json_generator_to_stream(jg, out, NULL, &err)) {
@@ -174,8 +185,8 @@ _scan(LDM *const ldm, gboolean ignore_errors,
}
gboolean
-ldm_scan(LDM *const ldm, const gint argc, gchar ** const argv,
- JsonBuilder * const jb)
+ldm_scan(LDM *const ldm, const _options_t * const opts, const gint argc,
+ gchar ** const argv, JsonBuilder * const jb)
{
return _scan(ldm, FALSE, argc, argv, jb);
}
@@ -477,8 +488,8 @@ show_disk(LDM *const ldm, const gint argc, gchar ** const argv,
}
gboolean
-ldm_show(LDM *const ldm, const gint argc, gchar ** const argv,
- JsonBuilder * const jb)
+ldm_show(LDM *const ldm, const _options_t * const opts, const gint argc,
+ gchar ** const argv, JsonBuilder * const jb)
{
if (argc == 0) return usage_show();
@@ -499,8 +510,8 @@ typedef gboolean (*_usage_t)();
typedef gboolean (*_vol_action_t)(const LDMVolume *, GString **, GError **);
static gboolean
-_ldm_vol_action(LDM *const ldm, const gint argc, gchar ** const argv,
- JsonBuilder * const jb,
+_ldm_vol_action(LDM *const ldm, const _options_t * const opts, const gint argc,
+ gchar ** const argv, JsonBuilder * const jb,
const gchar * const action_desc,
_usage_t const usage, _vol_action_t const action)
{
@@ -509,6 +520,11 @@ _ldm_vol_action(LDM *const ldm, const gint argc, gchar ** const argv,
if (argc == 1) {
if (g_strcmp0(argv[0], "all") != 0) return (*usage)();
+ if (!uuid_is_null(opts->uuid_override)) {
+ g_warning("UUID override cannot be used for multiple volumes");
+ return FALSE;
+ }
+
GArray *dgs = ldm_get_disk_groups(ldm);
for (guint i = 0; i < dgs->len; i++) {
LDMDiskGroup * const dg = g_array_index(dgs, LDMDiskGroup *, i);
@@ -567,6 +583,10 @@ _ldm_vol_action(LDM *const ldm, const gint argc, gchar ** const argv,
return FALSE;
}
+ if (!uuid_is_null(opts->uuid_override)) {
+ ldm_volume_override_uuid(vol, opts->uuid_override);
+ }
+
GError *err = NULL;
GString *device = NULL;
if (!(*action)(vol, &device, &err)) {
@@ -592,25 +612,30 @@ _ldm_vol_action(LDM *const ldm, const gint argc, gchar ** const argv,
}
gboolean
-ldm_create(LDM *const ldm, const gint argc, gchar ** const argv,
- JsonBuilder * const jb)
+ldm_create(LDM *const ldm, const _options_t * const opts, const gint argc,
+ gchar ** const argv, JsonBuilder * const jb)
{
- return _ldm_vol_action(ldm, argc, argv, jb,
+ return _ldm_vol_action(ldm, opts, argc, argv, jb,
"create", usage_create, ldm_volume_dm_create);
}
gboolean
-ldm_remove(LDM *const ldm, const gint argc, gchar ** const argv,
- JsonBuilder * const jb)
+ldm_remove(LDM *const ldm, const _options_t * const opts, const gint argc,
+ gchar ** const argv, JsonBuilder * const jb)
{
- return _ldm_vol_action(ldm, argc, argv, jb,
+ return _ldm_vol_action(ldm, opts, argc, argv, jb,
"remove", usage_remove, ldm_volume_dm_remove);
}
gboolean
-shell(LDM * const ldm, gchar ** const devices,
+shell(LDM * const ldm, const _options_t * const opts, gchar ** const devices,
JsonGenerator * const jg, GOutputStream * const out)
{
+ if (!uuid_is_null(opts->uuid_override)) {
+ g_warning("UUID override cannot be used in shell mode");
+ return FALSE;
+ }
+
int history_len = 0;
rl_readline_name = "ldmtool";
@@ -659,7 +684,7 @@ shell(LDM * const ldm, gchar ** const devices,
free(line);
gboolean result = FALSE;
- if (!do_command(ldm, argc, argv, &result, out, jg, jb)) {
+ if (!do_command(ldm, opts, argc, argv, &result, out, jg, jb)) {
if (g_strcmp0("quit", argv[0]) == 0 ||
g_strcmp0("exit", argv[0]) == 0)
{
@@ -739,7 +764,7 @@ get_devices(void)
}
gboolean
-cmdline(LDM * const ldm, gchar **devices,
+cmdline(LDM * const ldm, const _options_t * const opts, gchar **devices,
JsonGenerator * const jg, GOutputStream * const out,
const int argc, char *argv[])
{
@@ -757,7 +782,7 @@ cmdline(LDM * const ldm, gchar **devices,
jb = json_builder_new();
gboolean result;
- if (!do_command(ldm, argc, argv, &result, out, jg, jb)) {
+ if (!do_command(ldm, opts, argc, argv, &result, out, jg, jb)) {
g_warning("Unrecognised command: %s", argv[0]);
goto error;
}
@@ -789,11 +814,14 @@ int
main(int argc, char *argv[])
{
static gchar **devices = NULL;
+ static gchar *uuid_override_str = NULL;
static const GOptionEntry entries[] =
{
{ "device", 'd', 0, G_OPTION_ARG_FILENAME_ARRAY,
&devices, "Block device to scan for LDM metadata", NULL },
+ { "uuid_override", 0, 0, G_OPTION_ARG_STRING,
+ &uuid_override_str, "UUID override for device mapper", NULL },
{ NULL }
};
@@ -813,6 +841,17 @@ main(int argc, char *argv[])
}
g_option_context_free(context);
+ _options_t opts;
+ uuid_clear(opts.uuid_override);
+ if (uuid_override_str) {
+ if (uuid_parse(uuid_override_str, opts.uuid_override)) {
+ g_warning("Failed to parse %s as a UUID", uuid_override_str);
+ return 1;
+ }
+ g_free(uuid_override_str);
+ uuid_override_str = NULL;
+ }
+
#if !GLIB_CHECK_VERSION(2,35,0)
g_type_init();
#endif
@@ -828,11 +867,11 @@ main(int argc, char *argv[])
json_generator_set_indent(jg, 2);
if (argc > 1) {
- if (!cmdline(ldm, devices, jg, out, argc - 1, argv + 1)) {
+ if (!cmdline(ldm, &opts, devices, jg, out, argc - 1, argv + 1)) {
ret = 1;
}
} else {
- if (!shell(ldm, devices, jg, out)) {
+ if (!shell(ldm, &opts, devices, jg, out)) {
ret = 1;
}
}
diff --git a/test/Makefile.am b/test/Makefile.am
index 423034f..ec80394 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -21,7 +21,7 @@ EXTRA_DIST = checkmount.pl data/ldm-data.tar.xz
check_PROGRAMS = partread ldmread
partread_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/src
-partread_LDADD = $(top_builddir)/src/libldm-1.0.la
+partread_LDADD = $(top_builddir)/src/libldm-1.0.la $(UUID_LIBS)
ldmread_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/src $(GOBJECT_CFLAGS)
ldmread_LDADD = $(top_builddir)/src/libldm-1.0.la $(GOBJECT_LIBS)
--
2.48.1