Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP3:GA
lvm2.1005
device-add-physical-block-size-info-and-make-su...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File device-add-physical-block-size-info-and-make-sure-VG.patch of Package lvm2.1005
From dbcbdd66d64d4e2ecc59406d59f383c98b320c93 Mon Sep 17 00:00:00 2001 From: Liuhua Wang <lwang@suse.com> Date: Mon, 2 Nov 2015 13:08:36 +0800 Subject: [PATCH] device: add physical block size info and make sure VG extent size >= PV's phys. block size Upstream-commit: 32080c4ff748e4afbeacf9dbc4a98bfea658a392 --- lib/device/dev-cache.c | 1 + lib/device/dev-io.c | 67 ++++++++++++++++++---------------------- lib/device/device.h | 3 +- lib/metadata/metadata-exported.h | 1 + lib/metadata/metadata.c | 56 +++++++++++++++++++++++++++++---- lib/metadata/metadata.h | 3 ++ man/vgchange.8.in | 6 ++-- man/vgcreate.8.in | 6 ++-- tools/vgchange.c | 6 ++++ 9 files changed, 101 insertions(+), 48 deletions(-) diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c index d08b07f..71a00e1 100644 --- a/lib/device/dev-cache.c +++ b/lib/device/dev-cache.c @@ -56,6 +56,7 @@ static int _insert(const char *path, int rec, int check_with_udev_db); /* Setup non-zero members of passed zeroed 'struct device' */ static void _dev_init(struct device *dev, int max_error_count) { + dev->phys_block_size = -1; dev->block_size = -1; dev->fd = -1; dev->read_ahead = -1; diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c index c81cac2..1f88d9e 100644 --- a/lib/device/dev-io.c +++ b/lib/device/dev-io.c @@ -124,23 +124,44 @@ static int _io(struct device_area *where, char *buffer, int should_write) *---------------------------------------------------------------*/ /* - * Get the sector size from an _open_ device. + * Get the physical and logical block size for a device. */ -static int _get_block_size(struct device *dev, unsigned int *size) +int dev_get_block_size(struct device *dev, unsigned int *physical_block_size, unsigned int *block_size) { const char *name = dev_name(dev); + int needs_open; + int r = 1; + + needs_open = (!dev->open_count && (dev->phys_block_size == -1 || dev->block_size == -1)); + + if (needs_open && !dev_open_readonly(dev)) + return_0; + + if (dev->phys_block_size == -1) { + if (ioctl(dev_fd(dev), BLKPBSZGET, &dev->phys_block_size) < 0) { + log_sys_error("ioctl BLKPBSZGET", name); + r = 0; + goto out; + } + log_debug("%s: physical block size is %u bytes", name, dev->phys_block_size); + } if (dev->block_size == -1) { if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) { log_sys_error("ioctl BLKBSZGET", name); - return 0; - } + r = 0; + goto out; + } log_debug("%s: block size is %u bytes", name, dev->block_size); } - *size = (unsigned int) dev->block_size; + *physical_block_size = (unsigned int) dev->phys_block_size; + *block_size = (unsigned int) dev->block_size; +out: + if (needs_open) + dev_close(dev); - return 1; + return r; } /* @@ -169,13 +190,14 @@ static int _aligned_io(struct device_area *where, char *buffer, int should_write) { char *bounce, *bounce_buf; + unsigned int physical_block_size = 0; unsigned int block_size = 0; uintptr_t mask; struct device_area widened; int r = 0; if (!(where->dev->flags & DEV_REGULAR) && - !_get_block_size(where->dev, &block_size)) + !dev_get_block_size(where->dev, &physical_block_size, &block_size)) return_0; if (!block_size) @@ -371,36 +393,6 @@ int dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64_t size_ return _dev_discard_blocks(dev, offset_bytes, size_bytes); } -/* FIXME Unused -int dev_get_sectsize(struct device *dev, uint32_t *size) -{ - int fd; - int s; - const char *name = dev_name(dev); - - if ((fd = open(name, O_RDONLY)) < 0) { - log_sys_error("open", name); - return 0; - } - - if (ioctl(fd, BLKSSZGET, &s) < 0) { - log_sys_error("ioctl BLKSSZGET", name); - if (close(fd)) - log_sys_error("close", name); - return 0; - } - - if (close(fd)) - log_sys_error("close", name); - - *size = (uint32_t) s; - - log_very_verbose("%s: sector size is %" PRIu32 " bytes", name, *size); - - return 1; -} -*/ - void dev_flush(struct device *dev) { if (!(dev->flags & DEV_REGULAR) && ioctl(dev->fd, BLKFLSBUF, 0) >= 0) @@ -572,6 +564,7 @@ static void _close(struct device *dev) if (close(dev->fd)) log_sys_error("close", dev_name(dev)); dev->fd = -1; + dev->phys_block_size = -1; dev->block_size = -1; dm_list_del(&dev->open_list); diff --git a/lib/device/device.h b/lib/device/device.h index 355cf4f..54db946 100644 --- a/lib/device/device.h +++ b/lib/device/device.h @@ -41,6 +41,7 @@ struct device { int open_count; int error_count; int max_error_count; + int phys_block_size; int block_size; int read_ahead; uint32_t flags; @@ -65,8 +66,8 @@ struct device_area { /* * All io should use these routines. */ +int dev_get_block_size(struct device *dev, unsigned int *phys_block_size, unsigned int *block_size); int dev_get_size(const struct device *dev, uint64_t *size); -int dev_get_sectsize(struct device *dev, uint32_t *size); int dev_get_read_ahead(struct device *dev, uint32_t *read_ahead); int dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64_t size_bytes); diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index d149f95..c001224 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -716,6 +716,7 @@ int vg_remove_snapshot(struct logical_volume *cow); int vg_check_status(const struct volume_group *vg, uint64_t status); +int vg_check_pv_dev_block_sizes(const struct volume_group *vg); /* * Check if the VG reached maximal LVs count (if set) diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index c210a63..6b21d6c 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -631,6 +631,40 @@ int vg_remove(struct volume_group *vg) return ret; } +int check_dev_block_size_for_vg(struct device *dev, const struct volume_group *vg, + unsigned int *max_phys_block_size_found) +{ + unsigned int phys_block_size, block_size; + + if (!(dev_get_block_size(dev, &phys_block_size, &block_size))) + return_0; + + if (phys_block_size > *max_phys_block_size_found) + *max_phys_block_size_found = phys_block_size; + + if (phys_block_size >> SECTOR_SHIFT > vg->extent_size) { + log_error("Physical extent size used for volume group %s " + "is less than physical block size that %s uses.", + vg->name, dev_name(dev)); + return 0; + } + + return 1; +} + +int vg_check_pv_dev_block_sizes(const struct volume_group *vg) +{ + struct pv_list *pvl; + unsigned int max_phys_block_size_found = 0; + + dm_list_iterate_items(pvl, &vg->pvs) { + if (!check_dev_block_size_for_vg(pvl->pv->dev, vg, &max_phys_block_size_found)) + return 0; + } + + return 1; +} + /* * Extend a VG by a single PV / device path * @@ -638,10 +672,12 @@ int vg_remove(struct volume_group *vg) * - vg: handle of volume group to extend by 'pv_name' * - pv_name: device path of PV to add to VG * - pp: parameters to pass to implicit pvcreate; if NULL, do not pvcreate + * - max_phys_block_size: largest physical block size found amongst PVs in a VG * */ static int vg_extend_single_pv(struct volume_group *vg, char *pv_name, - struct pvcreate_params *pp) + struct pvcreate_params *pp, + unsigned int *max_phys_block_size) { struct physical_volume *pv; @@ -655,11 +691,18 @@ static int vg_extend_single_pv(struct volume_group *vg, char *pv_name, if (!(pv = pvcreate_single(vg->cmd, pv_name, pp, 0))) return_0; } - if (!add_pv_to_vg(vg, pv_name, pv, pp)) { - free_pv_fid(pv); - return_0; - } + + if (!(check_dev_block_size_for_vg(pv->dev, (const struct volume_group *) vg, + max_phys_block_size))) + goto_bad; + + if (!add_pv_to_vg(vg, pv_name, pv, pp)) + goto_bad; + return 1; +bad: + free_pv_fid(pv); + return 0; } /* @@ -677,6 +720,7 @@ int vg_extend(struct volume_group *vg, int pv_count, const char *const *pv_names { int i; char *pv_name; + unsigned int max_phys_block_size = 0; if (_vg_bad_status_bits(vg, RESIZEABLE_VG)) return_0; @@ -688,7 +732,7 @@ int vg_extend(struct volume_group *vg, int pv_count, const char *const *pv_names return 0; } dm_unescape_colons_and_at_signs(pv_name, NULL, NULL); - if (!vg_extend_single_pv(vg, pv_name, pp)) { + if (!vg_extend_single_pv(vg, pv_name, pp, &max_phys_block_size)) { log_error("Unable to add physical volume '%s' to " "volume group '%s'.", pv_name, vg->name); dm_free(pv_name); diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index 7bc7eaf..00af492 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -344,6 +344,9 @@ int vg_validate(struct volume_group *vg); int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv); +int check_dev_block_size_for_vg(struct device *dev, const struct volume_group *vg, + unsigned int *max_phys_block_size_found); + /* Manipulate PV structures */ int pv_add(struct volume_group *vg, struct physical_volume *pv); int pv_remove(struct volume_group *vg, struct physical_volume *pv); diff --git a/man/vgchange.8.in b/man/vgchange.8.in index 0f5fc58..b0db14f 100644 --- a/man/vgchange.8.in +++ b/man/vgchange.8.in @@ -169,8 +169,10 @@ minimize metadata read and write overhead. .BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize [ \fIBbBsSkKmMgGtTpPeE ] Changes the physical extent size on physical volumes of this volume group. A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes -is the default if no suffix is present. -The default is 4 MiB and it must be at least 1 KiB and a power of 2. +is the default if no suffix is present. The value must be at least 1 sector +for LVM2 format (where the sector size is the largest sector size of the +PVs currently used in the VG) or 8KiB for LVM1 format and it must be a +power of 2. The default is 4 MiB. Before increasing the physical extent size, you might need to use lvresize, pvresize and/or pvmove so that everything fits. For example, every diff --git a/man/vgcreate.8.in b/man/vgcreate.8.in index 577fee2..e62df9e 100644 --- a/man/vgcreate.8.in +++ b/man/vgcreate.8.in @@ -94,8 +94,10 @@ The default value is \fIunmanaged\fP. .BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize [ \fIbBsSkKmMgGtTpPeE ] Sets the physical extent size on physical volumes of this volume group. A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes -is the default if no suffix is present. -The default is 4 MiB and it must be at least 1 KiB and a power of 2. +is the default if no suffix is present. The value must be at least 1 sector +for LVM2 format (where the sector size is the largest sector size of the +PVs currently used in the VG) or 8KiB for LVM1 format and it must be a +power of 2. The default is 4 MiB. Once this value has been set, it is difficult to change it without recreating the volume group which would involve backing up and restoring data on any diff --git a/tools/vgchange.c b/tools/vgchange.c index 7168e42..ce9f8a5 100644 --- a/tools/vgchange.c +++ b/tools/vgchange.c @@ -391,6 +391,12 @@ static int _vgchange_pesize(struct cmd_context *cmd, struct volume_group *vg) if (!vg_set_extent_size(vg, extent_size)) return_0; + if (!vg_check_pv_dev_block_sizes(vg)) { + log_error("Failed to change physical extent size for VG %s.", + vg->name); + return 0; + } + return 1; } -- 1.8.4.5
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor