579 lines
19 KiB
Diff
579 lines
19 KiB
Diff
|
From 64c243930b4f7073962cd7464c7c7d2cba08a041 Mon Sep 17 00:00:00 2001
|
||
|
From: David Teigland <teigland@redhat.com>
|
||
|
Date: Tue, 23 Apr 2024 17:08:26 -0500
|
||
|
Subject: [PATCH 3/9] Allow system.devices to be automatically created on first
|
||
|
boot
|
||
|
|
||
|
An OS installer can create system.devices for the system and
|
||
|
disks, but an OS image cannot create the system-specific
|
||
|
system.devices. The OS image can instead configure the
|
||
|
image so that lvm will create system.devices on first boot.
|
||
|
|
||
|
Image preparation steps to enable auto creation of system.devices:
|
||
|
- create empty file /etc/lvm/devices/auto-import-rootvg
|
||
|
- remove any existing /etc/lvm/devices/system.devices
|
||
|
- enable lvm-devices-import.path
|
||
|
- enable lvm-devices-import.service
|
||
|
|
||
|
On first boot of the prepared image:
|
||
|
- udev triggers vgchange -aay --autoactivation event <rootvg>
|
||
|
- vgchange activates LVs in the root VG
|
||
|
- vgchange finds the file /etc/lvm/devices/auto-import-rootvg,
|
||
|
and no /etc/lvm/devices/system.devices, so it creates
|
||
|
/run/lvm/lvm-devices-import
|
||
|
- lvm-devices-import.path is run when /run/lvm/lvm-devices-import
|
||
|
appears, and triggers lvm-devices-import.service
|
||
|
- lvm-devices-import.service runs vgimportdevices --rootvg --auto
|
||
|
- vgimportdevices finds /etc/lvm/devices/auto-import-rootvg,
|
||
|
and no system.devices, so it creates system.devices containing
|
||
|
PVs in the root VG, and removes /etc/lvm/devices/auto-import-rootvg
|
||
|
and /run/lvm/lvm-devices-import
|
||
|
|
||
|
Run directly, vgimportdevices --rootvg (without --auto), will create
|
||
|
a new system.devices for the root VG, or will add devices for the
|
||
|
root VG to an existing system.devices.
|
||
|
|
||
|
(cherry picked from commit c609dedc2f035f770b5f645c4695924abf15c2ca)
|
||
|
(cherry picked from commit 3321a669d8f2df99df9d6dcd4ebb2b4d30731c7a)
|
||
|
---
|
||
|
lib/commands/toolcontext.h | 1 +
|
||
|
lib/config/defaults.h | 2 +
|
||
|
lib/device/device_id.c | 5 +-
|
||
|
scripts/lvm-devices-import.path | 12 +++
|
||
|
scripts/lvm-devices-import.service | 12 +++
|
||
|
tools/args.h | 11 ++
|
||
|
tools/command-lines.in | 5 +
|
||
|
tools/pvscan.c | 4 +-
|
||
|
tools/tools.h | 2 +-
|
||
|
tools/vgchange.c | 155 ++++++++++++++++++++++++++++-
|
||
|
tools/vgimportdevices.c | 114 ++++++++++++++++++++-
|
||
|
11 files changed, 315 insertions(+), 8 deletions(-)
|
||
|
create mode 100644 scripts/lvm-devices-import.path
|
||
|
create mode 100644 scripts/lvm-devices-import.service
|
||
|
|
||
|
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
|
||
|
index fec0a52cf..043afbf76 100644
|
||
|
--- a/lib/commands/toolcontext.h
|
||
|
+++ b/lib/commands/toolcontext.h
|
||
|
@@ -217,6 +217,7 @@ struct cmd_context {
|
||
|
unsigned device_ids_check_hostname:1;
|
||
|
unsigned device_ids_refresh_trigger:1;
|
||
|
unsigned device_ids_invalid:1;
|
||
|
+ unsigned device_ids_auto_import:1;
|
||
|
unsigned get_vgname_from_options:1; /* used by lvconvert */
|
||
|
|
||
|
/*
|
||
|
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
|
||
|
index ed0c4f404..efe36d1fa 100644
|
||
|
--- a/lib/config/defaults.h
|
||
|
+++ b/lib/config/defaults.h
|
||
|
@@ -337,6 +337,8 @@
|
||
|
#define VGS_ONLINE_DIR DEFAULT_RUN_DIR "/vgs_online"
|
||
|
#define PVS_LOOKUP_DIR DEFAULT_RUN_DIR "/pvs_lookup"
|
||
|
|
||
|
+#define DEVICES_IMPORT_PATH DEFAULT_RUN_DIR "/lvm-devices-import"
|
||
|
+
|
||
|
#define DEFAULT_DEVICE_ID_SYSFS_DIR "/sys/" /* trailing / to match dm_sysfs_dir() */
|
||
|
|
||
|
#define DEFAULT_DEVICESFILE_BACKUP_LIMIT 50
|
||
|
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
|
||
|
index 2b183810a..1ce7927ed 100644
|
||
|
--- a/lib/device/device_id.c
|
||
|
+++ b/lib/device/device_id.c
|
||
|
@@ -1726,9 +1726,10 @@ int device_ids_write(struct cmd_context *cmd)
|
||
|
|
||
|
if ((fc_bytes = snprintf(fc, sizeof(fc),
|
||
|
"# LVM uses devices listed in this file.\n" \
|
||
|
- "# Created by LVM command %s pid %d at %s" \
|
||
|
+ "# Created by LVM command %s%s pid %d at %s" \
|
||
|
"# HASH=%u\n",
|
||
|
- cmd->name, getpid(), ctime(&t), hash)) < 0) {
|
||
|
+ cmd->name, cmd->device_ids_auto_import ? " (auto)" : "",
|
||
|
+ getpid(), ctime(&t), hash)) < 0) {
|
||
|
log_error("Failed to write buffer for devices file content.");
|
||
|
goto out;
|
||
|
}
|
||
|
diff --git a/scripts/lvm-devices-import.path b/scripts/lvm-devices-import.path
|
||
|
new file mode 100644
|
||
|
index 000000000..bcf0dcd4c
|
||
|
--- /dev/null
|
||
|
+++ b/scripts/lvm-devices-import.path
|
||
|
@@ -0,0 +1,12 @@
|
||
|
+[Unit]
|
||
|
+Description=lvm-devices-import to create system.devices
|
||
|
+
|
||
|
+# /run/lvm/lvm-devices-import created by vgchange -aay <rootvg>
|
||
|
+
|
||
|
+[Path]
|
||
|
+PathExists=/run/lvm/lvm-devices-import
|
||
|
+Unit=lvm-devices-import.service
|
||
|
+ConditionPathExists=!/etc/lvm/devices/system.devices
|
||
|
+
|
||
|
+[Install]
|
||
|
+WantedBy=multi-user.target
|
||
|
diff --git a/scripts/lvm-devices-import.service b/scripts/lvm-devices-import.service
|
||
|
new file mode 100644
|
||
|
index 000000000..9d3bda2ee
|
||
|
--- /dev/null
|
||
|
+++ b/scripts/lvm-devices-import.service
|
||
|
@@ -0,0 +1,12 @@
|
||
|
+[Unit]
|
||
|
+Description=Create lvm system.devices
|
||
|
+
|
||
|
+[Service]
|
||
|
+Type=oneshot
|
||
|
+RemainAfterExit=no
|
||
|
+ExecStart=/usr/sbin/vgimportdevices --rootvg --auto
|
||
|
+ConditionPathExists=!/etc/lvm/devices/system.devices
|
||
|
+
|
||
|
+[Install]
|
||
|
+WantedBy=multi-user.target
|
||
|
+
|
||
|
diff --git a/tools/args.h b/tools/args.h
|
||
|
index 09b2ad551..ed0fb9620 100644
|
||
|
--- a/tools/args.h
|
||
|
+++ b/tools/args.h
|
||
|
@@ -94,6 +94,14 @@ arg(atversion_ARG, '\0', "atversion", string_VAL, 0, 0,
|
||
|
"which does not contain any newer settings for which LVM would\n"
|
||
|
"issue a warning message when checking the configuration.\n")
|
||
|
|
||
|
+arg(auto_ARG, '\0', "auto", 0, 0, 0,
|
||
|
+ "This option is used when automatically importing devices for the root VG.\n"
|
||
|
+ "The auto import is intended to be done once, on first boot, to create an\n"
|
||
|
+ "initial system.devices file for the root VG.\n"
|
||
|
+ "When this option is used, the vgimportdevices --rootvg command does nothing\n"
|
||
|
+ "if system.devices exists, or the file auto-import-rootvg does not exist\n"
|
||
|
+ "(both in the /etc/lvm/devices/ directory.)\n")
|
||
|
+
|
||
|
arg(autoactivation_ARG, '\0', "autoactivation", string_VAL, 0, 0,
|
||
|
"Specify if autoactivation is being used from an event.\n"
|
||
|
"This allows the command to apply settings that are specific\n"
|
||
|
@@ -754,6 +762,9 @@ arg(resync_ARG, '\0', "resync", 0, 0, 0,
|
||
|
"which the LV is without a complete redundant copy of the data.\n"
|
||
|
"See \\fBlvmraid\\fP(7) for more information.\n")
|
||
|
|
||
|
+arg(rootvg_ARG, '\0', "rootvg", 0, 0, 0,
|
||
|
+ "Import devices used for the root VG.\n")
|
||
|
+
|
||
|
arg(rows_ARG, '\0', "rows", 0, 0, 0,
|
||
|
"Output columns as rows.\n")
|
||
|
|
||
|
diff --git a/tools/command-lines.in b/tools/command-lines.in
|
||
|
index 1c728afa0..3ad5d3c46 100644
|
||
|
--- a/tools/command-lines.in
|
||
|
+++ b/tools/command-lines.in
|
||
|
@@ -1911,6 +1911,11 @@ OO: --foreign, --reportformat ReportFmt
|
||
|
ID: vgimportdevices_all
|
||
|
DESC: Add devices from all accessible VGs to the devices file.
|
||
|
|
||
|
+vgimportdevices --rootvg
|
||
|
+OO: --auto, --reportformat ReportFmt
|
||
|
+ID: vgimportdevices_root
|
||
|
+DESC: Add devices from root VG to the devices file.
|
||
|
+
|
||
|
---
|
||
|
|
||
|
vgmerge VG VG
|
||
|
diff --git a/tools/pvscan.c b/tools/pvscan.c
|
||
|
index f88e1b751..0a9cb59df 100644
|
||
|
--- a/tools/pvscan.c
|
||
|
+++ b/tools/pvscan.c
|
||
|
@@ -495,7 +495,7 @@ static int _pvscan_aa_single(struct cmd_context *cmd, const char *vg_name,
|
||
|
|
||
|
log_debug("pvscan autoactivating VG %s.", vg_name);
|
||
|
|
||
|
- if (!vgchange_activate(cmd, vg, CHANGE_AAY, 1)) {
|
||
|
+ if (!vgchange_activate(cmd, vg, CHANGE_AAY, 1, NULL)) {
|
||
|
log_error_pvscan(cmd, "%s: autoactivation failed.", vg->name);
|
||
|
pp->activate_errors++;
|
||
|
}
|
||
|
@@ -755,7 +755,7 @@ static int _pvscan_aa_quick(struct cmd_context *cmd, struct pvscan_aa_params *pp
|
||
|
|
||
|
log_debug("pvscan autoactivating VG %s.", vgname);
|
||
|
|
||
|
- if (!vgchange_activate(cmd, vg, CHANGE_AAY, 1)) {
|
||
|
+ if (!vgchange_activate(cmd, vg, CHANGE_AAY, 1, NULL)) {
|
||
|
log_error_pvscan(cmd, "%s: autoactivation failed.", vg->name);
|
||
|
pp->activate_errors++;
|
||
|
}
|
||
|
diff --git a/tools/tools.h b/tools/tools.h
|
||
|
index f4a0c94d7..58708c695 100644
|
||
|
--- a/tools/tools.h
|
||
|
+++ b/tools/tools.h
|
||
|
@@ -164,7 +164,7 @@ int mirror_remove_missing(struct cmd_context *cmd,
|
||
|
|
||
|
|
||
|
int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
|
||
|
- activation_change_t activate, int vg_complete_to_activate);
|
||
|
+ activation_change_t activate, int vg_complete_to_activate, char *root_dm_uuid);
|
||
|
|
||
|
int vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg);
|
||
|
|
||
|
diff --git a/tools/vgchange.c b/tools/vgchange.c
|
||
|
index 378ded16e..2004d6e92 100644
|
||
|
--- a/tools/vgchange.c
|
||
|
+++ b/tools/vgchange.c
|
||
|
@@ -16,11 +16,14 @@
|
||
|
#include "tools.h"
|
||
|
#include "lib/device/device_id.h"
|
||
|
#include "lib/label/hints.h"
|
||
|
+#include "device_mapper/misc/dm-ioctl.h"
|
||
|
+#include <mntent.h>
|
||
|
|
||
|
struct vgchange_params {
|
||
|
int lock_start_count;
|
||
|
unsigned int lock_start_sanlock : 1;
|
||
|
unsigned int vg_complete_to_activate : 1;
|
||
|
+ char *root_dm_uuid; /* dm uuid of LV under root fs */
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
@@ -197,7 +200,7 @@ int vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg
|
||
|
}
|
||
|
|
||
|
int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
|
||
|
- activation_change_t activate, int vg_complete_to_activate)
|
||
|
+ activation_change_t activate, int vg_complete_to_activate, char *root_dm_uuid)
|
||
|
{
|
||
|
int lv_open, active, monitored = 0, r = 1;
|
||
|
const struct lv_list *lvl;
|
||
|
@@ -279,6 +282,43 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
|
||
|
r = 0;
|
||
|
}
|
||
|
|
||
|
+ /*
|
||
|
+ * Possibly trigger auto-generation of system.devices:
|
||
|
+ * - if root_dm_uuid contains vg->id, and
|
||
|
+ * - /etc/lvm/devices/auto-import-rootvg exists, and
|
||
|
+ * - /etc/lvm/devices/system.devices does not exist, then
|
||
|
+ * - create /run/lvm/lvm-devices-import to
|
||
|
+ * trigger lvm-devices-import.path and .service
|
||
|
+ * - lvm-devices-import will run vgimportdevices --rootvg
|
||
|
+ * to create system.devices
|
||
|
+ */
|
||
|
+ if (root_dm_uuid) {
|
||
|
+ char path[PATH_MAX];
|
||
|
+ struct stat info;
|
||
|
+ FILE *fp;
|
||
|
+
|
||
|
+ if (memcmp(root_dm_uuid + 4, &vg->id, ID_LEN))
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ if (cmd->enable_devices_file || devices_file_exists(cmd))
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ if (dm_snprintf(path, sizeof(path), "%s/devices/auto-import-rootvg", cmd->system_dir) < 0)
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ if (stat(path, &info) < 0)
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ log_debug("Found %s creating %s", path, DEVICES_IMPORT_PATH);
|
||
|
+
|
||
|
+ if (!(fp = fopen(DEVICES_IMPORT_PATH, "w"))) {
|
||
|
+ log_debug("failed to create %s", DEVICES_IMPORT_PATH);
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ if (fclose(fp))
|
||
|
+ stack;
|
||
|
+ }
|
||
|
+out:
|
||
|
/* Print message only if there was not found a missing VG */
|
||
|
log_print_unless_silent("%d logical volume(s) in volume group \"%s\" now active",
|
||
|
lvs_in_vg_activated(vg), vg->name);
|
||
|
@@ -714,7 +754,7 @@ static int _vgchange_single(struct cmd_context *cmd, const char *vg_name,
|
||
|
|
||
|
if (arg_is_set(cmd, activate_ARG)) {
|
||
|
activate = (activation_change_t) arg_uint_value(cmd, activate_ARG, 0);
|
||
|
- if (!vgchange_activate(cmd, vg, activate, vp->vg_complete_to_activate))
|
||
|
+ if (!vgchange_activate(cmd, vg, activate, vp->vg_complete_to_activate, vp->root_dm_uuid))
|
||
|
return_ECMD_FAILED;
|
||
|
} else if (arg_is_set(cmd, refresh_ARG)) {
|
||
|
/* refreshes the visible LVs (which starts polling) */
|
||
|
@@ -735,6 +775,115 @@ static int _vgchange_single(struct cmd_context *cmd, const char *vg_name,
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * Automatic creation of system.devices for root VG on first boot
|
||
|
+ * is useful for OS images where the OS installer is not used to
|
||
|
+ * customize the OS for system.
|
||
|
+ *
|
||
|
+ * - OS image prep:
|
||
|
+ * . rm /etc/lvm/devices/system.devices (if it exists)
|
||
|
+ * . touch /etc/lvm/devices/auto-import-rootvg
|
||
|
+ * . enable lvm-devices-import.path
|
||
|
+ * . enable lvm-devices-import.service
|
||
|
+ *
|
||
|
+ * - lvchange -ay <rootvg>/<rootlv>
|
||
|
+ * . run by initrd so root fs can be mounted
|
||
|
+ * . does not use system.devices
|
||
|
+ * . named <rootvg>/<rootlv> comes from kernel command line rd.lvm
|
||
|
+ * . uses first device that appears containing the named root LV
|
||
|
+ *
|
||
|
+ * - vgchange -aay <rootvg>
|
||
|
+ * . triggered by udev when all PVs from root VG are online
|
||
|
+ * . activate LVs in root VG (in addition to the already active root LV)
|
||
|
+ * . check for /etc/lvm/devices/auto-import-rootvg (found)
|
||
|
+ * . check for /etc/lvm/devices/system.devices (not found)
|
||
|
+ * . create /run/lvm/lvm-devices-import because
|
||
|
+ * auto-import-rootvg was found and system.devices was not found
|
||
|
+ *
|
||
|
+ * - lvm-devices-import.path
|
||
|
+ * . triggered by /run/lvm/lvm-devices-import
|
||
|
+ * . start lvm-devices-import.service
|
||
|
+ *
|
||
|
+ * - lvm-devices-import.service
|
||
|
+ * . check for /etc/lvm/devices/system.devices, do nothing if found
|
||
|
+ * . run vgimportdevices --rootvg --auto
|
||
|
+ *
|
||
|
+ * - vgimportdevices --rootvg --auto
|
||
|
+ * . check for /etc/lvm/devices/auto-import-rootvg (found)
|
||
|
+ * . check for /etc/lvm/devices/system.devices (not found)
|
||
|
+ * . creates /etc/lvm/devices/system.devices for PVs in root VG
|
||
|
+ * . removes /etc/lvm/devices/auto-import-rootvg
|
||
|
+ * . removes /run/lvm/lvm-devices-import
|
||
|
+ *
|
||
|
+ * On future startup, /etc/lvm/devices/system.devices will exist,
|
||
|
+ * and /etc/lvm/devices/auto-import-rootvg will not exist, so
|
||
|
+ * vgchange -aay <rootvg> will not create /run/lvm/lvm-devices-import,
|
||
|
+ * and lvm-devices-import.path and lvm-device-import.service will not run.
|
||
|
+ *
|
||
|
+ * lvm-devices-import.path:
|
||
|
+ * [Path]
|
||
|
+ * PathExists=/run/lvm/lvm-devices-import
|
||
|
+ * Unit=lvm-devices-import.service
|
||
|
+ * ConditionPathExists=!/etc/lvm/devices/system.devices
|
||
|
+ *
|
||
|
+ * lvm-devices-import.service:
|
||
|
+ * [Service]
|
||
|
+ * Type=oneshot
|
||
|
+ * RemainAfterExit=no
|
||
|
+ * ExecStart=/usr/sbin/vgimportdevices --rootvg --auto
|
||
|
+ * ConditionPathExists=!/etc/lvm/devices/system.devices
|
||
|
+ */
|
||
|
+
|
||
|
+static void _get_rootvg_dev(struct cmd_context *cmd, char **dm_uuid_out)
|
||
|
+{
|
||
|
+ char path[PATH_MAX];
|
||
|
+ char dm_uuid[DM_UUID_LEN];
|
||
|
+ struct stat info;
|
||
|
+ FILE *fme = NULL;
|
||
|
+ struct mntent *me;
|
||
|
+ int found = 0;
|
||
|
+
|
||
|
+ if (cmd->enable_devices_file || devices_file_exists(cmd))
|
||
|
+ return;
|
||
|
+
|
||
|
+ if (dm_snprintf(path, sizeof(path), "%s/devices/auto-import-rootvg", cmd->system_dir) < 0)
|
||
|
+ return;
|
||
|
+
|
||
|
+ if (stat(path, &info) < 0)
|
||
|
+ return;
|
||
|
+
|
||
|
+ if (!(fme = setmntent("/etc/mtab", "r")))
|
||
|
+ return;
|
||
|
+
|
||
|
+ while ((me = getmntent(fme))) {
|
||
|
+ if ((me->mnt_dir[0] == '/') && (me->mnt_dir[1] == '\0')) {
|
||
|
+ found = 1;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ endmntent(fme);
|
||
|
+
|
||
|
+ if (!found)
|
||
|
+ return;
|
||
|
+
|
||
|
+ if (stat(me->mnt_dir, &info) < 0)
|
||
|
+ return;
|
||
|
+
|
||
|
+ if (!get_dm_uuid_from_sysfs(dm_uuid, sizeof(dm_uuid), (int)MAJOR(info.st_dev), (int)MINOR(info.st_dev)))
|
||
|
+ return;
|
||
|
+
|
||
|
+ log_debug("Found root dm_uuid %s", dm_uuid);
|
||
|
+
|
||
|
+ /* UUID_PREFIX = "LVM-" */
|
||
|
+ if (strncmp(dm_uuid, UUID_PREFIX, 4))
|
||
|
+ return;
|
||
|
+
|
||
|
+ if (strlen(dm_uuid) < 4 + ID_LEN)
|
||
|
+ return;
|
||
|
+
|
||
|
+ *dm_uuid_out = dm_pool_strdup(cmd->mem, dm_uuid);
|
||
|
+}
|
||
|
+
|
||
|
static int _vgchange_autoactivation_setup(struct cmd_context *cmd,
|
||
|
struct vgchange_params *vp,
|
||
|
int *skip_command,
|
||
|
@@ -778,6 +927,8 @@ static int _vgchange_autoactivation_setup(struct cmd_context *cmd,
|
||
|
|
||
|
get_single_vgname_cmd_arg(cmd, NULL, &vgname);
|
||
|
|
||
|
+ _get_rootvg_dev(cmd, &vp->root_dm_uuid);
|
||
|
+
|
||
|
/*
|
||
|
* Lock the VG before scanning the PVs so _vg_read can avoid the normal
|
||
|
* lock_vol+rescan (READ_WITHOUT_LOCK avoids the normal lock_vol and
|
||
|
diff --git a/tools/vgimportdevices.c b/tools/vgimportdevices.c
|
||
|
index bccd94f61..70d12e500 100644
|
||
|
--- a/tools/vgimportdevices.c
|
||
|
+++ b/tools/vgimportdevices.c
|
||
|
@@ -15,11 +15,16 @@
|
||
|
#include "tools.h"
|
||
|
#include "lib/cache/lvmcache.h"
|
||
|
#include "lib/device/device_id.h"
|
||
|
+#include "device_mapper/misc/dm-ioctl.h"
|
||
|
/* coverity[unnecessary_header] needed for MuslC */
|
||
|
#include <sys/file.h>
|
||
|
+#include <mntent.h>
|
||
|
|
||
|
struct vgimportdevices_params {
|
||
|
uint32_t added_devices;
|
||
|
+ int root_vg_found;
|
||
|
+ char *root_dm_uuid;
|
||
|
+ char *root_vg_name;
|
||
|
};
|
||
|
|
||
|
static int _vgimportdevices_single(struct cmd_context *cmd,
|
||
|
@@ -35,6 +40,13 @@ static int _vgimportdevices_single(struct cmd_context *cmd,
|
||
|
int updated_pvs = 0;
|
||
|
const char *idtypestr = NULL; /* deviceidtype_ARG ? */
|
||
|
|
||
|
+ if (vp->root_dm_uuid) {
|
||
|
+ if (memcmp(vp->root_dm_uuid + 4, &vg->id, ID_LEN))
|
||
|
+ return ECMD_PROCESSED;
|
||
|
+ vp->root_vg_found = 1;
|
||
|
+ vp->root_vg_name = dm_pool_strdup(cmd->mem, vg_name);
|
||
|
+ }
|
||
|
+
|
||
|
dm_list_iterate_items(pvl, &vg->pvs) {
|
||
|
if (is_missing_pv(pvl->pv) || !pvl->pv->dev) {
|
||
|
memcpy(pvid, &pvl->pv->id.uuid, ID_LEN);
|
||
|
@@ -86,6 +98,87 @@ static int _vgimportdevices_single(struct cmd_context *cmd,
|
||
|
return ECMD_PROCESSED;
|
||
|
}
|
||
|
|
||
|
+static int _get_rootvg_dev(struct cmd_context *cmd, char **dm_uuid_out, int *skip)
|
||
|
+{
|
||
|
+ char path[PATH_MAX];
|
||
|
+ char dm_uuid[DM_UUID_LEN];
|
||
|
+ struct stat info;
|
||
|
+ FILE *fme = NULL;
|
||
|
+ struct mntent *me;
|
||
|
+ int found = 0;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * When --auto is set, the command does nothing
|
||
|
+ * if /etc/lvm/devices/system.devices exists, or
|
||
|
+ * if /etc/lvm/devices/auto-import-rootvg does not exist.
|
||
|
+ */
|
||
|
+ if (arg_is_set(cmd, auto_ARG)) {
|
||
|
+ if (devices_file_exists(cmd)) {
|
||
|
+ *skip = 1;
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (dm_snprintf(path, sizeof(path), "%s/devices/auto-import-rootvg", cmd->system_dir) < 0)
|
||
|
+ return_0;
|
||
|
+
|
||
|
+ if (stat(path, &info) < 0) {
|
||
|
+ *skip = 1;
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * This flag is just used in device_ids_write to enable
|
||
|
+ * an extra comment in system.devices indicating that
|
||
|
+ * the file was auto generated for the root vg.
|
||
|
+ */
|
||
|
+ cmd->device_ids_auto_import = 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!(fme = setmntent("/etc/mtab", "r")))
|
||
|
+ return_0;
|
||
|
+
|
||
|
+ while ((me = getmntent(fme))) {
|
||
|
+ if ((me->mnt_dir[0] == '/') && (me->mnt_dir[1] == '\0')) {
|
||
|
+ found = 1;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ endmntent(fme);
|
||
|
+
|
||
|
+ if (!found)
|
||
|
+ return_0;
|
||
|
+
|
||
|
+ if (stat(me->mnt_dir, &info) < 0)
|
||
|
+ return_0;
|
||
|
+
|
||
|
+ if (!get_dm_uuid_from_sysfs(dm_uuid, sizeof(dm_uuid), (int)MAJOR(info.st_dev), (int)MINOR(info.st_dev)))
|
||
|
+ return_0;
|
||
|
+
|
||
|
+ /* UUID_PREFIX = "LVM-" */
|
||
|
+ if (strncmp(dm_uuid, UUID_PREFIX, 4))
|
||
|
+ return_0;
|
||
|
+
|
||
|
+ if (strlen(dm_uuid) < 4 + ID_LEN)
|
||
|
+ return_0;
|
||
|
+
|
||
|
+ *dm_uuid_out = dm_pool_strdup(cmd->mem, dm_uuid);
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
+static void _clear_rootvg_auto(struct cmd_context *cmd)
|
||
|
+{
|
||
|
+ char path[PATH_MAX];
|
||
|
+
|
||
|
+ if (dm_snprintf(path, sizeof(path), "%s/devices/auto-import-rootvg", cmd->system_dir) < 0)
|
||
|
+ return;
|
||
|
+
|
||
|
+ if (unlink(path) < 0)
|
||
|
+ log_debug("Failed to unlink %s", path);
|
||
|
+
|
||
|
+ if (unlink(DEVICES_IMPORT_PATH) < 0)
|
||
|
+ log_debug("Failed to unlink %s", DEVICES_IMPORT_PATH);
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* This command always scans all devices on the system,
|
||
|
* any pre-existing devices_file does not limit the scope.
|
||
|
@@ -130,6 +223,19 @@ int vgimportdevices(struct cmd_context *cmd, int argc, char **argv)
|
||
|
/* So that we can warn about this. */
|
||
|
cmd->handles_missing_pvs = 1;
|
||
|
|
||
|
+ /* Import devices for the root VG. */
|
||
|
+ if (arg_is_set(cmd, rootvg_ARG)) {
|
||
|
+ int skip = 0;
|
||
|
+ if (!_get_rootvg_dev(cmd, &vp.root_dm_uuid, &skip)) {
|
||
|
+ log_error("Failed to find root VG.");
|
||
|
+ return ECMD_FAILED;
|
||
|
+ }
|
||
|
+ if (skip) {
|
||
|
+ log_print("Root VG auto import is not enabled.");
|
||
|
+ return ECMD_PROCESSED;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
if (!lock_global(cmd, "ex"))
|
||
|
return ECMD_FAILED;
|
||
|
|
||
|
@@ -230,7 +336,13 @@ int vgimportdevices(struct cmd_context *cmd, int argc, char **argv)
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
- log_print("Added %u devices to devices file.", vp.added_devices);
|
||
|
+ if (vp.root_vg_found)
|
||
|
+ log_print("Added %u devices to devices file for root VG %s.", vp.added_devices, vp.root_vg_name);
|
||
|
+ else
|
||
|
+ log_print("Added %u devices to devices file.", vp.added_devices);
|
||
|
+
|
||
|
+ if (vp.root_vg_found && arg_is_set(cmd, auto_ARG))
|
||
|
+ _clear_rootvg_auto(cmd);
|
||
|
out:
|
||
|
if ((ret == ECMD_FAILED) && created_file)
|
||
|
if (unlink(cmd->devices_file_path) < 0)
|
||
|
--
|
||
|
2.46.0
|
||
|
|