]> sourceware.org Git - lvm2.git/commitdiff
activate: add autoactivation hooks
authorPeter Rajnoha <prajnoha@redhat.com>
Wed, 27 Jun 2012 12:59:34 +0000 (08:59 -0400)
committerPeter Rajnoha <prajnoha@redhat.com>
Thu, 28 Jun 2012 13:42:47 +0000 (09:42 -0400)
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...).

12 files changed:
WHATS_NEW
lib/activate/activate.c
lib/activate/activate.h
lib/cache/lvmetad.c
lib/cache/lvmetad.h
lib/metadata/metadata-exported.h
lib/metadata/metadata.c
tools/lvmcmdline.c
tools/pvremove.c
tools/pvscan.c
tools/tools.h
tools/vgchange.c

index 0f900801febc563ad102ebba456e2d236ee9de2a..7e29cb00e1c9471af9e833e6bdc4392609aeeaac 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -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.
index 1f2157318a3dc7a676222e936fb65fc77a283699..939de6c79ea3bc21a6c922ecd75e8674aa668bcc 100644 (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)
index 2b90a7b8a9c3e7486e3aad5869c56c0d7ff37222..f698fc99070fcb724d66aadc891022f5a9b0ece3 100644 (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);
 /*
index d70e4905134010b8ed8958401a67870593e52b43..6ef30db118b8db74085be87620724ed12a70afc6 100644 (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;
        }
index 091ff5e321d7ee47598c012afd5b4799b3508a47..713c5a308b8f8bd7dda5c349a695c609a6c7af14 100644 (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 */
 
index 403367e178cd58754fd10e96cd34f1c7bfb7271b..8c655c7650545116719f1b8b90791a2e295a0a10 100644 (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! */
index 7c22785c4072fda7d14240ff0160ea56dec5bfb7..c14125aaf4c350188327675c5d0d90ecf93e8f7c 100644 (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;
index 37b86dac2ea4f0140a2ece067b251dfd91ed64f4..16e15a18747f991810a35f8fa67bd092d3cc7790 100644 (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;
index 0c06c7f47a7b7ef81222c185d1e0f303d0767f7c..7d05758435a4e6c9f8e82ca457c82091acd8e5a1 100644 (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",
index 62034c9ba874488d6af2e1e9c25eb31d59edfaa3..beba17433f6a6f81cd2e624b694acedaaa975917 100644 (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;
                }
index 8ddd351e7076609f874db97363142a8d252809db..7a4465107e4e309b101a9ab6d8d2028c58850c90 100644 (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
index fdad81f13a2c65bdd435f5cefbb8ad581f7a8e0b..29562a58ec8a236f877a90ef607b3e830cde6b48 100644 (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,35 +211,32 @@ 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
         * 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) {
@@ -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;
        }
 
This page took 0.061128 seconds and 5 git commands to generate.