mirror of
git://sourceware.org/git/lvm2.git
synced 2025-10-01 21:44:22 +03:00
Compare commits
57 Commits
dev-mcsont
...
v2_02_150
Author | SHA1 | Date | |
---|---|---|---|
|
3aab784aa5 | ||
|
af148a9d77 | ||
|
5cfa6cb347 | ||
|
74e704bb44 | ||
|
a09d65891f | ||
|
f40dfb48ad | ||
|
e6768997e1 | ||
|
ed0c779bd1 | ||
|
50866034a2 | ||
|
f2e59e05ed | ||
|
248f47d489 | ||
|
9ab53dddf5 | ||
|
8b2108e6b1 | ||
|
097a724bda | ||
|
e2d4f53c82 | ||
|
7dcbf1dfd0 | ||
|
f19ec0e36d | ||
|
55001ae9ec | ||
|
307ab2c179 | ||
|
07c25429e2 | ||
|
9be7bca4be | ||
|
0584e85736 | ||
|
261a85ced9 | ||
|
5b2227c2c1 | ||
|
7c1937f8df | ||
|
d4c03cf7b2 | ||
|
76fc41fb9d | ||
|
2d0d58b867 | ||
|
60befab773 | ||
|
42f04a0f77 | ||
|
9f28eb4c20 | ||
|
15d1824fac | ||
|
7ed5a65ee5 | ||
|
91d32f9d1b | ||
|
0e774d5ae7 | ||
|
c577984630 | ||
|
bc5376b151 | ||
|
5034bb8d18 | ||
|
b10253ab4d | ||
|
86db143307 | ||
|
fc7dacaa4c | ||
|
8bbec41bd4 | ||
|
fe7ae37f5e | ||
|
9a086a6607 | ||
|
06ef7ba876 | ||
|
8b258a005b | ||
|
52e0d0db44 | ||
|
8c27c52749 | ||
|
91bb202ded | ||
|
bc0372cf9d | ||
|
d6e8f18e4d | ||
|
b9d07f7a12 | ||
|
a5d53aec83 | ||
|
d243db5466 | ||
|
109b7e2095 | ||
|
37b548c6b5 | ||
|
6129d2e64d |
@@ -1 +1 @@
|
||||
1.02.121-git (2016-03-19)
|
||||
1.02.122-git (2016-04-09)
|
||||
|
19
WHATS_NEW
19
WHATS_NEW
@@ -1,5 +1,22 @@
|
||||
Version 2.02.148 -
|
||||
Version 2.02.150 - 9th April 2016
|
||||
=================================
|
||||
Avoid using flushing dm status ioctl when checking for usable DM device.
|
||||
Check for devices without LVM- uuid prefix only with kernels < 3.X.
|
||||
Reuse %FREE size aproximation with lvcreate -l%PVS thin-pool.
|
||||
Allow the lvmdump directory to exist already provided it is empty.
|
||||
Show lvconverted percentage with 2 decimal digits.
|
||||
Fix regression in suspend when repairing --type mirror (2.02.133).
|
||||
|
||||
Version 2.02.149 - 1st April 2016
|
||||
=================================
|
||||
Do not flush thin-pool when checking metadata fullness.
|
||||
Remove spurious error about no value in /sys/dev/block/major:minor/dm/uuid.
|
||||
Fix device mismatch detection for LV if persistent .cache file is used.
|
||||
Fix holder device not being found in /dev while sysfs has it during dev scan.
|
||||
|
||||
Version 2.02.148 - 26th March 2016
|
||||
==================================
|
||||
Introduce TARGET_NAME and MODULE NAME macros.
|
||||
Replace hard-coded module and target names with macros.
|
||||
Add pv_major and pv_minor report fields.
|
||||
Detect and warn about mismatch between devices used and assumed for an LV.
|
||||
|
@@ -1,5 +1,10 @@
|
||||
Version 1.02.121 -
|
||||
Version 1.02.122 - 9th April 2016
|
||||
=================================
|
||||
Change log_debug ioctl flags from single characters into words.
|
||||
|
||||
Version 1.02.121 - 26th March 2016
|
||||
==================================
|
||||
Adjust raid status function.
|
||||
|
||||
Version 1.02.120 - 11th March 2016
|
||||
==================================
|
||||
|
@@ -853,11 +853,14 @@ global {
|
||||
|
||||
# Configuration option global/use_lvmlockd.
|
||||
# Use lvmlockd for locking among hosts using LVM on shared storage.
|
||||
# See lvmlockd(8) for more information.
|
||||
# Applicable only if LVM is compiled with lockd support in which
|
||||
# case there is also lvmlockd(8) man page available for more
|
||||
# information.
|
||||
use_lvmlockd = 0
|
||||
|
||||
# Configuration option global/lvmlockd_lock_retries.
|
||||
# Retry lvmlockd lock requests this many times.
|
||||
# Applicable only if LVM is compiled with lockd support
|
||||
# This configuration option has an automatic default value.
|
||||
# lvmlockd_lock_retries = 3
|
||||
|
||||
@@ -867,7 +870,8 @@ global {
|
||||
# LVs have been created, the internal LV needs to be extended. lvcreate
|
||||
# will automatically extend the internal LV when needed by the amount
|
||||
# specified here. Setting this to 0 disables the automatic extension
|
||||
# and can cause lvcreate to fail.
|
||||
# and can cause lvcreate to fail. Applicable only if LVM is compiled
|
||||
# with lockd support
|
||||
# This configuration option has an automatic default value.
|
||||
# sanlock_lv_extend = 256
|
||||
|
||||
@@ -1014,6 +1018,7 @@ global {
|
||||
# a native systemd service, which allows it to be started on demand,
|
||||
# and to use its own control group. When this option is disabled, LVM
|
||||
# commands will supervise long running operations by forking themselves.
|
||||
# Applicable only if LVM is compiled with lvmpolld support.
|
||||
use_lvmpolld = @DEFAULT_USE_LVMPOLLD@
|
||||
|
||||
# Configuration option global/notify_dbus.
|
||||
|
@@ -51,6 +51,7 @@ local {
|
||||
# Configuration option local/host_id.
|
||||
# The lvmlockd sanlock host_id.
|
||||
# This must be unique among all hosts, and must be between 1 and 2000.
|
||||
# Applicable only if LVM is compiled with lockd support
|
||||
# This configuration option has an automatic default value.
|
||||
# host_id = 0
|
||||
}
|
||||
|
@@ -855,9 +855,9 @@ int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void dm_event_log_set(int debug_level, int use_syslog)
|
||||
void dm_event_log_set(int debug_log_level, int use_syslog)
|
||||
{
|
||||
_debug_level = debug_level;
|
||||
_debug_level = debug_log_level;
|
||||
_use_syslog = use_syslog;
|
||||
}
|
||||
|
||||
|
@@ -106,7 +106,7 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh);
|
||||
int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
|
||||
|
||||
/* Set debug level for logging, and whether to log on stdout/stderr or syslog */
|
||||
void dm_event_log_set(int debug_level, int use_syslog);
|
||||
void dm_event_log_set(int debug_log_level, int use_syslog);
|
||||
|
||||
/* Log messages acroding to current debug level */
|
||||
__attribute__((format(printf, 6, 0)))
|
||||
|
@@ -389,7 +389,7 @@ def round_size(size_bytes):
|
||||
return size_bytes + bs - remainder
|
||||
|
||||
|
||||
_ALLOWABLE_CH = string.ascii_letters + string.digits + '#+.:=@_\/%'
|
||||
_ALLOWABLE_CH = string.ascii_letters + string.digits + '#+-.:=@_\/%'
|
||||
_ALLOWABLE_CH_SET = set(_ALLOWABLE_CH)
|
||||
|
||||
_ALLOWABLE_VG_LV_CH = string.ascii_letters + string.digits + '.-_+'
|
||||
|
@@ -660,7 +660,7 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
/* New thin-pool has no layer, but -tpool suffix needs to be queried */
|
||||
if (!use_layer && lv_is_new_thin_pool(lv)) {
|
||||
/* Check if there isn't existing old thin pool mapping in the table */
|
||||
if (!dev_manager_info(cmd->mem, lv, NULL, 0, 0, &dminfo, NULL, NULL))
|
||||
if (!dev_manager_info(cmd, lv, NULL, 0, 0, &dminfo, NULL, NULL))
|
||||
return_0;
|
||||
if (!dminfo.exists)
|
||||
use_layer = 1;
|
||||
@@ -669,7 +669,7 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
if (seg_status)
|
||||
seg_status->seg = seg;
|
||||
|
||||
if (!dev_manager_info(cmd->mem, lv,
|
||||
if (!dev_manager_info(cmd, lv,
|
||||
(use_layer) ? lv_layer(lv) : NULL,
|
||||
with_open_count, with_read_ahead,
|
||||
&dminfo, (info) ? &info->read_ahead : NULL,
|
||||
@@ -1160,7 +1160,7 @@ int lv_thin_pool_transaction_id(const struct logical_volume *lv,
|
||||
if (!lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0))
|
||||
return 0;
|
||||
|
||||
log_debug_activation("Checking thin-pool percent for LV %s.",
|
||||
log_debug_activation("Checking thin-pool transaction id for LV %s.",
|
||||
display_lvname(lv));
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
@@ -1827,7 +1827,7 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
const struct logical_volume *lv_pre_to_free = NULL;
|
||||
struct logical_volume *lv_pre_tmp;
|
||||
struct seg_list *sl;
|
||||
struct lv_segment *snap_seg;
|
||||
struct lv_segment *snap_seg;
|
||||
struct lvinfo info;
|
||||
int r = 0, lockfs = 0, flush_required = 0;
|
||||
struct detached_lv_data detached;
|
||||
@@ -1933,6 +1933,16 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush is ATM required for the tested cases
|
||||
* NOTE: Mirror repair requires noflush for proper repair!
|
||||
* TODO: Relax this limiting condition further */
|
||||
if (!flush_required &&
|
||||
(lv_is_pvmove(lv) ||
|
||||
(!lv_is_mirror(lv) && !lv_is_thin_pool(lv) && !lv_is_thin_volume(lv)))) {
|
||||
log_debug("Requiring flush for LV %s.", display_lvname(lv));
|
||||
flush_required = 1;
|
||||
}
|
||||
|
||||
if (!monitor_dev_for_events(cmd, lv, laopts, 0))
|
||||
/* FIXME Consider aborting here */
|
||||
stack;
|
||||
|
@@ -337,13 +337,8 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
|
||||
* We avoid another system call if we can, but if a device is
|
||||
* dead, we have no choice but to look up the table too.
|
||||
*/
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_set_major_minor(dmt, MAJOR(dev->dev), MINOR(dev->dev), 1))
|
||||
goto_out;
|
||||
|
||||
if (activation_checks() && !dm_task_enable_checks(dmt))
|
||||
if (!(dmt = _setup_task(NULL, NULL, NULL, DM_DEVICE_TABLE,
|
||||
MAJOR(dev->dev), MINOR(dev->dev), 0)))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
@@ -384,13 +379,8 @@ static int _device_is_suspended(int major, int minor)
|
||||
struct dm_info info;
|
||||
int r = 0;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
|
||||
return 0;
|
||||
|
||||
if (!dm_task_set_major_minor(dmt, major, minor, 1))
|
||||
goto_out;
|
||||
|
||||
if (activation_checks() && !dm_task_enable_checks(dmt))
|
||||
if (!(dmt = _setup_task(NULL, NULL, NULL, DM_DEVICE_INFO,
|
||||
major, minor, 0)))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt) ||
|
||||
@@ -414,13 +404,8 @@ static int _ignore_suspended_snapshot_component(struct device *dev)
|
||||
int major1, minor1, major2, minor2;
|
||||
int r = 0;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_set_major_minor(dmt, MAJOR(dev->dev), MINOR(dev->dev), 1))
|
||||
goto_out;
|
||||
|
||||
if (activation_checks() && !dm_task_enable_checks(dmt))
|
||||
if (!(dmt = _setup_task(NULL, NULL, NULL, DM_DEVICE_TABLE,
|
||||
MAJOR(dev->dev), MINOR(dev->dev), 0)))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
@@ -466,32 +451,29 @@ static int _ignore_unusable_thins(struct device *dev)
|
||||
if (!(mem = dm_pool_create("unusable_thins", 128)))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
|
||||
goto_out;
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
goto_out;
|
||||
if (!dm_task_set_major_minor(dmt, MAJOR(dev->dev), MINOR(dev->dev), 1))
|
||||
if (!(dmt = _setup_task(NULL, NULL, NULL, DM_DEVICE_TABLE,
|
||||
MAJOR(dev->dev), MINOR(dev->dev), 0)))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
log_error("Failed to get state of mapped device.");
|
||||
goto out;
|
||||
}
|
||||
dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
||||
if (!params || sscanf(params, "%d:%d", &minor, &major) != 2) {
|
||||
if (!params || sscanf(params, "%d:%d", &major, &minor) != 2) {
|
||||
log_error("Failed to get thin-pool major:minor for thin device %d:%d.",
|
||||
(int)MAJOR(dev->dev), (int)MINOR(dev->dev));
|
||||
goto out;
|
||||
}
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
|
||||
if (!(dmt = _setup_task(NULL, NULL, NULL, DM_DEVICE_STATUS,
|
||||
major, minor, 0)))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_no_flush(dmt))
|
||||
log_warn("Can't set no_flush.");
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
goto_out;
|
||||
if (!dm_task_set_major_minor(dmt, minor, major, 1))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
log_error("Failed to get state of mapped device.");
|
||||
goto out;
|
||||
@@ -545,15 +527,14 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
|
||||
int only_error_target = 1;
|
||||
int r = 0;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_set_major_minor(dmt, MAJOR(dev->dev), MINOR(dev->dev), 1))
|
||||
if (!(dmt = _setup_task(NULL, NULL, NULL, DM_DEVICE_STATUS,
|
||||
MAJOR(dev->dev), MINOR(dev->dev), 0)))
|
||||
goto_out;
|
||||
|
||||
if (activation_checks() && !dm_task_enable_checks(dmt))
|
||||
goto_out;
|
||||
|
||||
/* Non-blocking status read */
|
||||
if (!dm_task_no_flush(dmt))
|
||||
log_warn("WARNING: Can't set no_flush for dm status.");
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
log_error("Failed to get state of mapped device");
|
||||
goto out;
|
||||
@@ -674,7 +655,32 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _info(const char *dlid, int with_open_count, int with_read_ahead,
|
||||
/*
|
||||
* If active LVs were activated by a version of LVM2 before 2.02.00 we must
|
||||
* perform additional checks to find them because they do not have the LVM-
|
||||
* prefix on their dm uuids.
|
||||
* As of 2.02.150, we've chosen to disable this compatibility arbitrarily if
|
||||
* we're running kernel version 3 or above.
|
||||
*/
|
||||
#define MIN_KERNEL_MAJOR 3
|
||||
|
||||
static int _original_uuid_format_check_required(struct cmd_context *cmd)
|
||||
{
|
||||
static int _kernel_major = 0;
|
||||
|
||||
if (!_kernel_major) {
|
||||
if ((sscanf(cmd->kernel_vsn, "%d", &_kernel_major) == 1) &&
|
||||
(_kernel_major >= MIN_KERNEL_MAJOR))
|
||||
log_debug_activation("Skipping checks for old devices without " UUID_PREFIX
|
||||
" dm uuid prefix (kernel vsn %d >= %d).", _kernel_major, MIN_KERNEL_MAJOR);
|
||||
else
|
||||
_kernel_major = -1;
|
||||
}
|
||||
|
||||
return (_kernel_major == -1);
|
||||
}
|
||||
|
||||
static int _info(struct cmd_context *cmd, const char *dlid, int with_open_count, int with_read_ahead,
|
||||
struct dm_info *dminfo, uint32_t *read_ahead,
|
||||
struct lv_seg_status *seg_status)
|
||||
{
|
||||
@@ -703,6 +709,10 @@ static int _info(const char *dlid, int with_open_count, int with_read_ahead,
|
||||
}
|
||||
}
|
||||
|
||||
/* Must we still check for the pre-2.02.00 dm uuid format? */
|
||||
if (!_original_uuid_format_check_required(cmd))
|
||||
return r;
|
||||
|
||||
/* Check for dlid before UUID_PREFIX was added */
|
||||
if ((r = _info_run(seg_status ? STATUS : INFO, NULL, dlid + sizeof(UUID_PREFIX) - 1,
|
||||
dminfo, read_ahead, seg_status, with_open_count,
|
||||
@@ -717,7 +727,7 @@ static int _info_by_dev(uint32_t major, uint32_t minor, struct dm_info *info)
|
||||
return _info_run(INFO, NULL, NULL, info, NULL, 0, 0, 0, major, minor);
|
||||
}
|
||||
|
||||
int dev_manager_info(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
int dev_manager_info(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
const char *layer,
|
||||
int with_open_count, int with_read_ahead,
|
||||
struct dm_info *dminfo, uint32_t *read_ahead,
|
||||
@@ -726,19 +736,19 @@ int dev_manager_info(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
char *dlid, *name;
|
||||
int r;
|
||||
|
||||
if (!(name = dm_build_dm_name(mem, lv->vg->name, lv->name, layer)))
|
||||
if (!(name = dm_build_dm_name(cmd->mem, lv->vg->name, lv->name, layer)))
|
||||
return_0;
|
||||
|
||||
if (!(dlid = build_dm_uuid(mem, lv, layer))) {
|
||||
if (!(dlid = build_dm_uuid(cmd->mem, lv, layer))) {
|
||||
r = 0;
|
||||
goto_out;
|
||||
}
|
||||
|
||||
log_debug_activation("Getting device info for %s [%s]", name, dlid);
|
||||
r = _info(dlid, with_open_count, with_read_ahead,
|
||||
r = _info(cmd, dlid, with_open_count, with_read_ahead,
|
||||
dminfo, read_ahead, seg_status);
|
||||
out:
|
||||
dm_pool_free(mem, name);
|
||||
dm_pool_free(cmd->mem, name);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -884,20 +894,22 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
char *params = NULL;
|
||||
const struct dm_list *segh = lv ? &lv->segments : NULL;
|
||||
struct lv_segment *seg = NULL;
|
||||
struct segment_type *segtype;
|
||||
int first_time = 1;
|
||||
dm_percent_t percent = DM_PERCENT_INVALID;
|
||||
|
||||
uint64_t total_numerator = 0, total_denominator = 0;
|
||||
struct segment_type *segtype;
|
||||
|
||||
*overall_percent = percent;
|
||||
|
||||
if (!(segtype = get_segtype_from_string(dm->cmd, target_type)))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task(name, dlid, event_nr,
|
||||
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS, 0, 0, 0)))
|
||||
return_0;
|
||||
|
||||
/* No freeze on overfilled thin-pool, read existing slightly outdated data */
|
||||
if (lv && lv_is_thin_pool(lv) &&
|
||||
if (segtype_is_thin(segtype) &&
|
||||
!dm_task_no_flush(dmt))
|
||||
log_warn("Can't set no_flush flag."); /* Non fatal */
|
||||
|
||||
@@ -926,9 +938,6 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
if (!type || !params)
|
||||
continue;
|
||||
|
||||
if (!(segtype = get_segtype_from_string(dm->cmd, target_type)))
|
||||
continue;
|
||||
|
||||
if (strcmp(type, target_type)) {
|
||||
/* If kernel's type isn't an exact match is it compatible? */
|
||||
if (!segtype->ops->target_status_compatible ||
|
||||
@@ -986,7 +995,8 @@ static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
|
||||
if (_percent_run(dm, NULL, dlid, target_type, wait, lv, percent,
|
||||
event_nr, fail_if_percent_unsupported))
|
||||
return 1;
|
||||
else if (_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
|
||||
else if (_original_uuid_format_check_required(dm->cmd) &&
|
||||
_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
|
||||
target_type, wait, lv, percent,
|
||||
event_nr, fail_if_percent_unsupported))
|
||||
return 1;
|
||||
@@ -1329,10 +1339,10 @@ int dev_manager_cache_status(struct dev_manager *dm,
|
||||
* ->target_percent() API is able to transfer only a single value.
|
||||
* Needs to be able to pass whole structure.
|
||||
*/
|
||||
if (!dm_get_status_cache(dm->mem, params, &((*status)->cache)))
|
||||
if (!dm_get_status_cache(dm->mem, params, &c))
|
||||
goto_out;
|
||||
|
||||
c = (*status)->cache;
|
||||
(*status)->cache = c;
|
||||
(*status)->mem = dm->mem; /* User has to destroy this mem pool later */
|
||||
if (c->fail || c->error) {
|
||||
(*status)->data_usage =
|
||||
@@ -1435,7 +1445,7 @@ int dev_manager_thin_percent(struct dev_manager *dm,
|
||||
return_0;
|
||||
|
||||
log_debug_activation("Getting device status percentage for %s", name);
|
||||
if (!(_percent(dm, name, dlid, "thin", 0,
|
||||
if (!(_percent(dm, name, dlid, TARGET_NAME_THIN, 0,
|
||||
(mapped) ? NULL : lv, percent, NULL, 1)))
|
||||
return_0;
|
||||
|
||||
@@ -1664,7 +1674,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
return_0;
|
||||
|
||||
log_debug_activation("Getting device info for %s [%s]", name, dlid);
|
||||
if (!_info(dlid, 1, 0, &info, NULL, NULL)) {
|
||||
if (!_info(dm->cmd, dlid, 1, 0, &info, NULL, NULL)) {
|
||||
log_error("Failed to get info for %s [%s].", name, dlid);
|
||||
return 0;
|
||||
}
|
||||
@@ -1862,8 +1872,8 @@ static int _pool_callback(struct dm_tree_node *node,
|
||||
log_sys_error("close", argv[args]);
|
||||
|
||||
if (ret == (int) DM_ARRAY_SIZE(buf)) {
|
||||
log_debug("%s skipped, detect empty disk header on %s.",
|
||||
argv[0], argv[args]);
|
||||
log_debug_activation("%s skipped, detect empty disk header on %s.",
|
||||
argv[0], argv[args]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -2188,7 +2198,7 @@ static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
return_NULL;
|
||||
|
||||
log_debug_activation("Getting device info for %s [%s]", name, dlid);
|
||||
if (!_info(dlid, 1, 0, &info, NULL, NULL)) {
|
||||
if (!_info(dm->cmd, dlid, 1, 0, &info, NULL, NULL)) {
|
||||
log_error("Failed to get info for %s [%s].", name, dlid);
|
||||
return 0;
|
||||
}
|
||||
@@ -3024,7 +3034,7 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
break;
|
||||
case SUSPEND:
|
||||
dm_tree_skip_lockfs(root);
|
||||
if (!dm->flush_required && !lv_is_pvmove(lv))
|
||||
if (!dm->flush_required)
|
||||
dm_tree_use_no_flush_suspend(root);
|
||||
/* Fall through */
|
||||
case SUSPEND_WITH_LOCKFS:
|
||||
@@ -3045,12 +3055,11 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
|
||||
if ((dm_tree_node_size_changed(root) < 0))
|
||||
dm->flush_required = 1;
|
||||
|
||||
/* Currently keep the code require flush for any
|
||||
* non 'thin pool/volume, mirror' or with any size change */
|
||||
if (!lv_is_thin_volume(lv) &&
|
||||
!lv_is_thin_pool(lv) &&
|
||||
(!lv_is_mirror(lv) || dm_tree_node_size_changed(root)))
|
||||
* non 'thin pool/volume' and size increase */
|
||||
else if (!lv_is_thin_volume(lv) &&
|
||||
!lv_is_thin_pool(lv) &&
|
||||
dm_tree_node_size_changed(root))
|
||||
dm->flush_required = 1;
|
||||
|
||||
if (action == ACTIVATE) {
|
||||
@@ -3095,6 +3104,8 @@ int dev_manager_activate(struct dev_manager *dm, const struct logical_volume *lv
|
||||
int dev_manager_preload(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
struct lv_activate_opts *laopts, int *flush_required)
|
||||
{
|
||||
dm->flush_required = *flush_required;
|
||||
|
||||
if (!_tree_action(dm, lv, laopts, PRELOAD))
|
||||
return_0;
|
||||
|
||||
|
@@ -45,11 +45,12 @@ void dev_manager_exit(void);
|
||||
* (eg, an origin is created before its snapshot, but is not
|
||||
* unsuspended until the snapshot is also created.)
|
||||
*/
|
||||
int dev_manager_info(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
int dev_manager_info(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
const char *layer,
|
||||
int with_open_count, int with_read_ahead,
|
||||
struct dm_info *dminfo, uint32_t *read_ahead,
|
||||
struct lv_seg_status *seg_status);
|
||||
|
||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
dm_percent_t *percent);
|
||||
|
2
lib/cache/lvmcache.c
vendored
2
lib/cache/lvmcache.c
vendored
@@ -1133,7 +1133,7 @@ struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct i
|
||||
}
|
||||
|
||||
const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
|
||||
const char *devname)
|
||||
const char *devname)
|
||||
{
|
||||
struct device *dev;
|
||||
struct label *label;
|
||||
|
2
lib/cache/lvmcache.h
vendored
2
lib/cache/lvmcache.h
vendored
@@ -108,7 +108,7 @@ const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgnam
|
||||
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
|
||||
unsigned *scan_done_once, uint64_t *label_sector);
|
||||
const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
|
||||
const char *dev_name);
|
||||
const char *devname);
|
||||
char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid);
|
||||
const char *lvmcache_vgname_from_info(struct lvmcache_info *info);
|
||||
int lvmcache_vgs_locked(void);
|
||||
|
@@ -856,10 +856,13 @@ cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL,
|
||||
|
||||
cfg(global_use_lvmlockd_CFG, "use_lvmlockd", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 124), NULL, 0, NULL,
|
||||
"Use lvmlockd for locking among hosts using LVM on shared storage.\n"
|
||||
"See lvmlockd(8) for more information.\n")
|
||||
"Applicable only if LVM is compiled with lockd support in which\n"
|
||||
"case there is also lvmlockd(8) man page available for more\n"
|
||||
"information.\n")
|
||||
|
||||
cfg(global_lvmlockd_lock_retries_CFG, "lvmlockd_lock_retries", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_LVMLOCKD_LOCK_RETRIES, vsn(2, 2, 125), NULL, 0, NULL,
|
||||
"Retry lvmlockd lock requests this many times.\n")
|
||||
"Retry lvmlockd lock requests this many times.\n"
|
||||
"Applicable only if LVM is compiled with lockd support\n")
|
||||
|
||||
cfg(global_sanlock_lv_extend_CFG, "sanlock_lv_extend", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_SANLOCK_LV_EXTEND_MB, vsn(2, 2, 124), NULL, 0, NULL,
|
||||
"Size in MiB to extend the internal LV holding sanlock locks.\n"
|
||||
@@ -867,7 +870,8 @@ cfg(global_sanlock_lv_extend_CFG, "sanlock_lv_extend", global_CFG_SECTION, CFG_D
|
||||
"LVs have been created, the internal LV needs to be extended. lvcreate\n"
|
||||
"will automatically extend the internal LV when needed by the amount\n"
|
||||
"specified here. Setting this to 0 disables the automatic extension\n"
|
||||
"and can cause lvcreate to fail.\n")
|
||||
"and can cause lvcreate to fail. Applicable only if LVM is compiled\n"
|
||||
"with lockd support\n")
|
||||
|
||||
cfg(global_thin_check_executable_CFG, "thin_check_executable", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, THIN_CHECK_CMD, vsn(2, 2, 94), "@THIN_CHECK_CMD@", 0, NULL,
|
||||
"The full path to the thin_check command.\n"
|
||||
@@ -993,7 +997,8 @@ cfg(global_use_lvmpolld_CFG, "use_lvmpolld", global_CFG_SECTION, 0, CFG_TYPE_BOO
|
||||
"manage the progress of ongoing operations. lvmpolld can be used as\n"
|
||||
"a native systemd service, which allows it to be started on demand,\n"
|
||||
"and to use its own control group. When this option is disabled, LVM\n"
|
||||
"commands will supervise long running operations by forking themselves.\n")
|
||||
"commands will supervise long running operations by forking themselves.\n"
|
||||
"Applicable only if LVM is compiled with lvmpolld support.\n")
|
||||
|
||||
cfg(global_notify_dbus_CFG, "notify_dbus", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_NOTIFY_DBUS, vsn(2, 2, 145), NULL, 0, NULL,
|
||||
"Enable D-Bus notification from LVM commands.\n"
|
||||
@@ -1779,6 +1784,7 @@ cfg_array(local_extra_system_ids_CFG, "extra_system_ids", local_CFG_SECTION, CFG
|
||||
|
||||
cfg(local_host_id_CFG, "host_id", local_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 124), NULL, 0, NULL,
|
||||
"The lvmlockd sanlock host_id.\n"
|
||||
"This must be unique among all hosts, and must be between 1 and 2000.\n")
|
||||
"This must be unique among all hosts, and must be between 1 and 2000.\n"
|
||||
"Applicable only if LVM is compiled with lockd support\n")
|
||||
|
||||
cfg(CFG_COUNT, NULL, root_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL, 0, NULL, NULL)
|
||||
|
@@ -42,6 +42,7 @@ static struct {
|
||||
struct dm_hash_table *names;
|
||||
struct dm_hash_table *vgid_index;
|
||||
struct dm_hash_table *lvid_index;
|
||||
struct btree *sysfs_only_devices; /* see comments in _get_device_for_sysfs_dev_name_using_devno */
|
||||
struct btree *devices;
|
||||
struct dm_regex *preferred_names_matcher;
|
||||
const char *dev_dir;
|
||||
@@ -362,7 +363,7 @@ static int _add_alias(struct device *dev, const char *path)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _get_sysfs_value(const char *path, char *buf, size_t buf_size)
|
||||
static int _get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value)
|
||||
{
|
||||
FILE *fp;
|
||||
size_t len;
|
||||
@@ -379,8 +380,10 @@ static int _get_sysfs_value(const char *path, char *buf, size_t buf_size)
|
||||
}
|
||||
|
||||
if (!(len = strlen(buf)) || (len == 1 && buf[0] == '\n')) {
|
||||
log_error("_get_sysfs_value: %s: no value", path);
|
||||
goto out;
|
||||
if (error_if_no_value) {
|
||||
log_error("_get_sysfs_value: %s: no value", path);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf[len - 1] == '\n')
|
||||
@@ -403,7 +406,7 @@ static int _get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int mi
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _get_sysfs_value(path, buf, buf_size);
|
||||
return _get_sysfs_value(path, buf, buf_size, 0);
|
||||
}
|
||||
|
||||
static struct dm_list *_get_or_add_list_by_index_key(struct dm_hash_table *idx, const char *key)
|
||||
@@ -428,26 +431,80 @@ static struct dm_list *_get_or_add_list_by_index_key(struct dm_hash_table *idx,
|
||||
return list;
|
||||
}
|
||||
|
||||
static struct device *_insert_sysfs_dev(dev_t devno, const char *devname)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char *path_copy;
|
||||
struct device *dev;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s%s", _cache.dev_dir, devname) < 0) {
|
||||
log_error("_insert_sysfs_dev: %s: dm_snprintf failed", devname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(dev = _dev_create(devno)))
|
||||
return_NULL;
|
||||
|
||||
if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
|
||||
log_error("_insert_sysfs_dev: %s: dm_pool_strdup failed", devname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_add_alias(dev, path_copy)) {
|
||||
log_error("Couldn't add alias to dev cache.");
|
||||
_free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!btree_insert(_cache.sysfs_only_devices, (uint32_t) devno, dev)) {
|
||||
log_error("Couldn't add device to binary tree of sysfs-only devices in dev cache.");
|
||||
_free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
static struct device *_get_device_for_sysfs_dev_name_using_devno(const char *devname)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char buf[PATH_MAX];
|
||||
int major, minor;
|
||||
dev_t devno;
|
||||
struct device *dev;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%sblock/%s/dev", dm_sysfs_dir(), devname) < 0) {
|
||||
log_error("_get_device_for_non_dm_dev: %s: dm_snprintf failed", devname);
|
||||
log_error("_get_device_for_sysfs_dev_name_using_devno: %s: dm_snprintf failed", devname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_get_sysfs_value(path, buf, sizeof(buf)))
|
||||
if (!_get_sysfs_value(path, buf, sizeof(buf), 1))
|
||||
return_NULL;
|
||||
|
||||
if (sscanf(buf, "%d:%d", &major, &minor) != 2) {
|
||||
log_error("_get_device_for_non_dm_dev: %s: failed to get major and minor number", devname);
|
||||
log_error("_get_device_for_sysfs_dev_name_using_devno: %s: failed to get major and minor number", devname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (struct device *) btree_lookup(_cache.devices, (uint32_t) MKDEV(major, minor));
|
||||
devno = MKDEV(major, minor);
|
||||
if (!(dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) devno))) {
|
||||
/*
|
||||
* If we get here, it means the device is referenced in sysfs, but it's not yet in /dev.
|
||||
* This may happen in some rare cases right after LVs get created - we sync with udev
|
||||
* (or alternatively we create /dev content ourselves) while VG lock is held. However,
|
||||
* dev scan is done without VG lock so devices may already be in sysfs, but /dev may
|
||||
* not be updated yet if we call LVM command right after LV creation. This is not a
|
||||
* problem with devtmpfs as there's at least kernel name for device in /dev as soon
|
||||
* as the sysfs item exists, but we still support environments without devtmpfs or
|
||||
* where different directory for dev nodes is used (e.g. our test suite). So track
|
||||
* such devices in _cache.sysfs_only_devices hash for the vgid/lvid check to work still.
|
||||
*/
|
||||
if (!(dev = (struct device *) btree_lookup(_cache.sysfs_only_devices, (uint32_t) devno)) &&
|
||||
!(dev = _insert_sysfs_dev(devno, devname)))
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
#define NOT_LVM_UUID "-"
|
||||
@@ -494,6 +551,10 @@ static int _index_dev_by_vgid_and_lvid(struct device *dev)
|
||||
struct device_list *dl_vgid, *dl_lvid;
|
||||
int r = 0;
|
||||
|
||||
if (dev->flags & DEV_USED_FOR_LV)
|
||||
/* already indexed */
|
||||
return 1;
|
||||
|
||||
/* Get holders for device. */
|
||||
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/holders/", dm_sysfs_dir(), (int) MAJOR(dev->dev), (int) MINOR(dev->dev)) < 0) {
|
||||
log_error("%s: dm_snprintf failed for path to holders directory.", devname);
|
||||
@@ -623,14 +684,15 @@ static int _insert_dev(const char *path, dev_t d)
|
||||
}
|
||||
|
||||
/* is this device already registered ? */
|
||||
if (!(dev = (struct device *) btree_lookup(_cache.devices,
|
||||
(uint32_t) d))) {
|
||||
/* create new device */
|
||||
if (loopfile) {
|
||||
if (!(dev = dev_create_file(path, NULL, NULL, 0)))
|
||||
if (!(dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) d))) {
|
||||
if (!(dev = (struct device *) btree_lookup(_cache.sysfs_only_devices, (uint32_t) d))) {
|
||||
/* create new device */
|
||||
if (loopfile) {
|
||||
if (!(dev = dev_create_file(path, NULL, NULL, 0)))
|
||||
return_0;
|
||||
} else if (!(dev = _dev_create(d)))
|
||||
return_0;
|
||||
} else if (!(dev = _dev_create(d)))
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!(btree_insert(_cache.devices, (uint32_t) d, dev))) {
|
||||
log_error("Couldn't insert device into binary tree.");
|
||||
@@ -738,6 +800,108 @@ static int _insert_file(const char *path)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _dev_cache_iterate_devs_for_index(void)
|
||||
{
|
||||
struct btree_iter *iter = btree_first(_cache.devices);
|
||||
struct device *dev;
|
||||
int r = 1;
|
||||
|
||||
while (iter) {
|
||||
dev = btree_get_data(iter);
|
||||
|
||||
if (!_index_dev_by_vgid_and_lvid(dev))
|
||||
r = 0;
|
||||
|
||||
iter = btree_next(iter);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _dev_cache_iterate_sysfs_for_index(const char *path)
|
||||
{
|
||||
char devname[PATH_MAX];
|
||||
DIR *d;
|
||||
struct dirent *dirent;
|
||||
int major, minor;
|
||||
dev_t devno;
|
||||
struct device *dev;
|
||||
int partial_failure = 0;
|
||||
int r = 0;
|
||||
|
||||
if (!(d = opendir(path))) {
|
||||
log_sys_error("opendir", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((dirent = readdir(d))) {
|
||||
if (!strcmp(".", dirent->d_name) ||
|
||||
!strcmp("..", dirent->d_name))
|
||||
continue;
|
||||
|
||||
if (sscanf(dirent->d_name, "%d:%d", &major, &minor) != 2) {
|
||||
log_error("_dev_cache_iterate_sysfs_for_index: %s: failed "
|
||||
"to get major and minor number", dirent->d_name);
|
||||
partial_failure = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
devno = MKDEV(major, minor);
|
||||
if (!(dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) devno)) &&
|
||||
!(dev = (struct device *) btree_lookup(_cache.sysfs_only_devices, (uint32_t) devno))) {
|
||||
if (!dm_device_get_name(major, minor, 1, devname, sizeof(devname)) ||
|
||||
!(dev = _insert_sysfs_dev(devno, devname))) {
|
||||
partial_failure = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_index_dev_by_vgid_and_lvid(dev))
|
||||
partial_failure = 1;
|
||||
}
|
||||
|
||||
r = !partial_failure;
|
||||
|
||||
if (closedir(d))
|
||||
log_sys_error("closedir", path);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int dev_cache_index_devs(void)
|
||||
{
|
||||
static int sysfs_has_dev_block = -1;
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%sdev/block", dm_sysfs_dir()) < 0) {
|
||||
log_error("dev_cache_index_devs: dm_snprintf failed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip indexing if /sys/dev/block is not available.*/
|
||||
if (sysfs_has_dev_block == -1) {
|
||||
struct stat info;
|
||||
if (stat(path, &info) == 0)
|
||||
sysfs_has_dev_block = 1;
|
||||
else {
|
||||
if (errno == ENOENT) {
|
||||
sysfs_has_dev_block = 0;
|
||||
return 1;
|
||||
} else {
|
||||
log_sys_error("stat", path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if (!sysfs_has_dev_block)
|
||||
return 1;
|
||||
|
||||
int with_udev = obtain_device_list_from_udev() &&
|
||||
udev_get_library_context();
|
||||
|
||||
return with_udev ? _dev_cache_iterate_devs_for_index()
|
||||
: _dev_cache_iterate_sysfs_for_index(path);
|
||||
}
|
||||
|
||||
#ifdef UDEV_SYNC_SUPPORT
|
||||
|
||||
static int _device_in_udev_db(const dev_t d)
|
||||
@@ -815,24 +979,6 @@ bad:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _add_devs_to_index(void)
|
||||
{
|
||||
struct btree_iter *iter = btree_first(_cache.devices);
|
||||
struct device *dev;
|
||||
int r = 1;
|
||||
|
||||
while (iter) {
|
||||
dev = btree_get_data(iter);
|
||||
|
||||
if (!_index_dev_by_vgid_and_lvid(dev))
|
||||
r = 0;
|
||||
|
||||
iter = btree_next(iter);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void _insert_dirs(struct dm_list *dirs)
|
||||
{
|
||||
struct dir_list *dl;
|
||||
@@ -854,7 +1000,7 @@ static void _insert_dirs(struct dm_list *dirs)
|
||||
"device cache fully", dl->dir);
|
||||
}
|
||||
|
||||
(void) _add_devs_to_index();
|
||||
(void) dev_cache_index_devs();
|
||||
}
|
||||
|
||||
#else /* UDEV_SYNC_SUPPORT */
|
||||
@@ -1029,6 +1175,11 @@ int dev_cache_init(struct cmd_context *cmd)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(_cache.sysfs_only_devices = btree_create(_cache.mem))) {
|
||||
log_error("Couldn't create binary tree for sysfs-only devices in dev cache.");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(_cache.dev_dir = _strdup(cmd->dev_dir))) {
|
||||
log_error("strdup dev_dir failed.");
|
||||
goto bad;
|
||||
|
@@ -31,6 +31,7 @@ struct dev_filter {
|
||||
unsigned use_count;
|
||||
};
|
||||
|
||||
int dev_cache_index_devs(void);
|
||||
struct dm_list *dev_cache_get_dev_list_for_vgid(const char *vgid);
|
||||
struct dm_list *dev_cache_get_dev_list_for_lvid(const char *lvid);
|
||||
|
||||
|
@@ -129,6 +129,8 @@ int persistent_filter_load(struct dev_filter *f, struct dm_config_tree **cft_out
|
||||
if (dm_hash_get_num_entries(pf->devices)) {
|
||||
/* We populated dev_cache ourselves */
|
||||
dev_cache_scan(0);
|
||||
if (!dev_cache_index_devs())
|
||||
stack;
|
||||
r = 1;
|
||||
}
|
||||
|
||||
|
@@ -1061,7 +1061,7 @@ struct lv_segment *get_only_segment_using_this_lv(const struct logical_volume *l
|
||||
* Useful functions for managing snapshots.
|
||||
*/
|
||||
int lv_is_origin(const struct logical_volume *lv);
|
||||
int lv_is_thin_origin(const struct logical_volume *lv, unsigned *snapshot_count);
|
||||
int lv_is_thin_origin(const struct logical_volume *lv, unsigned *snap_count);
|
||||
int lv_is_cache_origin(const struct logical_volume *lv);
|
||||
int lv_is_cow(const struct logical_volume *lv);
|
||||
int lv_is_merging_cow(const struct logical_volume *cow);
|
||||
|
@@ -66,7 +66,7 @@ bad:
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct udev* udev_get_library_context(void)
|
||||
void *udev_get_library_context(void)
|
||||
{
|
||||
return _udev;
|
||||
}
|
||||
@@ -78,6 +78,11 @@ int udev_init_library_context(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *udev_get_library_context(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void udev_fin_library_context(void)
|
||||
{
|
||||
}
|
||||
|
@@ -16,12 +16,8 @@
|
||||
#ifndef _LVM_WRAPPERS_H
|
||||
#define _LVM_WRAPPERS_H
|
||||
|
||||
#ifdef UDEV_SYNC_SUPPORT
|
||||
struct udev;
|
||||
struct udev *udev_get_library_context(void);
|
||||
#endif
|
||||
|
||||
int udev_init_library_context(void);
|
||||
void *udev_get_library_context(void);
|
||||
void udev_fin_library_context(void);
|
||||
int udev_is_running(void);
|
||||
|
||||
|
@@ -3667,7 +3667,6 @@ static const struct dm_report_object_type _report_types[] = {
|
||||
{ PVS, "Physical Volume", "pv_", _obj_get_pv },
|
||||
{ LABEL, "Physical Volume Label", "pv_", _obj_get_label },
|
||||
{ SEGS, "Logical Volume Segment", "seg_", _obj_get_seg },
|
||||
{ SEGSSTATUS, "Logical Volume Device Segment Status", "seg_", _obj_get_lv_with_info_and_seg_status },
|
||||
{ PVSEGS, "Physical Volume Segment", "pvseg_", _obj_get_pvseg },
|
||||
{ 0, "", "", NULL },
|
||||
};
|
||||
|
@@ -28,10 +28,9 @@ typedef enum {
|
||||
PVS = 16,
|
||||
VGS = 32,
|
||||
SEGS = 64,
|
||||
SEGSSTATUS = 128,
|
||||
PVSEGS = 256,
|
||||
LABEL = 512,
|
||||
DEVTYPES = 1024
|
||||
PVSEGS = 128,
|
||||
LABEL = 256,
|
||||
DEVTYPES = 512
|
||||
} report_type_t;
|
||||
|
||||
/*
|
||||
|
@@ -1814,7 +1814,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
|
||||
}
|
||||
|
||||
log_debug_activation("dm %s %s%s %s%s%s %s%.0d%s%.0d%s"
|
||||
"%s%c%c%s%s%s%s%s%s%s %.0" PRIu64 " %s [%u] (*%u)",
|
||||
"%s[ %s%s%s%s%s%s%s%s%s] %.0" PRIu64 " %s [%u] (*%u)",
|
||||
_cmd_data_v4[dmt->type].name,
|
||||
dmt->new_uuid ? "UUID " : "",
|
||||
dmi->name, dmi->uuid, dmt->newname ? " " : "",
|
||||
@@ -1825,15 +1825,15 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
|
||||
dmt->minor > 0 ? dmt->minor : 0,
|
||||
dmt->major > 0 && dmt->minor == 0 ? "0" : "",
|
||||
dmt->major > 0 ? ") " : "",
|
||||
dmt->no_open_count ? 'N' : 'O',
|
||||
dmt->no_flush ? 'N' : 'F',
|
||||
dmt->read_only ? "R" : "",
|
||||
dmt->skip_lockfs ? "S " : "",
|
||||
dmt->retry_remove ? "T " : "",
|
||||
dmt->deferred_remove ? "D " : "",
|
||||
dmt->secure_data ? "W " : "",
|
||||
dmt->query_inactive_table ? "I " : "",
|
||||
dmt->enable_checks ? "C" : "",
|
||||
dmt->no_open_count ? "noopencount " : "opencount ",
|
||||
dmt->no_flush ? "noflush " : "flush ",
|
||||
dmt->read_only ? "readonly " : "",
|
||||
dmt->skip_lockfs ? "skiplockfs " : "",
|
||||
dmt->retry_remove ? "retryremove " : "",
|
||||
dmt->deferred_remove ? "deferredremove " : "",
|
||||
dmt->secure_data ? "securedata " : "",
|
||||
dmt->query_inactive_table ? "inactive " : "",
|
||||
dmt->enable_checks ? "enablechecks " : "",
|
||||
dmt->sector, _sanitise_message(dmt->message),
|
||||
dmi->data_size, retry_repeat_count);
|
||||
#ifdef DM_IOCTLS
|
||||
|
@@ -321,8 +321,8 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
|
||||
/* Parse params from STATUS call for raid target */
|
||||
struct dm_status_raid {
|
||||
uint64_t reserved;
|
||||
uint64_t total_regions;
|
||||
uint64_t insync_regions;
|
||||
uint64_t total_regions; /* sectors */
|
||||
uint64_t insync_regions; /* sectors */
|
||||
uint64_t mismatch_count;
|
||||
uint32_t dev_count;
|
||||
char *raid_type;
|
||||
|
@@ -4175,6 +4175,11 @@ static int _sort_rows(struct dm_report *rh)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define STANDARD_QUOTE "\'"
|
||||
#define STANDARD_PAIR "="
|
||||
|
||||
#define UNABLE_TO_EXTEND_OUTPUT_LINE_MSG "dm_report: Unable to extend output line"
|
||||
|
||||
/*
|
||||
* Produce report output
|
||||
*/
|
||||
@@ -4196,27 +4201,27 @@ static int _output_field(struct dm_report *rh, struct dm_report_field *field)
|
||||
}
|
||||
|
||||
if (!dm_pool_grow_object(rh->mem, rh->output_field_name_prefix, 0)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
dm_free(field_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_pool_grow_object(rh->mem, _toupperstr(field_id), 0)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
dm_free(field_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dm_free(field_id);
|
||||
|
||||
if (!dm_pool_grow_object(rh->mem, "=", 1)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
if (!dm_pool_grow_object(rh->mem, STANDARD_PAIR, 1)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(rh->flags & DM_REPORT_OUTPUT_FIELD_UNQUOTED) &&
|
||||
!dm_pool_grow_object(rh->mem, "\'", 1)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
!dm_pool_grow_object(rh->mem, STANDARD_QUOTE, 1)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -4225,7 +4230,7 @@ static int _output_field(struct dm_report *rh, struct dm_report_field *field)
|
||||
width = field->props->width;
|
||||
if (!(rh->flags & DM_REPORT_OUTPUT_ALIGNED)) {
|
||||
if (!dm_pool_grow_object(rh->mem, repstr, 0)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
@@ -4248,7 +4253,7 @@ static int _output_field(struct dm_report *rh, struct dm_report_field *field)
|
||||
goto bad;
|
||||
}
|
||||
if (!dm_pool_grow_object(rh->mem, buf, width)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
goto bad;
|
||||
}
|
||||
} else if (align & DM_REPORT_FIELD_ALIGN_RIGHT) {
|
||||
@@ -4258,7 +4263,7 @@ static int _output_field(struct dm_report *rh, struct dm_report_field *field)
|
||||
goto bad;
|
||||
}
|
||||
if (!dm_pool_grow_object(rh->mem, buf, width)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
@@ -4266,8 +4271,8 @@ static int _output_field(struct dm_report *rh, struct dm_report_field *field)
|
||||
|
||||
if ((rh->flags & DM_REPORT_OUTPUT_FIELD_NAME_PREFIX) &&
|
||||
!(rh->flags & DM_REPORT_OUTPUT_FIELD_UNQUOTED))
|
||||
if (!dm_pool_grow_object(rh->mem, "\'", 1)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
if (!dm_pool_grow_object(rh->mem, STANDARD_QUOTE, 1)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@@ -4345,7 +4350,7 @@ static int _output_as_rows(struct dm_report *rh)
|
||||
|
||||
if (!dm_list_end(&rh->rows, &row->list))
|
||||
if (!dm_pool_grow_object(rh->mem, rh->separator, 0)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
@@ -4393,7 +4398,7 @@ static int _output_as_columns(struct dm_report *rh)
|
||||
|
||||
if (!dm_list_end(&row->fields, fh))
|
||||
if (!dm_pool_grow_object(rh->mem, rh->separator, 0)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
|
@@ -373,7 +373,8 @@ is not used and metadata is read from disks.
|
||||
.br
|
||||
Cause the command to access shared VGs, that would otherwise be skipped
|
||||
when lvmlockd is not being used. It can be used to report or display a
|
||||
lockd VG without locking.
|
||||
lockd VG without locking. Applicable only if LVM is compiled with lockd
|
||||
support.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-addtag
|
||||
|
@@ -111,7 +111,8 @@ owned.
|
||||
.B Shared:
|
||||
A shared or "lockd" VG has lock_type set and no system_id.
|
||||
A shared VG is meant to be used on shared storage from multiple hosts,
|
||||
and is only accessible to hosts using lvmlockd.
|
||||
and is only accessible to hosts using lvmlockd. Applicable only if LVM
|
||||
is compiled with lockd support.
|
||||
|
||||
.B Clustered:
|
||||
A clustered or "clvm" VG has the clustered flag set and no system_id.
|
||||
@@ -308,7 +309,8 @@ extra_system_ids list.
|
||||
|
||||
A shared/lockd VG has no system_id set, allowing multiple hosts to
|
||||
use it via lvmlockd. Changing a VG to a lockd type will clear the
|
||||
existing system_id.
|
||||
existing system_id. Applicable only if LVM is compiled with lockd
|
||||
support.
|
||||
|
||||
.SS clustered VGs
|
||||
|
||||
|
@@ -132,8 +132,8 @@ be used on one node at once.
|
||||
|
||||
For local VGs, \-ay, \-aey, and \-asy are all equivalent.
|
||||
.IP
|
||||
In a shared VG, lvmlockd is used for locking, and the following options
|
||||
are possible:
|
||||
In a shared VG, lvmlockd is used for locking if LVM is compiled with lockd
|
||||
support, and the following options are possible:
|
||||
|
||||
With \-aey, the command activates the LV in exclusive mode, allowing a
|
||||
single host to activate the LV (the host running the command). Before
|
||||
|
@@ -130,10 +130,10 @@ The 2.4 kernel has a limitation of 2TiB per block device.
|
||||
|
||||
.TP
|
||||
.B \-\-shared
|
||||
Create a shared VG using lvmlockd. lvmlockd will select lock type sanlock
|
||||
or dlm depending on which lock manager is running. This allows multiple
|
||||
hosts to share a VG on shared devices. lvmlockd and a lock manager must
|
||||
be configured and running. See
|
||||
Create a shared VG using lvmlockd if LVM is compiled with lockd support.
|
||||
lvmlockd will select lock type sanlock or dlm depending on which lock
|
||||
manager is running. This allows multiple hosts to share a VG on shared
|
||||
devices. lvmlockd and a lock manager must be configured and running. See
|
||||
.BR lvmlockd (8).
|
||||
|
||||
.TP
|
||||
|
@@ -99,8 +99,13 @@ else
|
||||
dir="$HOME/$dirbase"
|
||||
fi
|
||||
|
||||
test -e $dir && die 3 "Fatal: $dir already exists"
|
||||
$MKDIR -p $dir || die 4 "Fatal: could not create $dir"
|
||||
if test -d $dir ; then
|
||||
(shopt -s nullglob dotglob; test -r $dir -a -w $dir -a -x $dir && cd $dir && files=(*) && ((! ${#files[@]}))) || \
|
||||
die 5 "Fatal: directory $dir already exists and is not empty or inaccessible"
|
||||
else
|
||||
test -e $dir && die 3 "Fatal: $dir already exists"
|
||||
$MKDIR -p $dir || die 4 "Fatal: could not create $dir"
|
||||
fi
|
||||
|
||||
log="$dir/lvmdump.log"
|
||||
|
||||
|
@@ -201,7 +201,7 @@ LIB_SHARED = check aux inittest utils get lvm-wrapper
|
||||
|
||||
install: .tests-stamp lib/paths-installed
|
||||
@echo $(srcdir)
|
||||
$(INSTALL_DIR) $(DATADIR)/{shell,api,lib} $(EXECDIR)
|
||||
$(INSTALL_DIR) $(DATADIR)/{shell,api,lib,dbus} $(EXECDIR)
|
||||
$(INSTALL_DATA) shell/*.sh $(DATADIR)/shell
|
||||
$(INSTALL_DATA) api/*.sh $(DATADIR)/api
|
||||
$(INSTALL_PROGRAM) api/*.{t,py} $(DATADIR)/api
|
||||
|
@@ -321,7 +321,7 @@ prepare_lvmdbusd() {
|
||||
# Setup the python path so we can run
|
||||
export PYTHONPATH=$abs_top_builddir/daemons
|
||||
else
|
||||
daemon="$(which lvmdbusd)"
|
||||
daemon="$(which lvmdbusd || :)"
|
||||
fi
|
||||
[[ -n $daemon && -x $daemon ]] || skip "The daemon is missing"
|
||||
|
||||
@@ -431,7 +431,7 @@ teardown_devs() {
|
||||
test ${#stray_loops[@]} -eq 0 || {
|
||||
teardown_devs_prefixed "$COMMON_PREFIX" 1
|
||||
echo "Removing stray loop devices containing $COMMON_PREFIX: ${stray_loops[@]}"
|
||||
for i in "${stray_loops[@]}" ; do test ! -b $i || losetup -d $i ; done
|
||||
for i in "${stray_loops[@]}" ; do test ! -b $i || losetup -d $i || true ; done
|
||||
# Leave test when udev processed all removed devices
|
||||
udev_wait
|
||||
}
|
||||
|
@@ -48,7 +48,8 @@ get lv_field $vg/corigin kernel_cache_settings | grep 'migration_threshold=333'
|
||||
lvchange --cachesettings 'migration_threshold = 233 sequential_threshold = 13' $vg/corigin
|
||||
get lv_field $vg/corigin kernel_cache_settings | tee out
|
||||
grep 'migration_threshold=233' out
|
||||
grep 'sequential_threshold=13' out
|
||||
|
||||
if grep 'sequential_threshold=13' out ; then
|
||||
|
||||
lvchange --cachesettings 'migration_threshold = 17' $vg/corigin
|
||||
get lv_field $vg/corigin kernel_cache_settings | tee out
|
||||
@@ -79,4 +80,10 @@ grep 'migration_threshold=2048' out
|
||||
grep 'sequential_threshold=13' out
|
||||
grep 'random_threshold=4' out
|
||||
|
||||
else
|
||||
# When MQ is emulated by SMQ policy it does not hold settings.
|
||||
# So just skip testing of param changes when sequential_threshold=0
|
||||
grep 'sequential_threshold=0' out
|
||||
fi
|
||||
|
||||
vgremove -f $vg
|
||||
|
@@ -25,7 +25,7 @@ which "$FSCK" || skip
|
||||
#
|
||||
# Main
|
||||
#
|
||||
aux have_cache 1 3 0 || skip
|
||||
aux have_cache 1 5 0 || skip
|
||||
|
||||
aux prepare_vg 4
|
||||
|
||||
@@ -101,13 +101,15 @@ sync
|
||||
# Seriously damage cache metadata
|
||||
aux error_dev "$dev1" 2054:2
|
||||
|
||||
# Here we usually for the 1st. notice needs_check
|
||||
check lv_attr_bit state $vg/$lv1 "c"
|
||||
|
||||
sleep .1
|
||||
|
||||
# And now cache is finaly Failed
|
||||
check lv_attr_bit health $vg/$lv1 "F"
|
||||
# On fixed kernel we get instant Fail here
|
||||
get lv_field $vg/$lv1 lv_attr | tee out
|
||||
grep "Cwi-a-C-F-" out || {
|
||||
# while on older unfixed we just notice needs_check
|
||||
grep "Cwi-c-C---" out
|
||||
sleep .1
|
||||
# And now cache is finaly Failed
|
||||
check lv_attr_bit health $vg/$lv1 "F"
|
||||
}
|
||||
check lv_field $vg/$lv1 lv_health_status "failed"
|
||||
|
||||
aux disable_dev "$dev1"
|
||||
|
79
test/shell/lvconvert-repair-mirror.sh
Normal file
79
test/shell/lvconvert-repair-mirror.sh
Normal file
@@ -0,0 +1,79 @@
|
||||
#!/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
|
||||
|
||||
SKIP_WITH_LVMLOCKD=1
|
||||
SKIP_WITH_LVMPOLLD=1
|
||||
|
||||
MKFS=mkfs.ext3
|
||||
MOUNT_DIR=mnt
|
||||
|
||||
. lib/inittest
|
||||
|
||||
which "$MKFS" || skp
|
||||
|
||||
cleanup_mounted_and_teardown()
|
||||
{
|
||||
umount "$MOUNT_DIR" || true
|
||||
aux teardown
|
||||
}
|
||||
|
||||
aux lvmconf 'allocation/mirror_logs_require_separate_pvs = 1'
|
||||
|
||||
aux prepare_vg 5
|
||||
|
||||
################### Check lost mirror leg #################
|
||||
#
|
||||
# NOTE: using --regionsize 1M has major impact on my box
|
||||
# on read performance while mirror is synchronized
|
||||
# with the default 512K - my C2D T61 reads just couple MB/s!
|
||||
#
|
||||
lvcreate -aey --type mirror -L10 --regionsize 1M -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3"
|
||||
"$MKFS" "$DM_DEV_DIR/$vg/$lv1"
|
||||
mkdir "$MOUNT_DIR"
|
||||
|
||||
aux delay_dev "$dev2" 0 500 $(get first_extent_sector "$dev2"):
|
||||
aux delay_dev "$dev4" 0 500 $(get first_extent_sector "$dev4"):
|
||||
#
|
||||
# Enforce syncronization
|
||||
# ATM requires unmounted/unused LV??
|
||||
#
|
||||
lvchange --yes --resync $vg/$lv1
|
||||
trap 'cleanup_mounted_and_teardown' EXIT
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" "$MOUNT_DIR"
|
||||
|
||||
# run 'dd' operation during failure of 'mlog/mimage' device
|
||||
|
||||
dd if=/dev/zero of=mnt/zero bs=4K count=100 conv=fdatasync 2>err &
|
||||
|
||||
PERCENT=$(get lv_field $vg/$lv1 copy_percent)
|
||||
PERCENT=${PERCENT%%\.*} # cut decimal
|
||||
# and check less then 50% mirror is in sync (could be unusable delay_dev ?)
|
||||
test "$PERCENT" -lt 50 || skip
|
||||
#lvs -a -o+devices $vg
|
||||
|
||||
#aux disable_dev "$dev3"
|
||||
aux disable_dev "$dev2"
|
||||
|
||||
lvconvert --yes --repair $vg/$lv1
|
||||
lvs -a $vg
|
||||
|
||||
aux enable_dev "$dev2"
|
||||
|
||||
wait
|
||||
# dd MAY NOT HAVE produced any error message
|
||||
not grep error err
|
||||
|
||||
lvs -a -o+devices $vg
|
||||
umount "$MOUNT_DIR"
|
||||
fsck -n "$DM_DEV_DIR/$vg/$lv1"
|
||||
|
||||
aux enable_dev "$dev4"
|
||||
lvremove -ff $vg
|
@@ -13,6 +13,9 @@ SKIP_WITH_LVMPOLLD=1
|
||||
|
||||
. lib/inittest
|
||||
|
||||
# We need "dm" directory for dm devices in sysfs.
|
||||
aux driver_at_least 4 15 || skip
|
||||
|
||||
aux prepare_devs 3 8
|
||||
|
||||
vgcreate $vg $dev1 $dev2
|
||||
|
@@ -152,10 +152,10 @@ progress_t poll_merge_progress(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
if (parms->progress_display)
|
||||
log_print_unless_silent("%s: %s: %.1f%%", lv->name, parms->progress_title,
|
||||
log_print_unless_silent("%s: %s: %.2f%%", lv->name, parms->progress_title,
|
||||
100.0 - dm_percent_to_float(percent));
|
||||
else
|
||||
log_verbose("%s: %s: %.1f%%", lv->name, parms->progress_title,
|
||||
log_verbose("%s: %s: %.2f%%", lv->name, parms->progress_title,
|
||||
100.0 - dm_percent_to_float(percent));
|
||||
|
||||
if (percent == DM_PERCENT_0)
|
||||
|
@@ -368,7 +368,7 @@ static int _update_extents_params(struct volume_group *vg,
|
||||
&lp->discards, &lp->zero))
|
||||
return_0;
|
||||
|
||||
if (lcp->percent == PERCENT_FREE) {
|
||||
if (lcp->percent == PERCENT_FREE || lcp->percent == PERCENT_PVS) {
|
||||
if (lp->extents <= (2 * lp->pool_metadata_extents)) {
|
||||
log_error("Not enough space for thin pool creation.");
|
||||
return 0;
|
||||
|
@@ -40,10 +40,10 @@ progress_t poll_mirror_progress(struct cmd_context *cmd,
|
||||
|
||||
overall_percent = copy_percent(lv);
|
||||
if (parms->progress_display)
|
||||
log_print_unless_silent("%s: %s: %.1f%%", name, parms->progress_title,
|
||||
log_print_unless_silent("%s: %s: %.2f%%", name, parms->progress_title,
|
||||
dm_percent_to_float(overall_percent));
|
||||
else
|
||||
log_verbose("%s: %s: %.1f%%", name, parms->progress_title,
|
||||
log_verbose("%s: %s: %.2f%%", name, parms->progress_title,
|
||||
dm_percent_to_float(overall_percent));
|
||||
|
||||
if (segment_percent != DM_PERCENT_100)
|
||||
|
@@ -409,10 +409,10 @@ static int _get_final_report_type(int args_are_pvs,
|
||||
*lv_info_needed = (report_type & (LVSINFO | LVSINFOSTATUS)) ? 1 : 0;
|
||||
|
||||
/* Do we need to acquire LV device status in addition? */
|
||||
*lv_segment_status_needed = (report_type & (SEGSSTATUS | LVSSTATUS | LVSINFOSTATUS)) ? 1 : 0;
|
||||
*lv_segment_status_needed = (report_type & (LVSSTATUS | LVSINFOSTATUS)) ? 1 : 0;
|
||||
|
||||
/* Ensure options selected are compatible */
|
||||
if (report_type & (SEGS | SEGSSTATUS))
|
||||
if (report_type & SEGS)
|
||||
report_type |= LVS;
|
||||
if (report_type & PVSEGS)
|
||||
report_type |= PVS;
|
||||
@@ -429,7 +429,7 @@ static int _get_final_report_type(int args_are_pvs,
|
||||
else if ((report_type & PVS) ||
|
||||
((report_type & LABEL) && (report_type & VGS)))
|
||||
report_type = PVS;
|
||||
else if (report_type & (SEGS | SEGSSTATUS))
|
||||
else if (report_type & SEGS)
|
||||
report_type = SEGS;
|
||||
else if (report_type & (LVS | LVSINFO | LVSSTATUS | LVSINFOSTATUS))
|
||||
report_type = LVS;
|
||||
@@ -733,10 +733,10 @@ out:
|
||||
static int _report(struct cmd_context *cmd, int argc, char **argv,
|
||||
report_type_t report_type)
|
||||
{
|
||||
void *report_handle;
|
||||
struct processing_handle handle = {0};
|
||||
void *report_handle = NULL;
|
||||
struct processing_handle *handle = NULL;
|
||||
const char *keys = NULL, *options = NULL, *selection = NULL, *separator;
|
||||
int r = ECMD_PROCESSED;
|
||||
int r = ECMD_FAILED;
|
||||
int aligned, buffered, headings, field_prefixes, quoted;
|
||||
int columns_as_rows;
|
||||
unsigned args_are_pvs;
|
||||
@@ -809,13 +809,13 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "Unknown report type.");
|
||||
return ECMD_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If -o supplied use it, else use default for report_type */
|
||||
if (arg_count(cmd, options_ARG) &&
|
||||
((r = _get_report_options(cmd, report_type, &options, &fields_to_compact) != ECMD_PROCESSED)))
|
||||
return r;
|
||||
goto_out;
|
||||
|
||||
/* -O overrides default sort settings */
|
||||
keys = arg_str_value(cmd, sort_ARG, keys);
|
||||
@@ -841,19 +841,24 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
|
||||
if (arg_count(cmd, select_ARG))
|
||||
selection = arg_str_value(cmd, select_ARG, NULL);
|
||||
|
||||
if (!(handle = init_processing_handle(cmd)))
|
||||
goto_out;
|
||||
|
||||
if (!(report_handle = report_init(cmd, options, keys, &report_type,
|
||||
separator, aligned, buffered,
|
||||
headings, field_prefixes, quoted,
|
||||
columns_as_rows, selection)))
|
||||
return_ECMD_FAILED;
|
||||
goto_out;
|
||||
|
||||
handle->internal_report_for_select = 0;
|
||||
handle->include_historical_lvs = cmd->include_historical_lvs;
|
||||
handle->custom_handle = report_handle;
|
||||
|
||||
if (!_get_final_report_type(args_are_pvs,
|
||||
report_type, &lv_info_needed,
|
||||
&lv_segment_status_needed,
|
||||
&report_type)) {
|
||||
dm_report_free(report_handle);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
&report_type))
|
||||
goto_out;
|
||||
|
||||
/*
|
||||
* We lock VG_GLOBAL to enable use of metadata cache.
|
||||
@@ -864,18 +869,13 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
|
||||
lock_global = 1;
|
||||
if (!lock_vol(cmd, VG_GLOBAL, LCK_VG_READ, NULL)) {
|
||||
log_error("Unable to obtain global lock.");
|
||||
dm_report_free(report_handle);
|
||||
return ECMD_FAILED;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
handle.internal_report_for_select = 0;
|
||||
handle.include_historical_lvs = cmd->include_historical_lvs;
|
||||
handle.custom_handle = report_handle;
|
||||
|
||||
switch (report_type) {
|
||||
case DEVTYPES:
|
||||
r = _process_each_devtype(cmd, argc, &handle);
|
||||
r = _process_each_devtype(cmd, argc, handle);
|
||||
break;
|
||||
case LVSINFO:
|
||||
/* fall through */
|
||||
@@ -884,7 +884,7 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
|
||||
case LVSINFOSTATUS:
|
||||
/* fall through */
|
||||
case LVS:
|
||||
r = process_each_lv(cmd, argc, argv, 0, &handle,
|
||||
r = process_each_lv(cmd, argc, argv, 0, handle,
|
||||
lv_info_needed && !lv_segment_status_needed ? &_lvs_with_info_single :
|
||||
!lv_info_needed && lv_segment_status_needed ? &_lvs_with_status_single :
|
||||
lv_info_needed && lv_segment_status_needed ? &_lvs_with_info_and_status_single :
|
||||
@@ -892,25 +892,23 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
|
||||
break;
|
||||
case VGS:
|
||||
r = process_each_vg(cmd, argc, argv, NULL, 0,
|
||||
&handle, &_vgs_single);
|
||||
handle, &_vgs_single);
|
||||
break;
|
||||
case LABEL:
|
||||
r = process_each_label(cmd, argc, argv,
|
||||
&handle, &_label_single);
|
||||
handle, &_label_single);
|
||||
break;
|
||||
case PVS:
|
||||
if (args_are_pvs)
|
||||
r = process_each_pv(cmd, argc, argv, NULL,
|
||||
arg_is_set(cmd, all_ARG), 0,
|
||||
&handle, &_pvs_single);
|
||||
handle, &_pvs_single);
|
||||
else
|
||||
r = process_each_vg(cmd, argc, argv, NULL, 0,
|
||||
&handle, &_pvs_in_vg);
|
||||
handle, &_pvs_in_vg);
|
||||
break;
|
||||
case SEGSSTATUS:
|
||||
/* fall through */
|
||||
case SEGS:
|
||||
r = process_each_lv(cmd, argc, argv, 0, &handle,
|
||||
r = process_each_lv(cmd, argc, argv, 0, handle,
|
||||
lv_info_needed && !lv_segment_status_needed ? &_lvsegs_with_info_single :
|
||||
!lv_info_needed && lv_segment_status_needed ? &_lvsegs_with_status_single :
|
||||
lv_info_needed && lv_segment_status_needed ? &_lvsegs_with_info_and_status_single :
|
||||
@@ -920,14 +918,14 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
|
||||
if (args_are_pvs)
|
||||
r = process_each_pv(cmd, argc, argv, NULL,
|
||||
arg_is_set(cmd, all_ARG), 0,
|
||||
&handle,
|
||||
handle,
|
||||
lv_info_needed && !lv_segment_status_needed ? &_pvsegs_with_lv_info_single :
|
||||
!lv_info_needed && lv_segment_status_needed ? &_pvsegs_with_lv_status_single :
|
||||
lv_info_needed && lv_segment_status_needed ? &_pvsegs_with_lv_info_and_status_single :
|
||||
&_pvsegs_single);
|
||||
else
|
||||
r = process_each_vg(cmd, argc, argv, NULL, 0,
|
||||
&handle, &_pvsegs_in_vg);
|
||||
handle, &_pvsegs_in_vg);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -942,11 +940,13 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
|
||||
|
||||
dm_report_output(report_handle);
|
||||
|
||||
dm_report_free(report_handle);
|
||||
|
||||
if (lock_global)
|
||||
unlock_vg(cmd, VG_GLOBAL);
|
||||
|
||||
out:
|
||||
if (handle)
|
||||
destroy_processing_handle(cmd, handle);
|
||||
if (report_handle)
|
||||
dm_report_free(report_handle);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user