mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
hints: new pvs_online type
Use a new form of hints to reduce device scanning in vgchange -aay run by the udev rule for event based autoactivation. Standard hints allow a command with a named VG arg to scan only the PVs in the named VG, rather than scanning all available PVs. Standard hints are useful with a stable set of system devices. When new devices are arriving, as occurs during system startup, the hints are repeatedly invalidated, which makes standard hints unhelpful while devices are regularly appearing. This is the situation in which vgchange -aay is used, so standard hints are not generally helpful for autoactivation. In the context of system startup, pvscan --cache is keeping track of available PVs using the pvs_online files, similar to what the hints file does for a running system. Given this, a new hint mode, hints = "pvs_online", is added which derives an equivalent to standard hints, based on pvs_online files that are being created by udev-run pvscans. This hint mode is useful while devices are appearing, e.g. during system startup, and vgchange -aay can benefit from it. pvscan --cache -aay autoactivation already has a similar optimization (the "quick" activation case) that is based on the pvs_online file, but it is not implemented as a form of hints. This new form of hints is mainly useful in the context of event based autoactivation, during which standard hints are not useful. Once the system is in a steady state after startup (devices are not regularly appearing), the standard hints are most useful. The pvs_online hint method could be used on a running system, but would be no better than standard hints, and may be inferior because pvs_online files are not rigidly updated after system startup.
This commit is contained in:
parent
5e79d61de7
commit
50cc98c820
@ -183,6 +183,7 @@ struct cmd_context {
|
|||||||
unsigned enable_hints:1; /* hints are enabled for cmds in general */
|
unsigned enable_hints:1; /* hints are enabled for cmds in general */
|
||||||
unsigned use_hints:1; /* if hints are enabled this cmd can use them */
|
unsigned use_hints:1; /* if hints are enabled this cmd can use them */
|
||||||
unsigned pvscan_recreate_hints:1; /* enable special case hint handling for pvscan --cache */
|
unsigned pvscan_recreate_hints:1; /* enable special case hint handling for pvscan --cache */
|
||||||
|
unsigned hints_pvs_online:1; /* hints="pvs_online" */
|
||||||
unsigned scan_lvs:1;
|
unsigned scan_lvs:1;
|
||||||
unsigned wipe_outdated_pvs:1;
|
unsigned wipe_outdated_pvs:1;
|
||||||
unsigned enable_devices_list:1; /* command is using --devices option */
|
unsigned enable_devices_list:1; /* command is using --devices option */
|
||||||
|
@ -332,4 +332,8 @@
|
|||||||
#define DEFAULT_EVENT_ACTIVATION_OPTION1 "service_to_event"
|
#define DEFAULT_EVENT_ACTIVATION_OPTION1 "service_to_event"
|
||||||
#define DEFAULT_EVENT_ACTIVATION_OPTIONS "#S" DEFAULT_EVENT_ACTIVATION_OPTION1
|
#define DEFAULT_EVENT_ACTIVATION_OPTIONS "#S" DEFAULT_EVENT_ACTIVATION_OPTION1
|
||||||
|
|
||||||
|
#define PVS_ONLINE_DIR DEFAULT_RUN_DIR "/pvs_online"
|
||||||
|
#define VGS_ONLINE_DIR DEFAULT_RUN_DIR "/vgs_online"
|
||||||
|
#define PVS_LOOKUP_DIR DEFAULT_RUN_DIR "/pvs_lookup"
|
||||||
|
|
||||||
#endif /* _LVM_DEFAULTS_H */
|
#endif /* _LVM_DEFAULTS_H */
|
||||||
|
@ -150,11 +150,14 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
|
int online_pvid_file_read(char *path, int *major, int *minor, char *vgname);
|
||||||
|
|
||||||
static const char *_hints_file = DEFAULT_RUN_DIR "/hints";
|
static const char *_hints_file = DEFAULT_RUN_DIR "/hints";
|
||||||
static const char *_nohints_file = DEFAULT_RUN_DIR "/nohints";
|
static const char *_nohints_file = DEFAULT_RUN_DIR "/nohints";
|
||||||
static const char *_newhints_file = DEFAULT_RUN_DIR "/newhints";
|
static const char *_newhints_file = DEFAULT_RUN_DIR "/newhints";
|
||||||
@ -1279,6 +1282,109 @@ check:
|
|||||||
free(name);
|
free(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _get_hints_from_pvs_online(struct cmd_context *cmd, struct dm_list *hints_out,
|
||||||
|
struct dm_list *devs_in, struct dm_list *devs_out)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char file_vgname[NAME_LEN];
|
||||||
|
struct dm_list hints_list;
|
||||||
|
struct hint file_hint;
|
||||||
|
struct hint *alloc_hint;
|
||||||
|
struct hint *hint, *hint2;
|
||||||
|
struct device_list *devl, *devl2;
|
||||||
|
int file_major, file_minor;
|
||||||
|
int found = 0;
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *de;
|
||||||
|
char *vgname = NULL;
|
||||||
|
char *pvid;
|
||||||
|
|
||||||
|
dm_list_init(&hints_list);
|
||||||
|
|
||||||
|
if (!(dir = opendir(PVS_ONLINE_DIR)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while ((de = readdir(dir))) {
|
||||||
|
if (de->d_name[0] == '.')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pvid = de->d_name;
|
||||||
|
|
||||||
|
if (strlen(pvid) != ID_LEN) /* 32 */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
memset(path, 0, sizeof(path));
|
||||||
|
snprintf(path, sizeof(path), "%s/%s", PVS_ONLINE_DIR, pvid);
|
||||||
|
|
||||||
|
memset(&file_hint, 0, sizeof(file_hint));
|
||||||
|
memset(file_vgname, 0, sizeof(file_vgname));
|
||||||
|
file_major = 0;
|
||||||
|
file_minor = 0;
|
||||||
|
|
||||||
|
if (!online_pvid_file_read(path, &file_major, &file_minor, file_vgname))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!dm_strncpy(file_hint.pvid, pvid, sizeof(file_hint.pvid)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
file_hint.devt = makedev(file_major, file_minor);
|
||||||
|
|
||||||
|
if (file_vgname[0] && validate_name(file_vgname)) {
|
||||||
|
if (!dm_strncpy(file_hint.vgname, file_vgname, sizeof(file_hint.vgname)))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(alloc_hint = malloc(sizeof(struct hint))))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
memcpy(alloc_hint, &file_hint, sizeof(struct hint));
|
||||||
|
|
||||||
|
log_debug("add hint %s %d:%d %s from pvs_online", file_hint.pvid, file_major, file_minor, file_vgname);
|
||||||
|
dm_list_add(&hints_list, &alloc_hint->list);
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closedir(dir))
|
||||||
|
stack;
|
||||||
|
|
||||||
|
log_debug("accept hints found %d from pvs_online", found);
|
||||||
|
|
||||||
|
_get_single_vgname_cmd_arg(cmd, &hints_list, &vgname);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* apply_hints equivalent, move devs from devs_in to devs_out if
|
||||||
|
* their devno matches the devno of a hint (and if the hint matches
|
||||||
|
* the vgname when a vgname is present.)
|
||||||
|
*/
|
||||||
|
dm_list_iterate_items_safe(devl, devl2, devs_in) {
|
||||||
|
dm_list_iterate_items_safe(hint, hint2, &hints_list) {
|
||||||
|
if ((MAJOR(devl->dev->dev) == MAJOR(hint->devt)) &&
|
||||||
|
(MINOR(devl->dev->dev) == MINOR(hint->devt))) {
|
||||||
|
|
||||||
|
if (vgname && hint->vgname[0] && strcmp(vgname, hint->vgname))
|
||||||
|
goto next_dev;
|
||||||
|
|
||||||
|
snprintf(hint->name, sizeof(hint->name), "%s", dev_name(devl->dev));
|
||||||
|
hint->chosen = 1;
|
||||||
|
|
||||||
|
dm_list_del(&devl->list);
|
||||||
|
dm_list_add(devs_out, &devl->list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next_dev:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("applied hints using %d other %d vgname %s from pvs_online",
|
||||||
|
dm_list_size(devs_out), dm_list_size(devs_in), vgname ?: "");
|
||||||
|
|
||||||
|
dm_list_splice(hints_out, &hints_list);
|
||||||
|
|
||||||
|
free(vgname);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns 0: no hints are used.
|
* Returns 0: no hints are used.
|
||||||
* . newhints is set if this command should create new hints after scan
|
* . newhints is set if this command should create new hints after scan
|
||||||
@ -1320,6 +1426,15 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
|
|||||||
if (!cmd->use_hints)
|
if (!cmd->use_hints)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* hints = "pvs_online" */
|
||||||
|
if (cmd->hints_pvs_online) {
|
||||||
|
if (!_get_hints_from_pvs_online(cmd, &hints_list, devs_in, devs_out)) {
|
||||||
|
log_debug("get_hints: pvs_online failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if another command created the nohints file to prevent us from
|
* Check if another command created the nohints file to prevent us from
|
||||||
* using hints.
|
* using hints.
|
||||||
|
@ -2540,6 +2540,8 @@ static int _get_current_settings(struct cmd_context *cmd)
|
|||||||
if (!strcmp(hint_mode, "none")) {
|
if (!strcmp(hint_mode, "none")) {
|
||||||
cmd->enable_hints = 0;
|
cmd->enable_hints = 0;
|
||||||
cmd->use_hints = 0;
|
cmd->use_hints = 0;
|
||||||
|
} else if (!strcmp(hint_mode, "pvs_online")) {
|
||||||
|
cmd->hints_pvs_online = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
|
int online_pvid_file_read(char *path, int *major, int *minor, char *vgname);
|
||||||
|
|
||||||
struct pvscan_params {
|
struct pvscan_params {
|
||||||
int new_pvs_found;
|
int new_pvs_found;
|
||||||
int pvs_found;
|
int pvs_found;
|
||||||
@ -305,7 +307,7 @@ static char *_vgname_in_pvid_file_buf(char *buf)
|
|||||||
|
|
||||||
#define MAX_PVID_FILE_SIZE 512
|
#define MAX_PVID_FILE_SIZE 512
|
||||||
|
|
||||||
static int _online_pvid_file_read(char *path, int *major, int *minor, char *vgname)
|
int online_pvid_file_read(char *path, int *major, int *minor, char *vgname)
|
||||||
{
|
{
|
||||||
char buf[MAX_PVID_FILE_SIZE] = { 0 };
|
char buf[MAX_PVID_FILE_SIZE] = { 0 };
|
||||||
char *name;
|
char *name;
|
||||||
@ -408,7 +410,7 @@ static void _online_pvid_file_remove_devno(int major, int minor)
|
|||||||
file_minor = 0;
|
file_minor = 0;
|
||||||
memset(file_vgname, 0, sizeof(file_vgname));
|
memset(file_vgname, 0, sizeof(file_vgname));
|
||||||
|
|
||||||
_online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
|
online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
|
||||||
|
|
||||||
if ((file_major == major) && (file_minor == minor)) {
|
if ((file_major == major) && (file_minor == minor)) {
|
||||||
log_debug("Unlink pv online %s", path);
|
log_debug("Unlink pv online %s", path);
|
||||||
@ -531,7 +533,7 @@ check_duplicate:
|
|||||||
|
|
||||||
memset(file_vgname, 0, sizeof(file_vgname));
|
memset(file_vgname, 0, sizeof(file_vgname));
|
||||||
|
|
||||||
_online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
|
online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
|
||||||
|
|
||||||
if ((file_major == major) && (file_minor == minor)) {
|
if ((file_major == major) && (file_minor == minor)) {
|
||||||
log_debug("Existing online file for %d:%d", major, minor);
|
log_debug("Existing online file for %d:%d", major, minor);
|
||||||
@ -931,7 +933,7 @@ static int _get_devs_from_saved_vg(struct cmd_context *cmd, const char *vgname,
|
|||||||
file_minor = 0;
|
file_minor = 0;
|
||||||
memset(file_vgname, 0, sizeof(file_vgname));
|
memset(file_vgname, 0, sizeof(file_vgname));
|
||||||
|
|
||||||
_online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
|
online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
|
||||||
|
|
||||||
if (file_vgname[0] && strcmp(vgname, file_vgname)) {
|
if (file_vgname[0] && strcmp(vgname, file_vgname)) {
|
||||||
log_error_pvscan(cmd, "Wrong VG found for %d:%d PVID %s: %s vs %s",
|
log_error_pvscan(cmd, "Wrong VG found for %d:%d PVID %s: %s vs %s",
|
||||||
@ -1330,7 +1332,7 @@ static void _set_pv_devices_online(struct cmd_context *cmd, struct volume_group
|
|||||||
minor = 0;
|
minor = 0;
|
||||||
file_vgname[0] = '\0';
|
file_vgname[0] = '\0';
|
||||||
|
|
||||||
_online_pvid_file_read(path, &major, &minor, file_vgname);
|
online_pvid_file_read(path, &major, &minor, file_vgname);
|
||||||
|
|
||||||
if (file_vgname[0] && strcmp(vg->name, file_vgname)) {
|
if (file_vgname[0] && strcmp(vg->name, file_vgname)) {
|
||||||
log_warn("WARNING: VG %s PV %s wrong vgname in online file %s",
|
log_warn("WARNING: VG %s PV %s wrong vgname in online file %s",
|
||||||
|
@ -90,7 +90,7 @@ ENV{SYSTEMD_READY}="1"
|
|||||||
#
|
#
|
||||||
|
|
||||||
IMPORT{program}="(LVM_EXEC)/lvm pvscan --cache --listvg --checkcomplete --vgonline --eventactivation event --udevoutput --journal=output $env{DEVNAME}"
|
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}"
|
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 --config devices/hints=pvs_online --eventactivation event $env{LVM_VG_NAME_COMPLETE}"
|
||||||
GOTO="lvm_end"
|
GOTO="lvm_end"
|
||||||
|
|
||||||
LABEL="lvm_end"
|
LABEL="lvm_end"
|
||||||
|
Loading…
Reference in New Issue
Block a user