summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2021-09-02 16:55:04 -0500
committerDavid Teigland <teigland@redhat.com>2021-10-11 14:22:23 -0500
commitff0eb5823a88e247e6b9aa6376a863b31a4b044c (patch)
treec87aed5baf99a2cbc4d25a460bfb1462bf05eb1b
parent240db28214a3ebb8e22b7d42904775333e6b96c1 (diff)
downloadlvm2-ff0eb5823a88e247e6b9aa6376a863b31a4b044c.tar.gz
add fixed event activation services
System startup runs two new fixed activation services: lvm-activate-vgs-main and lvm-activate-vgs-last These activate VGs that are present and complete at the time of system startup. The last service enables event activation by creating the file /run/lvm/event-activation-on. After that, new devices that appear will be processed by event based activation. lvm.conf event_activation_options can be used to configure service-based activation only, or event-based activation only, or the default hybrid approach.
-rw-r--r--configure.ac44
-rw-r--r--lib/config/config_settings.h12
-rw-r--r--lib/config/defaults.h3
-rw-r--r--lib/label/label.c3
-rw-r--r--scripts/Makefile.in24
-rw-r--r--scripts/blk_availability_systemd_red_hat.service.in2
-rw-r--r--scripts/lvm-activate-vgs-last.service.in22
-rw-r--r--scripts/lvm-activate-vgs-main.service.in19
-rw-r--r--scripts/lvm2_monitoring_systemd_red_hat.service.in4
-rw-r--r--spec/packages.inc18
-rw-r--r--tools/args.h5
-rw-r--r--tools/command-lines.in8
-rw-r--r--tools/pvscan.c123
-rw-r--r--tools/toollib.c58
-rw-r--r--tools/toollib.h5
-rw-r--r--tools/tools.h3
-rw-r--r--tools/vgchange.c129
-rw-r--r--udev/69-dm-lvm-metad.rules.in2
-rw-r--r--udev/69-dm-lvm.rules.in14
19 files changed, 411 insertions, 87 deletions
diff --git a/configure.ac b/configure.ac
index 31196d96c..ac9f17a31 100644
--- a/configure.ac
+++ b/configure.ac
@@ -773,39 +773,6 @@ AC_DEFINE_UNQUOTED(DEFAULT_RUN_DIR, ["$DEFAULT_RUN_DIR"],
[Default LVM run directory.])
################################################################################
-dnl -- Build cluster mirror log daemon
-AC_MSG_CHECKING(whether to build cluster mirror log daemon)
-AC_ARG_ENABLE(cmirrord,
- AS_HELP_STRING([--enable-cmirrord],
- [enable the cluster mirror log daemon]),
- CMIRRORD=$enableval, CMIRRORD=no)
-AC_MSG_RESULT($CMIRRORD)
-
-BUILD_CMIRRORD=$CMIRRORD
-
-################################################################################
-dnl -- cmirrord pidfile
-if test "$BUILD_CMIRRORD" = yes; then
- AC_ARG_WITH(cmirrord-pidfile,
- AS_HELP_STRING([--with-cmirrord-pidfile=PATH],
- [cmirrord pidfile [PID_DIR/cmirrord.pid]]),
- CMIRRORD_PIDFILE=$withval,
- CMIRRORD_PIDFILE="$DEFAULT_PID_DIR/cmirrord.pid")
- AC_DEFINE_UNQUOTED(CMIRRORD_PIDFILE, ["$CMIRRORD_PIDFILE"],
- [Path to cmirrord pidfile.])
-fi
-
-################################################################################
-dnl -- Look for corosync libraries if required.
-if [[ "$BUILD_CMIRRORD" = yes ]]; then
- pkg_config_init
-
- if test "$HAVE_CPG" != yes; then
- PKG_CHECK_MODULES(CPG, libcpg)
- fi
-fi
-
-################################################################################
dnl -- Enable debugging
AC_MSG_CHECKING(whether to enable debugging)
AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [enable debugging]),
@@ -1642,10 +1609,6 @@ fi
AC_MSG_CHECKING(whether to enable editline)
AC_MSG_RESULT($EDITLINE)
-if test "$BUILD_CMIRRORD" = yes; then
- AC_CHECK_FUNCS(atexit,,hard_bailout)
-fi
-
if test "$BUILD_LVMLOCKD" = yes; then
AS_IF([test "$HAVE_REALTIME" != yes], [AC_MSG_ERROR([Realtime clock support is mandatory for lvmlockd.])])
AC_CHECK_FUNCS(strtoull,,hard_bailout)
@@ -1808,7 +1771,6 @@ AC_DEFINE_UNQUOTED(LVM_CONFIGURE_LINE, "$CONFIGURE_LINE", [configure command lin
################################################################################
AC_SUBST(AWK)
AC_SUBST(BLKID_PC)
-AC_SUBST(BUILD_CMIRRORD)
AC_SUBST(BUILD_DMEVENTD)
AC_SUBST(BUILD_LVMDBUSD)
AC_SUBST(BUILD_LVMPOLLD)
@@ -1946,7 +1908,6 @@ AC_SUBST(WRITE_INSTALL)
AC_SUBST(DMEVENTD_PIDFILE)
AC_SUBST(LVMPOLLD_PIDFILE)
AC_SUBST(LVMLOCKD_PIDFILE)
-AC_SUBST(CMIRRORD_PIDFILE)
AC_SUBST(interface)
AC_SUBST(kerneldir)
AC_SUBST(missingkernel)
@@ -1968,7 +1929,6 @@ Makefile
make.tmpl
libdm/make.tmpl
daemons/Makefile
-daemons/cmirrord/Makefile
daemons/dmeventd/Makefile
daemons/dmeventd/libdevmapper-event.pc
daemons/dmeventd/plugins/Makefile
@@ -2002,14 +1962,14 @@ libdm/libdevmapper.pc
man/Makefile
po/Makefile
scripts/lvm2-pvscan.service
+scripts/lvm-activate-vgs-main.service
+scripts/lvm-activate-vgs-last.service
scripts/blkdeactivate.sh
scripts/blk_availability_init_red_hat
scripts/blk_availability_systemd_red_hat.service
-scripts/cmirrord_init_red_hat
scripts/com.redhat.lvmdbus1.service
scripts/dm_event_systemd_red_hat.service
scripts/dm_event_systemd_red_hat.socket
-scripts/lvm2_cmirrord_systemd_red_hat.service
scripts/lvm2_lvmdbusd_systemd_red_hat.service
scripts/lvm2_lvmpolld_init_red_hat
scripts/lvm2_lvmpolld_systemd_red_hat.service
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index d280e7adb..d2a40f234 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -1130,6 +1130,18 @@ cfg(global_event_activation_CFG, "event_activation", global_CFG_SECTION, CFG_DEF
"See the --setautoactivation option or the auto_activation_volume_list\n"
"setting to configure autoactivation for specific VGs or LVs.\n")
+cfg_array(global_event_activation_options_CFG, "event_activation_options", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_EVENT_ACTIVATION_OPTIONS, vsn(2, 3, 14), NULL, 0, NULL,
+ "Set event activation options.\n"
+ "service_to_event: begin with fixed activation services,\n"
+ "then switch to event based activation.\n"
+ "event_only: only use event based activation.\n"
+ "service_only: only use fixed activation services.\n"
+ "(This is equivalent to event_activation=0.)\n"
+ "Autoactivation commands should set --eventactivation service|event\n"
+ "to indicate if they are performing service or event activation.\n"
+ "An autoactivation command may then be skipped according to the\n"
+ "value of this setting.\n")
+
cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 2, 93), 0, vsn(2, 3, 0), NULL,
NULL)
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index a7a2a06df..e748ebb67 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -329,4 +329,7 @@
#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
+#define DEFAULT_EVENT_ACTIVATION_OPTION1 "service_to_event"
+#define DEFAULT_EVENT_ACTIVATION_OPTIONS "#S" DEFAULT_EVENT_ACTIVATION_OPTION1
+
#endif /* _LVM_DEFAULTS_H */
diff --git a/lib/label/label.c b/lib/label/label.c
index b5804c738..6815eb3ad 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -1129,6 +1129,9 @@ int label_scan(struct cmd_context *cmd)
}
}
}
+
+ log_debug_devs("Filtering devices to scan done (nodata)");
+
cmd->filter_nodata_only = 0;
dm_list_iterate_items(devl, &all_devs)
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
index 0d7f45680..bc567555e 100644
--- a/scripts/Makefile.in
+++ b/scripts/Makefile.in
@@ -15,9 +15,6 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
-SOURCES = lvm2_activation_generator_systemd_red_hat.c
-TARGETS = lvm2_activation_generator_systemd_red_hat
-
include $(top_builddir)/make.tmpl
ifeq ("@BUILD_DMEVENTD@", "yes")
@@ -66,7 +63,7 @@ install_initscripts:
@echo " [INSTALL] initscripts"
$(Q) $(INSTALL_DIR) $(initdir)
ifeq ("@BUILD_DMEVENTD@", "yes")
- $(Q) $(INSTALL_SCRIPT) lvm2_monitoring_init_red_hat $(initdir)/lvm2-monitor
+ $(Q) $(INSTALL_SCRIPT) lvm2_monitoring_init_red_hat $(initdir)/lvm-monitor
endif
ifeq ("@BUILD_LVMPOLLD@", "yes")
$(Q) $(INSTALL_SCRIPT) lvm2_lvmpolld_init_red_hat $(initdir)/lvm2-lvmpolld
@@ -78,24 +75,15 @@ ifeq ("@BLKDEACTIVATE@", "yes")
$(Q) $(INSTALL_SCRIPT) blk_availability_init_red_hat $(initdir)/blk-availability
endif
-CFLAGS_lvm2_activation_generator_systemd_red_hat.o += $(EXTRA_EXEC_CFLAGS)
-
-lvm2_activation_generator_systemd_red_hat: $(OBJECTS) $(LVMINTERNAL_LIBS)
- @echo " [CC] $@"
- $(Q) $(CC) -o $@ $(OBJECTS) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) $(LVMINTERNAL_LIBS) $(LIBS)
-
-install_systemd_generators:
- @echo " [INSTALL] systemd_generators"
- $(Q) $(INSTALL_DIR) $(systemd_generator_dir)
- $(Q) $(INSTALL_PROGRAM) lvm2_activation_generator_systemd_red_hat $(systemd_generator_dir)/lvm2-activation-generator
-
install_systemd_units: install_dbus_service
@echo " [INSTALL] systemd_units"
$(Q) $(INSTALL_DIR) $(systemd_unit_dir)
+ $(Q) $(INSTALL_DATA) lvm-activate-vgs-main.service $(systemd_unit_dir)/lvm-activate-vgs-main.service
+ $(Q) $(INSTALL_DATA) lvm-activate-vgs-last.service $(systemd_unit_dir)/lvm-activate-vgs-last.service
ifeq ("@BUILD_DMEVENTD@", "yes")
$(Q) $(INSTALL_DATA) dm_event_systemd_red_hat.socket $(systemd_unit_dir)/dm-event.socket
$(Q) $(INSTALL_DATA) dm_event_systemd_red_hat.service $(systemd_unit_dir)/dm-event.service
- $(Q) $(INSTALL_DATA) lvm2_monitoring_systemd_red_hat.service $(systemd_unit_dir)/lvm2-monitor.service
+ $(Q) $(INSTALL_DATA) lvm2_monitoring_systemd_red_hat.service $(systemd_unit_dir)/lvm-monitor.service
endif
ifeq ("@BLKDEACTIVATE@", "yes")
$(Q) $(INSTALL_DATA) blk_availability_systemd_red_hat.service $(systemd_unit_dir)/blk-availability.service
@@ -155,7 +143,9 @@ DISTCLEAN_TARGETS += \
lvm2_monitoring_init_red_hat \
lvm2_monitoring_systemd_red_hat.service \
lvm2_pvscan_systemd_red_hat@.service \
- lvm2_tmpfiles_red_hat.conf
+ lvm2_tmpfiles_red_hat.conf \
+ lvm-activate-vgs-main.service \
+ lvm-activate-vgs-last.service
# Remove ancient files
DISTCLEAN_TARGETS += \
diff --git a/scripts/blk_availability_systemd_red_hat.service.in b/scripts/blk_availability_systemd_red_hat.service.in
index 82d3b82d0..e42b3ab5f 100644
--- a/scripts/blk_availability_systemd_red_hat.service.in
+++ b/scripts/blk_availability_systemd_red_hat.service.in
@@ -1,7 +1,7 @@
[Unit]
Description=Availability of block devices
Before=shutdown.target
-After=lvm2-activation.service iscsi-shutdown.service iscsi.service iscsid.service fcoe.service rbdmap.service
+After=lvm-activate-vgs-main.service lvm-activate-vgs-last.service iscsi-shutdown.service iscsi.service iscsid.service fcoe.service rbdmap.service
DefaultDependencies=no
Conflicts=shutdown.target
diff --git a/scripts/lvm-activate-vgs-last.service.in b/scripts/lvm-activate-vgs-last.service.in
new file mode 100644
index 000000000..76eea5a8c
--- /dev/null
+++ b/scripts/lvm-activate-vgs-last.service.in
@@ -0,0 +1,22 @@
+[Unit]
+Description=Activate LVM Volume Groups (last)
+Documentation=man:vgchange(8)
+Wants=systemd-udev-settle.service
+After=lvm-activate-vgs-main.service systemd-udev-settle.service multipathd.service cryptsetup.target
+Before=local-fs-pre.target shutdown.target
+DefaultDependencies=no
+Conflicts=shutdown.target
+
+# "--eventactivation service" tells vgchange it is being called
+# from an activation service, so it will do nothing if
+# lvm.conf event_activation_options = "event_only".
+# "--eventactivation on" tells vgchange to enable event-based
+# pvscan activations by creating /run/lvm/event-activation-on.
+
+[Service]
+Type=oneshot
+ExecStart=@SBINDIR@/lvm vgchange -aay --nohints --vgonline --eventactivation service,on
+RemainAfterExit=yes
+
+[Install]
+WantedBy=sysinit.target
diff --git a/scripts/lvm-activate-vgs-main.service.in b/scripts/lvm-activate-vgs-main.service.in
new file mode 100644
index 000000000..94aad8426
--- /dev/null
+++ b/scripts/lvm-activate-vgs-main.service.in
@@ -0,0 +1,19 @@
+[Unit]
+Description=Activate LVM Volume Groups
+Documentation=man:vgchange(8)
+After=dm-event.socket dm-event.service
+Before=local-fs-pre.target shutdown.target
+DefaultDependencies=no
+Conflicts=shutdown.target
+
+# "--eventactivation service" tells vgchange it is being called
+# from an activation service, so it will do nothing if
+# lvm.conf event_activation_options = "event_only".
+
+[Service]
+Type=oneshot
+ExecStart=@SBINDIR@/lvm vgchange -aay --nohints --vgonline --eventactivation service
+RemainAfterExit=yes
+
+[Install]
+WantedBy=sysinit.target
diff --git a/scripts/lvm2_monitoring_systemd_red_hat.service.in b/scripts/lvm2_monitoring_systemd_red_hat.service.in
index 4bf744a7f..e912c6a85 100644
--- a/scripts/lvm2_monitoring_systemd_red_hat.service.in
+++ b/scripts/lvm2_monitoring_systemd_red_hat.service.in
@@ -1,8 +1,8 @@
[Unit]
-Description=Monitoring of LVM2 mirrors, snapshots etc. using dmeventd or progress polling
+Description=Monitor LVM Logical Volumes
Documentation=man:dmeventd(8) man:lvcreate(8) man:lvchange(8) man:vgchange(8)
Requires=dm-event.socket
-After=dm-event.socket dm-event.service lvm2-activation.service
+After=dm-event.socket dm-event.service lvm-activate-vgs-last.service
Before=local-fs-pre.target shutdown.target
DefaultDependencies=no
Conflicts=shutdown.target
diff --git a/spec/packages.inc b/spec/packages.inc
index 74d795520..3d6ef2de9 100644
--- a/spec/packages.inc
+++ b/spec/packages.inc
@@ -23,10 +23,10 @@ if [ $1 = 0 ]; then
fi
%triggerun -- %{name} < 2.02.86-2
-%{_bindir}/systemd-sysv-convert --save lvm2-monitor >/dev/null 2>&1 || :
-/bin/systemctl --no-reload enable lvm2-monitor.service > /dev/null 2>&1 || :
-/sbin/chkconfig --del lvm2-monitor > /dev/null 2>&1 || :
-/bin/systemctl try-restart lvm2-monitor.service > /dev/null 2>&1 || :
+%{_bindir}/systemd-sysv-convert --save lvm-monitor >/dev/null 2>&1 || :
+/bin/systemctl --no-reload enable lvm-monitor.service > /dev/null 2>&1 || :
+/sbin/chkconfig --del lvm-monitor > /dev/null 2>&1 || :
+/bin/systemctl try-restart lvm-monitor.service > /dev/null 2>&1 || :
# files in the main package
%files
@@ -100,9 +100,6 @@ fi
%{_mandir}/man8/lvm-config.8.gz
%{_mandir}/man8/lvm-dumpconfig.8.gz
%{_mandir}/man8/lvm.8.gz
-%if %{enable_systemd}
- %{_mandir}/man8/lvm2-activation-generator.8.gz
-%endif
%{_mandir}/man8/lvmconfig.8.gz
%{_mandir}/man8/lvmdevices.8.gz
%{_mandir}/man8/lvmdiskscan.8.gz
@@ -187,16 +184,17 @@ fi
%dir %{_default_run_dir}
%if %{enable_systemd}
%{_tmpfilesdir}/%{name}.conf
+ %{_unitdir}/lvm-activate-vgs-main.service
+ %{_unitdir}/lvm-activate-vgs-last.service
+ %{_unitdir}/lvm-monitor.service
%{_unitdir}/blk-availability.service
- %{_unitdir}/lvm2-monitor.service
- %attr(555, -, -) %{_prefix}/lib/systemd/system-generators/lvm2-activation-generator
%if %{have_service lvmpolld}
%{_unitdir}/lvm2-lvmpolld.service
%{_unitdir}/lvm2-lvmpolld.socket
%endif
%else
%{_sysconfdir}/rc.d/init.d/blk-availability
- %{_sysconfdir}/rc.d/init.d/lvm2-monitor
+ %{_sysconfdir}/rc.d/init.d/lvm-monitor
%if %{have_service lvmpolld}
%{_sysconfdir}/rc.d/init.d/lvm2-lvmpolld
%endif
diff --git a/tools/args.h b/tools/args.h
index 774ce33f4..f7a4fc6f7 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -278,6 +278,11 @@ arg(errorwhenfull_ARG, '\0', "errorwhenfull", bool_VAL, 0, 0,
"(Also see dm-thin-pool kernel module option no_space_timeout.)\n"
"See \\fBlvmthin\\fP(7) for more information.\n")
+arg(eventactivation_ARG, '\0', "eventactivation", string_VAL, 0, 0,
+ "Specify if the command is running autoactivation from an event\n"
+ "or a fixed service. The lvm.conf event_activation_options setting\n"
+ "determines if event or service based activation commands are used.\n")
+
arg(force_long_ARG, '\0', "force", 0, ARG_COUNTABLE, 0,
"Force metadata restore even with thin pool LVs.\n"
"Use with extreme caution. Most changes to thin metadata\n"
diff --git a/tools/command-lines.in b/tools/command-lines.in
index 23ea33e6d..6e00f22b4 100644
--- a/tools/command-lines.in
+++ b/tools/command-lines.in
@@ -1642,14 +1642,15 @@ DESC: Record that a PV is online or offline.
pvscan --cache_long --activate ay
OO: --ignorelockingfailure, --reportformat ReportFmt,
---major Number, --minor Number, --noudevsync
+--major Number, --minor Number, --noudevsync, --eventactivation String
OP: PV|String ...
IO: --background
ID: pvscan_cache
DESC: Record that a PV is online and autoactivate the VG if complete.
pvscan --cache_long --listvg PV
-OO: --ignorelockingfailure, --checkcomplete, --vgonline, --udevoutput
+OO: --ignorelockingfailure, --checkcomplete, --vgonline, --udevoutput,
+--eventactivation String
ID: pvscan_cache
DESC: Record that a PV is online and list the VG using the PV.
@@ -1747,7 +1748,8 @@ DESC: Start or stop processing LV conversions.
vgchange --activate Active
OO: --activationmode ActivationMode, --ignoreactivationskip, --partial, --sysinit,
---readonly, --ignorelockingfailure, --monitor Bool, --poll Bool, --vgonline, OO_VGCHANGE
+--readonly, --ignorelockingfailure, --monitor Bool, --poll Bool,
+--vgonline, --eventactivation String, OO_VGCHANGE
OP: VG|Tag|Select ...
IO: --ignoreskippedcluster
ID: vgchange_activate
diff --git a/tools/pvscan.c b/tools/pvscan.c
index ada1f07fe..625aedb9f 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -46,6 +46,8 @@ static const char *_pvs_online_dir = DEFAULT_RUN_DIR "/pvs_online";
static const char *_vgs_online_dir = DEFAULT_RUN_DIR "/vgs_online";
static const char *_pvs_lookup_dir = DEFAULT_RUN_DIR "/pvs_lookup";
+static const char *_event_activation_file = DEFAULT_RUN_DIR "/event-activation-on";
+
static int _pvscan_display_pv(struct cmd_context *cmd,
struct physical_volume *pv,
struct pvscan_params *params)
@@ -180,6 +182,84 @@ out:
}
/*
+ * Event based activation
+ * lvm.conf event_activation_options = "event_only"
+ * . all events are used for activation
+ * . no fixed services are used for activation
+ * . lvm.conf event_activation=1 required
+ *
+ * vgchange -aay --eventactivation service
+ * . does nothing
+ * vgchange -aay --eventactivation event
+ * . does activation
+ * pvscan --eventactivation event
+ * . does activation
+ *
+ * ---
+ *
+ * Non-event based activation
+ * lvm.conf event_activation_options = "service_only"
+ * . fixed services are used for activation
+ * . no events are used for activation
+ * . lvm.conf event_activation=0 is equivalent to
+ * event_activation=1 event_activation_options="service_only"
+ *
+ * vgchange -aay --eventactivation service
+ * . does activation
+ * vgchange -aay --eventactivation event
+ * . does nothing
+ * pvscan --eventactivation event
+ * . does nothing
+ *
+ * ---
+ *
+ * Mix of event and non-event based activation
+ * lvm.conf event_activation_options = "service_to_event"
+ * . both services and events are used for activation
+ * . fixed services are used for activation initially,
+ * and last service enables event based activation
+ * by creating the event-activation-on file
+ *
+ * vgchange -aay --eventactivation service
+ * . does activation only if event-activation-on does not exist
+ * vgchange -aay --eventactivation event
+ * . does activation only if event-activation-on exists
+ * vgchange -aay --eventactivation service,on
+ * . does activation only if event-activation-on does not exist
+ * . creates event-activation-on to enable event-based activation
+ * vgchange --eventactivation on|off
+ * . create or remove event-activation-on to enable|disable
+ * event-based activation
+ * pvscan --eventactivation event
+ * . does activation only if event-activation-on exists
+ *
+ */
+
+int event_activation_enable(struct cmd_context *cmd)
+{
+ FILE *fp;
+
+ if (!(fp = fopen(_event_activation_file, "w")))
+ return_0;
+ if (fclose(fp))
+ stack;
+ return 1;
+}
+
+int event_activation_is_on(struct cmd_context *cmd)
+{
+ struct stat buf;
+
+ if (!stat(_event_activation_file, &buf))
+ return 1;
+
+ if (errno != ENOENT)
+ log_debug("event_activation_is_on errno %d", errno);
+
+ return 0;
+}
+
+/*
* Avoid a duplicate pvscan[%d] prefix when logging to the journal.
* FIXME: this should probably replace if (udevoutput) with
* if (log_journal & LOG_JOURNAL_OUTPUT)
@@ -367,7 +447,7 @@ static void _online_files_remove(const char *dirpath)
log_sys_debug("closedir", dirpath);
}
-static int _online_pvid_file_create(struct cmd_context *cmd, struct device *dev, const char *vgname)
+int online_pvid_file_create(struct cmd_context *cmd, struct device *dev, const char *vgname, int ignore_existing, int *exists)
{
char path[PATH_MAX];
char buf[MAX_PVID_FILE_SIZE] = { 0 };
@@ -407,8 +487,13 @@ static int _online_pvid_file_create(struct cmd_context *cmd, struct device *dev,
fd = open(path, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
if (fd < 0) {
- if (errno == EEXIST)
+ if (errno == EEXIST) {
+ if (exists)
+ *exists = 1;
+ if (ignore_existing)
+ return 1;
goto check_duplicate;
+ }
log_error_pvscan(cmd, "Failed to create online file for %s path %s error %d", dev_name(dev), path, errno);
return 0;
}
@@ -427,7 +512,6 @@ static int _online_pvid_file_create(struct cmd_context *cmd, struct device *dev,
}
/* We don't care about syncing, these files are not even persistent. */
-
if (close(fd))
log_sys_debug("close", path);
@@ -1412,7 +1496,7 @@ static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvs
* Create file named for pvid to record this PV is online.
* The command creates/checks online files only when --cache is used.
*/
- if (do_cache && !_online_pvid_file_create(cmd, dev, vg ? vg->name : NULL)) {
+ if (do_cache && !online_pvid_file_create(cmd, dev, vg ? vg->name : NULL, 0, NULL)) {
log_error_pvscan(cmd, "PV %s failed to create online file.", dev_name(dev));
release_vg(vg);
ret = 0;
@@ -1857,6 +1941,7 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv)
{
struct pvscan_aa_params pp = { 0 };
struct dm_list complete_vgnames;
+ const char *ea;
int do_activate = arg_is_set(cmd, activate_ARG);
int event_activation;
int devno_args = 0;
@@ -1930,6 +2015,36 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv)
log_verbose("Ignoring pvscan --cache because event_activation is disabled.");
return ECMD_PROCESSED;
}
+
+
+ if ((ea = arg_str_value(cmd, eventactivation_ARG, NULL))) {
+ int service_only = 0, event_only = 0, service_to_event = 0;
+ int ea_service = 0, ea_event = 0, ea_on = 0;
+
+ if (!get_event_activation_config_settings(cmd, &service_only, &event_only, &service_to_event))
+ return ECMD_FAILED;
+ if (!get_event_activation_command_options(cmd, ea, &ea_service, &ea_event, &ea_on))
+ return ECMD_FAILED;
+
+ if (ea_event) {
+ if (!event_activation) {
+ log_print("Skip pvscan for event and event_activation=0.");
+ return ECMD_PROCESSED;
+ }
+ if (service_only) {
+ log_print("Skip pvscan for event and event_activation_options service_only.");
+ return ECMD_PROCESSED;
+ }
+ if (service_to_event && !event_activation_is_on(cmd)) {
+ log_print("Skip pvscan for event and no event-activation-on.");
+ return ECMD_PROCESSED;
+ }
+ } else {
+ log_error("Option --eventactivation %s is not used by pvscan.", ea);
+ return ECMD_FAILED;
+ }
+ }
+
if (!_pvscan_cache_args(cmd, argc, argv, &complete_vgnames))
return ECMD_FAILED;
}
diff --git a/tools/toollib.c b/tools/toollib.c
index 3682dfa0a..b87aef83e 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -5829,3 +5829,61 @@ bad:
out:
return 0;
}
+
+int get_event_activation_config_settings(struct cmd_context *cmd,
+ int *service_only, int *event_only, int *service_to_event)
+{
+ const struct dm_config_node *cn;
+ const struct dm_config_value *cv;
+ int eo = 0, so = 0, se = 0;
+
+ if (!(cn = find_config_tree_array(cmd, global_event_activation_options_CFG, NULL)))
+ return 1;
+
+ for (cv = cn->v; cv; cv = cv->next) {
+ if (cv->type != DM_CFG_STRING)
+ continue;
+ if (!strcmp(cv->v.str, "service_only"))
+ so = 1;
+ else if (!strcmp(cv->v.str, "event_only"))
+ eo = 1;
+ else if (!strcmp(cv->v.str, "service_to_event"))
+ se = 1;
+ else if (strlen(cv->v.str) > 0)
+ log_warn("WARNING: ignoring unrecognized event_activation_options value %s.", cv->v.str);
+ }
+
+ if (se && (so || eo)) {
+ log_warn("WARNING: ignoring incompatible event_activation_options, using service_to_event.");
+ *service_to_event = 1;
+ } else if (so && eo) {
+ log_warn("WARNING: ignoring incompatible event_activation_options, using event_only.");
+ *event_only = 1;
+ } else if (se) {
+ *service_to_event = 1;
+ } else if (so) {
+ *service_only = 1;
+ } else if (eo) {
+ *event_only = 1;
+ } else {
+ *service_to_event = 1;
+ }
+ return 1;
+}
+
+int get_event_activation_command_options(struct cmd_context *cmd, const char *ea, int *ea_service, int *ea_event, int *ea_on)
+{
+ if (strstr(ea, "service"))
+ *ea_service = 1;
+ if (strstr(ea, "event"))
+ *ea_event = 1;
+ if (strstr(ea, "on"))
+ *ea_on = 1;
+
+ if (*ea_service && *ea_event) {
+ log_error("Invalid --eventactivation options, service and event are incompatible.");
+ return 0;
+ }
+ return 1;
+}
+
diff --git a/tools/toollib.h b/tools/toollib.h
index f3a60fbc4..3f203d309 100644
--- a/tools/toollib.h
+++ b/tools/toollib.h
@@ -237,4 +237,9 @@ int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
int get_lvt_enum(struct logical_volume *lv);
+int get_event_activation_config_settings(struct cmd_context *cmd,
+ int *service_only, int *event_only, int *service_to_event);
+int get_event_activation_command_options(struct cmd_context *cmd,
+ const char *ea, int *ea_service, int *ea_event, int *ea_on);
+
#endif
diff --git a/tools/tools.h b/tools/tools.h
index e2661f272..37b7d5a7e 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -295,8 +295,11 @@ int lvconvert_cachevol_attach_single(struct cmd_context *cmd,
struct logical_volume *lv,
struct processing_handle *handle);
+int online_pvid_file_create(struct cmd_context *cmd, struct device *dev, const char *vgname, int ignore_existing, int *exists);
void online_vg_file_remove(const char *vgname);
int online_vg_file_create(struct cmd_context *cmd, const char *vgname);
void online_dir_setup(struct cmd_context *cmd);
+int event_activation_enable(struct cmd_context *cmd);
+int event_activation_is_on(struct cmd_context *cmd);
#endif
diff --git a/tools/vgchange.c b/tools/vgchange.c
index 985907a02..518e13551 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -194,6 +194,41 @@ int vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg
return 1;
}
+static int _online_pvid_file_create_all(struct cmd_context *cmd)
+{
+ struct lvmcache_info *info;
+ struct dev_iter *iter;
+ struct device *dev;
+ const char *vgname;
+ int exists;
+ int exist_count = 0;
+ int create_count = 0;
+
+ if (!(iter = dev_iter_create(NULL, 0)))
+ return 0;
+ while ((dev = dev_iter_get(cmd, iter))) {
+ if (dev->pvid[0] &&
+ (info = lvmcache_info_from_pvid(dev->pvid, dev, 0))) {
+ vgname = lvmcache_vgname_from_info(info);
+ if (vgname && !is_orphan_vg(vgname)) {
+ /*
+ * Ignore exsting pvid file because a pvscan may be creating
+ * the same file as the same time we are, which is expected.
+ */
+ exists = 0;
+ online_pvid_file_create(cmd, dev, vgname, 1, &exists);
+ if (exists)
+ exist_count++;
+ else
+ create_count++;
+ }
+ }
+ }
+ dev_iter_destroy(iter);
+ log_debug("PV online files created %d exist %d", create_count, exist_count);
+ return 1;
+}
+
int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
activation_change_t activate)
{
@@ -219,6 +254,11 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
return 1;
}
+ if (arg_is_set(cmd, vgonline_ARG) && !online_vg_file_create(cmd, vg->name)) {
+ log_print("VG %s already online", vg->name);
+ return 1;
+ }
+
/*
* Safe, since we never write out new metadata here. Required for
* partial activation to work.
@@ -262,11 +302,6 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
}
}
- if (arg_is_set(cmd, vgonline_ARG) && !online_vg_file_create(cmd, vg->name)) {
- log_print("VG %s finished", vg->name);
- return 1;
- }
-
if (!_activate_lvs_in_vg(cmd, vg, activate)) {
stack;
r = 0;
@@ -733,6 +768,7 @@ static int _vgchange_single(struct cmd_context *cmd, const char *vg_name,
int vgchange(struct cmd_context *cmd, int argc, char **argv)
{
struct processing_handle *handle;
+ const char *ea;
uint32_t flags = 0;
int ret;
@@ -845,6 +881,89 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
cmd->lockd_vg_enforce_sh = 1;
}
+ if ((ea = arg_str_value(cmd, eventactivation_ARG, NULL))) {
+ int service_only = 0, event_only = 0, service_to_event = 0;
+ int ea_service = 0, ea_event = 0, ea_on = 0;
+ int on_file_exists;
+ int event_activation;
+
+ if (!get_event_activation_config_settings(cmd, &service_only, &event_only, &service_to_event))
+ return ECMD_FAILED;
+ if (!get_event_activation_command_options(cmd, ea, &ea_service, &ea_event, &ea_on))
+ return ECMD_FAILED;
+ event_activation = find_config_tree_bool(cmd, global_event_activation_CFG, NULL);
+
+ /*
+ * The combination of lvm.conf event_activation/event_activation_options
+ * and the --eventactivation service|event value determines if this
+ * command should do anything or be skipped, along with the existence of
+ * the /run/lvm/event-activation-on file in case of service_to_event.
+ */
+ if (!event_activation) {
+ if (ea_event) {
+ log_print("Skip vgchange for event and event_activation=0.");
+ return ECMD_PROCESSED;
+ }
+ } else {
+ if (event_only && ea_service) {
+ log_print("Skip vgchange for service and event_activation_options event_only.");
+ return ECMD_PROCESSED;
+ }
+ if (service_only && ea_event) {
+ log_print("Skip vgchange for event and event_activation_options service_only.");
+ return ECMD_PROCESSED;
+ }
+
+ on_file_exists = event_activation_is_on(cmd);
+
+ if (service_to_event && ea_service && on_file_exists) {
+ log_print("Skip vgchange for service and event-activation-on.");
+ return ECMD_PROCESSED;
+ }
+ if (service_to_event && ea_event && !on_file_exists) {
+ log_print("Skip vgchange for event and no event-activation-on.");
+ return ECMD_PROCESSED;
+ }
+ }
+
+ /*
+ * Switch from service activation to event activation when:
+ * lvm.conf event_activation=1,
+ * event_activation_options=service_to_event,
+ * and --eventactivation service,on.
+ *
+ * When enabling event-based activation, first create the
+ * /run/lvm/event-activation-on file to tell other commands
+ * to begin responding to PV events and doing activation
+ * for newly completed VGs. It also needs to create online
+ * files for existing PVs because some VGs may be incomplete
+ * at this point, and future pvscan commands need to
+ * find online files for PVs that have already appeared.
+ * The label scan provides info to know which PVs are
+ * present and should have pvid online files created.
+ *
+ * process_each_vg() usually begins with lock_global() and
+ * lvmcache_label_scan(), and then processes each VG.
+ * In this case, lock_global/lvmcache_label_scan are done
+ * before calling process_each_vg. This allows a special
+ * step to be inserted between the label scan and processing
+ * vgs. That step creates the pvid online files, which
+ * requires label scan info. The lock_global and
+ * lvmcache_label_scan will be skipped by process_each_vg
+ * since they are already done here.
+ */
+ if (event_activation && service_to_event && ea_service && ea_on) {
+ if (!event_activation_enable(cmd))
+ log_warn("WARNING: Failed to create event-activation-on.");
+
+ if (!lock_global(cmd, "sh"))
+ return ECMD_FAILED;
+ lvmcache_label_scan(cmd);
+ _online_pvid_file_create_all(cmd);
+ flags |= PROCESS_SKIP_SCAN;
+ }
+ }
+
if (update)
flags |= READ_FOR_UPDATE;
else if (arg_is_set(cmd, activate_ARG))
diff --git a/udev/69-dm-lvm-metad.rules.in b/udev/69-dm-lvm-metad.rules.in
index 78f506520..3e2424d06 100644
--- a/udev/69-dm-lvm-metad.rules.in
+++ b/udev/69-dm-lvm-metad.rules.in
@@ -121,6 +121,6 @@ LABEL="direct_pvscan"
# MD | | X | X* | |
# loop | | X | X* | |
# other | X | | X | | X
-RUN+="(LVM_EXEC)/lvm pvscan --background --cache --activate ay --major $major --minor $minor", ENV{LVM_SCANNED}="1"
+RUN+="(LVM_EXEC)/lvm pvscan --cache -aay --eventactivation event --major $major --minor $minor", ENV{LVM_SCANNED}="1"
LABEL="lvm_end"
diff --git a/udev/69-dm-lvm.rules.in b/udev/69-dm-lvm.rules.in
index 39e5b9807..025b62e7b 100644
--- a/udev/69-dm-lvm.rules.in
+++ b/udev/69-dm-lvm.rules.in
@@ -78,9 +78,19 @@ ENV{SYSTEMD_READY}="1"
#
# TODO: adjust the output of vgchange -aay so that
# it's better suited to appearing in the journal.
+#
+# "--eventactivation event" used with pvscan or vgchange
+# tells the command that it is being run from an event.
+# The command does nothing if lvm.conf event_activation=0.
+# The command does nothing if lvm.conf event_activation=1,
+# and lvm.conf event_activation_options="service_only".
+# The command goes ahead if event_activation_options="event_only",
+# or if event_activation_options="service_to_event" and the
+# event-activation-on file exists.
+#
-IMPORT{program}="(LVM_EXEC)/lvm pvscan --cache --listvg --checkcomplete --vgonline --udevoutput --journal=output $env{DEVNAME}"
-ENV{LVM_VG_NAME_COMPLETE}=="?*", RUN+="/usr/bin/systemd-run -r --no-block --property DefaultDependencies=no --unit lvm-activate-$env{LVM_VG_NAME_COMPLETE} lvm vgchange -aay --nohints $env{LVM_VG_NAME_COMPLETE}"
+IMPORT{program}="(LVM_EXEC)/lvm pvscan --cache --listvg --checkcomplete --vgonline --eventactivation event --udevoutput --journal=output $env{DEVNAME}"
+ENV{LVM_VG_NAME_COMPLETE}=="?*", RUN+="/usr/bin/systemd-run -r --no-block --property DefaultDependencies=no --unit lvm-activate-$env{LVM_VG_NAME_COMPLETE} lvm vgchange -aay --nohints --eventactivation event $env{LVM_VG_NAME_COMPLETE}"
GOTO="lvm_end"
LABEL="lvm_end"