]> sourceware.org Git - lvm2.git/commitdiff
vgcreate/vgextend: restrict PVs with mixed block sizes
authorDavid Teigland <teigland@redhat.com>
Thu, 1 Aug 2019 15:06:47 +0000 (10:06 -0500)
committerDavid Teigland <teigland@redhat.com>
Thu, 1 Aug 2019 15:06:47 +0000 (10:06 -0500)
Avoid having PVs with different logical block sizes in the same VG.
This prevents LVs from having mixed block sizes, which can produce
file system errors.

The new config setting devices/allow_mixed_block_sizes (default 0)
can be changed to 1 to return to the unrestricted mode.

lib/commands/toolcontext.h
lib/config/config_settings.h
lib/metadata/metadata-exported.h
lib/metadata/metadata.c
tools/lvmcmdline.c
tools/toollib.c
tools/vgcreate.c

index 488752c8f5fd36291b4e3eab6d03ca4b7218c0df..655d9f2978bb12f434440e8b05c05fc6f8aac0e7 100644 (file)
@@ -153,6 +153,7 @@ struct cmd_context {
        unsigned include_shared_vgs:1;          /* report/display cmds can reveal lockd VGs */
        unsigned include_active_foreign_vgs:1;  /* cmd should process foreign VGs with active LVs */
        unsigned vg_read_print_access_error:1;  /* print access errors from vg_read */
+       unsigned allow_mixed_block_sizes:1;
        unsigned force_access_clustered:1;
        unsigned lockd_gl_disable:1;
        unsigned lockd_vg_disable:1;
index 527d5bd070aa58d6b274d60022c1d7f7eda4bca0..edfe4a31a5b4f12e8059be9b6c1264ee7db3a34f 100644 (file)
@@ -502,6 +502,11 @@ cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_
        "Enabling this setting allows the VG to be used as usual even with\n"
        "uncertain devices.\n")
 
+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,
+       "Allow PVs in the same VG with different logical block sizes.\n"
+       "When allowed, the user is responsible to ensure that an LV is\n"
+       "using PVs with matching block sizes when necessary.\n")
+
 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,
        "Advise LVM which PVs to use when searching for new space.\n"
        "When searching for free space to extend an LV, the 'cling' allocation\n"
index f18587a737e233b5ab1f6648815787d9b9b1deb9..e1767b78d90bb83c54b8783b8fa5499dc307a0d2 100644 (file)
@@ -623,6 +623,7 @@ struct pvcreate_params {
        unsigned is_remove : 1;         /* is removing PVs, not creating */
        unsigned preserve_existing : 1;
        unsigned check_failed : 1;
+       unsigned check_consistent_block_size : 1;
 };
 
 struct lvresize_params {
index f19df3d1dcde7ce65b44f4399c560f98f315ae28..e55adc2125a93ce7c1d3a5b9220ff399d8575ee6 100644 (file)
@@ -751,12 +751,40 @@ int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_params *pp)
 {
        struct pv_list *pvl;
        unsigned int max_phys_block_size = 0;
+       unsigned int physical_block_size, logical_block_size;
+       unsigned int prev_lbs = 0;
+       int inconsistent_existing_lbs = 0;
 
        log_debug_metadata("Adding PVs to VG %s.", vg->name);
 
        if (vg_bad_status_bits(vg, RESIZEABLE_VG))
                return_0;
 
+       /*
+        * Check if existing PVs have inconsistent block sizes.
+        * If so, do not enforce new devices to be consistent.
+        */
+       dm_list_iterate_items(pvl, &vg->pvs) {
+               logical_block_size = 0;
+               physical_block_size = 0;
+
+               if (!dev_get_direct_block_sizes(pvl->pv->dev, &physical_block_size, &logical_block_size))
+                       continue;
+
+               if (!logical_block_size)
+                       continue;
+
+               if (!prev_lbs) {
+                       prev_lbs = logical_block_size;
+                       continue;
+               }
+               
+               if (prev_lbs != logical_block_size) {
+                       inconsistent_existing_lbs = 1;
+                       break;
+               }
+       }
+
        dm_list_iterate_items(pvl, &pp->pvs) {
                log_debug_metadata("Adding PV %s to VG %s.", pv_dev_name(pvl->pv), vg->name);
 
@@ -767,6 +795,22 @@ int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_params *pp)
                        return 0;
                }
 
+               logical_block_size = 0;
+               physical_block_size = 0;
+
+               if (!dev_get_direct_block_sizes(pvl->pv->dev, &physical_block_size, &logical_block_size))
+                       log_warn("WARNING: PV %s has unknown block size.", pv_dev_name(pvl->pv));
+
+               else if (prev_lbs && logical_block_size && (logical_block_size != prev_lbs)) {
+                       if (vg->cmd->allow_mixed_block_sizes || inconsistent_existing_lbs)
+                               log_debug("Devices have inconsistent block sizes (%u and %u)", prev_lbs, logical_block_size);
+                       else {
+                               log_error("Devices have inconsistent logical block sizes (%u and %u).",
+                                         prev_lbs, logical_block_size);
+                               return 0;
+                       }
+               }
+
                if (!add_pv_to_vg(vg, pv_dev_name(pvl->pv), pvl->pv, 0)) {
                        log_error("PV %s cannot be added to VG %s.",
                                  pv_dev_name(pvl->pv), vg->name);
index 30f9d8133525b584ae8a3fc7137369127bdf5c6b..7d29b6fab5cb9651f55ea3cfe03be54180b429e9 100644 (file)
@@ -2319,6 +2319,8 @@ static int _get_current_settings(struct cmd_context *cmd)
 
        cmd->scan_lvs = find_config_tree_bool(cmd, devices_scan_lvs_CFG, NULL);
 
+       cmd->allow_mixed_block_sizes = find_config_tree_bool(cmd, devices_allow_mixed_block_sizes_CFG, NULL);
+
        /*
         * enable_hints is set to 1 if any commands are using hints.
         * use_hints is set to 1 if this command doesn't use the hints.
index b2313f8ff269e05a8930302f209c04688d946d7b..155528c4e20887db4206b5b9f16ac37db7ca8af7 100644 (file)
@@ -5355,6 +5355,8 @@ int pvcreate_each_device(struct cmd_context *cmd,
        struct pv_list *vgpvl;
        struct device_list *devl;
        const char *pv_name;
+       unsigned int physical_block_size, logical_block_size;
+       unsigned int prev_pbs = 0, prev_lbs = 0;
        int must_use_all = (cmd->cname->flags & MUST_USE_ALL_ARGS);
        int found;
        unsigned i;
@@ -5394,6 +5396,51 @@ int pvcreate_each_device(struct cmd_context *cmd,
        dm_list_iterate_items(pd, &pp->arg_devices)
                pd->dev = dev_cache_get(cmd, pd->name, cmd->filter);
 
+       /*
+        * Check for consistent block sizes.
+        */
+       if (pp->check_consistent_block_size) {
+               dm_list_iterate_items(pd, &pp->arg_devices) {
+                       if (!pd->dev)
+                               continue;
+
+                       logical_block_size = 0;
+                       physical_block_size = 0;
+
+                       if (!dev_get_direct_block_sizes(pd->dev, &physical_block_size, &logical_block_size)) {
+                               log_warn("WARNING: Unknown block size for device %s.", dev_name(pd->dev));
+                               continue;
+                       }
+
+                       if (!logical_block_size) {
+                               log_warn("WARNING: Unknown logical_block_size for device %s.", dev_name(pd->dev));
+                               continue;
+                       }
+
+                       if (!prev_lbs) {
+                               prev_lbs = logical_block_size;
+                               prev_pbs = physical_block_size;
+                               continue;
+                       }
+
+                       if (prev_lbs == logical_block_size) {
+                               /* Require lbs to match, just warn about unmatching pbs. */
+                               if (!cmd->allow_mixed_block_sizes && prev_pbs && physical_block_size &&
+                                   (prev_pbs != physical_block_size))
+                                       log_warn("WARNING: Devices have inconsistent physical block sizes (%u and %u).",
+                                                 prev_pbs, physical_block_size);
+                               continue;
+                       }
+
+                       if (!cmd->allow_mixed_block_sizes) {
+                               log_error("Devices have inconsistent logical block sizes (%u and %u).",
+                                         prev_lbs, logical_block_size);
+                               log_print("See lvm.conf allow_mixed_block_sizes.");
+                               return 0;
+                       }
+               }
+       }
+
        /*
         * Use process_each_pv to search all existing PVs and devices.
         *
index d594ec11084df20807daa46923930bb06a0ed7b2..09b6a6c953fffa7507b7ae57b66f0878ef46bddd 100644 (file)
@@ -47,6 +47,8 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
        /* Don't create a new PV on top of an existing PV like pvcreate does. */
        pp.preserve_existing = 1;
 
+       pp.check_consistent_block_size = 1;
+
        if (!vgcreate_params_set_defaults(cmd, &vp_def, NULL))
                return EINVALID_CMD_LINE;
        vp_def.vg_name = vg_name;
This page took 0.046749 seconds and 5 git commands to generate.