|
|
26e710 |
lib/commands/toolcontext.h | 1 +
|
|
|
26e710 |
lib/config/config_settings.h | 5 +++++
|
|
|
26e710 |
lib/metadata/metadata-exported.h | 1 +
|
|
|
26e710 |
lib/metadata/metadata.c | 44 +++++++++++++++++++++++++++++++++++++
|
|
|
26e710 |
tools/lvmcmdline.c | 2 ++
|
|
|
26e710 |
tools/toollib.c | 47 ++++++++++++++++++++++++++++++++++++++++
|
|
|
26e710 |
tools/vgcreate.c | 2 ++
|
|
|
26e710 |
7 files changed, 102 insertions(+)
|
|
|
26e710 |
|
|
|
26e710 |
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
|
|
|
26e710 |
index 488752c..655d9f2 100644
|
|
|
26e710 |
--- a/lib/commands/toolcontext.h
|
|
|
26e710 |
+++ b/lib/commands/toolcontext.h
|
|
|
26e710 |
@@ -153,6 +153,7 @@ struct cmd_context {
|
|
|
26e710 |
unsigned include_shared_vgs:1; /* report/display cmds can reveal lockd VGs */
|
|
|
26e710 |
unsigned include_active_foreign_vgs:1; /* cmd should process foreign VGs with active LVs */
|
|
|
26e710 |
unsigned vg_read_print_access_error:1; /* print access errors from vg_read */
|
|
|
26e710 |
+ unsigned allow_mixed_block_sizes:1;
|
|
|
26e710 |
unsigned force_access_clustered:1;
|
|
|
26e710 |
unsigned lockd_gl_disable:1;
|
|
|
26e710 |
unsigned lockd_vg_disable:1;
|
|
|
26e710 |
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
|
|
|
26e710 |
index f14f0b8..25650e3 100644
|
|
|
26e710 |
--- a/lib/config/config_settings.h
|
|
|
26e710 |
+++ b/lib/config/config_settings.h
|
|
|
26e710 |
@@ -502,6 +502,11 @@ cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_
|
|
|
26e710 |
"Enabling this setting allows the VG to be used as usual even with\n"
|
|
|
26e710 |
"uncertain devices.\n")
|
|
|
26e710 |
|
|
|
26e710 |
+cfg(devices_allow_mixed_block_sizes_CFG, "allow_mixed_block_sizes", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 3, 6), NULL, 0, NULL,
|
|
|
26e710 |
+ "Allow PVs in the same VG with different logical block sizes.\n"
|
|
|
26e710 |
+ "When allowed, the user is responsible to ensure that an LV is\n"
|
|
|
26e710 |
+ "using PVs with matching block sizes when necessary.\n")
|
|
|
26e710 |
+
|
|
|
26e710 |
cfg_array(allocation_cling_tag_list_CFG, "cling_tag_list", allocation_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 77), NULL, 0, NULL,
|
|
|
26e710 |
"Advise LVM which PVs to use when searching for new space.\n"
|
|
|
26e710 |
"When searching for free space to extend an LV, the 'cling' allocation\n"
|
|
|
26e710 |
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
|
|
|
26e710 |
index 77b971b..539845c 100644
|
|
|
26e710 |
--- a/lib/metadata/metadata-exported.h
|
|
|
26e710 |
+++ b/lib/metadata/metadata-exported.h
|
|
|
26e710 |
@@ -622,6 +622,7 @@ struct pvcreate_params {
|
|
|
26e710 |
unsigned is_remove : 1; /* is removing PVs, not creating */
|
|
|
26e710 |
unsigned preserve_existing : 1;
|
|
|
26e710 |
unsigned check_failed : 1;
|
|
|
26e710 |
+ unsigned check_consistent_block_size : 1;
|
|
|
26e710 |
};
|
|
|
26e710 |
|
|
|
26e710 |
struct lvresize_params {
|
|
|
26e710 |
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
|
|
|
26e710 |
index f7eeb52..55ae46d 100644
|
|
|
26e710 |
--- a/lib/metadata/metadata.c
|
|
|
26e710 |
+++ b/lib/metadata/metadata.c
|
|
|
26e710 |
@@ -751,12 +751,40 @@ int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_params *pp)
|
|
|
26e710 |
{
|
|
|
26e710 |
struct pv_list *pvl;
|
|
|
26e710 |
unsigned int max_phys_block_size = 0;
|
|
|
26e710 |
+ unsigned int physical_block_size, logical_block_size;
|
|
|
26e710 |
+ unsigned int prev_lbs = 0;
|
|
|
26e710 |
+ int inconsistent_existing_lbs = 0;
|
|
|
26e710 |
|
|
|
26e710 |
log_debug_metadata("Adding PVs to VG %s.", vg->name);
|
|
|
26e710 |
|
|
|
26e710 |
if (vg_bad_status_bits(vg, RESIZEABLE_VG))
|
|
|
26e710 |
return_0;
|
|
|
26e710 |
|
|
|
26e710 |
+ /*
|
|
|
26e710 |
+ * Check if existing PVs have inconsistent block sizes.
|
|
|
26e710 |
+ * If so, do not enforce new devices to be consistent.
|
|
|
26e710 |
+ */
|
|
|
26e710 |
+ dm_list_iterate_items(pvl, &vg->pvs) {
|
|
|
26e710 |
+ logical_block_size = 0;
|
|
|
26e710 |
+ physical_block_size = 0;
|
|
|
26e710 |
+
|
|
|
26e710 |
+ if (!dev_get_direct_block_sizes(pvl->pv->dev, &physical_block_size, &logical_block_size))
|
|
|
26e710 |
+ continue;
|
|
|
26e710 |
+
|
|
|
26e710 |
+ if (!logical_block_size)
|
|
|
26e710 |
+ continue;
|
|
|
26e710 |
+
|
|
|
26e710 |
+ if (!prev_lbs) {
|
|
|
26e710 |
+ prev_lbs = logical_block_size;
|
|
|
26e710 |
+ continue;
|
|
|
26e710 |
+ }
|
|
|
26e710 |
+
|
|
|
26e710 |
+ if (prev_lbs != logical_block_size) {
|
|
|
26e710 |
+ inconsistent_existing_lbs = 1;
|
|
|
26e710 |
+ break;
|
|
|
26e710 |
+ }
|
|
|
26e710 |
+ }
|
|
|
26e710 |
+
|
|
|
26e710 |
dm_list_iterate_items(pvl, &pp->pvs) {
|
|
|
26e710 |
log_debug_metadata("Adding PV %s to VG %s.", pv_dev_name(pvl->pv), vg->name);
|
|
|
26e710 |
|
|
|
26e710 |
@@ -767,6 +795,22 @@ int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_params *pp)
|
|
|
26e710 |
return 0;
|
|
|
26e710 |
}
|
|
|
26e710 |
|
|
|
26e710 |
+ logical_block_size = 0;
|
|
|
26e710 |
+ physical_block_size = 0;
|
|
|
26e710 |
+
|
|
|
26e710 |
+ if (!dev_get_direct_block_sizes(pvl->pv->dev, &physical_block_size, &logical_block_size))
|
|
|
26e710 |
+ log_warn("WARNING: PV %s has unknown block size.", pv_dev_name(pvl->pv));
|
|
|
26e710 |
+
|
|
|
26e710 |
+ else if (prev_lbs && logical_block_size && (logical_block_size != prev_lbs)) {
|
|
|
26e710 |
+ if (vg->cmd->allow_mixed_block_sizes || inconsistent_existing_lbs)
|
|
|
26e710 |
+ log_debug("Devices have inconsistent block sizes (%u and %u)", prev_lbs, logical_block_size);
|
|
|
26e710 |
+ else {
|
|
|
26e710 |
+ log_error("Devices have inconsistent logical block sizes (%u and %u).",
|
|
|
26e710 |
+ prev_lbs, logical_block_size);
|
|
|
26e710 |
+ return 0;
|
|
|
26e710 |
+ }
|
|
|
26e710 |
+ }
|
|
|
26e710 |
+
|
|
|
26e710 |
if (!add_pv_to_vg(vg, pv_dev_name(pvl->pv), pvl->pv, 0)) {
|
|
|
26e710 |
log_error("PV %s cannot be added to VG %s.",
|
|
|
26e710 |
pv_dev_name(pvl->pv), vg->name);
|
|
|
26e710 |
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
|
|
|
26e710 |
index 30f9d81..7d29b6f 100644
|
|
|
26e710 |
--- a/tools/lvmcmdline.c
|
|
|
26e710 |
+++ b/tools/lvmcmdline.c
|
|
|
26e710 |
@@ -2319,6 +2319,8 @@ static int _get_current_settings(struct cmd_context *cmd)
|
|
|
26e710 |
|
|
|
26e710 |
cmd->scan_lvs = find_config_tree_bool(cmd, devices_scan_lvs_CFG, NULL);
|
|
|
26e710 |
|
|
|
26e710 |
+ cmd->allow_mixed_block_sizes = find_config_tree_bool(cmd, devices_allow_mixed_block_sizes_CFG, NULL);
|
|
|
26e710 |
+
|
|
|
26e710 |
/*
|
|
|
26e710 |
* enable_hints is set to 1 if any commands are using hints.
|
|
|
26e710 |
* use_hints is set to 1 if this command doesn't use the hints.
|
|
|
26e710 |
diff --git a/tools/toollib.c b/tools/toollib.c
|
|
|
26e710 |
index b2313f8..155528c 100644
|
|
|
26e710 |
--- a/tools/toollib.c
|
|
|
26e710 |
+++ b/tools/toollib.c
|
|
|
26e710 |
@@ -5355,6 +5355,8 @@ int pvcreate_each_device(struct cmd_context *cmd,
|
|
|
26e710 |
struct pv_list *vgpvl;
|
|
|
26e710 |
struct device_list *devl;
|
|
|
26e710 |
const char *pv_name;
|
|
|
26e710 |
+ unsigned int physical_block_size, logical_block_size;
|
|
|
26e710 |
+ unsigned int prev_pbs = 0, prev_lbs = 0;
|
|
|
26e710 |
int must_use_all = (cmd->cname->flags & MUST_USE_ALL_ARGS);
|
|
|
26e710 |
int found;
|
|
|
26e710 |
unsigned i;
|
|
|
26e710 |
@@ -5395,6 +5397,51 @@ int pvcreate_each_device(struct cmd_context *cmd,
|
|
|
26e710 |
pd->dev = dev_cache_get(cmd, pd->name, cmd->filter);
|
|
|
26e710 |
|
|
|
26e710 |
/*
|
|
|
26e710 |
+ * Check for consistent block sizes.
|
|
|
26e710 |
+ */
|
|
|
26e710 |
+ if (pp->check_consistent_block_size) {
|
|
|
26e710 |
+ dm_list_iterate_items(pd, &pp->arg_devices) {
|
|
|
26e710 |
+ if (!pd->dev)
|
|
|
26e710 |
+ continue;
|
|
|
26e710 |
+
|
|
|
26e710 |
+ logical_block_size = 0;
|
|
|
26e710 |
+ physical_block_size = 0;
|
|
|
26e710 |
+
|
|
|
26e710 |
+ if (!dev_get_direct_block_sizes(pd->dev, &physical_block_size, &logical_block_size)) {
|
|
|
26e710 |
+ log_warn("WARNING: Unknown block size for device %s.", dev_name(pd->dev));
|
|
|
26e710 |
+ continue;
|
|
|
26e710 |
+ }
|
|
|
26e710 |
+
|
|
|
26e710 |
+ if (!logical_block_size) {
|
|
|
26e710 |
+ log_warn("WARNING: Unknown logical_block_size for device %s.", dev_name(pd->dev));
|
|
|
26e710 |
+ continue;
|
|
|
26e710 |
+ }
|
|
|
26e710 |
+
|
|
|
26e710 |
+ if (!prev_lbs) {
|
|
|
26e710 |
+ prev_lbs = logical_block_size;
|
|
|
26e710 |
+ prev_pbs = physical_block_size;
|
|
|
26e710 |
+ continue;
|
|
|
26e710 |
+ }
|
|
|
26e710 |
+
|
|
|
26e710 |
+ if (prev_lbs == logical_block_size) {
|
|
|
26e710 |
+ /* Require lbs to match, just warn about unmatching pbs. */
|
|
|
26e710 |
+ if (!cmd->allow_mixed_block_sizes && prev_pbs && physical_block_size &&
|
|
|
26e710 |
+ (prev_pbs != physical_block_size))
|
|
|
26e710 |
+ log_warn("WARNING: Devices have inconsistent physical block sizes (%u and %u).",
|
|
|
26e710 |
+ prev_pbs, physical_block_size);
|
|
|
26e710 |
+ continue;
|
|
|
26e710 |
+ }
|
|
|
26e710 |
+
|
|
|
26e710 |
+ if (!cmd->allow_mixed_block_sizes) {
|
|
|
26e710 |
+ log_error("Devices have inconsistent logical block sizes (%u and %u).",
|
|
|
26e710 |
+ prev_lbs, logical_block_size);
|
|
|
26e710 |
+ log_print("See lvm.conf allow_mixed_block_sizes.");
|
|
|
26e710 |
+ return 0;
|
|
|
26e710 |
+ }
|
|
|
26e710 |
+ }
|
|
|
26e710 |
+ }
|
|
|
26e710 |
+
|
|
|
26e710 |
+ /*
|
|
|
26e710 |
* Use process_each_pv to search all existing PVs and devices.
|
|
|
26e710 |
*
|
|
|
26e710 |
* This is a slightly different way to use process_each_pv, because the
|
|
|
26e710 |
diff --git a/tools/vgcreate.c b/tools/vgcreate.c
|
|
|
26e710 |
index d594ec1..09b6a6c 100644
|
|
|
26e710 |
--- a/tools/vgcreate.c
|
|
|
26e710 |
+++ b/tools/vgcreate.c
|
|
|
26e710 |
@@ -47,6 +47,8 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
|
|
|
26e710 |
/* Don't create a new PV on top of an existing PV like pvcreate does. */
|
|
|
26e710 |
pp.preserve_existing = 1;
|
|
|
26e710 |
|
|
|
26e710 |
+ pp.check_consistent_block_size = 1;
|
|
|
26e710 |
+
|
|
|
26e710 |
if (!vgcreate_params_set_defaults(cmd, &vp_def, NULL))
|
|
|
26e710 |
return EINVALID_CMD_LINE;
|
|
|
26e710 |
vp_def.vg_name = vg_name;
|