]> sourceware.org Git - lvm2.git/commitdiff
Add support for thin check
authorZdenek Kabelac <zkabelac@redhat.com>
Fri, 2 Mar 2012 21:49:43 +0000 (21:49 +0000)
committerZdenek Kabelac <zkabelac@redhat.com>
Fri, 2 Mar 2012 21:49:43 +0000 (21:49 +0000)
Use libdm callback to execute thin_check before activation
thin pool and after deactivation as well.

Supporting thin_check_executable which may pass in extra options for
the tool.

WHATS_NEW
doc/example.conf.in
lib/activate/dev_manager.c
lib/config/defaults.h

index ee17a078d7bc948af4b66046dffd2259f79c2e9c..2c16b0a998ec5d03bf15dbd1210a40fe33669b9b 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 2.02.94 - 
 ====================================
+  Add support to execute thin_check with each de/active of thin pool.
   Fix automatic estimation of metadata device size for thin pool.
   Test for alloc fail from _alloc_pv_segment() in _extend_pv().
   Check for alloc fail from get_segtype_from_string() in _lvcreate_params().
index 64e58bcb6725bd9512c61705e977379609825f46..72421acb6f7bf45fbf7e1afec430d67fa2e47004 100644 (file)
@@ -650,6 +650,16 @@ activation {
     thin_pool_autoextend_threshold = 100
     thin_pool_autoextend_percent = 20
 
+    # Full path of the utility called to check that a thin metadata device
+    # is in a state that allows it to be used.
+    # Each time a thin pool needs to be activated, this utility is executed.
+    # The activation will only proceed if the utility has an exit status of 0.
+    # Set to "" to skip this check.  (Not recommended.)
+    # The thin tools are available as part of the device-mapper-persistent-data
+    # package from https://github.com/jthornber/thin-provisioning-tools.
+    #
+    thin_check_executable = "/sbin/thin_check -q"
+
     # While activating devices, I/O to devices being (re)configured is
     # suspended, and as a precaution against deadlocks, LVM2 needs to pin
     # any memory it is using so it is not paged out.  Groups of pages that
index 263a7cab1e4a3a64dc2598041be6065b87f31614..0a4a08634eb8630adddf9a3e5362ded52076d68a 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "filter.h"
 #include "activate.h"
+#include "lvm-exec.h"
 
 #include <limits.h>
 #include <dirent.h>
@@ -1193,6 +1194,89 @@ static int _add_partial_replicator_to_dtree(struct dev_manager *dm,
        return 1;
 }
 
+struct thin_cb_data {
+       const struct logical_volume *pool_lv;
+       struct dev_manager *dm;
+};
+
+static int _thin_pool_callback(struct dm_tree_node *node,
+                              dm_node_callback_t type, void *cb_data)
+{
+       int ret, status;
+       const struct thin_cb_data *data = cb_data;
+       const char *dmdir = dm_dir();
+       const char *thin_check =
+               find_config_tree_str_allow_empty(data->pool_lv->vg->cmd,
+                                                "global/thin_check_executable",
+                                                DEFAULT_THIN_CHECK_EXECUTABLE);
+       const struct logical_volume *mlv = first_seg(data->pool_lv)->metadata_lv;
+       size_t len = strlen(dmdir) + strlen(mlv->vg->name) + strlen(mlv->name) + 3;
+       char meta_path[len];
+       int args;
+       char *argv[19]; /* Max supported 15 args */
+       char *split;
+
+       if (!thin_check[0])
+               return 1; /* Checking disabled */
+
+       if (dm_snprintf(meta_path, len, "%s/%s-%s", dmdir,
+                       mlv->vg->name, mlv->name) < 0) {
+               log_error("Failed to build thin metadata path.");
+               return 0;
+       }
+
+       if (!(split = dm_pool_strdup(data->dm->mem, thin_check))) {
+               log_error("Failed to duplicate thin check string.");
+               return 0;
+       }
+
+       args = dm_split_words(split, 16, 0, argv);
+       argv[args++] = meta_path;
+       argv[args] = NULL;
+
+       if (!(ret = exec_cmd(data->pool_lv->vg->cmd, (const char * const *)argv,
+                            &status, 0))) {
+               log_err_once("Check of thin pool %s/%s failed (status:%d). "
+                            "Manual repair required (thin_repair %s)!",
+                            data->pool_lv->vg->name, data->pool_lv->name,
+                            status, meta_path);
+               /*
+                * FIXME: What should we do here??
+                *
+                * Maybe mark the node, so it's not activating
+                * as thin_pool but as error/linear and let the
+                * dm tree resolve the issue.
+                */
+       }
+
+       dm_pool_free(data->dm->mem, split);
+
+       return ret;
+}
+
+static int _thin_pool_register_callback(struct dev_manager *dm,
+                                       struct dm_tree_node *node,
+                                       const struct logical_volume *lv)
+{
+       struct thin_cb_data *data;
+
+       /* Skip metadata testing for unused pool. */
+       if (!first_seg(lv)->transaction_id)
+               return 1;
+
+       if (!(data = dm_pool_alloc(dm->mem, sizeof(*data)))) {
+               log_error("Failed to allocated path for callback.");
+               return 0;
+       }
+
+       data->dm = dm;
+       data->pool_lv = lv;
+
+       dm_tree_node_set_callback(node, _thin_pool_callback, data);
+
+       return 1;
+}
+
 /*
  * Add LV and any known dependencies
  */
@@ -1202,11 +1286,8 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
        uint32_t s;
        struct seg_list *sl;
        struct lv_segment *seg = first_seg(lv);
-#if 0
-       /* FIXME For dm_tree_node_skip_children optimisation below */
        struct dm_tree_node *thin_node;
        const char *uuid;
-#endif
 
        if ((!origin_only || lv_is_thin_volume(lv)) &&
            !_add_dev_to_dtree(dm, dtree, lv, NULL))
@@ -1263,6 +1344,12 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
                        return_0;
                if (!_add_dev_to_dtree(dm, dtree, lv, _thin_layer))
                        return_0;
+               /* If the partial tree is used for deactivation, setup callback */
+               if (!(uuid = build_dm_uuid(dm->mem, lv->lvid.s, _thin_layer)))
+                       return_0;
+               if ((thin_node = dm_tree_find_node_by_uuid(dtree, uuid)) &&
+                   !_thin_pool_register_callback(dm, thin_node, lv))
+                       return_0;
        }
 
        return 1;
@@ -1879,6 +1966,11 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
 
        dm_tree_node_set_read_ahead(dnode, read_ahead, read_ahead_flags);
 
+       /* Setup thin pool callback */
+       if (layer && lv_is_thin_pool(lv) &&
+           !_thin_pool_register_callback(dm, dnode, lv))
+               return_0;
+
        /* Add any LVs referencing a PVMOVE LV unless told not to */
        if (dm->track_pvmove_deps && (lv->status & PVMOVE))
                dm_list_iterate_items(sl, &lv->segs_using_this_lv)
index 0d47fb399c638407cf45fa82f3c46750cb3794a6..cdb8757d19694387fa75d8d22d435d9418ce13d4 100644 (file)
@@ -64,6 +64,7 @@
 #define DEFAULT_DMEVENTD_MONITOR 1
 #define DEFAULT_BACKGROUND_POLLING 1
 
+#define DEFAULT_THIN_CHECK_EXECUTABLE  "/sbin/thin_check -q"
 #define DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
 #define DEFAULT_THIN_POOL_MAX_METADATA_SIZE (16 * 1024 * 1024)  /* KB */
 #define DEFAULT_THIN_POOL_MIN_METADATA_SIZE 2048  /* KB */
This page took 0.047405 seconds and 5 git commands to generate.