master - tools: improve error message about VG name and select
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=ad4ca55543428f...
Commit: ad4ca55543428f909fde8ba03e88d355560fe320
Parent: 6247364caf69cce766efcc79d972f70b175c5938
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu May 19 15:06:56 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Thu May 19 15:06:56 2016 -0500
tools: improve error message about VG name and select
---
tools/toollib.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tools/toollib.c b/tools/toollib.c
index 4859ec0..17a29e0 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1979,7 +1979,7 @@ static int _resolve_duplicate_vgnames(struct cmd_context *cmd,
* is unknown.
*/
log_error("Multiple VGs found with the same name: skipping %s", sl->str);
- log_error("Use the VG UUID with --select vg_uuid=<uuid>");
+ log_error("Use --select vg_uuid=<uuid> in place of the VG name.");
dm_list_del(&sl->list);
ret = ECMD_FAILED;
}
6 years, 10 months
master - tests: test change of cache mode
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=6247364caf69cc...
Commit: 6247364caf69cce766efcc79d972f70b175c5938
Parent: 9c083d34af0bc3ce690b3086714dd812c6a15193
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu May 19 18:21:07 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu May 19 18:40:14 2016 +0200
tests: test change of cache mode
---
test/shell/lvchange-cache-mode.sh | 71 +++++++++++++++++++++++++++++++++++++
1 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/test/shell/lvchange-cache-mode.sh b/test/shell/lvchange-cache-mode.sh
new file mode 100644
index 0000000..8a056d6
--- /dev/null
+++ b/test/shell/lvchange-cache-mode.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+# Copyright (C) 2016 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+# Exercise changing of caching mode on both cache pool and cached LV.
+
+SKIP_WITH_LVMLOCKD=1
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+aux have_cache 1 3 0 || skip
+
+aux prepare_vg 2
+
+lvcreate --type cache-pool -L18 -n cpool $vg "$dev1"
+lvcreate -H -L14 -n $lv1 --cachemode writeback --cachesettings migration_threshold=204800 --cachepool $vg/cpool $vg "$dev2"
+
+#cat "$DM_DEV_DIR/$vg/$lv1" >/dev/null
+#aux delay_dev "$dev2" 300 1000 $(get first_extent_sector "$dev2"):
+
+#dmsetup status $vg-$lv1
+#dmsetup table $vg-$lv1
+
+for i in $(seq 1 10) ; do
+echo 3 >/proc/sys/vm/drop_caches
+dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=64K count=20 conv=fdatasync || true
+echo 3 >/proc/sys/vm/drop_caches
+dd if="$DM_DEV_DIR/$vg/$lv1" of=/dev/null bs=64K count=20 || true
+done
+
+lvs -o+cache_dirty_blocks,cache_read_hits,cache_read_misses,cache_write_hits,cache_write_misses $vg/$lv1
+
+vgcfgbackup -f /tmp/ooo $vg
+
+
+#
+# Drop later, code loading dm tables directly without lvm
+# RHBZ 1337588
+#
+#dmsetup table
+#echo "STATUS before cleaner"
+#dmsetup status
+#dmsetup load --table "0 28672 cache 253:4 253:3 253:5 128 1 writethrough cleaner 0" $vg-$lv1
+#dmsetup resume $vg-$lv1
+#sleep 1
+#dmsetup table
+#echo "STATUS after cleaner 1sec"
+#dmsetup status --noflush
+#dmsetup suspend --noflush $vg-$lv1
+#dmsetup resume $vg-$lv1
+
+#dmsetup load --table "0 28672 cache 253:4 253:3 253:5 128 1 passthrough smq 2 migration_threshold 204800" $vg-$lv1
+#dmsetup resume $vg-$lv1
+
+check lv_field $vg/$lv1 cache_mode "writeback"
+lvchange --cachemode passthrough $vg/$lv1
+check lv_field $vg/$lv1 cache_mode "passthrough"
+lvchange --cachemode writethrough $vg/$lv1
+check lv_field $vg/$lv1 cache_mode "writethrough"
+lvchange --cachemode writeback $vg/$lv1
+check lv_field $vg/$lv1 cache_mode "writeback"
+
+vgremove -f $vg
6 years, 10 months
master - debug: use display_lvname
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=9c083d34af0bc3...
Commit: 9c083d34af0bc3ce690b3086714dd812c6a15193
Parent: 197066c863607a884c0eef2f16d969aa00adcab1
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed May 18 15:22:26 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu May 19 18:40:14 2016 +0200
debug: use display_lvname
Add some tracing message
---
lib/activate/dev_manager.c | 2 ++
lib/format_text/import_vsn1.c | 5 ++++-
2 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index c07af2d..f6cc0be 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -2154,6 +2154,7 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
dm_list_iterate(snh, &lv->snapshot_segs)
if (!_add_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow, 0))
return_0;
+
if (dm->activation && !origin_only && lv_is_merging_origin(lv) &&
!_add_lv_to_dtree(dm, dtree, find_snapshot(lv)->lv, 1))
return_0;
@@ -3104,6 +3105,7 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
/* Some targets may build bigger tree for activation */
dm->activation = ((action == PRELOAD) || (action == ACTIVATE));
dm->suspend = (action == SUSPEND_WITH_LOCKFS) || (action == SUSPEND);
+
if (!(dtree = _create_partial_dtree(dm, lv, laopts->origin_only)))
return_0;
diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
index f9a1040..d2219e4 100644
--- a/lib/format_text/import_vsn1.c
+++ b/lib/format_text/import_vsn1.c
@@ -569,8 +569,11 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)),
if (!(lv->name = dm_pool_strdup(mem, lvn->key)))
return_0;
+ log_debug_metadata("Importing logical volume %s.", display_lvname(lv));
+
if (!(lvn = lvn->child)) {
- log_error("Empty logical volume section.");
+ log_error("Empty logical volume section for %s.",
+ display_lvname(lv));
return 0;
}
6 years, 10 months
master - lvchange: allow change of cache mode
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=197066c863607a...
Commit: 197066c863607a884c0eef2f16d969aa00adcab1
Parent: 8fd886f735125de4b3e32fc0a188af0192a0d173
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Apr 25 13:39:30 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu May 19 18:40:14 2016 +0200
lvchange: allow change of cache mode
Add support for active cache LV.
Handle --cachemode args validation during command line processing.
Rework some lvm2 internal to use lvm2 defined CACHE_MODE enums
indepently on libdm defines and use enum around the code instead
of passing and comparing strings.
---
WHATS_NEW | 1 +
lib/cache_segtype/cache.c | 61 ++++++++++++------
lib/metadata/cache_manip.c | 132 ++++++++++++++++++++++---------------
lib/metadata/merge.c | 21 +++----
lib/metadata/metadata-exported.h | 18 ++++--
lib/report/report.c | 13 +----
man/lvchange.8.in | 18 +++++
test/shell/lvconvert-cache.sh | 4 +-
tools/args.h | 2 +-
tools/commands.h | 4 +-
tools/lvchange.c | 50 +++++++++++---
tools/lvconvert.c | 8 +-
tools/lvmcmdline.c | 13 ++++
tools/toollib.c | 6 +-
tools/toollib.h | 2 +-
tools/tools.h | 1 +
16 files changed, 227 insertions(+), 127 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 9b9265c..645e87e 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.155 -
================================
+ Add support for lvchange --cachemode for cached LV.
Fix liblvm2app error handling when setting up context.
Delay liblvm2app init in python code until it is needed.
Simplify thread locking in lvmetad to fix locking problems.
diff --git a/lib/cache_segtype/cache.c b/lib/cache_segtype/cache.c
index 9d56f32..4fb06e7 100644
--- a/lib/cache_segtype/cache.c
+++ b/lib/cache_segtype/cache.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2013-2016 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -26,6 +26,8 @@
#include "defaults.h"
static const char _cache_module[] = "cache";
+#define CACHE_POLICY_WHEN_MISSING "mq"
+#define CACHE_MODE_WHEN_MISSING CACHE_MODE_WRITETHROUGH
/* TODO: using static field here, maybe should be a part of segment_type */
static unsigned _feature_mask;
@@ -41,24 +43,21 @@ static unsigned _feature_mask;
*
* Needs both segments cache and cache_pool to be loaded.
*/
-static int _fix_missing_defaults(struct lv_segment *cpool_seg)
+static void _fix_missing_defaults(struct lv_segment *cpool_seg)
{
if (!cpool_seg->policy_name) {
- cpool_seg->policy_name = "mq";
- log_verbose("Cache is missing cache policy, using %s.",
+ cpool_seg->policy_name = CACHE_POLICY_WHEN_MISSING;
+ log_verbose("Cache pool %s is missing cache policy, using %s.",
+ display_lvname(cpool_seg->lv),
cpool_seg->policy_name);
}
- if (!cache_mode_is_set(cpool_seg)) {
- if (!cache_set_mode(cpool_seg, "writethrough")) {
- log_error(INTERNAL_ERROR "Failed to writethrough cache mode.");
- return 0;
- }
- log_verbose("Cache is missing cache mode, using %s.",
+ if (cpool_seg->cache_mode == CACHE_MODE_UNDEFINED) {
+ cpool_seg->cache_mode = CACHE_MODE_WHEN_MISSING;
+ log_verbose("Cache pool %s is missing cache mode, using %s.",
+ display_lvname(cpool_seg->lv),
get_cache_mode_name(cpool_seg));
}
-
- return 1;
}
static int _cache_pool_text_import(struct lv_segment *seg,
@@ -97,7 +96,7 @@ static int _cache_pool_text_import(struct lv_segment *seg,
if (dm_config_has_node(sn, "cache_mode")) {
if (!(str = dm_config_find_str(sn, "cache_mode", NULL)))
return SEG_LOG_ERROR("cache_mode must be a string in");
- if (!cache_set_mode(seg, str))
+ if (!set_cache_mode(&seg->cache_mode, str))
return SEG_LOG_ERROR("Unknown cache_mode in");
}
@@ -141,9 +140,9 @@ static int _cache_pool_text_import(struct lv_segment *seg,
if (!attach_pool_metadata_lv(seg, meta_lv))
return_0;
- if (!dm_list_empty(&seg->lv->segs_using_this_lv) &&
- !_fix_missing_defaults(seg))
- return_0;
+ /* when cache pool is used, we require policy and mode to be defined */
+ if (!dm_list_empty(&seg->lv->segs_using_this_lv))
+ _fix_missing_defaults(seg);
return 1;
}
@@ -170,7 +169,7 @@ static int _cache_pool_text_export(const struct lv_segment *seg,
* but not worth to break backward compatibility, by shifting
* content to cache segment
*/
- if (cache_mode_is_set(seg)) {
+ if (seg->cache_mode != CACHE_MODE_UNDEFINED) {
if (!(cache_mode = get_cache_mode_name(seg)))
return_0;
outf(f, "cache_mode = \"%s\"", cache_mode);
@@ -358,9 +357,9 @@ static int _cache_text_import(struct lv_segment *seg,
if (!attach_pool_lv(seg, pool_lv, NULL, NULL, NULL))
return_0;
- if (!dm_list_empty(&pool_lv->segments) &&
- !_fix_missing_defaults(first_seg(pool_lv)))
- return_0;
+ /* load order is unknown, could be cache origin or pool LV, so check for both */
+ if (!dm_list_empty(&pool_lv->segments))
+ _fix_missing_defaults(first_seg(pool_lv));
return 1;
}
@@ -399,6 +398,7 @@ static int _cache_add_target_line(struct dev_manager *dm,
{
struct lv_segment *cache_pool_seg;
char *metadata_uuid, *data_uuid, *origin_uuid;
+ uint64_t feature_flags = 0;
if (!seg->pool_lv || !seg_is_cache(seg)) {
log_error(INTERNAL_ERROR "Passed segment is not cache.");
@@ -406,6 +406,25 @@ static int _cache_add_target_line(struct dev_manager *dm,
}
cache_pool_seg = first_seg(seg->pool_lv);
+ if (seg->cleaner_policy)
+ /* With cleaner policy always pass writethrough */
+ feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
+ else
+ switch (cache_pool_seg->cache_mode) {
+ default:
+ log_error(INTERNAL_ERROR "LV %s has unknown cache mode %d.",
+ display_lvname(seg->lv), cache_pool_seg->cache_mode);
+ /* Fall through */
+ case CACHE_MODE_WRITETHROUGH:
+ feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
+ break;
+ case CACHE_MODE_WRITEBACK:
+ feature_flags |= DM_CACHE_FEATURE_WRITEBACK;
+ break;
+ case CACHE_MODE_PASSTHROUGH:
+ feature_flags |= DM_CACHE_FEATURE_PASSTHROUGH;
+ break;
+ }
if (!(metadata_uuid = build_dm_uuid(mem, cache_pool_seg->metadata_lv, NULL)))
return_0;
@@ -417,7 +436,7 @@ static int _cache_add_target_line(struct dev_manager *dm,
return_0;
if (!dm_tree_node_add_cache_target(node, len,
- cache_pool_seg->feature_flags,
+ feature_flags,
metadata_uuid,
data_uuid,
origin_uuid,
diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
index 27a716a..a39549d 100644
--- a/lib/metadata/cache_manip.c
+++ b/lib/metadata/cache_manip.c
@@ -29,76 +29,91 @@
#define DM_HINT_OVERHEAD_PER_BLOCK 8 /* bytes */
#define DM_MAX_HINT_WIDTH (4+16) /* bytes. FIXME Configurable? */
-int cache_mode_is_set(const struct lv_segment *seg)
+const char *display_cache_mode(const struct lv_segment *seg)
{
if (seg_is_cache(seg))
seg = first_seg(seg->pool_lv);
- return (seg->feature_flags & (DM_CACHE_FEATURE_WRITEBACK |
- DM_CACHE_FEATURE_WRITETHROUGH |
- DM_CACHE_FEATURE_PASSTHROUGH)) ? 1 : 0;
+ if (!seg_is_cache_pool(seg) ||
+ (seg->cache_mode == CACHE_MODE_UNDEFINED))
+ return "";
+
+ return get_cache_mode_name(seg);
}
-const char *get_cache_mode_name(const struct lv_segment *seg)
-{
- if (seg->feature_flags & DM_CACHE_FEATURE_PASSTHROUGH)
- return "passthrough";
- if (seg->feature_flags & DM_CACHE_FEATURE_WRITEBACK)
+const char *get_cache_mode_name(const struct lv_segment *pool_seg)
+{
+ switch (pool_seg->cache_mode) {
+ default:
+ log_error(INTERNAL_ERROR "Cache pool %s has undefined cache mode, using writethrough instead.",
+ display_lvname(pool_seg->lv));
+ /* Fall through */
+ case CACHE_MODE_WRITETHROUGH:
+ return "writethrough";
+ case CACHE_MODE_WRITEBACK:
return "writeback";
+ case CACHE_MODE_PASSTHROUGH:
+ return "passthrough";
+ }
+}
- if (!(seg->feature_flags & DM_CACHE_FEATURE_WRITETHROUGH))
- log_error(INTERNAL_ERROR "LV %s has uknown feature flags %" PRIu64 ", "
- "returning writethrough instead.",
- display_lvname(seg->lv), seg->feature_flags);
+int set_cache_mode(cache_mode_t *mode, const char *cache_mode)
+{
+ if (!strcasecmp(cache_mode, "writethrough"))
+ *mode = CACHE_MODE_WRITETHROUGH;
+ else if (!strcasecmp(cache_mode, "writeback"))
+ *mode = CACHE_MODE_WRITEBACK;
+ else if (!strcasecmp(cache_mode, "passthrough"))
+ *mode = CACHE_MODE_PASSTHROUGH;
+ else {
+ log_error("Unknown cache mode: %s.", cache_mode);
+ return 0;
+ }
- return "writethrough";
+ return 1;
}
-int cache_set_mode(struct lv_segment *seg, const char *str)
+int cache_set_cache_mode(struct lv_segment *seg, cache_mode_t mode)
{
struct cmd_context *cmd = seg->lv->vg->cmd;
+ const char *str;
int id;
- uint64_t mode;
-
- if (!str && !seg_is_cache(seg))
- return 1; /* Defaults only for cache */
if (seg_is_cache(seg))
seg = first_seg(seg->pool_lv);
+ else if (seg_is_cache_pool(seg)) {
+ if (mode == CACHE_MODE_UNDEFINED)
+ return 1; /* Defaults only for cache */
+ } else {
+ log_error(INTERNAL_ERROR "Cannot set cache mode for non cache volume %s.",
+ display_lvname(seg->lv));
+ return 0;
+ }
- if (!str) {
- if (cache_mode_is_set(seg))
- return 1; /* Default already set in cache pool */
+ if (mode != CACHE_MODE_UNDEFINED) {
+ seg->cache_mode = mode;
+ return 1;
+ }
- id = allocation_cache_mode_CFG;
+ if (seg->cache_mode != CACHE_MODE_UNDEFINED)
+ return 1; /* Default already set in cache pool */
- /* If present, check backward compatible settings */
- if (!find_config_node(cmd, cmd->cft, id) &&
- find_config_node(cmd, cmd->cft, allocation_cache_pool_cachemode_CFG))
- id = allocation_cache_pool_cachemode_CFG;
+ /* Figure default settings from config/profiles */
+ id = allocation_cache_mode_CFG;
- if (!(str = find_config_tree_str(cmd, id, NULL))) {
- log_error(INTERNAL_ERROR "Cache mode is not determined.");
- return 0;
- }
- }
+ /* If present, check backward compatible settings */
+ if (!find_config_node(cmd, cmd->cft, id) &&
+ find_config_node(cmd, cmd->cft, allocation_cache_pool_cachemode_CFG))
+ id = allocation_cache_pool_cachemode_CFG;
- if (!strcmp(str, "writeback"))
- mode = DM_CACHE_FEATURE_WRITEBACK;
- else if (!strcmp(str, "writethrough"))
- mode = DM_CACHE_FEATURE_WRITETHROUGH;
- else if (!strcmp(str, "passthrough"))
- mode = DM_CACHE_FEATURE_PASSTHROUGH;
- else {
- log_error("Cannot set unknown cache mode \"%s\".", str);
+ if (!(str = find_config_tree_str(cmd, id, NULL))) {
+ log_error(INTERNAL_ERROR "Cache mode is not determined.");
return 0;
}
- seg->feature_flags &= ~(DM_CACHE_FEATURE_WRITEBACK |
- DM_CACHE_FEATURE_WRITETHROUGH |
- DM_CACHE_FEATURE_PASSTHROUGH);
- seg->feature_flags |= mode;
+ if (!(set_cache_mode(&seg->cache_mode, str)))
+ return_0;
return 1;
}
@@ -111,7 +126,7 @@ void cache_check_for_warns(const struct lv_segment *seg)
struct logical_volume *origin_lv = seg_lv(seg, 0);
if (lv_is_raid(origin_lv) &&
- first_seg(seg->pool_lv)->feature_flags & DM_CACHE_FEATURE_WRITEBACK)
+ first_seg(seg->pool_lv)->cache_mode == CACHE_MODE_WRITEBACK)
log_warn("WARNING: Data redundancy is lost with writeback "
"caching of raid logical volume!");
@@ -313,6 +328,7 @@ struct logical_volume *lv_cache_create(struct logical_volume *pool_lv,
*/
int lv_cache_wait_for_clean(struct logical_volume *cache_lv, int *is_clean)
{
+ const struct logical_volume *lock_lv = lv_lock_holder(cache_lv);
struct lv_segment *cache_seg = first_seg(cache_lv);
struct lv_status_cache *status;
int cleaner_policy;
@@ -326,7 +342,8 @@ int lv_cache_wait_for_clean(struct logical_volume *cache_lv, int *is_clean)
return_0;
if (status->cache->fail) {
dm_pool_destroy(status->mem);
- log_warn("WARNING: Skippping flush for failed cache.");
+ log_warn("WARNING: Skippping flush for failed cache %s.",
+ display_lvname(cache_lv));
return 1;
}
@@ -342,23 +359,31 @@ int lv_cache_wait_for_clean(struct logical_volume *cache_lv, int *is_clean)
if (!dirty_blocks)
break;
+ log_print_unless_silent("Flushing " FMTu64 " blocks for cache %s.",
+ dirty_blocks, display_lvname(cache_lv));
if (cleaner_policy) {
- log_print_unless_silent(FMTu64 " blocks must still be flushed.",
- dirty_blocks);
/* TODO: Use centralized place */
usleep(500000);
continue;
}
/* Switch to cleaner policy to flush the cache */
- log_print_unless_silent("Flushing cache for %s.",
- display_lvname(cache_lv));
cache_seg->cleaner_policy = 1;
/* Reaload kernel with "cleaner" policy */
if (!lv_update_and_reload_origin(cache_lv))
return_0;
}
+ /*
+ * TODO: add check if extra suspend resume is necessary
+ * ATM this is workaround for missing cache sync when cache gets clean
+ */
+ if (1) {
+ if (!lv_refresh_suspend_resume(lock_lv->vg->cmd, lock_lv))
+ return_0;
+ }
+
+ cache_seg->cleaner_policy = 0;
*is_clean = 1;
return 1;
@@ -401,8 +426,7 @@ int lv_cache_remove(struct logical_volume *cache_lv)
return 0;
}
/* For inactive writethrough just drop cache layer */
- if (first_seg(cache_seg->pool_lv)->feature_flags &
- DM_CACHE_FEATURE_WRITETHROUGH) {
+ if (first_seg(cache_seg->pool_lv)->cache_mode == CACHE_MODE_WRITETHROUGH) {
corigin_lv = seg_lv(cache_seg, 0);
if (!detach_pool_lv(cache_seg))
return_0;
@@ -636,14 +660,14 @@ out:
* to update all commonly specified cache parameters
*/
int cache_set_params(struct lv_segment *seg,
- const char *cache_mode,
+ cache_mode_t mode,
const char *policy_name,
const struct dm_config_tree *policy_settings,
uint32_t chunk_size)
{
struct lv_segment *pool_seg;
- if (!cache_set_mode(seg, cache_mode))
+ if (!cache_set_cache_mode(seg, mode))
return_0;
if (!cache_set_policy(seg, policy_name, policy_settings))
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 17227c1..4f730e0 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -223,18 +223,15 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
}
if (seg_is_cache_pool(seg) &&
!dm_list_empty(&seg->lv->segs_using_this_lv)) {
- switch (seg->feature_flags &
- (DM_CACHE_FEATURE_PASSTHROUGH |
- DM_CACHE_FEATURE_WRITETHROUGH |
- DM_CACHE_FEATURE_WRITEBACK)) {
- case DM_CACHE_FEATURE_PASSTHROUGH:
- case DM_CACHE_FEATURE_WRITETHROUGH:
- case DM_CACHE_FEATURE_WRITEBACK:
- break;
- default:
- log_error("LV %s has invalid cache's feature flag.",
- lv->name);
- inc_error_count;
+ switch (seg->cache_mode) {
+ case CACHE_MODE_WRITETHROUGH:
+ case CACHE_MODE_WRITEBACK:
+ case CACHE_MODE_PASSTHROUGH:
+ break;
+ default:
+ log_error("LV %s has invalid cache's feature flag.",
+ lv->name);
+ inc_error_count;
}
if (!seg->policy_name) {
log_error("LV %s is missing cache policy name.", lv->name);
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index b3f450a..a850492 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -274,6 +274,13 @@ typedef enum {
} thin_discards_t;
typedef enum {
+ CACHE_MODE_UNDEFINED = 0,
+ CACHE_MODE_WRITETHROUGH,
+ CACHE_MODE_WRITEBACK,
+ CACHE_MODE_PASSTHROUGH,
+} cache_mode_t;
+
+typedef enum {
LOCK_TYPE_INVALID = -1,
LOCK_TYPE_NONE = 0,
LOCK_TYPE_CLVM = 1,
@@ -472,7 +479,7 @@ struct lv_segment {
struct logical_volume *pool_lv; /* For thin, cache */
uint32_t device_id; /* For thin, 24bit */
- uint64_t feature_flags; /* For cache_pool */
+ cache_mode_t cache_mode; /* For cache_pool */
const char *policy_name; /* For cache_pool */
struct dm_config_node *policy_settings; /* For cache_pool */
unsigned cleaner_policy; /* For cache */
@@ -948,7 +955,7 @@ struct lvcreate_params {
uint32_t min_recovery_rate; /* RAID */
uint32_t max_recovery_rate; /* RAID */
- const char *cache_mode; /* cache */
+ cache_mode_t cache_mode; /* cache */
const char *policy_name; /* cache */
struct dm_config_tree *policy_settings; /* cache */
@@ -1211,13 +1218,14 @@ struct lv_status_cache {
dm_percent_t dirty_usage;
};
+const char *display_cache_mode(const struct lv_segment *seg);
const char *get_cache_mode_name(const struct lv_segment *cache_seg);
-int cache_mode_is_set(const struct lv_segment *seg);
-int cache_set_mode(struct lv_segment *cache_seg, const char *str);
+int set_cache_mode(cache_mode_t *mode, const char *cache_mode);
+int cache_set_cache_mode(struct lv_segment *cache_seg, cache_mode_t mode);
int cache_set_policy(struct lv_segment *cache_seg, const char *name,
const struct dm_config_tree *settings);
int cache_set_params(struct lv_segment *seg,
- const char *cache_mode,
+ cache_mode_t mode,
const char *policy_name,
const struct dm_config_tree *policy_settings,
uint32_t chunk_size);
diff --git a/lib/report/report.c b/lib/report/report.c
index 3a58cee..92eb64c 100644
--- a/lib/report/report.c
+++ b/lib/report/report.c
@@ -2504,19 +2504,8 @@ static int _cachemode_disp(struct dm_report *rh, struct dm_pool *mem,
const void *data, void *private)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
- const char *cachemode_str;
- if (seg_is_cache(seg))
- seg = first_seg(seg->pool_lv);
-
- if (seg_is_cache_pool(seg) && cache_mode_is_set(seg)) {
- if (!(cachemode_str = get_cache_mode_name(seg)))
- return_0;
-
- return _field_string(rh, field, cachemode_str);
- }
-
- return _field_set_value(field, "", NULL);
+ return _field_string(rh, field, display_cache_mode(seg));
}
static int _originsize_disp(struct dm_report *rh, struct dm_pool *mem,
diff --git a/man/lvchange.8.in b/man/lvchange.8.in
index 34ce583..2bfe7c0 100644
--- a/man/lvchange.8.in
+++ b/man/lvchange.8.in
@@ -25,6 +25,8 @@ lvchange \(em change attributes of a logical volume
.IR AllocationPolicy ]
.RB [ \-A | \-\-autobackup
.RB { y | n }]
+.RB [ \-\-cachemode
+.RB { passthrough | writeback | writethrough }]
.RB [ \-\-cachepolicy
.IR Policy ]
.RB [ \-\-cachesettings
@@ -186,6 +188,22 @@ the flag is attached, use \fBlvs\fP(8) command where the state
of the flag is reported within \fBlv_attr\fP bits.
.
.HP
+.BR \-\-cachemode
+.RB { passthrough | writeback | writethrough }
+.br
+Specifying a cache mode determines when the writes to a cache LV
+are considered complete. When \fBwriteback\fP is specified, a write is
+considered complete as soon as it is stored in the cache pool LV.
+If \fBwritethough\fP is specified, a write is considered complete only
+when it has been stored in the cache pool LV and on the origin LV.
+While \fBwritethrough\fP may be slower for writes, it is more
+resilient if something should happen to a device associated with the
+cache pool LV. With \fBpassthrough\fP mode, all reads are served
+from origin LV (all reads miss the cache) and all writes are
+forwarded to the origin LV; additionally, write hits cause cache
+block invalidates. See \fBlvmcache(7)\fP for more details.
+.
+.HP
.BR \-\-cachepolicy
.IR Policy ,
.BR \-\-cachesettings
diff --git a/test/shell/lvconvert-cache.sh b/test/shell/lvconvert-cache.sh
index 8e38050..cab5964 100644
--- a/test/shell/lvconvert-cache.sh
+++ b/test/shell/lvconvert-cache.sh
@@ -1,5 +1,5 @@
#!/bin/sh
-# Copyright (C) 2014-2015 Red Hat, Inc. All rights reserved.
+# Copyright (C) 2014-2016 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
@@ -39,7 +39,7 @@ lvcreate -an -Zn -L 8 -n $lv4 $vg
lvcreate -an -Zn -L 16 -n $lv5 $vg
# check validation of cachemode arg works
-fail lvconvert --yes --type cache-pool --cachemode writethroughX --cachepool $vg/$lv1
+invalid lvconvert --yes --type cache-pool --cachemode writethroughX --cachepool $vg/$lv1
# by default no cache settings are attached to converted cache-pool
lvconvert --yes --type cache-pool --chunksize 256 $vg/$lv1
diff --git a/tools/args.h b/tools/args.h
index ebddd2e..ef9dbc9 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -27,7 +27,7 @@ arg(atversion_ARG, '\0', "atversion", string_arg, 0)
arg(binary_ARG, '\0', "binary", NULL, 0)
arg(bootloaderareasize_ARG, '\0', "bootloaderareasize", size_mb_arg, 0)
arg(cache_long_ARG, '\0', "cache", NULL, 0)
-arg(cachemode_ARG, '\0', "cachemode", string_arg, 0)
+arg(cachemode_ARG, '\0', "cachemode", cachemode_arg, 0)
arg(cachepool_ARG, '\0', "cachepool", string_arg, 0)
arg(commandprofile_ARG, '\0', "commandprofile", string_arg, 0)
arg(config_ARG, '\0', "config", string_arg, 0)
diff --git a/tools/commands.h b/tools/commands.h
index 7b32835..da432a7 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -146,6 +146,7 @@ xx(lvchange,
"\t[--addtag <Tag>]\n"
"\t[--alloc <AllocationPolicy>]\n"
"\t[-C|--contiguous {y|n}]\n"
+ "\t[--cachemode <CacheMode>]\n"
"\t[--cachepolicy <policyname>] [--cachesettings <parameter=value>]\n"
"\t[--commandprofile <ProfileName>]\n"
"\t[-d|--debug]\n"
@@ -185,7 +186,8 @@ xx(lvchange,
"\t<LogicalVolume[Path]> [<LogicalVolume[Path]>...]\n",
activationmode_ARG, addtag_ARG, alloc_ARG, autobackup_ARG, activate_ARG,
- available_ARG, cachepolicy_ARG, cachesettings_ARG, contiguous_ARG, deltag_ARG,
+ available_ARG, cachemode_ARG, cachepolicy_ARG, cachesettings_ARG,
+ contiguous_ARG, deltag_ARG,
discards_ARG, detachprofile_ARG, errorwhenfull_ARG, force_ARG,
ignorelockingfailure_ARG, ignoremonitoring_ARG, ignoreactivationskip_ARG,
ignoreskippedcluster_ARG, major_ARG, metadataprofile_ARG, minor_ARG,
diff --git a/tools/lvchange.c b/tools/lvchange.c
index 83da6bc..c37a597 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -678,24 +678,50 @@ static int _lvchange_persistent(struct cmd_context *cmd,
return 1;
}
-static int _lvchange_cachepolicy(struct cmd_context *cmd, struct logical_volume *lv)
+static int _lvchange_cache(struct cmd_context *cmd, struct logical_volume *lv)
{
+ cache_mode_t mode;
const char *name;
struct dm_config_tree *settings = NULL;
- int r = 0;
-
- if (!lv_is_cache(lv) && !lv_is_cache_pool(lv)) {
- log_error("LV %s is not a cache LV.", lv->name);
- log_error("Only cache or cache pool devices can have --cachepolicy set.");
+ struct lv_segment *pool_seg = first_seg(lv);
+ int r = 0, is_clean;
+
+ if (lv_is_cache(lv))
+ pool_seg = first_seg(pool_seg->pool_lv);
+ else if (!lv_is_cache_pool(lv)) {
+ log_error("LV %s is not a cache LV.", display_lvname(lv));
+ (void) arg_from_list_is_set(cmd, "is supported only with cache or cache pool LVs",
+ cachemode_ARG,
+ cachepolicy_ARG,
+ cachesettings_ARG,
+ -1);
goto out;
}
- if (!get_cache_params(cmd, NULL, &name, &settings))
+ if (!get_cache_params(cmd, &mode, &name, &settings))
+ goto_out;
+
+ if ((mode != CACHE_MODE_UNDEFINED) &&
+ (mode != pool_seg->cache_mode)) {
+ if (!lv_cache_wait_for_clean(lv, &is_clean))
+ return_0;
+ if (!is_clean) {
+ log_error("Cache %s is not clean, refusing to switch cache mode.",
+ display_lvname(lv));
+ return 0;
+ }
+ }
+
+ if (mode && !cache_set_cache_mode(first_seg(lv), mode))
goto_out;
- if (!cache_set_policy(first_seg(lv), name, settings))
+
+ if ((name || settings) &&
+ !cache_set_policy(first_seg(lv), name, settings))
goto_out;
+
if (!lv_update_and_reload(lv))
goto_out;
+
r = 1;
out:
if (settings)
@@ -1135,15 +1161,16 @@ static int _lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
docmds++;
}
- if (arg_count(cmd, cachepolicy_ARG) || arg_count(cmd, cachesettings_ARG)) {
+ if (arg_is_set(cmd, cachemode_ARG) ||
+ arg_count(cmd, cachepolicy_ARG) || arg_count(cmd, cachesettings_ARG)) {
if (!archive(lv->vg))
return_ECMD_FAILED;
- doit += _lvchange_cachepolicy(cmd, lv);
+ doit += _lvchange_cache(cmd, lv);
docmds++;
}
if (doit)
- log_print_unless_silent("Logical volume \"%s\" changed.", lv->name);
+ log_print_unless_silent("Logical volume %s changed.", display_lvname(lv));
if (arg_count(cmd, resync_ARG) &&
!_lvchange_resync(cmd, lv))
@@ -1199,6 +1226,7 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv)
int update_partial_unsafe =
arg_from_list_is_set(cmd, NULL,
alloc_ARG,
+ cachemode_ARG,
cachepolicy_ARG,
cachesettings_ARG,
discards_ARG,
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index c544e36..39ce759 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -51,7 +51,7 @@ struct lvconvert_params {
uint32_t stripes;
uint32_t stripe_size;
uint32_t read_ahead;
- const char *cache_mode; /* cache */
+ cache_mode_t cache_mode; /* cache */
const char *policy_name; /* cache */
struct dm_config_tree *policy_settings; /* cache */
@@ -2024,7 +2024,7 @@ static int _lvconvert_uncache(struct cmd_context *cmd,
/* TODO: Check for failed cache as well to get prompting? */
if (lv_is_partial(lv)) {
- if (strcmp("writethrough", get_cache_mode_name(first_seg(seg->pool_lv)))) {
+ if (first_seg(seg->pool_lv)->cache_mode != CACHE_MODE_WRITETHROUGH) {
if (!lp->force) {
log_error("Conversion aborted.");
log_error("Cannot uncache writethrough cache volume %s without --force.",
@@ -3116,7 +3116,7 @@ mda_write:
seg->zero_new_blocks = lp->zero ? 1 : 0;
if (lp->cache_mode &&
- !cache_set_mode(seg, lp->cache_mode))
+ !cache_set_cache_mode(seg, lp->cache_mode))
return_0;
if ((lp->policy_name || lp->policy_settings) &&
@@ -3228,7 +3228,7 @@ static int _lvconvert_cache(struct cmd_context *cmd,
if (!(cache_lv = lv_cache_create(pool_lv, origin_lv)))
return_0;
- if (!cache_set_mode(first_seg(cache_lv), lp->cache_mode))
+ if (!cache_set_cache_mode(first_seg(cache_lv), lp->cache_mode))
return_0;
if (!cache_set_policy(first_seg(cache_lv), lp->policy_name, lp->policy_settings))
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index fa9cd8f..4009921 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -328,6 +328,19 @@ int activation_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_v
return 1;
}
+int cachemode_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av)
+{
+ cache_mode_t mode;
+
+ if (!set_cache_mode(&mode, av->value))
+ return_0;
+
+ av->i_value = mode;
+ av->ui_value = mode;
+
+ return 1;
+}
+
int discards_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av)
{
thin_discards_t discards;
diff --git a/tools/toollib.c b/tools/toollib.c
index ab1361d..4859ec0 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1334,7 +1334,7 @@ static int _validate_cachepool_params(const char *name,
}
int get_cache_params(struct cmd_context *cmd,
- const char **mode,
+ cache_mode_t *cache_mode,
const char **name,
struct dm_config_tree **settings)
{
@@ -1344,8 +1344,8 @@ int get_cache_params(struct cmd_context *cmd,
struct dm_config_node *cn;
int ok = 0;
- if (mode)
- *mode = arg_str_value(cmd, cachemode_ARG, NULL);
+ if (cache_mode)
+ *cache_mode = (cache_mode_t) arg_uint_value(cmd, cachemode_ARG, CACHE_MODE_UNDEFINED);
if (name)
*name = arg_str_value(cmd, cachepolicy_ARG, NULL);
diff --git a/tools/toollib.h b/tools/toollib.h
index 19f4dd0..2b3ca6e 100644
--- a/tools/toollib.h
+++ b/tools/toollib.h
@@ -194,7 +194,7 @@ int get_stripe_params(struct cmd_context *cmd, uint32_t *stripes,
uint32_t *stripe_size);
int get_cache_params(struct cmd_context *cmd,
- const char **mode,
+ cache_mode_t *cache_mode,
const char **name,
struct dm_config_tree **settings);
diff --git a/tools/tools.h b/tools/tools.h
index cfb79de..2abc750 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -133,6 +133,7 @@ void usage(const char *name);
/* the argument verify/normalise functions */
int yes_no_arg(struct cmd_context *cmd, struct arg_values *av);
int activation_arg(struct cmd_context *cmd, struct arg_values *av);
+int cachemode_arg(struct cmd_context *cmd, struct arg_values *av);
int discards_arg(struct cmd_context *cmd, struct arg_values *av);
int mirrorlog_arg(struct cmd_context *cmd, struct arg_values *av);
int size_kb_arg(struct cmd_context *cmd, struct arg_values *av);
6 years, 10 months
master - libdm: trace missing settings
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=8fd886f735125d...
Commit: 8fd886f735125de4b3e32fc0a188af0192a0d173
Parent: e8ba5c9bd4f8a1ff5d67b597c10eea3d176b27e1
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed May 18 15:23:08 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu May 19 18:27:34 2016 +0200
libdm: trace missing settings
These settings have been missed in very verbose log.
---
WHATS_NEW_DM | 1 +
libdm/libdm-config.c | 15 ++++++++++++---
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index d446997..165cb90 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -12,6 +12,7 @@ Version 1.02.124 - 30th April 2016
Version 1.02.123 - 23rd April 2016
==================================
+ Trace more settings in very verbose mode for libdm-config.
Do not strip LVM- when debug reporting not found uuid.
Version 1.02.122 - 9th April 2016
diff --git a/libdm/libdm-config.c b/libdm/libdm-config.c
index dcb7c3f..86955c5 100644
--- a/libdm/libdm-config.c
+++ b/libdm/libdm-config.c
@@ -1154,8 +1154,11 @@ int dm_config_get_uint32(const struct dm_config_node *cn, const char *path,
if (!n || !n->v || n->v->type != DM_CFG_INT)
return 0;
- if (result)
+ if (result) {
+ log_very_verbose("Setting %s to %u", path, (uint32_t) n->v->v.i);
*result = n->v->v.i;
+ }
+
return 1;
}
@@ -1169,8 +1172,11 @@ int dm_config_get_uint64(const struct dm_config_node *cn, const char *path,
if (!n || !n->v || n->v->type != DM_CFG_INT)
return 0;
- if (result)
+ if (result) {
+ log_very_verbose("Setting %s to " FMTu64 , path, (uint64_t) n->v->v.i);
*result = (uint64_t) n->v->v.i;
+ }
+
return 1;
}
@@ -1184,8 +1190,11 @@ int dm_config_get_str(const struct dm_config_node *cn, const char *path,
if (!n || !n->v || n->v->type != DM_CFG_STRING)
return 0;
- if (result)
+ if (result) {
+ log_very_verbose("Setting %s to %s", path, n->v->v.str);
*result = n->v->v.str;
+ }
+
return 1;
}
6 years, 10 months
master - libdm: cache status reports passthrough cache mode
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=e8ba5c9bd4f8a1...
Commit: e8ba5c9bd4f8a1ff5d67b597c10eea3d176b27e1
Parent: e694e0896bd4d320f5d5017411763583698b28dc
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu May 19 18:20:11 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu May 19 18:26:07 2016 +0200
libdm: cache status reports passthrough cache mode
Report passthrough mode instead of 'Unknown feature'.
---
WHATS_NEW_DM | 1 +
libdm/libdm-targets.c | 2 ++
2 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index b6703c7..d446997 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.126 -
================================
+ Report passthrough caching mode when parsing cache mode.
Version 1.02.125 - 14th May 2016
================================
diff --git a/libdm/libdm-targets.c b/libdm/libdm-targets.c
index b91c7e9..c94e057 100644
--- a/libdm/libdm-targets.c
+++ b/libdm/libdm-targets.c
@@ -256,6 +256,8 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
s->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
else if (!strncmp(p, "writeback ", 10))
s->feature_flags |= DM_CACHE_FEATURE_WRITEBACK;
+ else if (!strncmp(p, "passthrough ", 11))
+ s->feature_flags |= DM_CACHE_FEATURE_PASSTHROUGH;
else
log_error("Unknown feature in status: %s", params);
6 years, 10 months
master - WHATS_NEW: include recent changes
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=e694e0896bd4d3...
Commit: e694e0896bd4d320f5d5017411763583698b28dc
Parent: 591ef307b30c2d828b2a0c59918203f970974bbb
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed May 18 09:20:37 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed May 18 09:20:52 2016 -0500
WHATS_NEW: include recent changes
---
WHATS_NEW | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 618e3dc..9b9265c 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,11 @@
Version 2.02.155 -
================================
+ Fix liblvm2app error handling when setting up context.
+ Delay liblvm2app init in python code until it is needed.
+ Simplify thread locking in lvmetad to fix locking problems.
+ Allow pvremove -ff to remove a duplicate PV.
+ Fix lvm2-activation-generator to read lvm.conf without full command setup.
+ Allow a minimal context to be used in lvm2app for reading lvm.conf.
Version 2.02.154 - 14th May 2016
================================
6 years, 10 months
master - lvm2_activation_generator: don't create full context for liblvm2app
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=591ef307b30c2d...
Commit: 591ef307b30c2d828b2a0c59918203f970974bbb
Parent: 7fd4119d24eee55323e888dd78c70257d7c97a15
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue May 17 12:03:25 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed May 18 09:05:26 2016 -0500
lvm2_activation_generator: don't create full context for liblvm2app
Don't use lvm_init() to create a full command context, which
does a lot of command setup (like connecting to daemons), which
is unnecessary for simply reading a value from lvm.conf.
Passing a NULL context arg to the lvm_config_ function is now
allowed, in which case lvm.conf is read without doing lvm
command setup.
---
.../lvm2_activation_generator_systemd_red_hat.c | 12 +++---------
1 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/scripts/lvm2_activation_generator_systemd_red_hat.c b/scripts/lvm2_activation_generator_systemd_red_hat.c
index 62467bd..d83e721 100644
--- a/scripts/lvm2_activation_generator_systemd_red_hat.c
+++ b/scripts/lvm2_activation_generator_systemd_red_hat.c
@@ -69,16 +69,10 @@ static void kmsg(int log_level, const char *format, ...)
static void lvm_get_use_lvmetad_and_lvmpolld(int *use_lvmetad, int *use_lvmpolld)
{
- lvm_t lvm;
-
*use_lvmetad = *use_lvmpolld = 0;
- if (!(lvm = lvm_init(NULL))) {
- kmsg(LOG_ERR, "LVM: Failed to initialize library context for activation generator.\n");
- return;
- }
- *use_lvmetad = lvm_config_find_bool(lvm, LVM_CONF_USE_LVMETAD, 0);
- *use_lvmpolld = lvm_config_find_bool(lvm, LVM_CONF_USE_LVMPOLLD, 0);
- lvm_quit(lvm);
+
+ *use_lvmetad = lvm_config_find_bool(NULL, LVM_CONF_USE_LVMETAD, 0);
+ *use_lvmpolld = lvm_config_find_bool(NULL, LVM_CONF_USE_LVMPOLLD, 0);
}
static int register_unit_with_target(const char *dir, const char *unit, const char *target)
6 years, 10 months
master - liblvm: allow config settings to be read without full lvm cmd
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7fd4119d24eee5...
Commit: 7fd4119d24eee55323e888dd78c70257d7c97a15
Parent: ba9b7b69d9200d9d977089a0b813f508961fcbee
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue May 17 11:54:13 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed May 18 09:04:25 2016 -0500
liblvm: allow config settings to be read without full lvm cmd
A program may be using liblvm2app for simply checking a config
setting in lvm.conf. In this case, a full lvm context is not
needed, only cmd->cft (which are the config settings read from
lvm.conf).
lvm_config_find_bool() can now be passed a NULL lvm context
in which case it will only create cmd->cft, check the config
setting asked for, and destroy the cmd.
---
lib/commands/toolcontext.c | 43 +++++++++++++++++++++++++++++++++++++++++++
lib/commands/toolcontext.h | 8 ++++++++
liblvm/lvm_base.c | 23 ++++++++++++++++++++---
3 files changed, 71 insertions(+), 3 deletions(-)
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 90e5d5a..1e3f14a 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -1776,6 +1776,49 @@ bad:
return 0;
}
+void destroy_config_context(struct cmd_context *cmd)
+{
+ _destroy_config(cmd);
+
+ if (cmd->mem)
+ dm_pool_destroy(cmd->mem);
+ if (cmd->libmem)
+ dm_pool_destroy(cmd->libmem);
+
+ dm_free(cmd);
+}
+
+/*
+ * A "config context" is a very light weight toolcontext that
+ * is only used for reading config settings from lvm.conf.
+ */
+struct cmd_context *create_config_context(void)
+{
+ struct cmd_context *cmd;
+
+ if (!(cmd = dm_zalloc(sizeof(*cmd))))
+ goto_out;
+
+ strcpy(cmd->system_dir, DEFAULT_SYS_DIR);
+
+ if (!_get_env_vars(cmd))
+ goto_out;
+
+ if (!(cmd->libmem = dm_pool_create("library", 4 * 1024)))
+ goto_out;
+
+ dm_list_init(&cmd->config_files);
+
+ if (!_init_lvm_conf(cmd))
+ goto_out;
+
+ return cmd;
+out:
+ if (cmd)
+ destroy_config_context(cmd);
+ return NULL;
+}
+
/* Entry point */
struct cmd_context *create_toolcontext(unsigned is_long_lived,
const char *system_dir,
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index c3b9b2e..2cecf27 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -218,6 +218,14 @@ int init_lvmcache_orphans(struct cmd_context *cmd);
int init_filters(struct cmd_context *cmd, unsigned load_persistent_cache);
int init_connections(struct cmd_context *cmd);
+/*
+ * A config context is a very light weight cmd struct that
+ * is only used for reading config settings from lvm.conf,
+ * which are at cmd->cft.
+ */
+struct cmd_context *create_config_context(void);
+void destroy_config_context(struct cmd_context *cmd);
+
struct format_type *get_format_by_name(struct cmd_context *cmd, const char *format);
const char *system_id_from_string(struct cmd_context *cmd, const char *str);
diff --git a/liblvm/lvm_base.c b/liblvm/lvm_base.c
index 8b4def2..fce994c 100644
--- a/liblvm/lvm_base.c
+++ b/liblvm/lvm_base.c
@@ -126,14 +126,31 @@ int lvm_config_override(lvm_t libh, const char *config_settings)
return rc;
}
+/*
+ * When full lvm connection is not being used, libh can be NULL
+ * and this command will internally create a single-use, light-weight
+ * cmd struct that only has cmd->cft populated from lvm.conf.
+ */
int lvm_config_find_bool(lvm_t libh, const char *config_path, int fail)
{
int rc = 0;
- struct cmd_context *cmd = (struct cmd_context *)libh;
- struct saved_env e = store_user_env((struct cmd_context *)libh);
+ struct cmd_context *cmd;
+ struct saved_env e;
+
+ if (libh) {
+ cmd = (struct cmd_context *)libh;
+ e = store_user_env((struct cmd_context *)libh);
+ } else {
+ if (!(cmd = create_config_context()))
+ return 0;
+ }
rc = dm_config_tree_find_bool(cmd->cft, config_path, fail);
- restore_user_env(&e);
+
+ if (libh)
+ restore_user_env(&e);
+ else
+ destroy_config_context(cmd);
return rc;
}
6 years, 10 months
master - pvremove: allow clearing a duplicate PV
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=ba9b7b69d9200d...
Commit: ba9b7b69d9200d9d977089a0b813f508961fcbee
Parent: e0c22df5c41a8658dab953a413a679ceb5acd663
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu May 12 16:19:57 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Mon May 16 14:40:43 2016 -0500
pvremove: allow clearing a duplicate PV
Add a special case to allow modifying a duplicate PV
to erase it with pvremove -ff.
---
lib/cache/lvmcache.c | 13 +++++++++++++
lib/cache/lvmcache.h | 2 ++
tools/toollib.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 58 insertions(+), 2 deletions(-)
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index fe2ad07..0934b20 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -459,6 +459,19 @@ int lvmcache_get_unused_duplicate_devs(struct cmd_context *cmd, struct dm_list *
return 1;
}
+void lvmcache_remove_unchosen_duplicate(struct device *dev)
+{
+ struct device_list *devl;
+
+ dm_list_iterate_items(devl, &_unused_duplicate_devs) {
+ if (devl->dev == dev) {
+ dm_list_del(&devl->list);
+ return;
+ }
+ }
+}
+
+
static void _vginfo_attach_info(struct lvmcache_vginfo *vginfo,
struct lvmcache_info *info)
{
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index 45318b9..4fb74db 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -211,4 +211,6 @@ void lvmcache_lock_ordering(int enable);
int lvmcache_dev_is_unchosen_duplicate(struct device *dev);
+void lvmcache_remove_unchosen_duplicate(struct device *dev);
+
#endif
diff --git a/tools/toollib.c b/tools/toollib.c
index 429ab91..ab1361d 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -4199,6 +4199,7 @@ int pvcreate_each_device(struct cmd_context *cmd,
struct physical_volume *pv;
struct volume_group *orphan_vg;
struct lvmcache_info *info;
+ struct dm_list remove_duplicates;
struct dm_list arg_sort;
struct pv_list *pvl;
struct pv_list *vgpvl;
@@ -4210,6 +4211,7 @@ int pvcreate_each_device(struct cmd_context *cmd,
set_pv_notify(cmd);
+ dm_list_init(&remove_duplicates);
dm_list_init(&arg_sort);
handle->custom_handle = pp;
@@ -4295,6 +4297,23 @@ int pvcreate_each_device(struct cmd_context *cmd,
goto_bad;
/*
+ * Special case: pvremove -ff is allowed to clear a duplicate device in
+ * the unchosen duplicates list. PVs in the unchosen duplicates list
+ * won't be found by normal process_each searches -- they are not in
+ * lvmcache and can't be processed normally. We save them here and
+ * erase them below without going through the normal processing code.
+ */
+ if (pp->is_remove && (pp->force == DONT_PROMPT_OVERRIDE) &&
+ !dm_list_empty(&pp->arg_devices) && lvmcache_found_duplicate_pvs()) {
+ dm_list_iterate_items_safe(pd, pd2, &pp->arg_devices) {
+ if (lvmcache_dev_is_unchosen_duplicate(pd->dev)) {
+ log_debug("Found pvremove arg %s: device is a duplicate.", pd->name);
+ dm_list_move(&remove_duplicates, &pd->list);
+ }
+ }
+ }
+
+ /*
* Check if all arg_devices were found by process_each_pv.
*/
dm_list_iterate_items(pd, &pp->arg_devices)
@@ -4313,9 +4332,9 @@ int pvcreate_each_device(struct cmd_context *cmd,
goto_bad;
/*
- * The command cannot continue if there are no devices to create.
+ * The command cannot continue if there are no devices to process.
*/
- if (dm_list_empty(&pp->arg_process)) {
+ if (dm_list_empty(&pp->arg_process) && dm_list_empty(&remove_duplicates)) {
log_debug("No devices to process.");
goto bad;
}
@@ -4606,6 +4625,28 @@ do_command:
pd->name);
}
+ /*
+ * Special case: pvremove duplicate PVs (also see above).
+ */
+ dm_list_iterate_items_safe(pd, pd2, &remove_duplicates) {
+ if (!label_remove(pd->dev)) {
+ log_error("Failed to wipe existing label(s) on %s.", pd->name);
+ dm_list_move(&pp->arg_fail, &pd->list);
+ continue;
+ }
+
+ if (!lvmetad_pv_gone_by_dev(pd->dev, NULL)) {
+ log_error("Failed to remove PV %s from lvmetad.", pd->name);
+ dm_list_move(&pp->arg_fail, &pd->list);
+ continue;
+ }
+
+ lvmcache_remove_unchosen_duplicate(pd->dev);
+
+ log_print_unless_silent("Labels on physical volume \"%s\" successfully wiped.",
+ pd->name);
+ }
+
dm_list_iterate_items(pd, &pp->arg_fail)
log_debug("%s: command failed for %s.",
cmd->command->name, pd->name);
6 years, 10 months