import lvm2-2.03.05-5.el8

This commit is contained in:
CentOS Sources 2019-11-06 11:35:32 -05:00 committed by Andrew Lukoshko
commit 086538bddf
46 changed files with 8644 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
SOURCES/LVM2.2.03.05.tgz

1
.lvm2.metadata Normal file
View File

@ -0,0 +1 @@
edfa340a4bbdb3e995521bebbe5307fd7687ac3b SOURCES/LVM2.2.03.05.tgz

View File

@ -0,0 +1,281 @@
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 4c21d97..72be5ec 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -1472,16 +1472,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)

View File

@ -0,0 +1,54 @@
daemons/lvmlockd/Makefile.in | 21 ++++++++++++++-------
daemons/lvmlockd/lvmlockd-core.c | 2 +-
2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/daemons/lvmlockd/Makefile.in b/daemons/lvmlockd/Makefile.in
index dca05b8..9c03401 100644
--- a/daemons/lvmlockd/Makefile.in
+++ b/daemons/lvmlockd/Makefile.in
@@ -38,18 +38,25 @@ TARGETS = lvmlockd lvmlockctl
include $(top_builddir)/make.tmpl
-CFLAGS += $(EXTRA_EXEC_CFLAGS) $(SYSTEMD_CFLAGS)
+CFLAGS += $(EXTRA_EXEC_CFLAGS)
INCLUDES += -I$(top_srcdir)/libdaemon/server
-LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
-LIBS += $(PTHREAD_LIBS) $(SYSTEMD_LIBS)
+LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
+LIBS += $(RT_LIBS) $(DAEMON_LIBS) $(PTHREAD_LIBS)
-lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/server/libdaemonserver.a $(INTERNAL_LIBS)
+
+ifeq ($(USE_SD_NOTIFY),yes)
+ CFLAGS += $(shell pkg-config --cflags libsystemd) -DUSE_SD_NOTIFY
+ LIBS += $(shell pkg-config --libs libsystemd)
+endif
+
+lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
+ $(top_builddir)/libdaemon/server/libdaemonserver.a
@echo " [CC] $@"
- $(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LOCK_LIBS) $(LIBS)
+ $(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LOCK_LIBS) -ldaemonserver $(INTERNAL_LIBS) $(LIBS)
-lvmlockctl: lvmlockctl.o $(INTERNAL_LIBS)
+lvmlockctl: lvmlockctl.o $(top_builddir)/libdaemon/client/libdaemonclient.a
@echo " [CC] $@"
- $(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
+ $(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmlockctl.o $(INTERNAL_LIBS) $(LIBS)
install_lvmlockd: lvmlockd
@echo " [INSTALL] $<"
diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c
index 5609ccc..39275fb 100644
--- a/daemons/lvmlockd/lvmlockd-core.c
+++ b/daemons/lvmlockd/lvmlockd-core.c
@@ -31,7 +31,7 @@
#include <sys/utsname.h>
#include <sys/un.h>
-#ifdef NOTIFYDBUS_SUPPORT
+#ifdef USE_SD_NOTIFY
#include <systemd/sd-daemon.h>
#endif

View File

@ -0,0 +1,15 @@
WHATS_NEW | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/WHATS_NEW b/WHATS_NEW
index 3a58de5..cb693de 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,3 +1,7 @@
+Version 2.03.06 -
+================================
+ Fix metadata writes from corrupting with large physical block size.
+
Version 2.03.05 - 15th June 2019
================================
Fix command definition for pvchange -a.

View File

@ -0,0 +1,14 @@
WHATS_NEW | 1 +
1 file changed, 1 insertion(+)
diff --git a/WHATS_NEW b/WHATS_NEW
index cb693de..a7ccd39 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.03.06 -
================================
+ Prevent creating VGs with PVs with different logical block sizes.
Fix metadata writes from corrupting with large physical block size.
Version 2.03.05 - 15th June 2019

View File

@ -0,0 +1,135 @@
conf/example.conf.in | 9 +++----
man/lvconvert.8_pregen | 70 +++++++++++++++++++++++++++-----------------------
2 files changed, 42 insertions(+), 37 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index b9cdf0c..ed6a3b6 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -143,7 +143,7 @@ devices {
#
# Example
# Accept every block device:
- # filter = [ "a|.*/|" ]
+ # filter = [ "a|.*|" ]
# Reject the cdrom drive:
# filter = [ "r|/dev/cdrom|" ]
# Work with just loopback devices, e.g. for testing:
@@ -151,10 +151,10 @@ devices {
# Accept all loop devices and ide drives except hdc:
# filter = [ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ]
# Use anchors to be very specific:
- # filter = [ "a|^/dev/hda8$|", "r|.*/|" ]
+ # filter = [ "a|^/dev/hda8$|", "r|.*|" ]
#
# This configuration option has an automatic default value.
- # filter = [ "a|.*/|" ]
+ # filter = [ "a|.*|" ]
# Configuration option devices/global_filter.
# Limit the block devices that are used by LVM system components.
@@ -164,7 +164,7 @@ devices {
# The syntax is the same as devices/filter. Devices rejected by
# global_filter are not opened by LVM.
# This configuration option has an automatic default value.
- # global_filter = [ "a|.*/|" ]
+ # global_filter = [ "a|.*|" ]
# Configuration option devices/types.
# List of additional acceptable block device types.
@@ -1752,7 +1752,6 @@ activation {
# additional space for VG metadata. The --metadatasize option overrides
# this setting.
# This configuration option does not have a default value defined.
- # This configuration option has an automatic default value.
# Configuration option metadata/pvmetadataignore.
# Ignore metadata areas on a new PV.
diff --git a/man/lvconvert.8_pregen b/man/lvconvert.8_pregen
index 7252f6f..846ea2d 100644
--- a/man/lvconvert.8_pregen
+++ b/man/lvconvert.8_pregen
@@ -378,6 +378,44 @@ Convert LV to striped.
.RE
-
+Convert LV to type mirror (also see type raid1),
+.br
+.P
+\fBlvconvert\fP \fB--type\fP \fBmirror\fP \fILV\fP
+.br
+.RS 4
+.ad l
+[ \fB-m\fP|\fB--mirrors\fP [\fB+\fP|\fB-\fP]\fINumber\fP ]
+.ad b
+.br
+.ad l
+[ \fB-I\fP|\fB--stripesize\fP \fISize\fP[k|UNIT] ]
+.ad b
+.br
+.ad l
+[ \fB-R\fP|\fB--regionsize\fP \fISize\fP[m|UNIT] ]
+.ad b
+.br
+.ad l
+[ \fB-i\fP|\fB--interval\fP \fINumber\fP ]
+.ad b
+.br
+.ad l
+[ \fB--stripes\fP \fINumber\fP ]
+.ad b
+.br
+.ad l
+[ \fB--mirrorlog\fP \fBcore\fP|\fBdisk\fP ]
+.ad b
+.br
+[ COMMON_OPTIONS ]
+.RE
+.br
+.RS 4
+[ \fIPV\fP ... ]
+.RE
+-
+
Convert LV to raid or change raid layout
.br
(a specific raid level must be used, e.g. raid1).
@@ -1636,38 +1674,6 @@ For example, LVM_VG_NAME can generally be substituted for a required VG paramete
.SH ADVANCED USAGE
Alternate command forms, advanced command usage, and listing of all valid syntax for completeness.
.P
-Convert LV to type mirror (also see type raid1),
-.br
-(also see lvconvert --mirrors).
-.br
-.P
-\fBlvconvert\fP \fB--type\fP \fBmirror\fP \fILV\fP
-.br
-.RS 4
-.ad l
-[ \fB-m\fP|\fB--mirrors\fP [\fB+\fP|\fB-\fP]\fINumber\fP ]
-.ad b
-.br
-.ad l
-[ \fB-R\fP|\fB--regionsize\fP \fISize\fP[m|UNIT] ]
-.ad b
-.br
-.ad l
-[ \fB-i\fP|\fB--interval\fP \fINumber\fP ]
-.ad b
-.br
-.ad l
-[ \fB--mirrorlog\fP \fBcore\fP|\fBdisk\fP ]
-.ad b
-.br
-[ COMMON_OPTIONS ]
-.RE
-.br
-.RS 4
-[ \fIPV\fP ... ]
-.RE
--
-
Change the region size of an LV.
.br
.P

View File

@ -0,0 +1,56 @@
test/shell/cache-single-options.sh | 2 +-
tools/lvchange.c | 8 ++++++++
tools/lvconvert.c | 8 ++++++++
3 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/test/shell/cache-single-options.sh b/test/shell/cache-single-options.sh
index da9cbba..6b71b2f 100644
--- a/test/shell/cache-single-options.sh
+++ b/test/shell/cache-single-options.sh
@@ -228,7 +228,7 @@ lvconvert -y --type cache --cachevol $lv2 $vg/$lv1
lvchange -ay $vg/$lv1
-lvchange --cachemode writeback $vg/$lv1
+lvchange -y --cachemode writeback $vg/$lv1
check lv_field $vg/$lv1 cachemode "writeback"
diff --git a/tools/lvchange.c b/tools/lvchange.c
index 7bdf997..92c6524 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -635,6 +635,14 @@ static int _lvchange_cache(struct cmd_context *cmd,
if (!get_cache_params(cmd, &chunk_size, &format, &mode, &name, &settings))
goto_out;
+ if (seg_is_cache(seg) && lv_is_cache_vol(seg->pool_lv) && (mode == CACHE_MODE_WRITEBACK)) {
+ log_warn("WARNING: repairing a damaged cachevol is not yet possible.");
+ log_warn("WARNING: cache mode writethrough is suggested for safe operation.");
+ if (!arg_count(cmd, yes_ARG) &&
+ yes_no_prompt("Continue using writeback without repair?") == 'n')
+ goto_out;
+ }
+
if ((mode != CACHE_MODE_UNSELECTED) &&
(mode != setting_seg->cache_mode) &&
lv_is_cache(lv)) {
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 24db8d2..ebc2243 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -3401,6 +3401,14 @@ static int _cache_vol_attach(struct cmd_context *cmd,
if (!cache_vol_set_params(cmd, cache_lv, lv_fast, poolmetadatasize, chunk_size, cache_metadata_format, cache_mode, policy_name, policy_settings))
goto_out;
+ if (cache_mode == CACHE_MODE_WRITEBACK) {
+ log_warn("WARNING: repairing a damaged cachevol is not yet possible.");
+ log_warn("WARNING: cache mode writethrough is suggested for safe operation.");
+ if (!arg_count(cmd, yes_ARG) &&
+ yes_no_prompt("Continue using writeback without repair?") == 'n')
+ goto_out;
+ }
+
/*
* lv/cache_lv keeps the same lockd lock it had before, the lock for
* lv_fast is freed, and lv_corig has no lock.

View File

@ -0,0 +1,16 @@
lib/config/config_settings.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index 70fb36d..f14f0b8 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -1694,7 +1694,7 @@ cfg(metadata_vgmetadatacopies_CFG, "vgmetadatacopies", metadata_CFG_SECTION, CFG
"and allows you to control which metadata areas are used at the\n"
"individual PV level using pvchange --metadataignore y|n.\n")
-cfg_runtime(metadata_pvmetadatasize_CFG, "pvmetadatasize", metadata_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, vsn(1, 0, 0), 0, NULL,
+cfg_runtime(metadata_pvmetadatasize_CFG, "pvmetadatasize", metadata_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, vsn(1, 0, 0), 0, NULL,
"The default size of the metadata area in units of 512 byte sectors.\n"
"The metadata area begins at an offset of the page size from the start\n"
"of the device. The first PE is by default at 1 MiB from the start of\n"

View File

@ -0,0 +1,38 @@
lib/config/config_settings.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index 3113fe1..70fb36d 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -288,7 +288,7 @@ cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, C
"preferred_names = [ \"^/dev/mpath/\", \"^/dev/mapper/mpath\", \"^/dev/[hs]d\" ]\n"
"#\n")
-cfg_array(devices_filter_CFG, "filter", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "#Sa|.*/|", vsn(1, 0, 0), NULL, 0, NULL,
+cfg_array(devices_filter_CFG, "filter", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "#Sa|.*|", vsn(1, 0, 0), NULL, 0, NULL,
"Limit the block devices that are used by LVM commands.\n"
"This is a list of regular expressions used to accept or reject block\n"
"device path names. Each regex is delimited by a vertical bar '|'\n"
@@ -306,7 +306,7 @@ cfg_array(devices_filter_CFG, "filter", devices_CFG_SECTION, CFG_DEFAULT_COMMENT
"#\n"
"Example\n"
"Accept every block device:\n"
- "filter = [ \"a|.*/|\" ]\n"
+ "filter = [ \"a|.*|\" ]\n"
"Reject the cdrom drive:\n"
"filter = [ \"r|/dev/cdrom|\" ]\n"
"Work with just loopback devices, e.g. for testing:\n"
@@ -314,10 +314,10 @@ cfg_array(devices_filter_CFG, "filter", devices_CFG_SECTION, CFG_DEFAULT_COMMENT
"Accept all loop devices and ide drives except hdc:\n"
"filter = [ \"a|loop|\", \"r|/dev/hdc|\", \"a|/dev/ide|\", \"r|.*|\" ]\n"
"Use anchors to be very specific:\n"
- "filter = [ \"a|^/dev/hda8$|\", \"r|.*/|\" ]\n"
+ "filter = [ \"a|^/dev/hda8$|\", \"r|.*|\" ]\n"
"#\n")
-cfg_array(devices_global_filter_CFG, "global_filter", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "#Sa|.*/|", vsn(2, 2, 98), NULL, 0, NULL,
+cfg_array(devices_global_filter_CFG, "global_filter", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "#Sa|.*|", vsn(2, 2, 98), NULL, 0, NULL,
"Limit the block devices that are used by LVM system components.\n"
"Because devices/filter may be overridden from the command line, it is\n"
"not suitable for system-wide device filtering, e.g. udev.\n"

View File

@ -0,0 +1,66 @@
configure | 6 +++---
configure.ac | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/configure b/configure
index ff3a59b..4c84765 100755
--- a/configure
+++ b/configure
@@ -3077,7 +3077,7 @@ if test -z "$CFLAGS"; then :
fi
case "$host_os" in
linux*)
- CLDFLAGS="${CLDFLAGS:"$LDFLAGS"} -Wl,--version-script,.export.sym"
+ CLDFLAGS="${CLDFLAGS-"$LDFLAGS"} -Wl,--version-script,.export.sym"
# equivalent to -rdynamic
ELDFLAGS="-Wl,--export-dynamic"
# FIXME Generate list and use --dynamic-list=.dlopen.sym
@@ -3098,7 +3098,7 @@ case "$host_os" in
;;
darwin*)
CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
- CLDFLAGS="${CLDFLAGS:"$LDFLAGS"}"
+ CLDFLAGS="${CLDFLAGS-"$LDFLAGS"}"
ELDFLAGS=
CLDWHOLEARCHIVE="-all_load"
CLDNOWHOLEARCHIVE=
@@ -3111,7 +3111,7 @@ case "$host_os" in
BLKDEACTIVATE=no
;;
*)
- CLDFLAGS="${CLDFLAGS:"$LDFLAGS"}"
+ CLDFLAGS="${CLDFLAGS-"$LDFLAGS"}"
;;
esac
diff --git a/configure.ac b/configure.ac
index 1e45c0e..9c82773 100644
--- a/configure.ac
+++ b/configure.ac
@@ -30,7 +30,7 @@ AC_CANONICAL_TARGET([])
AS_IF([test -z "$CFLAGS"], [COPTIMISE_FLAG="-O2"])
case "$host_os" in
linux*)
- CLDFLAGS="${CLDFLAGS:"$LDFLAGS"} -Wl,--version-script,.export.sym"
+ CLDFLAGS="${CLDFLAGS-"$LDFLAGS"} -Wl,--version-script,.export.sym"
# equivalent to -rdynamic
ELDFLAGS="-Wl,--export-dynamic"
# FIXME Generate list and use --dynamic-list=.dlopen.sym
@@ -51,7 +51,7 @@ case "$host_os" in
;;
darwin*)
CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
- CLDFLAGS="${CLDFLAGS:"$LDFLAGS"}"
+ CLDFLAGS="${CLDFLAGS-"$LDFLAGS"}"
ELDFLAGS=
CLDWHOLEARCHIVE="-all_load"
CLDNOWHOLEARCHIVE=
@@ -64,7 +64,7 @@ case "$host_os" in
BLKDEACTIVATE=no
;;
*)
- CLDFLAGS="${CLDFLAGS:"$LDFLAGS"}"
+ CLDFLAGS="${CLDFLAGS-"$LDFLAGS"}"
;;
esac

View File

@ -0,0 +1,16 @@
libdaemon/server/daemon-server.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libdaemon/server/daemon-server.c b/libdaemon/server/daemon-server.c
index 9dd0017..2df4e89 100644
--- a/libdaemon/server/daemon-server.c
+++ b/libdaemon/server/daemon-server.c
@@ -690,7 +690,7 @@ void daemon_start(daemon_state s)
out:
/* If activated by systemd, do not unlink the socket - systemd takes care of that! */
if (!_systemd_activation && s.socket_fd >= 0)
- if (unlink(s.socket_path))
+ if (s.socket_path && unlink(s.socket_path))
perror("unlink error");
if (s.socket_fd >= 0)

View File

@ -0,0 +1,34 @@
tools/command.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/command.c b/tools/command.c
index 724040e..2e69eff 100644
--- a/tools/command.c
+++ b/tools/command.c
@@ -1935,7 +1935,7 @@ void print_usage(struct command *cmd, int longhelp, int desc_first)
* see print_common_options_cmd()
*/
- if ((cname->variants > 1) && cname->common_options[opt_enum])
+ if (cname && (cname->variants > 1) && cname->common_options[opt_enum])
continue;
printf("\n\t[");
@@ -1975,7 +1975,7 @@ void print_usage(struct command *cmd, int longhelp, int desc_first)
* see print_common_options_cmd()
*/
- if ((cname->variants > 1) && cname->common_options[opt_enum])
+ if (cname && (cname->variants > 1) && cname->common_options[opt_enum])
continue;
printf("\n\t[");
@@ -3438,7 +3438,7 @@ static int _print_man(char *name, char *des_file, int secondary)
if (!prev_cmd || strcmp(prev_cmd->name, cmd->name)) {
printf(".SH NAME\n");
- if (cname->desc)
+ if (cname && cname->desc)
printf("%s - %s\n", lvmname, cname->desc);
else
printf("%s\n", lvmname);

View File

@ -0,0 +1,30 @@
daemons/dmeventd/plugins/raid/dmeventd_raid.c | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/daemons/dmeventd/plugins/raid/dmeventd_raid.c b/daemons/dmeventd/plugins/raid/dmeventd_raid.c
index aa2b578..3431f1e 100644
--- a/daemons/dmeventd/plugins/raid/dmeventd_raid.c
+++ b/daemons/dmeventd/plugins/raid/dmeventd_raid.c
@@ -76,16 +76,12 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
}
if (dead) {
- if (status->insync_regions < status->total_regions) {
- if (!state->warned) {
- state->warned = 1;
- log_warn("WARNING: waiting for resynchronization to finish "
- "before initiating repair on RAID device %s.", device);
- }
-
- goto out; /* Not yet done syncing with accessible devices */
- }
-
+ /*
+ * Use the first event to run a repair ignoring any additonal ones.
+ *
+ * We presume lvconvert to do pre-repair
+ * checks to avoid bloat in this plugin.
+ */
if (state->failed)
goto out; /* already reported */

View File

@ -0,0 +1,151 @@
lib/device/dev-cache.c | 19 +++++++++++++++++++
lib/device/dev-cache.h | 3 +++
lib/device/dev-md.c | 6 +++---
lib/label/label.c | 27 ++++++++++++++-------------
tools/pvscan.c | 7 +++++++
5 files changed, 46 insertions(+), 16 deletions(-)
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index 1492181..980dd3c 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -15,6 +15,7 @@
#include "base/memory/zalloc.h"
#include "lib/misc/lib.h"
+#include "lib/device/dev-type.h"
#include "lib/datastruct/btree.h"
#include "lib/config/config.h"
#include "lib/commands/toolcontext.h"
@@ -1634,3 +1635,21 @@ const char *dev_name(const struct device *dev)
return (dev && dev->aliases.n) ? dm_list_item(dev->aliases.n, struct dm_str_list)->str :
unknown_device_name();
}
+
+bool dev_cache_has_md_with_end_superblock(struct dev_types *dt)
+{
+ struct btree_iter *iter = btree_first(_cache.devices);
+ struct device *dev;
+
+ while (iter) {
+ dev = btree_get_data(iter);
+
+ if (dev_is_md_with_end_superblock(dt, dev))
+ return true;
+
+ iter = btree_next(iter);
+ }
+
+ return false;
+}
+
diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h
index 8a1c277..46c86c2 100644
--- a/lib/device/dev-cache.h
+++ b/lib/device/dev-cache.h
@@ -17,6 +17,7 @@
#define _LVM_DEV_CACHE_H
#include "lib/device/device.h"
+#include "lib/device/dev-type.h"
#include "lib/misc/lvm-wrappers.h"
struct cmd_context;
@@ -71,4 +72,6 @@ void dev_reset_error_count(struct cmd_context *cmd);
void dev_cache_failed_path(struct device *dev, const char *path);
+bool dev_cache_has_md_with_end_superblock(struct dev_types *dt);
+
#endif
diff --git a/lib/device/dev-md.c b/lib/device/dev-md.c
index 08143b7..9d0a363 100644
--- a/lib/device/dev-md.c
+++ b/lib/device/dev-md.c
@@ -302,12 +302,12 @@ static int _md_sysfs_attribute_scanf(struct dev_types *dt,
return ret;
if (!(fp = fopen(path, "r"))) {
- log_sys_error("fopen", path);
+ log_debug("_md_sysfs_attribute_scanf fopen failed %s", path);
return ret;
}
if (!fgets(buffer, sizeof(buffer), fp)) {
- log_sys_error("fgets", path);
+ log_debug("_md_sysfs_attribute_scanf fgets failed %s", path);
goto out;
}
@@ -449,7 +449,7 @@ int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev)
if (_md_sysfs_attribute_scanf(dt, dev, attribute,
"%s", &version_string) != 1)
- return -1;
+ return 0;
log_very_verbose("Device %s %s is %s.",
dev_name(dev), attribute, version_string);
diff --git a/lib/label/label.c b/lib/label/label.c
index a8d87ec..4c21d97 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -901,6 +901,20 @@ int label_scan(struct cmd_context *cmd)
dev_cache_scan();
/*
+ * If we know that there will be md components with an end
+ * superblock, then enable the full md filter before label
+ * scan begins. FIXME: we could skip the full md check on
+ * devs that are not identified as PVs, but then we'd need
+ * to do something other than using the standard md filter.
+ */
+ if (cmd->md_component_detection && !cmd->use_full_md_check &&
+ !strcmp(cmd->md_component_checks, "auto") &&
+ dev_cache_has_md_with_end_superblock(cmd->dev_types)) {
+ log_debug("Enable full md component check.");
+ cmd->use_full_md_check = 1;
+ }
+
+ /*
* Set up the iterator that is needed to step through each device in
* dev cache.
*/
@@ -938,19 +952,6 @@ int label_scan(struct cmd_context *cmd)
bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
_scan_dev_close(dev);
}
-
- /*
- * When md devices exist that use the old superblock at the
- * end of the device, then in order to detect and filter out
- * the component devices of those md devs, we enable the full
- * md filter which scans both the start and the end of every
- * device. This doubles the amount of scanning i/o, which we
- * want to avoid. FIXME: this forces start+end scanning of
- * every device, but it would be more efficient to limit the
- * end scan only to PVs.
- */
- if (dev_is_md_with_end_superblock(cmd->dev_types, dev))
- cmd->use_full_md_check = 1;
};
dev_iter_destroy(iter);
diff --git a/tools/pvscan.c b/tools/pvscan.c
index db813ad..0a91add 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -938,6 +938,13 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv)
/* Creates a list of dev names from /dev, sysfs, etc; does not read any. */
dev_cache_scan();
+ if (cmd->md_component_detection && !cmd->use_full_md_check &&
+ !strcmp(cmd->md_component_checks, "auto") &&
+ dev_cache_has_md_with_end_superblock(cmd->dev_types)) {
+ log_debug("Enable full md component check.");
+ cmd->use_full_md_check = 1;
+ }
+
/*
* For each device command arg (from either position or --major/--minor),
* decide if that device is being added to the system (a dev node exists

View File

@ -0,0 +1,629 @@
lib/commands/toolcontext.h | 1 +
lib/metadata/metadata-exported.h | 1 -
lib/metadata/metadata.c | 42 ++++++++++++++++++++++----------
tools/command.c | 1 +
tools/commands.h | 29 +++++++++++-----------
tools/lvmcmdline.c | 2 ++
tools/pvchange.c | 7 +-----
tools/pvresize.c | 7 +-----
tools/toollib.c | 52 +++++++++++++++++++++++++++++++---------
tools/tools.h | 2 ++
tools/vgchange.c | 22 ++++-------------
tools/vgck.c | 3 ---
tools/vgimport.c | 6 ++---
tools/vgimportclone.c | 4 ++--
tools/vgreduce.c | 5 ++--
tools/vgremove.c | 3 ---
tools/vgrename.c | 3 +--
tools/vgsplit.c | 12 ++++++++--
18 files changed, 115 insertions(+), 87 deletions(-)
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index 6e4530c..488752c 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -148,6 +148,7 @@ struct cmd_context {
unsigned unknown_system_id:1;
unsigned include_historical_lvs:1; /* also process/report/display historical LVs */
unsigned record_historical_lvs:1; /* record historical LVs */
+ unsigned include_exported_vgs:1;
unsigned include_foreign_vgs:1; /* report/display cmds can reveal foreign VGs */
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 */
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 9029d3f..77b971b 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -181,7 +181,6 @@
#define MIRROR_SKIP_INIT_SYNC 0x00000010U /* skip initial sync */
/* vg_read and vg_read_for_update flags */
-#define READ_ALLOW_EXPORTED 0x00020000U
#define READ_OK_NOTFOUND 0x00040000U
#define READ_WARN_INCONSISTENT 0x00080000U
#define READ_FOR_UPDATE 0x00100000U /* A meta-flag, useful with toollib for_each_* functions. */
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 039a7d6..dc1b501 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -593,9 +593,6 @@ int vg_remove_check(struct volume_group *vg)
return 0;
}
- if (!vg_check_status(vg, EXPORTED_VG))
- return 0;
-
lv_count = vg_visible_lvs(vg);
if (lv_count) {
@@ -3709,12 +3706,6 @@ uint32_t vg_bad_status_bits(const struct volume_group *vg, uint64_t status)
/* Return because other flags are considered undefined. */
return FAILED_CLUSTERED;
- if ((status & EXPORTED_VG) &&
- vg_is_exported(vg)) {
- log_error("Volume group %s is exported", vg->name);
- failure |= FAILED_EXPORTED;
- }
-
if ((status & LVM_WRITE) &&
!(vg->status & LVM_WRITE)) {
log_error("Volume group %s is read-only", vg->name);
@@ -3733,7 +3724,7 @@ uint32_t vg_bad_status_bits(const struct volume_group *vg, uint64_t status)
/**
* vg_check_status - check volume group status flags and log error
* @vg - volume group to check status flags
- * @status - specific status flags to check (e.g. EXPORTED_VG)
+ * @status - specific status flags to check
*/
int vg_check_status(const struct volume_group *vg, uint64_t status)
{
@@ -3914,6 +3905,28 @@ static int _access_vg_systemid(struct cmd_context *cmd, struct volume_group *vg)
return 0;
}
+static int _access_vg_exported(struct cmd_context *cmd, struct volume_group *vg)
+{
+ if (!vg_is_exported(vg))
+ return 1;
+
+ if (cmd->include_exported_vgs)
+ return 1;
+
+ /*
+ * Some commands want the error printed by vg_read, others by ignore_vg.
+ * Those using ignore_vg may choose to skip the error.
+ */
+ if (cmd->vg_read_print_access_error) {
+ log_error("Volume group %s is exported", vg->name);
+ return 0;
+ }
+
+ /* Silently ignore exported vgs. */
+
+ return 0;
+}
+
/*
* Test the validity of a VG handle returned by vg_read() or vg_read_for_update().
*/
@@ -4883,8 +4896,7 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, const
goto_bad;
}
- if (writing && !(read_flags & READ_ALLOW_EXPORTED) && vg_is_exported(vg)) {
- log_error("Volume group %s is exported", vg->name);
+ if (!_access_vg_exported(cmd, vg)) {
failure |= FAILED_EXPORTED;
goto_bad;
}
@@ -4895,6 +4907,12 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, const
goto_bad;
}
+ if (writing && !(vg->status & LVM_WRITE)) {
+ log_error("Volume group %s is read-only", vg->name);
+ failure |= FAILED_READ_ONLY;
+ goto_bad;
+ }
+
if (!cmd->handles_missing_pvs && (missing_pv_dev || missing_pv_flag) && writing) {
log_error("Cannot change VG %s while PVs are missing.", vg->name);
log_error("See vgreduce --removemissing and vgextend --restoremissing.");
diff --git a/tools/command.c b/tools/command.c
index bdd18d6..724040e 100644
--- a/tools/command.c
+++ b/tools/command.c
@@ -137,6 +137,7 @@ static inline int configtype_arg(struct cmd_context *cmd __attribute__((unused))
#define GET_VGNAME_FROM_OPTIONS 0x00001000
#define CAN_USE_ONE_SCAN 0x00002000
#define ALLOW_HINTS 0x00004000
+#define ALLOW_EXPORTED 0x00008000
/* create foo_CMD enums for command def ID's in command-lines.in */
diff --git a/tools/commands.h b/tools/commands.h
index 4006fab..c1670ae 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -35,7 +35,7 @@ xx(help,
xx(fullreport,
"Display full report",
- PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH | ALLOW_HINTS)
+ PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH | ALLOW_HINTS | ALLOW_EXPORTED)
xx(lastlog,
"Display last command's log report",
@@ -71,7 +71,7 @@ xx(lvmconfig,
xx(lvmdiskscan,
"List devices that may be used as physical volumes",
- PERMITTED_READ_ONLY | ENABLE_ALL_DEVS)
+ PERMITTED_READ_ONLY | ENABLE_ALL_DEVS | ALLOW_EXPORTED)
xx(lvmsadc,
"Collect activity data",
@@ -115,7 +115,7 @@ xx(pvresize,
xx(pvck,
"Check metadata on physical volumes",
- LOCKD_VG_SH)
+ LOCKD_VG_SH | ALLOW_EXPORTED)
xx(pvcreate,
"Initialize physical volume(s) for use by LVM",
@@ -127,7 +127,7 @@ xx(pvdata,
xx(pvdisplay,
"Display various attributes of physical volume(s)",
- PERMITTED_READ_ONLY | ENABLE_ALL_DEVS | ENABLE_DUPLICATE_DEVS | LOCKD_VG_SH | CAN_USE_ONE_SCAN | ALLOW_HINTS)
+ PERMITTED_READ_ONLY | ENABLE_ALL_DEVS | ENABLE_DUPLICATE_DEVS | LOCKD_VG_SH | CAN_USE_ONE_SCAN | ALLOW_HINTS | ALLOW_EXPORTED)
/* ALL_VGS_IS_DEFAULT is for polldaemon to find pvmoves in-progress using process_each_vg. */
@@ -145,11 +145,11 @@ xx(pvremove,
xx(pvs,
"Display information about physical volumes",
- PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | ENABLE_ALL_DEVS | ENABLE_DUPLICATE_DEVS | LOCKD_VG_SH | CAN_USE_ONE_SCAN | ALLOW_HINTS)
+ PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | ENABLE_ALL_DEVS | ENABLE_DUPLICATE_DEVS | LOCKD_VG_SH | CAN_USE_ONE_SCAN | ALLOW_HINTS | ALLOW_EXPORTED)
xx(pvscan,
"List all physical volumes",
- PERMITTED_READ_ONLY | LOCKD_VG_SH)
+ PERMITTED_READ_ONLY | LOCKD_VG_SH | ALLOW_EXPORTED)
xx(segtypes,
"List available segment types",
@@ -165,11 +165,11 @@ xx(tags,
xx(vgcfgbackup,
"Backup volume group configuration(s)",
- PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH)
+ PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH | ALLOW_EXPORTED)
xx(vgcfgrestore,
"Restore volume group configuration",
- 0)
+ ALLOW_EXPORTED)
xx(vgchange,
"Change volume group attributes",
@@ -189,7 +189,7 @@ xx(vgcreate,
xx(vgdisplay,
"Display volume group information",
- PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH | CAN_USE_ONE_SCAN | ALLOW_HINTS)
+ PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH | CAN_USE_ONE_SCAN | ALLOW_HINTS | ALLOW_EXPORTED)
xx(vgexport,
"Unregister volume group(s) from the system",
@@ -201,10 +201,11 @@ xx(vgextend,
xx(vgimport,
"Register exported volume group with system",
- ALL_VGS_IS_DEFAULT)
+ ALL_VGS_IS_DEFAULT | ALLOW_EXPORTED)
xx(vgimportclone,
- "Import a VG from cloned PVs", 0)
+ "Import a VG from cloned PVs",
+ ALLOW_EXPORTED)
xx(vgmerge,
"Merge volume groups",
@@ -224,15 +225,15 @@ xx(vgremove,
xx(vgrename,
"Rename a volume group",
- ALLOW_UUID_AS_NAME)
+ ALLOW_UUID_AS_NAME | ALLOW_EXPORTED)
xx(vgs,
"Display information about volume groups",
- PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH | CAN_USE_ONE_SCAN | ALLOW_HINTS)
+ PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH | CAN_USE_ONE_SCAN | ALLOW_HINTS | ALLOW_EXPORTED)
xx(vgscan,
"Search for all volume groups",
- PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH)
+ PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH | ALLOW_EXPORTED)
xx(vgsplit,
"Move physical volumes into a new or existing volume group",
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 3fec702..30f9d81 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -2315,6 +2315,8 @@ static int _get_current_settings(struct cmd_context *cmd)
if (cmd->cname->flags & CAN_USE_ONE_SCAN)
cmd->can_use_one_scan = 1;
+ cmd->include_exported_vgs = (cmd->cname->flags & ALLOW_EXPORTED) ? 1 : 0;
+
cmd->scan_lvs = find_config_tree_bool(cmd, devices_scan_lvs_CFG, NULL);
/*
diff --git a/tools/pvchange.c b/tools/pvchange.c
index f37fd91..1ece34a 100644
--- a/tools/pvchange.c
+++ b/tools/pvchange.c
@@ -35,11 +35,6 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
params->total++;
- if (vg && vg_is_exported(vg)) {
- log_error("Volume group %s is exported", vg->name);
- goto bad;
- }
-
/*
* The primary location of this check is in vg_write(), but it needs
* to be copied here to prevent the pv_write() which is called before
@@ -239,7 +234,7 @@ int pvchange(struct cmd_context *cmd, int argc, char **argv)
clear_hint_file(cmd);
- ret = process_each_pv(cmd, argc, argv, NULL, 0, READ_FOR_UPDATE | READ_ALLOW_EXPORTED, handle, _pvchange_single);
+ ret = process_each_pv(cmd, argc, argv, NULL, 0, READ_FOR_UPDATE, handle, _pvchange_single);
log_print_unless_silent("%d physical volume%s changed / %d physical volume%s not changed",
params.done, params.done == 1 ? "" : "s",
diff --git a/tools/pvresize.c b/tools/pvresize.c
index c7e750d..2c7f543 100644
--- a/tools/pvresize.c
+++ b/tools/pvresize.c
@@ -36,11 +36,6 @@ static int _pvresize_single(struct cmd_context *cmd,
}
params->total++;
- if (vg && vg_is_exported(vg)) {
- log_error("Volume group %s is exported", vg->name);
- return ECMD_FAILED;
- }
-
/*
* Needed to change a property on an orphan PV.
* i.e. the global lock is only needed for orphans.
@@ -93,7 +88,7 @@ int pvresize(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &params;
- ret = process_each_pv(cmd, argc, argv, NULL, 0, READ_FOR_UPDATE | READ_ALLOW_EXPORTED, handle, _pvresize_single);
+ ret = process_each_pv(cmd, argc, argv, NULL, 0, READ_FOR_UPDATE, handle, _pvresize_single);
log_print_unless_silent("%d physical volume(s) resized or updated / %d physical volume(s) "
"not resized", params.done, params.total - params.done);
diff --git a/tools/toollib.c b/tools/toollib.c
index 506ad2d..b2313f8 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -223,6 +223,17 @@ static int _ignore_vg(struct cmd_context *cmd,
}
}
+ if (read_error & FAILED_EXPORTED) {
+ if (arg_vgnames && str_list_match_item(arg_vgnames, vg_name)) {
+ log_error("Volume group %s is exported", vg_name);
+ return 1;
+ } else {
+ read_error &= ~FAILED_EXPORTED; /* Check for other errors */
+ log_verbose("Skipping exported volume group %s", vg_name);
+ *skip = 1;
+ }
+ }
+
/*
* Commands that operate on "all vgs" shouldn't be bothered by
* skipping a foreign VG, and the command shouldn't fail when
@@ -3032,11 +3043,6 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
dm_list_init(&final_lvs);
dm_list_init(&found_arg_lvnames);
- if (!vg_check_status(vg, EXPORTED_VG)) {
- ret_max = ECMD_FAILED;
- goto_out;
- }
-
if (tags_in && !dm_list_empty(tags_in))
tags_supplied = 1;
@@ -4161,6 +4167,7 @@ static int _process_pvs_in_vg(struct cmd_context *cmd,
int process_all_pvs,
int process_all_devices,
int skip,
+ uint32_t error_flags,
struct processing_handle *handle,
process_single_pv_fn_t process_single_pv)
{
@@ -4216,21 +4223,42 @@ static int _process_pvs_in_vg(struct cmd_context *cmd,
}
process_pv = process_all_pvs;
+ dil = NULL;
/* Remove each arg_devices entry as it is processed. */
- if (!process_pv && !dm_list_empty(arg_devices) &&
- (dil = _device_list_find_dev(arg_devices, pv->dev))) {
- process_pv = 1;
- _device_list_remove(arg_devices, dil->dev);
+ if (arg_devices && !dm_list_empty(arg_devices)) {
+ if ((dil = _device_list_find_dev(arg_devices, pv->dev)))
+ _device_list_remove(arg_devices, dil->dev);
}
+ if (!process_pv && dil)
+ process_pv = 1;
+
if (!process_pv && !dm_list_empty(arg_tags) &&
str_list_match_list(arg_tags, &pv->tags, NULL))
process_pv = 1;
process_pv = process_pv && select_match_pv(cmd, handle, vg, pv) && _select_matches(handle);
+ /*
+ * The command has asked to process a specific PV
+ * named on the command line, but the VG containing
+ * that PV cannot be accessed. In this case report
+ * and return an error. If the inaccessible PV is
+ * not explicitly named on the command line, it is
+ * silently skipped.
+ */
+ if (process_pv && skip && dil && error_flags) {
+ if (error_flags & FAILED_EXPORTED)
+ log_error("Cannot use PV %s in exported VG %s.", pv_name, vg->name);
+ if (error_flags & FAILED_SYSTEMID)
+ log_error("Cannot use PV %s in foreign VG %s.", pv_name, vg->name);
+ if (error_flags & (FAILED_LOCK_TYPE | FAILED_LOCK_MODE))
+ log_error("Cannot use PV %s in shared VG %s.", pv_name, vg->name);
+ ret_max = ECMD_FAILED;
+ }
+
if (process_pv) {
if (skip)
log_verbose("Skipping PV %s in VG %s.", pv_name, vg->name);
@@ -4352,6 +4380,8 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t read_flags,
log_debug("Processing PVs in VG %s", vg_name);
+ error_flags = 0;
+
vg = vg_read(cmd, vg_name, vg_uuid, read_flags, lockd_state, &error_flags, &error_vg);
if (_ignore_vg(cmd, error_flags, error_vg, vg_name, NULL, read_flags, &skip, &notfound)) {
stack;
@@ -4359,7 +4389,7 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t read_flags,
report_log_ret_code(ret_max);
if (!skip)
goto endvg;
- /* Drop through to eliminate a clustered VG's PVs from the devices list */
+ /* Drop through to eliminate unmpermitted PVs from the devices list */
}
if (notfound)
goto endvg;
@@ -4370,7 +4400,7 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t read_flags,
*/
ret = _process_pvs_in_vg(cmd, vg ? vg : error_vg, all_devices, arg_devices, arg_tags,
- process_all_pvs, process_all_devices, skip,
+ process_all_pvs, process_all_devices, skip, error_flags,
handle, process_single_pv);
if (ret != ECMD_PROCESSED)
stack;
diff --git a/tools/tools.h b/tools/tools.h
index 69132a5..b78c471 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -136,6 +136,8 @@ struct arg_value_group_list {
#define CAN_USE_ONE_SCAN 0x00002000
/* Command can use hints file */
#define ALLOW_HINTS 0x00004000
+/* Command can access exported vg. */
+#define ALLOW_EXPORTED 0x00008000
void usage(const char *name);
diff --git a/tools/vgchange.c b/tools/vgchange.c
index a17f456..1ef94d6 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -630,13 +630,6 @@ static int _vgchange_single(struct cmd_context *cmd, const char *vg_name,
{ detachprofile_ARG, &_vgchange_profile },
};
- 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;
- }
-
/*
* FIXME: DEFAULT_BACKGROUND_POLLING should be "unspecified".
* If --poll is explicitly provided use it; otherwise polling
@@ -982,11 +975,6 @@ static int _vgchange_locktype_single(struct cmd_context *cmd, const char *vg_nam
struct volume_group *vg,
struct processing_handle *handle)
{
- if (vg_is_exported(vg)) {
- log_error("Volume group \"%s\" is exported", vg_name);
- return ECMD_FAILED;
- }
-
if (!archive(vg))
return_ECMD_FAILED;
@@ -1145,11 +1133,14 @@ int vgchange_lock_start_stop_cmd(struct cmd_context *cmd, int argc, char **argv)
/* Disable the lockd_gl in process_each_vg. */
cmd->lockd_gl_disable = 1;
+ } else {
+ /* If the VG was started when it was exported, allow it to be stopped. */
+ cmd->include_exported_vgs = 1;
}
handle->custom_handle = &vp;
- ret = process_each_vg(cmd, argc, argv, NULL, NULL, READ_ALLOW_EXPORTED, 0, handle, &_vgchange_lock_start_stop_single);
+ ret = process_each_vg(cmd, argc, argv, NULL, NULL, 0, 0, handle, &_vgchange_lock_start_stop_single);
/* Wait for lock-start ops that were initiated in vgchange_lockstart. */
@@ -1178,11 +1169,6 @@ static int _vgchange_systemid_single(struct cmd_context *cmd, const char *vg_nam
struct volume_group *vg,
struct processing_handle *handle)
{
- if (vg_is_exported(vg)) {
- log_error("Volume group \"%s\" is exported", vg_name);
- return ECMD_FAILED;
- }
-
if (!archive(vg))
return_ECMD_FAILED;
diff --git a/tools/vgck.c b/tools/vgck.c
index 90fc5a3..46ad594 100644
--- a/tools/vgck.c
+++ b/tools/vgck.c
@@ -71,9 +71,6 @@ static int vgck_single(struct cmd_context *cmd __attribute__((unused)),
struct volume_group *vg,
struct processing_handle *handle __attribute__((unused)))
{
- if (!vg_check_status(vg, EXPORTED_VG))
- return_ECMD_FAILED;
-
if (!vg_validate(vg))
return_ECMD_FAILED;
diff --git a/tools/vgimport.c b/tools/vgimport.c
index 26c6363..0d8b0f2 100644
--- a/tools/vgimport.c
+++ b/tools/vgimport.c
@@ -87,8 +87,6 @@ int vgimport(struct cmd_context *cmd, int argc, char **argv)
cmd->handles_missing_pvs = 1;
}
- return process_each_vg(cmd, argc, argv, NULL, NULL,
- READ_FOR_UPDATE | READ_ALLOW_EXPORTED,
- 0, NULL,
- &_vgimport_single);
+ return process_each_vg(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE,
+ 0, NULL, &_vgimport_single);
}
diff --git a/tools/vgimportclone.c b/tools/vgimportclone.c
index a3af841..be01861 100644
--- a/tools/vgimportclone.c
+++ b/tools/vgimportclone.c
@@ -235,7 +235,7 @@ int vgimportclone(struct cmd_context *cmd, int argc, char **argv)
log_debug("Finding devices to import.");
cmd->cname->flags |= ENABLE_DUPLICATE_DEVS;
- process_each_pv(cmd, argc, argv, NULL, 0, READ_ALLOW_EXPORTED, handle, _vgimportclone_pv_single);
+ process_each_pv(cmd, argc, argv, NULL, 0, 0, handle, _vgimportclone_pv_single);
if (vp.found_args != argc) {
log_error("Failed to find all devices.");
@@ -342,7 +342,7 @@ retry_name:
clear_hint_file(cmd);
- ret = process_each_vg(cmd, 0, NULL, vp.old_vgname, NULL, READ_FOR_UPDATE | READ_ALLOW_EXPORTED, 0, handle, _vgimportclone_vg_single);
+ ret = process_each_vg(cmd, 0, NULL, vp.old_vgname, NULL, READ_FOR_UPDATE, 0, handle, _vgimportclone_vg_single);
unlock_vg(cmd, NULL, vp.new_vgname);
out:
diff --git a/tools/vgreduce.c b/tools/vgreduce.c
index bc1f5b6..b001ccb 100644
--- a/tools/vgreduce.c
+++ b/tools/vgreduce.c
@@ -135,7 +135,7 @@ static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
{
int r;
- if (!vg_check_status(vg, EXPORTED_VG | LVM_WRITE | RESIZEABLE_VG))
+ if (!vg_check_status(vg, LVM_WRITE | RESIZEABLE_VG))
return ECMD_FAILED;
r = vgreduce_single(cmd, vg, pv, 1);
@@ -250,8 +250,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
init_ignore_suspended_devices(1);
- process_each_vg(cmd, 0, NULL, vg_name, NULL,
- READ_FOR_UPDATE | READ_ALLOW_EXPORTED,
+ process_each_vg(cmd, 0, NULL, vg_name, NULL, READ_FOR_UPDATE,
0, handle, &_vgreduce_repair_single);
if (vp.already_consistent) {
diff --git a/tools/vgremove.c b/tools/vgremove.c
index 23640f6..8f73297 100644
--- a/tools/vgremove.c
+++ b/tools/vgremove.c
@@ -42,9 +42,6 @@ static int _vgremove_single(struct cmd_context *cmd, const char *vg_name,
unsigned lv_count, missing;
int ret;
- if (!vg_check_status(vg, EXPORTED_VG))
- return_ECMD_FAILED;
-
lv_count = vg_visible_lvs(vg);
if (lv_count) {
diff --git a/tools/vgrename.c b/tools/vgrename.c
index 4735e8b..8b76d0b 100644
--- a/tools/vgrename.c
+++ b/tools/vgrename.c
@@ -233,8 +233,7 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &vp;
- ret = process_each_vg(cmd, 0, NULL, vg_name_old, NULL,
- READ_FOR_UPDATE | READ_ALLOW_EXPORTED,
+ ret = process_each_vg(cmd, 0, NULL, vg_name_old, NULL, READ_FOR_UPDATE,
0, handle, _vgrename_single);
/* Needed if process_each_vg returns error before calling _single. */
diff --git a/tools/vgsplit.c b/tools/vgsplit.c
index 61cb13b..1bcc308 100644
--- a/tools/vgsplit.c
+++ b/tools/vgsplit.c
@@ -665,8 +665,16 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
if (!test_mode()) {
unlock_vg(cmd, NULL, vg_name_to);
release_vg(vg_to);
- vg_to = vg_read_for_update(cmd, vg_name_to, NULL,
- READ_ALLOW_EXPORTED, 0);
+
+ /*
+ * This command uses the exported vg flag internally, but
+ * exported VGs are not allowed to be split from the command
+ * level, so ALLOW_EXPORTED is not set in commands.h.
+ */
+ cmd->include_exported_vgs = 1;
+
+ vg_to = vg_read_for_update(cmd, vg_name_to, NULL, 0, 0);
+
if (vg_read_error(vg_to)) {
log_error("Volume group \"%s\" became inconsistent: "
"please fix manually", vg_name_to);

View File

@ -0,0 +1,89 @@
lib/label/label.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/lib/label/label.c b/lib/label/label.c
index 72be5ec..09bbb92 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -29,6 +29,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
+#include <sys/resource.h>
/* FIXME Allow for larger labels? Restricted to single sector currently */
@@ -867,6 +868,57 @@ static void _free_hints(struct dm_list *hints)
}
/*
+ * We don't know how many of num_devs will be PVs that we need to
+ * keep open, but if it's greater than the soft limit, then we'll
+ * need the soft limit raised, so do that before starting.
+ *
+ * If opens approach the raised soft/hard limit while scanning, then
+ * we could also attempt to raise the soft/hard limits during the scan.
+ */
+
+#define BASE_FD_COUNT 32 /* Number of open files we want apart from devs */
+
+static void _prepare_open_file_limit(struct cmd_context *cmd, unsigned int num_devs)
+{
+ struct rlimit old, new;
+ unsigned int want = num_devs + BASE_FD_COUNT;
+ int rv;
+
+ rv = prlimit(0, RLIMIT_NOFILE, NULL, &old);
+ if (rv < 0) {
+ log_debug("Checking fd limit for num_devs %u failed %d", num_devs, errno);
+ return;
+ }
+
+ log_debug("Checking fd limit for num_devs %u want %u soft %lld hard %lld",
+ num_devs, want, (long long)old.rlim_cur, (long long)old.rlim_max);
+
+ /* Current soft limit is enough */
+ if (old.rlim_cur > want)
+ return;
+
+ /* Soft limit already raised to max */
+ if (old.rlim_cur == old.rlim_max)
+ return;
+
+ /* Raise soft limit up to hard/max limit */
+ new.rlim_cur = old.rlim_max;
+ new.rlim_max = old.rlim_max;
+
+ log_debug("Setting fd limit for num_devs %u soft %lld hard %lld",
+ num_devs, (long long)new.rlim_cur, (long long)new.rlim_max);
+
+ rv = prlimit(0, RLIMIT_NOFILE, &new, &old);
+ if (rv < 0) {
+ if (errno == EPERM)
+ log_warn("WARNING: permission error setting open file limit for scanning %u devices.", num_devs);
+ else
+ log_warn("WARNING: cannot set open file limit for scanning %u devices.", num_devs);
+ return;
+ }
+}
+
+/*
* Scan devices on the system to discover which are LVM devices.
* Info about the LVM devices (PVs) is saved in lvmcache in a
* basic/summary form (info/vginfo structs). The vg_read phase
@@ -984,6 +1036,15 @@ int label_scan(struct cmd_context *cmd)
log_debug("Will scan %d devices skip %d", dm_list_size(&scan_devs), dm_list_size(&all_devs));
/*
+ * If the total number of devices exceeds the soft open file
+ * limit, then increase the soft limit to the hard/max limit
+ * in case the number of PVs in scan_devs (it's only the PVs
+ * which we want to keep open) is higher than the current
+ * soft limit.
+ */
+ _prepare_open_file_limit(cmd, dm_list_size(&scan_devs));
+
+ /*
* Do the main scan.
*/
_scan_list(cmd, cmd->filter, &scan_devs, NULL);

View File

@ -0,0 +1,22 @@
tools/command-lines.in | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/tools/command-lines.in b/tools/command-lines.in
index 73a1e64..f914650 100644
--- a/tools/command-lines.in
+++ b/tools/command-lines.in
@@ -343,13 +343,11 @@ DESC: Convert LV to striped.
RULE: all not lv_is_locked lv_is_pvmove
lvconvert --type mirror LV
-OO: --mirrors SNumber, --regionsize RegionSize, --interval Number, --mirrorlog MirrorLog, OO_LVCONVERT
+OO: --mirrors SNumber, --stripes_long Number, --stripesize SizeKB, --regionsize RegionSize, --interval Number, --mirrorlog MirrorLog, OO_LVCONVERT
OP: PV ...
ID: lvconvert_raid_types
DESC: Convert LV to type mirror (also see type raid1),
-DESC: (also see lvconvert --mirrors).
RULE: all not lv_is_locked lv_is_pvmove
-FLAGS: SECONDARY_SYNTAX
# When LV is already raid, this changes the raid layout
# (changing layout of raid0 and raid1 not allowed.)

View File

@ -0,0 +1,51 @@
lib/metadata/metadata.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index dc1b501..f7eeb52 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -3504,19 +3504,41 @@ static void _set_pv_device(struct format_instance *fid,
struct physical_volume *pv)
{
char buffer[64] __attribute__((aligned(8)));
+ struct cmd_context *cmd = fid->fmt->cmd;
+ struct device *dev;
uint64_t size;
- if (!(pv->dev = lvmcache_device_from_pvid(fid->fmt->cmd, &pv->id, &pv->label_sector))) {
+ if (!(dev = lvmcache_device_from_pvid(cmd, &pv->id, &pv->label_sector))) {
if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
buffer[0] = '\0';
- if (fid->fmt->cmd && !fid->fmt->cmd->pvscan_cache_single)
+ if (cmd && !cmd->pvscan_cache_single)
log_warn("WARNING: Couldn't find device with uuid %s.", buffer);
else
log_debug_metadata("Couldn't find device with uuid %s.", buffer);
}
/*
+ * If the device and PV are not the size, it's a clue that we might
+ * be reading an MD component (but not necessarily). Skip this check:
+ * . if md component detection is disabled
+ * . if we are already doing full a md check in label scan
+ * . if md_component_checks is auto, not none (full means use_full_md_check is set)
+ */
+ if (dev && (pv->size != dev->size) && cmd &&
+ cmd->md_component_detection &&am