mrc0mmand / rpms / lvm2

Forked from rpms/lvm2 3 years ago
Clone

Blame SOURCES/lvm2-2_02_187-vgcreate-vgextend-restrict-PVs-with-mixed-block-size.patch

2b52f6
From f450ffed18936a3b9a6249ad46b24741f7e7b2a3 Mon Sep 17 00:00:00 2001
2b52f6
From: David Teigland <teigland@redhat.com>
2b52f6
Date: Thu, 1 Aug 2019 10:06:47 -0500
2b52f6
Subject: [PATCH 2/6] vgcreate/vgextend: restrict PVs with mixed block sizes
2b52f6
2b52f6
Avoid having PVs with different logical block sizes in the same VG.
2b52f6
This prevents LVs from having mixed block sizes, which can produce
2b52f6
file system errors.
2b52f6
2b52f6
The new config setting devices/allow_mixed_block_sizes (default 0)
2b52f6
can be changed to 1 to return to the unrestricted mode.
2b52f6
2b52f6
(cherry picked from commit 0404539edb25e4a9d3456bb3e6b402aa2767af6b)
2b52f6
2b52f6
Conflicts:
2b52f6
	tools/lvmcmdline.c
2b52f6
	tools/toollib.c
2b52f6
2b52f6
(cherry picked from commit a57b92dec396ac79c57e02e54c04e205aa85f084)
2b52f6
---
2b52f6
 lib/commands/toolcontext.h       |  1 +
2b52f6
 lib/config/config_settings.h     |  5 +++++
2b52f6
 lib/metadata/metadata-exported.h |  1 +
2b52f6
 lib/metadata/metadata.c          | 44 +++++++++++++++++++++++++++++++++++++
2b52f6
 tools/lvmcmdline.c               |  2 ++
2b52f6
 tools/toollib.c                  | 47 ++++++++++++++++++++++++++++++++++++++++
2b52f6
 tools/vgcreate.c                 |  2 ++
2b52f6
 7 files changed, 102 insertions(+)
2b52f6
2b52f6
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
2b52f6
index 4b2a079..497f4bd 100644
2b52f6
--- a/lib/commands/toolcontext.h
2b52f6
+++ b/lib/commands/toolcontext.h
2b52f6
@@ -155,6 +155,7 @@ struct cmd_context {
2b52f6
 	unsigned include_shared_vgs:1;		/* report/display cmds can reveal lockd VGs */
2b52f6
 	unsigned include_active_foreign_vgs:1;	/* cmd should process foreign VGs with active LVs */
2b52f6
 	unsigned vg_read_print_access_error:1;	/* print access errors from vg_read */
2b52f6
+	unsigned allow_mixed_block_sizes:1;
2b52f6
 	unsigned force_access_clustered:1;
2b52f6
 	unsigned lockd_gl_disable:1;
2b52f6
 	unsigned lockd_vg_disable:1;
2b52f6
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
2b52f6
index 9904a62..622e982 100644
2b52f6
--- a/lib/config/config_settings.h
2b52f6
+++ b/lib/config/config_settings.h
2b52f6
@@ -470,6 +470,11 @@ cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_
2b52f6
 	"Enabling this setting allows the VG to be used as usual even with\n"
2b52f6
 	"uncertain devices.\n")
2b52f6
 
2b52f6
+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,
2b52f6
+	"Allow PVs in the same VG with different logical block sizes.\n"
2b52f6
+	"When allowed, the user is responsible to ensure that an LV is\n"
2b52f6
+	"using PVs with matching block sizes when necessary.\n")
2b52f6
+
2b52f6
 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,
2b52f6
 	"Advise LVM which PVs to use when searching for new space.\n"
2b52f6
 	"When searching for free space to extend an LV, the 'cling' allocation\n"
2b52f6
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
2b52f6
index 2245c29..5674545 100644
2b52f6
--- a/lib/metadata/metadata-exported.h
2b52f6
+++ b/lib/metadata/metadata-exported.h
2b52f6
@@ -593,6 +593,7 @@ struct pvcreate_params {
2b52f6
 	unsigned is_remove : 1;         /* is removing PVs, not creating */
2b52f6
 	unsigned preserve_existing : 1;
2b52f6
 	unsigned check_failed : 1;
2b52f6
+	unsigned check_consistent_block_size : 1;
2b52f6
 };
2b52f6
 
2b52f6
 struct lvresize_params {
2b52f6
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
2b52f6
index 3620240..123f7f5 100644
2b52f6
--- a/lib/metadata/metadata.c
2b52f6
+++ b/lib/metadata/metadata.c
2b52f6
@@ -699,12 +699,40 @@ int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_params *pp)
2b52f6
 {
2b52f6
 	struct pv_list *pvl;
2b52f6
 	unsigned int max_phys_block_size = 0;
2b52f6
+	unsigned int physical_block_size, logical_block_size;
2b52f6
+	unsigned int prev_lbs = 0;
2b52f6
+	int inconsistent_existing_lbs = 0;
2b52f6
 
2b52f6
 	log_debug_metadata("Adding PVs to VG %s.", vg->name);
2b52f6
 
2b52f6
 	if (vg_bad_status_bits(vg, RESIZEABLE_VG))
2b52f6
 		return_0;
2b52f6
 
2b52f6
+	/*
2b52f6
+	 * Check if existing PVs have inconsistent block sizes.
2b52f6
+	 * If so, do not enforce new devices to be consistent.
2b52f6
+	 */
2b52f6
+	dm_list_iterate_items(pvl, &vg->pvs) {
2b52f6
+		logical_block_size = 0;
2b52f6
+		physical_block_size = 0;
2b52f6
+
2b52f6
+		if (!dev_get_direct_block_sizes(pvl->pv->dev, &physical_block_size, &logical_block_size))
2b52f6
+			continue;
2b52f6
+
2b52f6
+		if (!logical_block_size)
2b52f6
+			continue;
2b52f6
+
2b52f6
+		if (!prev_lbs) {
2b52f6
+			prev_lbs = logical_block_size;
2b52f6
+			continue;
2b52f6
+		}
2b52f6
+		
2b52f6
+		if (prev_lbs != logical_block_size) {
2b52f6
+			inconsistent_existing_lbs = 1;
2b52f6
+			break;
2b52f6
+		}
2b52f6
+	}
2b52f6
+
2b52f6
 	dm_list_iterate_items(pvl, &pp->pvs) {
2b52f6
 		log_debug_metadata("Adding PV %s to VG %s.", pv_dev_name(pvl->pv), vg->name);
2b52f6
 
2b52f6
@@ -715,6 +743,22 @@ int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_params *pp)
2b52f6
 			return 0;
2b52f6
 		}
2b52f6
 
2b52f6
+		logical_block_size = 0;
2b52f6
+		physical_block_size = 0;
2b52f6
+
2b52f6
+		if (!dev_get_direct_block_sizes(pvl->pv->dev, &physical_block_size, &logical_block_size))
2b52f6
+			log_warn("WARNING: PV %s has unknown block size.", pv_dev_name(pvl->pv));
2b52f6
+
2b52f6
+		else if (prev_lbs && logical_block_size && (logical_block_size != prev_lbs)) {
2b52f6
+			if (vg->cmd->allow_mixed_block_sizes || inconsistent_existing_lbs)
2b52f6
+				log_debug("Devices have inconsistent block sizes (%u and %u)", prev_lbs, logical_block_size);
2b52f6
+			else {
2b52f6
+				log_error("Devices have inconsistent logical block sizes (%u and %u).",
2b52f6
+					  prev_lbs, logical_block_size);
2b52f6
+				return 0;
2b52f6
+			}
2b52f6
+		}
2b52f6
+
2b52f6
 		if (!add_pv_to_vg(vg, pv_dev_name(pvl->pv), pvl->pv, 0)) {
2b52f6
 			log_error("PV %s cannot be added to VG %s.",
2b52f6
 				  pv_dev_name(pvl->pv), vg->name);
2b52f6
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
2b52f6
index f238b64..f82827d 100644
2b52f6
--- a/tools/lvmcmdline.c
2b52f6
+++ b/tools/lvmcmdline.c
2b52f6
@@ -2308,6 +2308,8 @@ static int _get_current_settings(struct cmd_context *cmd)
2b52f6
 	if (cmd->cname->flags & CAN_USE_ONE_SCAN)
2b52f6
 		cmd->can_use_one_scan = 1;
2b52f6
 
2b52f6
+	cmd->allow_mixed_block_sizes = find_config_tree_bool(cmd, devices_allow_mixed_block_sizes_CFG, NULL);
2b52f6
+
2b52f6
 	cmd->partial_activation = 0;
2b52f6
 	cmd->degraded_activation = 0;
2b52f6
 	activation_mode = find_config_tree_str(cmd, activation_mode_CFG, NULL);
2b52f6
diff --git a/tools/toollib.c b/tools/toollib.c
2b52f6
index 81953ee..0b957cc 100644
2b52f6
--- a/tools/toollib.c
2b52f6
+++ b/tools/toollib.c
2b52f6
@@ -5506,6 +5506,8 @@ int pvcreate_each_device(struct cmd_context *cmd,
2b52f6
 	struct device_list *devl;
2b52f6
 	const char *pv_name;
2b52f6
 	int consistent = 0;
2b52f6
+	unsigned int physical_block_size, logical_block_size;
2b52f6
+	unsigned int prev_pbs = 0, prev_lbs = 0;
2b52f6
 	int must_use_all = (cmd->cname->flags & MUST_USE_ALL_ARGS);
2b52f6
 	int found;
2b52f6
 	unsigned i;
2b52f6
@@ -5584,6 +5586,51 @@ int pvcreate_each_device(struct cmd_context *cmd,
2b52f6
 		pd->dev = dev_cache_get(pd->name, cmd->full_filter);
2b52f6
 
2b52f6
 	/*
2b52f6
+	 * Check for consistent block sizes.
2b52f6
+	 */
2b52f6
+	if (pp->check_consistent_block_size) {
2b52f6
+		dm_list_iterate_items(pd, &pp->arg_devices) {
2b52f6
+			if (!pd->dev)
2b52f6
+				continue;
2b52f6
+
2b52f6
+			logical_block_size = 0;
2b52f6
+			physical_block_size = 0;
2b52f6
+
2b52f6
+			if (!dev_get_direct_block_sizes(pd->dev, &physical_block_size, &logical_block_size)) {
2b52f6
+				log_warn("WARNING: Unknown block size for device %s.", dev_name(pd->dev));
2b52f6
+				continue;
2b52f6
+			}
2b52f6
+
2b52f6
+			if (!logical_block_size) {
2b52f6
+				log_warn("WARNING: Unknown logical_block_size for device %s.", dev_name(pd->dev));
2b52f6
+				continue;
2b52f6
+			}
2b52f6
+
2b52f6
+			if (!prev_lbs) {
2b52f6
+				prev_lbs = logical_block_size;
2b52f6
+				prev_pbs = physical_block_size;
2b52f6
+				continue;
2b52f6
+			}
2b52f6
+
2b52f6
+			if (prev_lbs == logical_block_size) {
2b52f6
+				/* Require lbs to match, just warn about unmatching pbs. */
2b52f6
+				if (!cmd->allow_mixed_block_sizes && prev_pbs && physical_block_size &&
2b52f6
+				    (prev_pbs != physical_block_size))
2b52f6
+					log_warn("WARNING: Devices have inconsistent physical block sizes (%u and %u).",
2b52f6
+						  prev_pbs, physical_block_size);
2b52f6
+				continue;
2b52f6
+			}
2b52f6
+
2b52f6
+			if (!cmd->allow_mixed_block_sizes) {
2b52f6
+				log_error("Devices have inconsistent logical block sizes (%u and %u).",
2b52f6
+					  prev_lbs, logical_block_size);
2b52f6
+				log_print("See lvm.conf allow_mixed_block_sizes.");
2b52f6
+				return 0;
2b52f6
+			}
2b52f6
+		}
2b52f6
+	}
2b52f6
+
2b52f6
+	/*
2b52f6
 	 * Use process_each_pv to search all existing PVs and devices.
2b52f6
 	 *
2b52f6
 	 * This is a slightly different way to use process_each_pv, because the
2b52f6
diff --git a/tools/vgcreate.c b/tools/vgcreate.c
2b52f6
index 4356d99..7add53b 100644
2b52f6
--- a/tools/vgcreate.c
2b52f6
+++ b/tools/vgcreate.c
2b52f6
@@ -48,6 +48,8 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
2b52f6
 	/* Don't create a new PV on top of an existing PV like pvcreate does. */
2b52f6
 	pp.preserve_existing = 1;
2b52f6
 
2b52f6
+	pp.check_consistent_block_size = 1;
2b52f6
+
2b52f6
 	if (!vgcreate_params_set_defaults(cmd, &vp_def, NULL))
2b52f6
 		return EINVALID_CMD_LINE;
2b52f6
 	vp_def.vg_name = vg_name;
2b52f6
-- 
2b52f6
1.8.3.1
2b52f6