stable-2.02 - vgchange: don't fail monitor command if vg is exported
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=5ddd1ead2dcaf9594a0...
Commit: 5ddd1ead2dcaf9594a025a15986b8bac573c81b2
Parent: b387d026bd065b99f894a5c7b67d1f0441b583f3
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Jun 20 15:59:36 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Jul 31 13:18:58 2019 -0500
vgchange: don't fail monitor command if vg is exported
When monitoring, skip exported VGs without causing a command
failure.
The lvm2-monitor service runs 'vgchange --monitor y', so
any exported VG on the system would cause the service to
fail.
---
tools/vgchange.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/tools/vgchange.c b/tools/vgchange.c
index 24c2253..e15fca7 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -712,6 +712,8 @@ static int _vgchange_single(struct cmd_context *cmd, const char *vg_name,
};
if (vg_is_exported(vg)) {
+ if (cmd->command->command_enum == vgchange_monitor_CMD)
+ return ECMD_PROCESSED;
log_error("Volume group \"%s\" is exported", vg_name);
return ECMD_FAILED;
}
4 years, 4 months
stable-2.02 - WHATS_NEW: fix large physical block size
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=b387d026bd065b99f89...
Commit: b387d026bd065b99f894a5c7b67d1f0441b583f3
Parent: a178ad0858a9fa3fbef97b3fa5148ab432b61422
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Jul 30 16:14:46 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Tue Jul 30 16:14:46 2019 -0500
WHATS_NEW: fix large physical block size
---
WHATS_NEW | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index d3da403..d30e5cd 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.186 -
================================
+ Fix metadata writes from corrupting with large physical block size.
Report no_discard_passdown for cache LVs with lvs -o+kernel_discards.
Prevent shared active mirror LVs with lvmlockd.
4 years, 4 months
stable-2.02 - tests: large-physical-sector-size
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=a178ad0858a9fa3fbef...
Commit: a178ad0858a9fa3fbef97b3fa5148ab432b61422
Parent: 7550665ba49ac7d497d5b212e14b69298ef01361
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Jul 30 15:59:11 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Tue Jul 30 16:12:45 2019 -0500
tests: large-physical-sector-size
---
test/shell/large-physical-sector-size.sh | 43 ++++++++++++++++++++++++++++++
1 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/test/shell/large-physical-sector-size.sh b/test/shell/large-physical-sector-size.sh
new file mode 100644
index 0000000..891f409
--- /dev/null
+++ b/test/shell/large-physical-sector-size.sh
@@ -0,0 +1,43 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2019 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_LVMPOLLD=1
+
+. lib/inittest
+
+LOGICAL_BLOCK_SIZE=4096
+
+# PHYSICAL_BLOCK_SIZE is set with physblk_exp which
+# shifts the logical block size value.
+
+# 4096 << 9 = 2MB physical block size
+PHYSICAL_BLOCK_SHIFT=9
+
+aux prepare_scsi_debug_dev 256 sector_size=$LOGICAL_BLOCK_SIZE physblk_exp=$PHYSICAL_BLOCK_SHIFT
+
+check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size "$LOGICAL_BLOCK_SIZE"
+
+aux prepare_pvs 1 256
+
+get_devs
+
+vgcreate $SHARED $vg "$dev1"
+
+for i in `seq 1 40`; do lvcreate -an -l1 $vg; done;
+
+lvs $vg
+
+lvremove -y $vg
+
+vgremove $vg
+
+aux cleanup_scsi_debug_dev
4 years, 4 months
stable-2.02 - Fix rounding writes up to sector size
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=7550665ba49ac7d497d...
Commit: 7550665ba49ac7d497d5b212e14b69298ef01361
Parent: 3d980172b076547865efe5ca0839cabedc05a7b9
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed Jul 24 11:32:13 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Thu Jul 25 17:06:43 2019 -0500
Fix rounding writes up to sector size
Do this at two levels, although one would be enough to
fix the problem seen recently:
- Ignore any reported sector size other than 512 of 4096.
If either sector size (physical or logical) is reported
as 512, then use 512. If neither are reported as 512,
and one or the other is reported as 4096, then use 4096.
If neither is reported as either 512 or 4096, then use 512.
- When rounding up a limited write in bcache to be a multiple
of the sector size, check that the resulting write size is
not larger than the bcache block itself. (This shouldn't
happen if the sector size is 512 or 4096.)
---
lib/device/bcache.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++-
lib/device/dev-io.c | 52 +++++++++++++++++++++++++++++
lib/device/device.h | 8 +++-
lib/label/label.c | 27 +++++++++++++--
4 files changed, 168 insertions(+), 8 deletions(-)
diff --git a/lib/device/bcache.c b/lib/device/bcache.c
index 261164e..a250bfd 100644
--- a/lib/device/bcache.c
+++ b/lib/device/bcache.c
@@ -169,6 +169,7 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd,
sector_t offset;
sector_t nbytes;
sector_t limit_nbytes;
+ sector_t orig_nbytes;
sector_t extra_nbytes = 0;
if (((uintptr_t) data) & e->page_mask) {
@@ -191,11 +192,41 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd,
return false;
}
+ /*
+ * If the bcache block offset+len goes beyond where lvm is
+ * intending to write, then reduce the len being written
+ * (which is the bcache block size) so we don't write past
+ * the limit set by lvm. If after applying the limit, the
+ * resulting size is not a multiple of the sector size (512
+ * or 4096) then extend the reduced size to be a multiple of
+ * the sector size (we don't want to write partial sectors.)
+ */
if (offset + nbytes > _last_byte_offset) {
limit_nbytes = _last_byte_offset - offset;
- if (limit_nbytes % _last_byte_sector_size)
+
+ if (limit_nbytes % _last_byte_sector_size) {
extra_nbytes = _last_byte_sector_size - (limit_nbytes % _last_byte_sector_size);
+ /*
+ * adding extra_nbytes to the reduced nbytes (limit_nbytes)
+ * should make the final write size a multiple of the
+ * sector size. This should never result in a final size
+ * larger than the bcache block size (as long as the bcache
+ * block size is a multiple of the sector size).
+ */
+ if (limit_nbytes + extra_nbytes > nbytes) {
+ log_warn("Skip extending write at %llu len %llu limit %llu extra %llu sector_size %llu",
+ (unsigned long long)offset,
+ (unsigned long long)nbytes,
+ (unsigned long long)limit_nbytes,
+ (unsigned long long)extra_nbytes,
+ (unsigned long long)_last_byte_sector_size);
+ extra_nbytes = 0;
+ }
+ }
+
+ orig_nbytes = nbytes;
+
if (extra_nbytes) {
log_debug("Limit write at %llu len %llu to len %llu rounded to %llu",
(unsigned long long)offset,
@@ -210,6 +241,22 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd,
(unsigned long long)limit_nbytes);
nbytes = limit_nbytes;
}
+
+ /*
+ * This shouldn't happen, the reduced+extended
+ * nbytes value should never be larger than the
+ * bcache block size.
+ */
+ if (nbytes > orig_nbytes) {
+ log_error("Invalid adjusted write at %llu len %llu adjusted %llu limit %llu extra %llu sector_size %llu",
+ (unsigned long long)offset,
+ (unsigned long long)orig_nbytes,
+ (unsigned long long)nbytes,
+ (unsigned long long)limit_nbytes,
+ (unsigned long long)extra_nbytes,
+ (unsigned long long)_last_byte_sector_size);
+ return false;
+ }
}
}
@@ -404,6 +451,7 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
uint64_t nbytes = len;
sector_t limit_nbytes = 0;
sector_t extra_nbytes = 0;
+ sector_t orig_nbytes = 0;
if (offset > _last_byte_offset) {
log_error("Limit write at %llu len %llu beyond last byte %llu",
@@ -416,9 +464,30 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
if (offset + nbytes > _last_byte_offset) {
limit_nbytes = _last_byte_offset - offset;
- if (limit_nbytes % _last_byte_sector_size)
+
+ if (limit_nbytes % _last_byte_sector_size) {
extra_nbytes = _last_byte_sector_size - (limit_nbytes % _last_byte_sector_size);
+ /*
+ * adding extra_nbytes to the reduced nbytes (limit_nbytes)
+ * should make the final write size a multiple of the
+ * sector size. This should never result in a final size
+ * larger than the bcache block size (as long as the bcache
+ * block size is a multiple of the sector size).
+ */
+ if (limit_nbytes + extra_nbytes > nbytes) {
+ log_warn("Skip extending write at %llu len %llu limit %llu extra %llu sector_size %llu",
+ (unsigned long long)offset,
+ (unsigned long long)nbytes,
+ (unsigned long long)limit_nbytes,
+ (unsigned long long)extra_nbytes,
+ (unsigned long long)_last_byte_sector_size);
+ extra_nbytes = 0;
+ }
+ }
+
+ orig_nbytes = nbytes;
+
if (extra_nbytes) {
log_debug("Limit write at %llu len %llu to len %llu rounded to %llu",
(unsigned long long)offset,
@@ -433,6 +502,22 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
(unsigned long long)limit_nbytes);
nbytes = limit_nbytes;
}
+
+ /*
+ * This shouldn't happen, the reduced+extended
+ * nbytes value should never be larger than the
+ * bcache block size.
+ */
+ if (nbytes > orig_nbytes) {
+ log_error("Invalid adjusted write at %llu len %llu adjusted %llu limit %llu extra %llu sector_size %llu",
+ (unsigned long long)offset,
+ (unsigned long long)orig_nbytes,
+ (unsigned long long)nbytes,
+ (unsigned long long)limit_nbytes,
+ (unsigned long long)extra_nbytes,
+ (unsigned long long)_last_byte_sector_size);
+ return false;
+ }
}
where = offset;
diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c
index 99ff803..fd8d349 100644
--- a/lib/device/dev-io.c
+++ b/lib/device/dev-io.c
@@ -135,6 +135,58 @@ static int _io(struct device_area *where, char *buffer, int should_write, dev_io
return (total == (size_t) where->size);
}
+int dev_get_direct_block_sizes(struct device *dev, unsigned int *physical_block_size,
+ unsigned int *logical_block_size)
+{
+ int fd = dev->bcache_fd;
+ int do_close = 0;
+ unsigned int pbs = 0;
+ unsigned int lbs = 0;
+
+ if (dev->physical_block_size || dev->logical_block_size) {
+ *physical_block_size = dev->physical_block_size;
+ *logical_block_size = dev->logical_block_size;
+ return 1;
+ }
+
+ if (fd <= 0) {
+ if (!dev_open_readonly(dev))
+ return 0;
+ fd = dev_fd(dev);
+ do_close = 1;
+ }
+
+ /*
+ * BLKPBSZGET from kernel comment for blk_queue_physical_block_size:
+ * "the lowest possible sector size that the hardware can operate on
+ * without reverting to read-modify-write operations"
+ */
+ if (ioctl(fd, BLKPBSZGET, &pbs)) {
+ stack;
+ pbs = 0;
+ }
+
+ /*
+ * BLKSSZGET from kernel comment for blk_queue_logical_block_size:
+ * "the lowest possible block size that the storage device can address."
+ */
+ if (ioctl(fd, BLKSSZGET, &lbs)) {
+ stack;
+ lbs = 0;
+ }
+
+ dev->physical_block_size = pbs;
+ dev->logical_block_size = lbs;
+
+ *physical_block_size = pbs;
+ *logical_block_size = lbs;
+
+ if (do_close && !dev_close_immediate(dev))
+ stack;
+
+ return 1;
+}
+
/*-----------------------------------------------------------------
* LVM2 uses O_DIRECT when performing metadata io, which requires
* block size aligned accesses. If any io is not aligned we have
diff --git a/lib/device/device.h b/lib/device/device.h
index bbd965a..aafc401 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -67,8 +67,10 @@ struct device {
int open_count;
int error_count;
int max_error_count;
- int phys_block_size;
- int block_size;
+ int phys_block_size; /* From either BLKPBSZGET or BLKSSZGET, don't use */
+ int block_size; /* From BLKBSZGET, returns bdev->bd_block_size, likely set by fs, probably don't use */
+ int physical_block_size; /* From BLKPBSZGET: lowest possible sector size that the hardware can operate on without reverting to read-modify-write operations */
+ int logical_block_size; /* From BLKSSZGET: lowest possible block size that the storage device can address */
int read_ahead;
int bcache_fd;
uint32_t flags;
@@ -132,6 +134,8 @@ void dev_size_seqno_inc(void);
* 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_direct_block_sizes(struct device *dev, unsigned int *physical_block_size,
+ unsigned int *logical_block_size);
int dev_get_size(struct device *dev, uint64_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/label/label.c b/lib/label/label.c
index bc31a7c..8107e33 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -1498,15 +1498,34 @@ bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val)
void dev_set_last_byte(struct device *dev, uint64_t offset)
{
- unsigned int phys_block_size = 0;
- unsigned int block_size = 0;
+ unsigned int physical_block_size = 0;
+ unsigned int logical_block_size = 0;
+ unsigned int bs;
- if (!dev_get_block_size(dev, &phys_block_size, &block_size)) {
+ if (!dev_get_direct_block_sizes(dev, &physical_block_size, &logical_block_size)) {
stack;
return; /* FIXME: error path ? */
}
- bcache_set_last_byte(scan_bcache, dev->bcache_fd, offset, phys_block_size);
+ if ((physical_block_size == 512) && (logical_block_size == 512))
+ bs = 512;
+ else if ((physical_block_size == 4096) && (logical_block_size == 4096))
+ bs = 4096;
+ else if ((physical_block_size == 512) || (logical_block_size == 512)) {
+ log_debug("Set last byte mixed block sizes physical %u logical %u using 512",
+ physical_block_size, logical_block_size);
+ bs = 512;
+ } else if ((physical_block_size == 4096) || (logical_block_size == 4096)) {
+ log_debug("Set last byte mixed block sizes physical %u logical %u using 4096",
+ physical_block_size, logical_block_size);
+ bs = 4096;
+ } else {
+ log_debug("Set last byte mixed block sizes physical %u logical %u using 512",
+ physical_block_size, logical_block_size);
+ bs = 512;
+ }
+
+ bcache_set_last_byte(scan_bcache, dev->bcache_fd, offset, bs);
}
void dev_unset_last_byte(struct device *dev)
4 years, 4 months
master - WHATS_NEW: fix large physical block size
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=c1996c78c18ee0b555e...
Commit: c1996c78c18ee0b555e4f7eba16858d8dd4fa0a1
Parent: e3ba8561fa128e145c6952f4b962c11fc93f4ebc
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Jul 30 16:14:28 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Tue Jul 30 16:14:28 2019 -0500
WHATS_NEW: fix large physical block size
---
WHATS_NEW | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index e4d1ac7..cb693de 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.03.06 -
================================
+ Fix metadata writes from corrupting with large physical block size.
Version 2.03.05 - 15th June 2019
================================
4 years, 4 months
master - tests: large-physical-sector-size
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=e3ba8561fa128e145c6...
Commit: e3ba8561fa128e145c6952f4b962c11fc93f4ebc
Parent: 7f347698e3d09b15b4f9aed9c61239fda7b9e8c8
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Jul 30 15:59:11 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Tue Jul 30 15:59:11 2019 -0500
tests: large-physical-sector-size
---
test/shell/large-physical-sector-size.sh | 43 ++++++++++++++++++++++++++++++
1 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/test/shell/large-physical-sector-size.sh b/test/shell/large-physical-sector-size.sh
new file mode 100644
index 0000000..891f409
--- /dev/null
+++ b/test/shell/large-physical-sector-size.sh
@@ -0,0 +1,43 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2019 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_LVMPOLLD=1
+
+. lib/inittest
+
+LOGICAL_BLOCK_SIZE=4096
+
+# PHYSICAL_BLOCK_SIZE is set with physblk_exp which
+# shifts the logical block size value.
+
+# 4096 << 9 = 2MB physical block size
+PHYSICAL_BLOCK_SHIFT=9
+
+aux prepare_scsi_debug_dev 256 sector_size=$LOGICAL_BLOCK_SIZE physblk_exp=$PHYSICAL_BLOCK_SHIFT
+
+check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size "$LOGICAL_BLOCK_SIZE"
+
+aux prepare_pvs 1 256
+
+get_devs
+
+vgcreate $SHARED $vg "$dev1"
+
+for i in `seq 1 40`; do lvcreate -an -l1 $vg; done;
+
+lvs $vg
+
+lvremove -y $vg
+
+vgremove $vg
+
+aux cleanup_scsi_debug_dev
4 years, 4 months
master - Fix rounding writes up to sector size
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=7f347698e3d09b15b4f...
Commit: 7f347698e3d09b15b4f9aed9c61239fda7b9e8c8
Parent: dd19fa9ff36ce8a17452f83e6264bbf6c34f83ae
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Jul 26 14:21:08 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Jul 26 14:21:08 2019 -0500
Fix rounding writes up to sector size
Do this at two levels, although one would be enough to
fix the problem seen recently:
- Ignore any reported sector size other than 512 of 4096.
If either sector size (physical or logical) is reported
as 512, then use 512. If neither are reported as 512,
and one or the other is reported as 4096, then use 4096.
If neither is reported as either 512 or 4096, then use 512.
- When rounding up a limited write in bcache to be a multiple
of the sector size, check that the resulting write size is
not larger than the bcache block itself. (This shouldn't
happen if the sector size is 512 or 4096.)
---
lib/device/bcache.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++-
lib/device/dev-io.c | 52 +++++++++++++++++++++++++++++
lib/device/device.h | 8 +++-
lib/label/label.c | 30 ++++++++++++++---
4 files changed, 169 insertions(+), 10 deletions(-)
diff --git a/lib/device/bcache.c b/lib/device/bcache.c
index 7b09353..04fbf35 100644
--- a/lib/device/bcache.c
+++ b/lib/device/bcache.c
@@ -169,6 +169,7 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd,
sector_t offset;
sector_t nbytes;
sector_t limit_nbytes;
+ sector_t orig_nbytes;
sector_t extra_nbytes = 0;
if (((uintptr_t) data) & e->page_mask) {
@@ -191,11 +192,41 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd,
return false;
}
+ /*
+ * If the bcache block offset+len goes beyond where lvm is
+ * intending to write, then reduce the len being written
+ * (which is the bcache block size) so we don't write past
+ * the limit set by lvm. If after applying the limit, the
+ * resulting size is not a multiple of the sector size (512
+ * or 4096) then extend the reduced size to be a multiple of
+ * the sector size (we don't want to write partial sectors.)
+ */
if (offset + nbytes > _last_byte_offset) {
limit_nbytes = _last_byte_offset - offset;
- if (limit_nbytes % _last_byte_sector_size)
+
+ if (limit_nbytes % _last_byte_sector_size) {
extra_nbytes = _last_byte_sector_size - (limit_nbytes % _last_byte_sector_size);
+ /*
+ * adding extra_nbytes to the reduced nbytes (limit_nbytes)
+ * should make the final write size a multiple of the
+ * sector size. This should never result in a final size
+ * larger than the bcache block size (as long as the bcache
+ * block size is a multiple of the sector size).
+ */
+ if (limit_nbytes + extra_nbytes > nbytes) {
+ log_warn("Skip extending write at %llu len %llu limit %llu extra %llu sector_size %llu",
+ (unsigned long long)offset,
+ (unsigned long long)nbytes,
+ (unsigned long long)limit_nbytes,
+ (unsigned long long)extra_nbytes,
+ (unsigned long long)_last_byte_sector_size);
+ extra_nbytes = 0;
+ }
+ }
+
+ orig_nbytes = nbytes;
+
if (extra_nbytes) {
log_debug("Limit write at %llu len %llu to len %llu rounded to %llu",
(unsigned long long)offset,
@@ -210,6 +241,22 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd,
(unsigned long long)limit_nbytes);
nbytes = limit_nbytes;
}
+
+ /*
+ * This shouldn't happen, the reduced+extended
+ * nbytes value should never be larger than the
+ * bcache block size.
+ */
+ if (nbytes > orig_nbytes) {
+ log_error("Invalid adjusted write at %llu len %llu adjusted %llu limit %llu extra %llu sector_size %llu",
+ (unsigned long long)offset,
+ (unsigned long long)orig_nbytes,
+ (unsigned long long)nbytes,
+ (unsigned long long)limit_nbytes,
+ (unsigned long long)extra_nbytes,
+ (unsigned long long)_last_byte_sector_size);
+ return false;
+ }
}
}
@@ -403,6 +450,7 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
uint64_t nbytes = len;
sector_t limit_nbytes = 0;
sector_t extra_nbytes = 0;
+ sector_t orig_nbytes = 0;
if (offset > _last_byte_offset) {
log_error("Limit write at %llu len %llu beyond last byte %llu",
@@ -415,9 +463,30 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
if (offset + nbytes > _last_byte_offset) {
limit_nbytes = _last_byte_offset - offset;
- if (limit_nbytes % _last_byte_sector_size)
+
+ if (limit_nbytes % _last_byte_sector_size) {
extra_nbytes = _last_byte_sector_size - (limit_nbytes % _last_byte_sector_size);
+ /*
+ * adding extra_nbytes to the reduced nbytes (limit_nbytes)
+ * should make the final write size a multiple of the
+ * sector size. This should never result in a final size
+ * larger than the bcache block size (as long as the bcache
+ * block size is a multiple of the sector size).
+ */
+ if (limit_nbytes + extra_nbytes > nbytes) {
+ log_warn("Skip extending write at %llu len %llu limit %llu extra %llu sector_size %llu",
+ (unsigned long long)offset,
+ (unsigned long long)nbytes,
+ (unsigned long long)limit_nbytes,
+ (unsigned long long)extra_nbytes,
+ (unsigned long long)_last_byte_sector_size);
+ extra_nbytes = 0;
+ }
+ }
+
+ orig_nbytes = nbytes;
+
if (extra_nbytes) {
log_debug("Limit write at %llu len %llu to len %llu rounded to %llu",
(unsigned long long)offset,
@@ -432,6 +501,22 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
(unsigned long long)limit_nbytes);
nbytes = limit_nbytes;
}
+
+ /*
+ * This shouldn't happen, the reduced+extended
+ * nbytes value should never be larger than the
+ * bcache block size.
+ */
+ if (nbytes > orig_nbytes) {
+ log_error("Invalid adjusted write at %llu len %llu adjusted %llu limit %llu extra %llu sector_size %llu",
+ (unsigned long long)offset,
+ (unsigned long long)orig_nbytes,
+ (unsigned long long)nbytes,
+ (unsigned long long)limit_nbytes,
+ (unsigned long long)extra_nbytes,
+ (unsigned long long)_last_byte_sector_size);
+ return false;
+ }
}
where = offset;
diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c
index 3fe2647..5fa0b7a 100644
--- a/lib/device/dev-io.c
+++ b/lib/device/dev-io.c
@@ -250,6 +250,58 @@ static int _dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64
return 1;
}
+int dev_get_direct_block_sizes(struct device *dev, unsigned int *physical_block_size,
+ unsigned int *logical_block_size)
+{
+ int fd = dev->bcache_fd;
+ int do_close = 0;
+ unsigned int pbs = 0;
+ unsigned int lbs = 0;
+
+ if (dev->physical_block_size || dev->logical_block_size) {
+ *physical_block_size = dev->physical_block_size;
+ *logical_block_size = dev->logical_block_size;
+ return 1;
+ }
+
+ if (fd <= 0) {
+ if (!dev_open_readonly(dev))
+ return 0;
+ fd = dev_fd(dev);
+ do_close = 1;
+ }
+
+ /*
+ * BLKPBSZGET from kernel comment for blk_queue_physical_block_size:
+ * "the lowest possible sector size that the hardware can operate on
+ * without reverting to read-modify-write operations"
+ */
+ if (ioctl(fd, BLKPBSZGET, &pbs)) {
+ stack;
+ pbs = 0;
+ }
+
+ /*
+ * BLKSSZGET from kernel comment for blk_queue_logical_block_size:
+ * "the lowest possible block size that the storage device can address."
+ */
+ if (ioctl(fd, BLKSSZGET, &lbs)) {
+ stack;
+ lbs = 0;
+ }
+
+ dev->physical_block_size = pbs;
+ dev->logical_block_size = lbs;
+
+ *physical_block_size = pbs;
+ *logical_block_size = lbs;
+
+ if (do_close && !dev_close_immediate(dev))
+ stack;
+
+ return 1;
+}
+
/*-----------------------------------------------------------------
* Public functions
*---------------------------------------------------------------*/
diff --git a/lib/device/device.h b/lib/device/device.h
index 30e1e79..bb65f84 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -67,8 +67,10 @@ struct device {
/* private */
int fd;
int open_count;
- int phys_block_size;
- int block_size;
+ int phys_block_size; /* From either BLKPBSZGET or BLKSSZGET, don't use */
+ int block_size; /* From BLKBSZGET, returns bdev->bd_block_size, likely set by fs, probably don't use */
+ int physical_block_size; /* From BLKPBSZGET: lowest possible sector size that the hardware can operate on without reverting to read-modify-write operations */
+ int logical_block_size; /* From BLKSSZGET: lowest possible block size that the storage device can address */
int read_ahead;
int bcache_fd;
uint32_t flags;
@@ -132,6 +134,8 @@ void dev_size_seqno_inc(void);
* 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_direct_block_sizes(struct device *dev, unsigned int *physical_block_size,
+ unsigned int *logical_block_size);
int dev_get_size(struct device *dev, uint64_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/label/label.c b/lib/label/label.c
index fb7ad1d..5d8a0f5 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -1495,16 +1495,34 @@ bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val)
void dev_set_last_byte(struct device *dev, uint64_t offset)
{
- unsigned int phys_block_size = 0;
- unsigned int block_size = 0;
+ unsigned int physical_block_size = 0;
+ unsigned int logical_block_size = 0;
+ unsigned int bs;
- if (!dev_get_block_size(dev, &phys_block_size, &block_size)) {
+ if (!dev_get_direct_block_sizes(dev, &physical_block_size, &logical_block_size)) {
stack;
- /* FIXME ASSERT or regular error testing is missing */
- return;
+ return; /* FIXME: error path ? */
+ }
+
+ if ((physical_block_size == 512) && (logical_block_size == 512))
+ bs = 512;
+ else if ((physical_block_size == 4096) && (logical_block_size == 4096))
+ bs = 4096;
+ else if ((physical_block_size == 512) || (logical_block_size == 512)) {
+ log_debug("Set last byte mixed block sizes physical %u logical %u using 512",
+ physical_block_size, logical_block_size);
+ bs = 512;
+ } else if ((physical_block_size == 4096) || (logical_block_size == 4096)) {
+ log_debug("Set last byte mixed block sizes physical %u logical %u using 4096",
+ physical_block_size, logical_block_size);
+ bs = 4096;
+ } else {
+ log_debug("Set last byte mixed block sizes physical %u logical %u using 512",
+ physical_block_size, logical_block_size);
+ bs = 512;
}
- bcache_set_last_byte(scan_bcache, dev->bcache_fd, offset, phys_block_size);
+ bcache_set_last_byte(scan_bcache, dev->bcache_fd, offset, bs);
}
void dev_unset_last_byte(struct device *dev)
4 years, 4 months
master - tests: Fix unbound variable
by Marian Csontos
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=dd19fa9ff36ce8a1745...
Commit: dd19fa9ff36ce8a17452f83e6264bbf6c34f83ae
Parent: aa58f9bd9b28e8b734a6d723234f9ed1de28265b
Author: Marian Csontos <mcsontos(a)redhat.com>
AuthorDate: Tue Jul 23 15:36:13 2019 +0200
Committer: Marian Csontos <mcsontos(a)redhat.com>
CommitterDate: Wed Jul 24 16:30:15 2019 +0200
tests: Fix unbound variable
Test `aux kernel_at_least 5 1` fails even for newer kernel
with `$3: unbound variable` when using `set -u`.
---
test/lib/aux.sh | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/test/lib/aux.sh b/test/lib/aux.sh
index 0cc26a4..e3f624c 100644
--- a/test/lib/aux.sh
+++ b/test/lib/aux.sh
@@ -1387,17 +1387,17 @@ version_at_least() {
IFS=".-" read -r major minor revision <<< "$1"
shift
- test -z "${1:-}" && return 0
+ test -n "${1:-}" || return 0
test -n "$major" || return 1
test "$major" -gt "$1" && return 0
test "$major" -eq "$1" || return 1
- test -n "$2" || return 0
+ test -n "${2:-}" || return 0
test -n "$minor" || return 1
test "$minor" -gt "$2" && return 0
test "$minor" -eq "$2" || return 1
- test -n "$3" || return 0
+ test -n "${3:-}" || return 0
test "$revision" -ge "$3" 2>/dev/null || return 1
}
#
4 years, 4 months
stable-2.02 - vgrename: use global lock
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=3d980172b076547865e...
Commit: 3d980172b076547865efe5ca0839cabedc05a7b9
Parent: e3c8cebd87f9bd7591529f3d65783cc6f1fd3f92
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Mon Jul 22 12:12:42 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Mon Jul 22 12:22:12 2019 -0500
vgrename: use global lock
Should fix a reported problem of pvs seeing bad orphan
info while vgrename was running.
---
tools/vgrename.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/tools/vgrename.c b/tools/vgrename.c
index 4f2a08b..f13289e 100644
--- a/tools/vgrename.c
+++ b/tools/vgrename.c
@@ -202,6 +202,11 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
if (!(vp.vg_name_new = dm_pool_strdup(cmd->mem, vg_name_new)))
return_ECMD_FAILED;
+ if (!lock_vol(cmd, VG_GLOBAL, LCK_VG_WRITE, NULL)) {
+ log_error("Unable to obtain global lock.");
+ return_ECMD_FAILED;
+ }
+
/* Needed change the global VG namespace. */
if (!lockd_gl(cmd, "ex", LDGL_UPDATE_NAMES))
return_ECMD_FAILED;
4 years, 4 months
master - tests: lvm-on-md use variable run dir
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=aa58f9bd9b28e8b734a...
Commit: aa58f9bd9b28e8b734a6d723234f9ed1de28265b
Parent: bbca70a0b7de682ce3f4547f313f55a9a44ed89d
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Jul 12 16:51:49 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Jul 12 16:51:49 2019 -0500
tests: lvm-on-md use variable run dir
for hints file
---
test/shell/lvm-on-md.sh | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/test/shell/lvm-on-md.sh b/test/shell/lvm-on-md.sh
index c848083..2877ea2 100644
--- a/test/shell/lvm-on-md.sh
+++ b/test/shell/lvm-on-md.sh
@@ -16,6 +16,7 @@ RUNDIR="/run"
test -d "$RUNDIR" || RUNDIR="/var/run"
PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online"
VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online"
+HINTS="$RUNDIR/lvm/hints"
_clear_online_files() {
# wait till udev is finished
@@ -330,10 +331,10 @@ pvs > out
not grep "$dev1" out
not grep "$dev2" out
-grep "$mddev" /run/lvm/hints
-grep "$dev3" /run/lvm/hints
-not grep "$dev1" /run/lvm/hints
-not grep "$dev2" /run/lvm/hints
+grep "$mddev" $HINTS
+grep "$dev3" $HINTS
+not grep "$dev1" $HINTS
+not grep "$dev2" $HINTS
sleep 1
@@ -363,7 +364,7 @@ not grep "$mddev" out2
not grep "$dev1" out2
not grep "$dev2" out2
grep "$dev3" out2
-cat /run/lvm/hints
+cat $HINTS
pvs 2>&1|tee out1
grep -v WARNING out1 > out2
@@ -372,7 +373,7 @@ not grep "$mddev" out2
not grep "$dev1" out2
not grep "$dev2" out2
grep "$dev3" out2
-cat /run/lvm/hints
+cat $HINTS
# The md components should still be detected and excluded.
not pvs "$dev1"
4 years, 4 months