1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

activate: add autoactivation hooks

Define an 'activation_handler' that gets called automatically on
PV appearance/disappearance while processing the lvmetad_pv_found
and lvmetad_pv_gone functions that are supposed to update the
lvmetad state based on PV availability state. For now, the actual
support is for PV appearance only, leaving room for PV disappearance
support as well (which is a more complex problem to solve as this
needs to count with possible device stack).

Add a new activation change mode - CHANGE_AAY exposed as
'--activate ay/-aay' argument ('activate automatically').

Factor out the vgchange activation functionality for use in other
tools (like pvscan...).
This commit is contained in:
Peter Rajnoha 2012-06-27 08:59:34 -04:00
parent 2729720fd3
commit 95ced7a7be
12 changed files with 104 additions and 48 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.97 -
===============================
Add support for volume autoactivation using lvmetad.
Add --activate synonym for --available arg and prefer --activate.
Never issue discards when LV extents are being reconfigured, not deleted.
Allow release_lv_segment_area to fail as functions it calls can fail.

View File

@ -328,10 +328,8 @@ int activation(void)
return _activation;
}
static int _passes_volumes_filter(struct cmd_context *cmd,
struct logical_volume *lv,
const struct dm_config_node *cn,
const char *config_path)
int lv_passes_volumes_filter(struct cmd_context *cmd, struct logical_volume *lv,
const struct dm_config_node *cn, const char *config_path)
{
const struct dm_config_value *cv;
const char *str;
@ -429,7 +427,7 @@ static int _passes_activation_filter(struct cmd_context *cmd,
return 0;
}
return _passes_volumes_filter(cmd, lv, cn, "activation/volume_list");
return lv_passes_volumes_filter(cmd, lv, cn, "activation/volume_list");
}
static int _passes_readonly_filter(struct cmd_context *cmd,
@ -440,7 +438,21 @@ static int _passes_readonly_filter(struct cmd_context *cmd,
if (!(cn = find_config_tree_node(cmd, "activation/read_only_volume_list")))
return 0;
return _passes_volumes_filter(cmd, lv, cn, "activation/read_only_volume_list");
return lv_passes_volumes_filter(cmd, lv, cn, "activation/read_only_volume_list");
}
int lv_passes_auto_activation_filter(struct cmd_context *cmd, struct logical_volume *lv)
{
const struct dm_config_node *cn;
if (!(cn = find_config_tree_node(cmd, "activation/auto_activation_volume_list"))) {
log_verbose("activation/auto_activation_volume_list configuration setting "
"not defined: All logical volumes will be auto-activated.");
return 1;
}
return lv_passes_volumes_filter(cmd, lv, cn, "activation/auto_activation_volume_list");
}
int library_version(char *version, size_t size)

View File

@ -93,6 +93,14 @@ int lv_check_not_in_use(struct cmd_context *cmd, struct logical_volume *lv,
*/
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
int *activate_lv);
int lv_passes_volumes_filter(struct cmd_context *cmd, struct logical_volume *lv,
const struct dm_config_node *cn, const char *config_path);
/*
* Checks against the auto_activation_volume_list and
* returns 1 if the LV should be activated, 0 otherwise.
*/
int lv_passes_auto_activation_filter(struct cmd_context *cmd, struct logical_volume *lv);
int lv_check_transient(struct logical_volume *lv);
/*

39
lib/cache/lvmetad.c vendored
View File

@ -322,7 +322,7 @@ int lvmetad_vg_update(struct volume_group *vg)
/* NB. the PV fmt pointer is sometimes wrong during vgconvert */
if (pvl->pv->dev && !lvmetad_pv_found(pvl->pv->id, pvl->pv->dev,
vg->fid ? vg->fid->fmt : pvl->pv->fmt,
pvl->pv->label_sector, NULL))
pvl->pv->label_sector, NULL, NULL))
return 0;
}
@ -536,7 +536,7 @@ static const char *_print_mdas(struct lvmcache_info *info)
}
int lvmetad_pv_found(struct id pvid, struct device *device, const struct format_type *fmt,
uint64_t label_sector, struct volume_group *vg)
uint64_t label_sector, struct volume_group *vg, activation_handler handler)
{
char uuid[64];
daemon_reply reply;
@ -544,6 +544,7 @@ int lvmetad_pv_found(struct id pvid, struct device *device, const struct format_
const char *mdas = NULL;
char *pvmeta;
char *buf = NULL;
const char *status;
int result;
if (!_using_lvmetad)
@ -603,12 +604,26 @@ int lvmetad_pv_found(struct id pvid, struct device *device, const struct format_
dm_free(pvmeta);
result = _lvmetad_handle_reply(reply, "update PV", uuid, NULL);
if (result && handler) {
status = daemon_reply_str(reply, "status", "<missing>");
if (!strcmp(status, "partial"))
handler(vg, 1, CHANGE_AAY);
else if (!strcmp(status, "complete"))
handler(vg, 0, CHANGE_AAY);
else if (!strcmp(status, "orphan"))
;
else
log_error("Request to %s %s in lvmetad gave status %s.",
"update PV", uuid, status);
}
daemon_reply_destroy(reply);
return result;
}
int lvmetad_pv_gone(dev_t device, const char *pv_name)
int lvmetad_pv_gone(dev_t device, const char *pv_name, activation_handler handler)
{
daemon_reply reply;
int result;
@ -617,6 +632,13 @@ int lvmetad_pv_gone(dev_t device, const char *pv_name)
if (!_using_lvmetad)
return 1;
/*
* TODO: automatic volume deactivation takes place here *before*
* all cached info is gone - call handler. Also, consider
* integrating existing deactivation script that deactivates
* the whole stack from top to bottom (not yet upstream).
*/
reply = daemon_send_simple(_lvmetad, "pv_gone", "device = %d", device, NULL);
result = _lvmetad_handle_reply(reply, "drop PV", pv_name, &found);
@ -627,9 +649,9 @@ int lvmetad_pv_gone(dev_t device, const char *pv_name)
return result;
}
int lvmetad_pv_gone_by_dev(struct device *dev)
int lvmetad_pv_gone_by_dev(struct device *dev, activation_handler handler)
{
return lvmetad_pv_gone(dev->dev, dev_name(dev));
return lvmetad_pv_gone(dev->dev, dev_name(dev), handler);
}
int lvmetad_active(void)
@ -665,7 +687,8 @@ static int _pvscan_lvmetad_single(struct metadata_area *mda, void *baton)
return 1;
}
int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev)
int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev,
activation_handler handler)
{
struct label *label;
struct lvmcache_info *info;
@ -680,7 +703,7 @@ int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev)
if (!label_read(dev, &label, 0)) {
log_print("No PV label found on %s.", dev_name(dev));
if (!lvmetad_pv_gone_by_dev(dev))
if (!lvmetad_pv_gone_by_dev(dev, handler))
goto_bad;
return 1;
}
@ -704,7 +727,7 @@ int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev)
* sync needs to be killed.
*/
if (!lvmetad_pv_found(*(struct id *)dev->pvid, dev, lvmcache_fmt(info),
label->sector, baton.vg)) {
label->sector, baton.vg, handler)) {
release_vg(baton.vg);
goto_bad;
}

19
lib/cache/lvmetad.h vendored
View File

@ -19,6 +19,8 @@ struct volume_group;
struct cmd_context;
struct dm_config_tree;
typedef int (*activation_handler) (struct volume_group *vg, int partial, int activate);
#ifdef LVMETAD_SUPPORT
/*
* Initialise the communication with lvmetad. Normally called by
@ -64,13 +66,13 @@ int lvmetad_vg_remove(struct volume_group *vg);
*/
int lvmetad_pv_found(struct id pvid, struct device *device,
const struct format_type *fmt, uint64_t label_sector,
struct volume_group *vg);
struct volume_group *vg, activation_handler handler);
/*
* Inform the daemon that the device no longer exists.
*/
int lvmetad_pv_gone(dev_t devno, const char *pv_name);
int lvmetad_pv_gone_by_dev(struct device *dev);
int lvmetad_pv_gone(dev_t devno, const char *pv_name, activation_handler handler);
int lvmetad_pv_gone_by_dev(struct device *dev, activation_handler handler);
/*
* Request a list of all PVs available to lvmetad. If requested, this will also
@ -102,7 +104,8 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd,
/*
* Scan a single device and update lvmetad with the result(s).
*/
int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev);
int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev,
activation_handler handler);
# else /* LVMETAD_SUPPORT */
@ -111,15 +114,15 @@ int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev);
# define lvmetad_active() (0)
# define lvmetad_vg_update(vg) (1)
# define lvmetad_vg_remove(vg) (1)
# define lvmetad_pv_found(pvid, device, fmt, label_sector, vg) (1)
# define lvmetad_pv_gone(devno, pv_name) (1)
# define lvmetad_pv_gone_by_dev(dev) (1)
# define lvmetad_pv_found(pvid, device, fmt, label_sector, vg, handler) (1)
# define lvmetad_pv_gone(devno, pv_name, handler) (1)
# define lvmetad_pv_gone_by_dev(dev, handler) (1)
# define lvmetad_pv_list_to_lvmcache(cmd) (1)
# define lvmetad_pv_lookup(cmd, pvid, found) (0)
# define lvmetad_pv_lookup_by_dev(cmd, dev, found) (0)
# define lvmetad_vg_list_to_lvmcache(cmd) (1)
# define lvmetad_vg_lookup(cmd, vgname, vgid) (NULL)
# define pvscan_lvmetad_single(cmd, dev) (0)
# define pvscan_lvmetad_single(cmd, dev, handler) (0)
# endif /* LVMETAD_SUPPORT */

View File

@ -567,7 +567,8 @@ typedef enum {
CHANGE_AN = 1, /* deactivate */
CHANGE_AE = 2, /* activate exclusively */
CHANGE_ALY = 3, /* activate locally */
CHANGE_ALN = 4 /* deactivate locally */
CHANGE_ALN = 4, /* deactivate locally */
CHANGE_AAY = 5 /* automatic activation */
} activation_change_t;
/* FIXME: refactor and reduce the size of this struct! */

View File

@ -3800,7 +3800,8 @@ int pv_write(struct cmd_context *cmd __attribute__((unused)),
if (!pv->fmt->ops->pv_write(pv->fmt, pv))
return_0;
if (!lvmetad_pv_found(pv->id, pv->dev, pv->fmt, pv->label_sector, NULL))
if (!lvmetad_pv_found(pv->id, pv->dev, pv->fmt, pv->label_sector,
NULL, NULL))
return_0;
return 1;

View File

@ -188,6 +188,12 @@ int activation_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_v
av->ui_value = CHANGE_AY;
}
else if (!strcmp(av->value, "a") || !strcmp(av->value, "ay") ||
!strcmp(av->value, "ya")) {
av->i_value = CHANGE_AAY;
av->ui_value = CHANGE_AAY;
}
else if (!strcmp(av->value, "n") || !strcmp(av->value, "en") ||
!strcmp(av->value, "ne")) {
av->i_value = CHANGE_AN;

View File

@ -128,7 +128,7 @@ static int pvremove_single(struct cmd_context *cmd, const char *pv_name,
goto out;
}
if (!lvmetad_pv_gone_by_dev(dev))
if (!lvmetad_pv_gone_by_dev(dev, NULL))
goto_out;
log_print("Labels on physical volume \"%s\" successfully wiped",

View File

@ -97,7 +97,7 @@ static void _pvscan_display_single(struct cmd_context *cmd,
pv_pe_size(pv)));
}
static int _pvscan_lvmetad_all_devs(struct cmd_context *cmd)
static int _pvscan_lvmetad_all_devs(struct cmd_context *cmd, activation_handler handler)
{
struct dev_iter *iter;
struct device *dev;
@ -109,7 +109,7 @@ static int _pvscan_lvmetad_all_devs(struct cmd_context *cmd)
}
while ((dev = dev_iter_get(iter))) {
if (!pvscan_lvmetad_single(cmd, dev)) {
if (!pvscan_lvmetad_single(cmd, dev, handler)) {
r = 0;
break;
}
@ -134,6 +134,7 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
struct arg_value_group_list *current_group;
dev_t devno;
char *buf;
activation_handler handler = NULL;
if (arg_count(cmd, major_ARG) + arg_count(cmd, minor_ARG))
devno_args = 1;
@ -150,7 +151,7 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
/* Scan everything? */
if (!argc && !devno_args) {
if (!_pvscan_lvmetad_all_devs(cmd))
if (!_pvscan_lvmetad_all_devs(cmd, handler))
ret = ECMD_FAILED;
goto out;
}
@ -167,7 +168,7 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
continue;
}
if (!pvscan_lvmetad_single(cmd, dev)) {
if (!pvscan_lvmetad_single(cmd, dev, handler)) {
ret = ECMD_FAILED;
break;
}
@ -192,7 +193,7 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
if (!dm_asprintf(&buf, "%" PRIi32 ":%" PRIi32, major, minor))
stack;
/* FIXME Filters? */
if (!lvmetad_pv_gone(devno, buf ? : "")) {
if (!lvmetad_pv_gone(devno, buf ? : "", handler)) {
ret = ECMD_FAILED;
if (buf)
dm_free(buf);
@ -206,7 +207,7 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
continue;
}
if (!pvscan_lvmetad_single(cmd, dev)) {
if (!pvscan_lvmetad_single(cmd, dev, handler)) {
ret = ECMD_FAILED;
break;
}

View File

@ -185,4 +185,7 @@ int mirror_remove_missing(struct cmd_context *cmd,
struct logical_volume *lv, int force);
uint32_t percent_of_extents(uint32_t percents, uint32_t count, int roundup);
int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
activation_change_t activate);
#endif

View File

@ -81,8 +81,8 @@ static int _poll_lvs_in_vg(struct cmd_context *cmd,
return count;
}
static int _activate_lvs_in_vg(struct cmd_context *cmd,
struct volume_group *vg, int activate)
static int _activate_lvs_in_vg(struct cmd_context *cmd, struct volume_group *vg,
activation_change_t activate)
{
struct lv_list *lvl;
struct logical_volume *lv;
@ -211,11 +211,13 @@ static int _vgchange_background_polling(struct cmd_context *cmd, struct volume_g
return 1;
}
static int _vgchange_activate(struct cmd_context *cmd, struct volume_group *vg)
int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
activation_change_t activate)
{
int lv_open, active, monitored = 0;
int activate_arg, r = 1;
int activate = 1;
int lv_open, active, monitored = 0, r = 1, do_activate = 1;
if ((activate == CHANGE_AN) || (activate == CHANGE_ALN))
do_activate = 0;
/*
* Safe, since we never write out new metadata here. Required for
@ -223,23 +225,18 @@ static int _vgchange_activate(struct cmd_context *cmd, struct volume_group *vg)
*/
cmd->handles_missing_pvs = 1;
activate_arg = arg_uint_value(cmd, activate_ARG, 0);
if ((activate_arg == CHANGE_AN) || (activate_arg == CHANGE_ALN))
activate = 0;
/* FIXME: Force argument to deactivate them? */
if (!activate && (lv_open = lvs_in_vg_opened(vg))) {
if (!do_activate && (lv_open = lvs_in_vg_opened(vg))) {
log_error("Can't deactivate volume group \"%s\" with %d open "
"logical volume(s)", vg->name, lv_open);
return 0;
}
/* FIXME Move into library where clvmd can use it */
if (activate)
if (do_activate)
check_current_backup(vg);
if (activate && (active = lvs_in_vg_activated(vg))) {
if (do_activate && (active = lvs_in_vg_activated(vg))) {
log_verbose("%d logical volume(s) in volume group \"%s\" "
"already active", active, vg->name);
if (dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) {
@ -252,7 +249,7 @@ static int _vgchange_activate(struct cmd_context *cmd, struct volume_group *vg)
}
}
if (!_activate_lvs_in_vg(cmd, vg, activate_arg))
if (!_activate_lvs_in_vg(cmd, vg, activate))
r = 0;
/* Print message only if there was not found a missing VG */
@ -509,7 +506,7 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
}
if (arg_count(cmd, activate_ARG)) {
if (!_vgchange_activate(cmd, vg))
if (!vgchange_activate(cmd, vg, arg_uint_value(cmd, activate_ARG, CHANGE_AY)))
return ECMD_FAILED;
}