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.
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;
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,
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)
*/
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);
/*
/* 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;
}
}
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;
const char *mdas = NULL;
char *pvmeta;
char *buf = NULL;
+ const char *status;
int result;
if (!_using_lvmetad)
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;
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);
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)
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;
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;
}
* 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;
}
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
*/
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
/*
* 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 */
# 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 */
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! */
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;
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;
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",
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;
}
while ((dev = dev_iter_get(iter))) {
- if (!pvscan_lvmetad_single(cmd, dev)) {
+ if (!pvscan_lvmetad_single(cmd, dev, handler)) {
r = 0;
break;
}
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;
/* Scan everything? */
if (!argc && !devno_args) {
- if (!_pvscan_lvmetad_all_devs(cmd))
+ if (!_pvscan_lvmetad_all_devs(cmd, handler))
ret = ECMD_FAILED;
goto out;
}
continue;
}
- if (!pvscan_lvmetad_single(cmd, dev)) {
+ if (!pvscan_lvmetad_single(cmd, dev, handler)) {
ret = ECMD_FAILED;
break;
}
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);
continue;
}
- if (!pvscan_lvmetad_single(cmd, dev)) {
+ if (!pvscan_lvmetad_single(cmd, dev, handler)) {
ret = ECMD_FAILED;
break;
}
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
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;
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
* partial activation to work.
*/
- 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;
+ cmd->handles_missing_pvs = 1;
/* 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) {
}
}
- 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 */
}
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;
}