|
|
146ac4 |
From 455dbd8444074aa235c284d0e3285410b9096401 Mon Sep 17 00:00:00 2001
|
|
|
146ac4 |
From: David Teigland <teigland@redhat.com>
|
|
|
146ac4 |
Date: Thu, 21 Feb 2019 15:52:45 -0600
|
|
|
146ac4 |
Subject: [PATCH 2/5] pvscan: fix autoactivation from concurrent pvscans
|
|
|
146ac4 |
|
|
|
146ac4 |
Use a file lock to ensure that only one pvscan will do
|
|
|
146ac4 |
initialization of pvs_online, otherwise multiple concurrent
|
|
|
146ac4 |
pvscans may all see an empty pvs_online directory and
|
|
|
146ac4 |
do initialization.
|
|
|
146ac4 |
|
|
|
146ac4 |
The pvscan that is doing initialization should also only
|
|
|
146ac4 |
attempt to activate complete VGs.
|
|
|
146ac4 |
---
|
|
|
146ac4 |
tools/pvscan.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++---------
|
|
|
146ac4 |
1 file changed, 120 insertions(+), 21 deletions(-)
|
|
|
146ac4 |
|
|
|
146ac4 |
diff --git a/tools/pvscan.c b/tools/pvscan.c
|
|
|
146ac4 |
index 2a884df..df46e04 100644
|
|
|
146ac4 |
--- a/tools/pvscan.c
|
|
|
146ac4 |
+++ b/tools/pvscan.c
|
|
|
146ac4 |
@@ -19,6 +19,7 @@
|
|
|
146ac4 |
#include "lib/metadata/metadata.h"
|
|
|
146ac4 |
|
|
|
146ac4 |
#include <dirent.h>
|
|
|
146ac4 |
+#include <sys/file.h>
|
|
|
146ac4 |
|
|
|
146ac4 |
struct pvscan_params {
|
|
|
146ac4 |
int new_pvs_found;
|
|
|
146ac4 |
@@ -32,10 +33,61 @@ struct pvscan_params {
|
|
|
146ac4 |
};
|
|
|
146ac4 |
|
|
|
146ac4 |
struct pvscan_aa_params {
|
|
|
146ac4 |
- int refresh_all;
|
|
|
146ac4 |
unsigned int activate_errors;
|
|
|
146ac4 |
};
|
|
|
146ac4 |
|
|
|
146ac4 |
+static const char *_online_file = DEFAULT_RUN_DIR "/pvs_online_lock";
|
|
|
146ac4 |
+static int _online_fd = -1;
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+static int _lock_online(int mode, int nonblock)
|
|
|
146ac4 |
+{
|
|
|
146ac4 |
+ int fd;
|
|
|
146ac4 |
+ int op = mode;
|
|
|
146ac4 |
+ int ret;
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+ if (nonblock)
|
|
|
146ac4 |
+ op |= LOCK_NB;
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+ if (_online_fd != -1) {
|
|
|
146ac4 |
+ log_warn("lock_online existing fd %d", _online_fd);
|
|
|
146ac4 |
+ return 0;
|
|
|
146ac4 |
+ }
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+ fd = open(_online_file, O_RDWR | S_IRUSR | S_IWUSR);
|
|
|
146ac4 |
+ if (fd < 0) {
|
|
|
146ac4 |
+ log_debug("lock_online open errno %d", errno);
|
|
|
146ac4 |
+ return 0;
|
|
|
146ac4 |
+ }
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+ ret = flock(fd, op);
|
|
|
146ac4 |
+ if (!ret) {
|
|
|
146ac4 |
+ _online_fd = fd;
|
|
|
146ac4 |
+ return 1;
|
|
|
146ac4 |
+ }
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+ if (close(fd))
|
|
|
146ac4 |
+ stack;
|
|
|
146ac4 |
+ return 0;
|
|
|
146ac4 |
+}
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+static void _unlock_online(void)
|
|
|
146ac4 |
+{
|
|
|
146ac4 |
+ int ret;
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+ if (_online_fd == -1) {
|
|
|
146ac4 |
+ log_warn("unlock_online no existing fd");
|
|
|
146ac4 |
+ return;
|
|
|
146ac4 |
+ }
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+ ret = flock(_online_fd, LOCK_UN);
|
|
|
146ac4 |
+ if (ret)
|
|
|
146ac4 |
+ log_warn("unlock_online flock errno %d", errno);
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+ if (close(_online_fd))
|
|
|
146ac4 |
+ stack;
|
|
|
146ac4 |
+ _online_fd = -1;
|
|
|
146ac4 |
+}
|
|
|
146ac4 |
+
|
|
|
146ac4 |
static int _pvscan_display_pv(struct cmd_context *cmd,
|
|
|
146ac4 |
struct physical_volume *pv,
|
|
|
146ac4 |
struct pvscan_params *params)
|
|
|
146ac4 |
@@ -341,6 +393,20 @@ static void _online_pvid_dir_setup(void)
|
|
|
146ac4 |
log_debug("Failed to create %s", _pvs_online_dir);
|
|
|
146ac4 |
}
|
|
|
146ac4 |
|
|
|
146ac4 |
+static void _online_file_setup(void)
|
|
|
146ac4 |
+{
|
|
|
146ac4 |
+ FILE *fp;
|
|
|
146ac4 |
+ struct stat st;
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+ if (!stat(_online_file, &st))
|
|
|
146ac4 |
+ return;
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+ if (!(fp = fopen(_online_file, "w")))
|
|
|
146ac4 |
+ return;
|
|
|
146ac4 |
+ if (fclose(fp))
|
|
|
146ac4 |
+ stack;
|
|
|
146ac4 |
+}
|
|
|
146ac4 |
+
|
|
|
146ac4 |
static int _online_pvid_files_missing(void)
|
|
|
146ac4 |
{
|
|
|
146ac4 |
DIR *dir;
|
|
|
146ac4 |
@@ -584,12 +650,12 @@ static int _pvscan_aa_single(struct cmd_context *cmd, const char *vg_name,
|
|
|
146ac4 |
}
|
|
|
146ac4 |
|
|
|
146ac4 |
static int _pvscan_aa(struct cmd_context *cmd, struct pvscan_aa_params *pp,
|
|
|
146ac4 |
- int all_vgs, struct dm_list *vgnames)
|
|
|
146ac4 |
+ struct dm_list *vgnames)
|
|
|
146ac4 |
{
|
|
|
146ac4 |
struct processing_handle *handle = NULL;
|
|
|
146ac4 |
int ret;
|
|
|
146ac4 |
|
|
|
146ac4 |
- if (!all_vgs && dm_list_empty(vgnames)) {
|
|
|
146ac4 |
+ if (dm_list_empty(vgnames)) {
|
|
|
146ac4 |
log_debug("No VGs to autoactivate.");
|
|
|
146ac4 |
return ECMD_PROCESSED;
|
|
|
146ac4 |
}
|
|
|
146ac4 |
@@ -601,11 +667,6 @@ static int _pvscan_aa(struct cmd_context *cmd, struct pvscan_aa_params *pp,
|
|
|
146ac4 |
|
|
|
146ac4 |
handle->custom_handle = pp;
|
|
|
146ac4 |
|
|
|
146ac4 |
- if (all_vgs) {
|
|
|
146ac4 |
- cmd->cname->flags |= ALL_VGS_IS_DEFAULT;
|
|
|
146ac4 |
- pp->refresh_all = 1;
|
|
|
146ac4 |
- }
|
|
|
146ac4 |
-
|
|
|
146ac4 |
ret = process_each_vg(cmd, 0, NULL, NULL, vgnames, READ_FOR_UPDATE, 0, handle, _pvscan_aa_single);
|
|
|
146ac4 |
|
|
|
146ac4 |
destroy_processing_handle(cmd, handle);
|
|
|
146ac4 |
@@ -617,7 +678,8 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv)
|
|
|
146ac4 |
{
|
|
|
146ac4 |
struct pvscan_aa_params pp = { 0 };
|
|
|
146ac4 |
struct dm_list single_devs;
|
|
|
146ac4 |
- struct dm_list found_vgnames;
|
|
|
146ac4 |
+ struct dm_list vgnames;
|
|
|
146ac4 |
+ struct dm_list *complete_vgnames = NULL;
|
|
|
146ac4 |
struct device *dev;
|
|
|
146ac4 |
struct device_list *devl;
|
|
|
146ac4 |
const char *pv_name;
|
|
|
146ac4 |
@@ -628,12 +690,14 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv)
|
|
|
146ac4 |
struct arg_value_group_list *current_group;
|
|
|
146ac4 |
dev_t devno;
|
|
|
146ac4 |
int do_activate = arg_is_set(cmd, activate_ARG);
|
|
|
146ac4 |
- int all_vgs = 0;
|
|
|
146ac4 |
int add_errors = 0;
|
|
|
146ac4 |
int ret = ECMD_PROCESSED;
|
|
|
146ac4 |
|
|
|
146ac4 |
dm_list_init(&single_devs);
|
|
|
146ac4 |
- dm_list_init(&found_vgnames);
|
|
|
146ac4 |
+ dm_list_init(&vgnames);
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+ if (do_activate)
|
|
|
146ac4 |
+ complete_vgnames = &vgnames;
|
|
|
146ac4 |
|
|
|
146ac4 |
if (arg_is_set(cmd, major_ARG) + arg_is_set(cmd, minor_ARG))
|
|
|
146ac4 |
devno_args = 1;
|
|
|
146ac4 |
@@ -644,6 +708,7 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv)
|
|
|
146ac4 |
}
|
|
|
146ac4 |
|
|
|
146ac4 |
_online_pvid_dir_setup();
|
|
|
146ac4 |
+ _online_file_setup();
|
|
|
146ac4 |
|
|
|
146ac4 |
if (!lock_vol(cmd, VG_GLOBAL, LCK_VG_READ, NULL)) {
|
|
|
146ac4 |
log_error("Unable to obtain global lock.");
|
|
|
146ac4 |
@@ -654,19 +719,53 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv)
|
|
|
146ac4 |
* Scan all devices when no args are given.
|
|
|
146ac4 |
*/
|
|
|
146ac4 |
if (!argc && !devno_args) {
|
|
|
146ac4 |
- log_verbose("pvscan all devices.");
|
|
|
146ac4 |
+ _lock_online(LOCK_EX, 0);
|
|
|
146ac4 |
+ log_verbose("pvscan all devices for requested refresh.");
|
|
|
146ac4 |
_online_pvid_files_remove();
|
|
|
146ac4 |
- _online_pvscan_all_devs(cmd, NULL, NULL);
|
|
|
146ac4 |
- all_vgs = 1;
|
|
|
146ac4 |
+ /* identify complete vgs, and only activate those vgs */
|
|
|
146ac4 |
+ _online_pvscan_all_devs(cmd, complete_vgnames, NULL);
|
|
|
146ac4 |
+ _unlock_online();
|
|
|
146ac4 |
goto activate;
|
|
|
146ac4 |
}
|
|
|
146ac4 |
|
|
|
146ac4 |
+ /*
|
|
|
146ac4 |
+ * Initialization case:
|
|
|
146ac4 |
+ * lock_online ex
|
|
|
146ac4 |
+ * if empty
|
|
|
146ac4 |
+ * pvscan all
|
|
|
146ac4 |
+ * create pvid files
|
|
|
146ac4 |
+ * identify complete vgs
|
|
|
146ac4 |
+ * unlock_online
|
|
|
146ac4 |
+ * activate complete vgs
|
|
|
146ac4 |
+ *
|
|
|
146ac4 |
+ * Non-initialization case:
|
|
|
146ac4 |
+ * lock_online ex
|
|
|
146ac4 |
+ * if not empty
|
|
|
146ac4 |
+ * unlock_unlock
|
|
|
146ac4 |
+ * pvscan devs
|
|
|
146ac4 |
+ * create pvid files
|
|
|
146ac4 |
+ * identify complete vgs
|
|
|
146ac4 |
+ * activate complete vgs
|
|
|
146ac4 |
+ *
|
|
|
146ac4 |
+ * In the non-init case, a VG with two PVs, where both PVs appear at once
|
|
|
146ac4 |
+ * two parallel pvscans for each PV create the pvid files for each PV in
|
|
|
146ac4 |
+ * parallel, then both pvscans see the vg has completed, and both pvscans
|
|
|
146ac4 |
+ * activate the VG in parallel. The activations should be serialized by
|
|
|
146ac4 |
+ * the VG lock.
|
|
|
146ac4 |
+ */
|
|
|
146ac4 |
+
|
|
|
146ac4 |
+ _lock_online(LOCK_EX, 0);
|
|
|
146ac4 |
+
|
|
|
146ac4 |
if (_online_pvid_files_missing()) {
|
|
|
146ac4 |
log_verbose("pvscan all devices to initialize available PVs.");
|
|
|
146ac4 |
_online_pvid_files_remove();
|
|
|
146ac4 |
- _online_pvscan_all_devs(cmd, NULL, NULL);
|
|
|
146ac4 |
- all_vgs = 1;
|
|
|
146ac4 |
+ /* identify complete vgs, and only activate those vgs */
|
|
|
146ac4 |
+ _online_pvscan_all_devs(cmd, complete_vgnames, NULL);
|
|
|
146ac4 |
+ _unlock_online();
|
|
|
146ac4 |
goto activate;
|
|
|
146ac4 |
+ } else {
|
|
|
146ac4 |
+ log_verbose("pvscan only specific devices.");
|
|
|
146ac4 |
+ _unlock_online();
|
|
|
146ac4 |
}
|
|
|
146ac4 |
|
|
|
146ac4 |
if (argc || devno_args) {
|
|
|
146ac4 |
@@ -743,7 +842,7 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv)
|
|
|
146ac4 |
* Devices that exist and pass the lvmetad filter
|
|
|
146ac4 |
* are online.
|
|
|
146ac4 |
*/
|
|
|
146ac4 |
- if (!_online_pvscan_one(cmd, dev, NULL, &found_vgnames, 0, &pvid_without_metadata))
|
|
|
146ac4 |
+ if (!_online_pvscan_one(cmd, dev, NULL, complete_vgnames, 0, &pvid_without_metadata))
|
|
|
146ac4 |
add_errors++;
|
|
|
146ac4 |
}
|
|
|
146ac4 |
}
|
|
|
146ac4 |
@@ -794,7 +893,7 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv)
|
|
|
146ac4 |
* Devices that exist and pass the lvmetad filter
|
|
|
146ac4 |
* are online.
|
|
|
146ac4 |
*/
|
|
|
146ac4 |
- if (!_online_pvscan_one(cmd, devl->dev, NULL, &found_vgnames, 0, &pvid_without_metadata))
|
|
|
146ac4 |
+ if (!_online_pvscan_one(cmd, devl->dev, NULL, complete_vgnames, 0, &pvid_without_metadata))
|
|
|
146ac4 |
add_errors++;
|
|
|
146ac4 |
}
|
|
|
146ac4 |
}
|
|
|
146ac4 |
@@ -809,10 +908,10 @@ activate:
|
|
|
146ac4 |
* scan all devs and pick out the complete VG holding this
|
|
|
146ac4 |
* device so we can then autoactivate that VG.
|
|
|
146ac4 |
*/
|
|
|
146ac4 |
- if (!dm_list_empty(&single_devs) && dm_list_empty(&found_vgnames) &&
|
|
|
146ac4 |
+ if (!dm_list_empty(&single_devs) && complete_vgnames && dm_list_empty(complete_vgnames) &&
|
|
|
146ac4 |
pvid_without_metadata && do_activate) {
|
|
|
146ac4 |
log_verbose("pvscan all devices for PV without metadata: %s.", pvid_without_metadata);
|
|
|
146ac4 |
- _online_pvscan_all_devs(cmd, &found_vgnames, &single_devs);
|
|
|
146ac4 |
+ _online_pvscan_all_devs(cmd, complete_vgnames, &single_devs);
|
|
|
146ac4 |
}
|
|
|
146ac4 |
|
|
|
146ac4 |
/*
|
|
|
146ac4 |
@@ -821,7 +920,7 @@ activate:
|
|
|
146ac4 |
* list, and we can attempt to autoactivate LVs in the VG.
|
|
|
146ac4 |
*/
|
|
|
146ac4 |
if (do_activate)
|
|
|
146ac4 |
- ret = _pvscan_aa(cmd, &pp, all_vgs, &found_vgnames);
|
|
|
146ac4 |
+ ret = _pvscan_aa(cmd, &pp, complete_vgnames);
|
|
|
146ac4 |
|
|
|
146ac4 |
out:
|
|
|
146ac4 |
if (add_errors || pp.activate_errors)
|
|
|
146ac4 |
--
|
|
|
146ac4 |
1.8.3.1
|
|
|
146ac4 |
|