From 12cbd3f6a8a25e7b2728d576dcb5544d3215f068 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jan 29 2019 15:48:24 +0000 Subject: import lvm2-2.02.180-10.el7_6.3 --- diff --git a/SOURCES/lvm2-2_02_182-scan-enable-full-md-filter-when-md-1.0-devices-are-p.patch b/SOURCES/lvm2-2_02_182-scan-enable-full-md-filter-when-md-1.0-devices-are-p.patch new file mode 100644 index 0000000..ec9b960 --- /dev/null +++ b/SOURCES/lvm2-2_02_182-scan-enable-full-md-filter-when-md-1.0-devices-are-p.patch @@ -0,0 +1,115 @@ + lib/filters/filter-md.c | 33 +++++++-------------------------- + lib/label/label.c | 13 ++++++++++++- + 2 files changed, 19 insertions(+), 27 deletions(-) + +diff --git a/lib/filters/filter-md.c b/lib/filters/filter-md.c +index ad5b8e4..e03ff50 100644 +--- a/lib/filters/filter-md.c ++++ b/lib/filters/filter-md.c +@@ -16,6 +16,9 @@ + #include "lib.h" + #include "filter.h" + ++/* See label.c comment about this hack. */ ++extern int use_full_md_check; ++ + #ifdef __linux__ + + #define MSG_SKIPPING "%s: Skipping md component device" +@@ -80,7 +83,7 @@ + * that will not pass. + */ + +-static int _passes_md_filter(struct device *dev, int full) ++static int _passes_md_filter(struct dev_filter *f, struct device *dev) + { + int ret; + +@@ -91,7 +94,7 @@ static int _passes_md_filter(struct device *dev, int full) + if (!md_filtering()) + return 1; + +- ret = dev_is_md(dev, NULL, full); ++ ret = dev_is_md(dev, NULL, use_full_md_check); + + if (ret == -EAGAIN) { + /* let pass, call again after scan */ +@@ -104,6 +107,7 @@ static int _passes_md_filter(struct device *dev, int full) + return 1; + + if (ret == 1) { ++ log_debug_devs("md filter full %d excluding md component %s", use_full_md_check, dev_name(dev)); + if (dev->ext.src == DEV_EXT_NONE) + log_debug_devs(MSG_SKIPPING, dev_name(dev)); + else +@@ -121,18 +125,6 @@ static int _passes_md_filter(struct device *dev, int full) + return 1; + } + +-static int _passes_md_filter_lite(struct dev_filter *f __attribute__((unused)), +- struct device *dev) +-{ +- return _passes_md_filter(dev, 0); +-} +- +-static int _passes_md_filter_full(struct dev_filter *f __attribute__((unused)), +- struct device *dev) +-{ +- return _passes_md_filter(dev, 1); +-} +- + static void _destroy(struct dev_filter *f) + { + if (f->use_count) +@@ -150,18 +142,7 @@ struct dev_filter *md_filter_create(struct cmd_context *cmd, struct dev_types *d + return NULL; + } + +- /* +- * FIXME: for commands that want a full md check (pvcreate, vgcreate, +- * vgextend), we do an extra read at the end of every device that the +- * filter looks at. This isn't necessary; we only need to do the full +- * md check on the PVs that these commands are trying to use. +- */ +- +- if (cmd->use_full_md_check) +- f->passes_filter = _passes_md_filter_full; +- else +- f->passes_filter = _passes_md_filter_lite; +- ++ f->passes_filter = _passes_md_filter; + f->destroy = _destroy; + f->use_count = 0; + f->private = dt; +diff --git a/lib/label/label.c b/lib/label/label.c +index 6fb35ff..03726d0 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -27,6 +27,7 @@ + #include + #include + ++int use_full_md_check; + + /* FIXME Allow for larger labels? Restricted to single sector currently */ + +@@ -884,8 +885,18 @@ int label_scan(struct cmd_context *cmd) + * devs in 'pvs', which is a pretty harmless effect from a + * pretty uncommon situation. + */ +- if (dev_is_md_with_end_superblock(cmd->dev_types, dev)) ++ if (dev_is_md_with_end_superblock(cmd->dev_types, dev)) { + cmd->use_full_md_check = 1; ++ ++ /* This is a hack because 'cmd' is not passed ++ into the filters so we can't check the flag ++ in the cmd struct. The master branch has ++ changed the filters in commit 8eab37593eccb ++ to accept cmd, but it's a complex change ++ that I'm trying to avoid in the stable branch. */ ++ ++ use_full_md_check = 1; ++ } + }; + dev_iter_destroy(iter); + diff --git a/SOURCES/lvm2-2_02_182-scan-use-full-md-filter-when-md-1.0-devices-are-pres.patch b/SOURCES/lvm2-2_02_182-scan-use-full-md-filter-when-md-1.0-devices-are-pres.patch new file mode 100644 index 0000000..03d3546 --- /dev/null +++ b/SOURCES/lvm2-2_02_182-scan-use-full-md-filter-when-md-1.0-devices-are-pres.patch @@ -0,0 +1,201 @@ + lib/cache/lvmcache.c | 2 +- + lib/device/dev-md.c | 27 ++++++++++---- + lib/device/dev-type.h | 1 + + lib/filters/filter-md.c | 74 +++++++++++++++++++------------------- + lib/label/label.c | 14 ++++++++ + test/shell/pvcreate-md-fake-hdr.sh | 3 +- + 6 files changed, 75 insertions(+), 46 deletions(-) + +diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c +index 2fba3ff..f55a14c 100644 +--- a/lib/cache/lvmcache.c ++++ b/lib/cache/lvmcache.c +@@ -1002,7 +1002,7 @@ int lvmcache_dev_is_unchosen_duplicate(struct device *dev) + * unused_duplicate_devs list, and restrict what we allow done with it. + * + * In the case of md components, we usually filter these out in filter-md, +- * but in the special case of md superblocks <= 1.0 where the superblock ++ * but in the special case of md superblock version 1.0 where the superblock + * is at the end of the device, filter-md doesn't always eliminate them + * first, so we eliminate them here. + * +diff --git a/lib/device/dev-md.c b/lib/device/dev-md.c +index f5a736f..7196dc0 100644 +--- a/lib/device/dev-md.c ++++ b/lib/device/dev-md.c +@@ -142,13 +142,6 @@ static int _native_dev_is_md(struct device *dev, uint64_t *offset_found, int ful + * command if it should do a full check (cmd->use_full_md_check), + * and set it for commands that could possibly write to an md dev + * (pvcreate/vgcreate/vgextend). +- * +- * For old md versions with magic numbers at the end of devices, +- * the md dev components won't be filtered out here when full is 0, +- * so they will be scanned, and appear as duplicate PVs in lvmcache. +- * The md device itself will be chosen as the primary duplicate, +- * and the components are dropped from the list of duplicates in, +- * i.e. a kind of post-scan filtering. + */ + if (!full) { + sb_offset = 0; +@@ -414,6 +407,26 @@ unsigned long dev_md_stripe_width(struct dev_types *dt, struct device *dev) + return stripe_width_sectors; + } + ++int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev) ++{ ++ char version_string[MD_MAX_SYSFS_SIZE]; ++ const char *attribute = "metadata_version"; ++ ++ if (MAJOR(dev->dev) != dt->md_major) ++ return 0; ++ ++ if (_md_sysfs_attribute_scanf(dt, dev, attribute, ++ "%s", &version_string) != 1) ++ return -1; ++ ++ log_very_verbose("Device %s %s is %s.", ++ dev_name(dev), attribute, version_string); ++ ++ if (!strcmp(version_string, "1.0")) ++ return 1; ++ return 0; ++} ++ + #else + + int dev_is_md(struct device *dev __attribute__((unused)), +diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h +index 843e254..f629a02 100644 +--- a/lib/device/dev-type.h ++++ b/lib/device/dev-type.h +@@ -76,6 +76,7 @@ int wipe_known_signatures(struct cmd_context *cmd, struct device *dev, const cha + + /* Type-specific device properties */ + unsigned long dev_md_stripe_width(struct dev_types *dt, struct device *dev); ++int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev); + + /* Partitioning */ + int major_max_partitions(struct dev_types *dt, int major); +diff --git a/lib/filters/filter-md.c b/lib/filters/filter-md.c +index ab97b59..ad5b8e4 100644 +--- a/lib/filters/filter-md.c ++++ b/lib/filters/filter-md.c +@@ -29,43 +29,43 @@ + * + * (This is assuming lvm.conf md_component_detection=1.) + * +- * If lvm does *not* ignore the components, then lvm will read lvm +- * labels from the md dev and from the component devs, and will see +- * them all as duplicates of each other. LVM duplicate resolution +- * will then kick in and keep the md dev around to use and ignore +- * the components. +- * +- * It is better to exclude the components as early as possible during +- * lvm processing, ideally before lvm even looks for labels on the +- * components, so that duplicate resolution can be avoided. There are +- * a number of ways that md components can be excluded earlier than +- * the duplicate resolution phase: +- * +- * - When external_device_info_source="udev", lvm discovers a device is +- * an md component by asking udev during the initial filtering phase. +- * However, lvm's default is to not use udev for this. The +- * alternative is "native" detection in which lvm tries to detect +- * md components itself. +- * +- * - When using native detection, lvm's md filter looks for the md +- * superblock at the start of devices. It will see the md superblock +- * on the components, exclude them in the md filter, and avoid +- * handling them later in duplicate resolution. +- * +- * - When using native detection, lvm's md filter will not detect +- * components when the md device has an older superblock version that +- * places the superblock at the end of the device. This case will +- * fall back to duplicate resolution to exclude components. +- * +- * A variation of the description above occurs for lvm commands that +- * intend to create new PVs on devices (pvcreate, vgcreate, vgextend). +- * For these commands, the native md filter also reads the end of all +- * devices to check for the odd md superblocks. +- * +- * (The reason that external_device_info_source is not set to udev by +- * default is that there have be issues with udev not being promptly +- * or reliably updated about md state changes, causing the udev info +- * that lvm uses to be occasionally wrong.) ++ * If lvm does *not* ignore the components, then lvm may read lvm ++ * labels from the component devs and potentially the md dev, ++ * which can trigger duplicate detection, and/or cause lvm to display ++ * md components as PVs rather than ignoring them. ++ * ++ * If scanning md componenents causes duplicates to be seen, then ++ * the lvm duplicate resolution will exclude the components. ++ * ++ * The lvm md filter has three modes: ++ * ++ * 1. look for md superblock at the start of the device ++ * 2. look for md superblock at the start and end of the device ++ * 3. use udev to detect components ++ * ++ * mode 1 will not detect and exclude components of md devices ++ * that use superblock version 1.0 which is at the end of the device. ++ * ++ * mode 2 will detect these, but mode 2 doubles the i/o done by label ++ * scan, since there's a read at both the start and end of every device. ++ * ++ * mode 3 is used when external_device_info_source="udev". It does ++ * not require any io from lvm, but this mode is not used by default ++ * because there have been problems getting reliable info from udev. ++ * ++ * lvm uses mode 2 when: ++ * ++ * - the command is pvcreate/vgcreate/vgextend, which format new ++ * devices, and if the user ran these commands on a component ++ * device of an md device 1.0, then it would cause problems. ++ * FIXME: this would only really need to scan the end of the ++ * devices being formatted, not all devices. ++ * ++ * - it sees an md device on the system using version 1.0. ++ * The point of this is just to avoid displaying md components ++ * from the 'pvs' command. ++ * FIXME: the cost (double i/o) may not be worth the benefit ++ * (not showing md components). + */ + + /* +diff --git a/lib/label/label.c b/lib/label/label.c +index e7e3997..6fb35ff 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -872,6 +872,20 @@ 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 need to 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: it may not be worth the ++ * cost of double i/o just to avoid displaying md component ++ * devs in 'pvs', which is a pretty harmless effect from a ++ * pretty uncommon situation. ++ */ ++ if (dev_is_md_with_end_superblock(cmd->dev_types, dev)) ++ cmd->use_full_md_check = 1; + }; + dev_iter_destroy(iter); + +diff --git a/test/shell/pvcreate-md-fake-hdr.sh b/test/shell/pvcreate-md-fake-hdr.sh +index b89fe43..4c9ac7c 100644 +--- a/test/shell/pvcreate-md-fake-hdr.sh ++++ b/test/shell/pvcreate-md-fake-hdr.sh +@@ -89,6 +89,7 @@ sleep 1 + # (when mdadm supports repair) + if mdadm --action=repair "$mddev" ; then + sleep 1 ++ pvscan -vvvv + # should be showing correctly PV3 & PV4 +- pvs ++ pvs -vvvv "$dev3" "$dev4" + fi diff --git a/SOURCES/lvm2-2_02_183-WHATS_NEW-sync-io.patch b/SOURCES/lvm2-2_02_183-WHATS_NEW-sync-io.patch new file mode 100644 index 0000000..defd1ec --- /dev/null +++ b/SOURCES/lvm2-2_02_183-WHATS_NEW-sync-io.patch @@ -0,0 +1,19 @@ + WHATS_NEW | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/WHATS_NEW b/WHATS_NEW +index a1da4b7..82dd0c8 100644 +--- a/WHATS_NEW ++++ b/WHATS_NEW +@@ -1,5 +1,11 @@ ++Version 2.02.183 - ++==================================== ++ Use sync io if async io_setup fails, or use_aio=0 is set in config. ++ + Version 2.02.182 - + ============================== ++ Fix possible write race between last metadata block and the first extent. ++ Fix filtering of md 1.0 devices so they are not seen as duplicate PVs. + Fix change of monitoring in clustered volumes. + Fix lvconvert striped/raid0/raid0_meta -> raid6 regression. + Add After=rbdmap.service to {lvm2-activation-net,blk-availability}.service. diff --git a/SOURCES/lvm2-2_02_183-WHATS_NEW.patch b/SOURCES/lvm2-2_02_183-WHATS_NEW.patch new file mode 100644 index 0000000..ed6ef08 --- /dev/null +++ b/SOURCES/lvm2-2_02_183-WHATS_NEW.patch @@ -0,0 +1,30 @@ + WHATS_NEW | 3 ++- + WHATS_NEW_DM | 6 +++++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/WHATS_NEW b/WHATS_NEW +index 82dd0c8..47db4a3 100644 +--- a/WHATS_NEW ++++ b/WHATS_NEW +@@ -1,5 +1,6 @@ + Version 2.02.183 - +-==================================== ++===================================== ++ Fix component detection for md version 0.90. + Use sync io if async io_setup fails, or use_aio=0 is set in config. + + Version 2.02.182 - +diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM +index 42cf2a8..bbd1057 100644 +--- a/WHATS_NEW_DM ++++ b/WHATS_NEW_DM +@@ -1,4 +1,8 @@ +-Version 1.02.151 - ++Version 1.02.154 - ++============================== ++ Fix dmstats report printing no output. ++ ++Version 1.02.152 - + ============================== + Add hot fix to avoiding locking collision when monitoring thin-pools. + diff --git a/SOURCES/lvm2-2_02_183-bcache-sync-io-fixes.patch b/SOURCES/lvm2-2_02_183-bcache-sync-io-fixes.patch new file mode 100644 index 0000000..558d2ab --- /dev/null +++ b/SOURCES/lvm2-2_02_183-bcache-sync-io-fixes.patch @@ -0,0 +1,112 @@ + lib/device/bcache.c | 69 ++++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 47 insertions(+), 22 deletions(-) + +diff --git a/lib/device/bcache.c b/lib/device/bcache.c +index 1cb1b2f..6886b74 100644 +--- a/lib/device/bcache.c ++++ b/lib/device/bcache.c +@@ -320,7 +320,7 @@ struct io_engine *create_async_io_engine(void) + e->aio_context = 0; + r = io_setup(MAX_IO, &e->aio_context); + if (r < 0) { +- log_warn("io_setup failed"); ++ log_debug("io_setup failed %d", r); + dm_free(e); + return NULL; + } +@@ -363,8 +363,11 @@ static void _sync_destroy(struct io_engine *ioe) + static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd, + sector_t sb, sector_t se, void *data, void *context) + { +- int r; +- uint64_t len = (se - sb) * 512, where; ++ int rv; ++ off_t off; ++ uint64_t where; ++ uint64_t pos = 0; ++ uint64_t len = (se - sb) * 512; + struct sync_engine *e = _to_sync(ioe); + struct sync_io *io = malloc(sizeof(*io)); + if (!io) { +@@ -373,11 +376,17 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd, + } + + where = sb * 512; +- r = lseek(fd, where, SEEK_SET); +- if (r < 0) { +- log_warn("unable to seek to position %llu", (unsigned long long) where); +- free(io); +- return false; ++ ++ off = lseek(fd, where, SEEK_SET); ++ if (off == (off_t) -1) { ++ log_warn("Device seek error %d for offset %llu", errno, (unsigned long long)where); ++ free(io); ++ return false; ++ } ++ if (off != (off_t) where) { ++ log_warn("Device seek failed for offset %llu", (unsigned long long)where); ++ free(io); ++ return false; + } + + /* +@@ -422,28 +431,44 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd, + len = nbytes; + } + +- while (len) { +- do { +- if (d == DIR_READ) +- r = read(fd, data, len); +- else +- r = write(fd, data, len); ++ while (pos < len) { ++ if (d == DIR_READ) ++ rv = read(fd, (char *)data + pos, len - pos); ++ else ++ rv = write(fd, (char *)data + pos, len - pos); + +- } while ((r < 0) && ((r == EINTR) || (r == EAGAIN))); ++ if (rv == -1 && errno == EINTR) ++ continue; ++ if (rv == -1 && errno == EAGAIN) ++ continue; ++ ++ if (!rv) ++ break; + +- if (r < 0) { +- log_warn("io failed %d", r); ++ if (rv < 0) { ++ if (d == DIR_READ) ++ log_debug("Device read error %d offset %llu len %llu", errno, ++ (unsigned long long)(where + pos), ++ (unsigned long long)(len - pos)); ++ else ++ log_debug("Device write error %d offset %llu len %llu", errno, ++ (unsigned long long)(where + pos), ++ (unsigned long long)(len - pos)); + free(io); + return false; +- } +- +- len -= r; ++ } ++ pos += rv; + } + +- if (len) { +- log_warn("short io %u bytes remaining", (unsigned) len); ++ if (pos < len) { ++ if (d == DIR_READ) ++ log_warn("Device read short %u bytes remaining", (unsigned)(len - pos)); ++ else ++ log_warn("Device write short %u bytes remaining", (unsigned)(len - pos)); ++ /* + free(io); + return false; ++ */ + } + + diff --git a/SOURCES/lvm2-2_02_183-build-make-generate.patch b/SOURCES/lvm2-2_02_183-build-make-generate.patch new file mode 100644 index 0000000..c6eb9d1 --- /dev/null +++ b/SOURCES/lvm2-2_02_183-build-make-generate.patch @@ -0,0 +1,19 @@ + conf/example.conf.in | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/conf/example.conf.in b/conf/example.conf.in +index 742812c..b37e0b2 100644 +--- a/conf/example.conf.in ++++ b/conf/example.conf.in +@@ -903,6 +903,11 @@ global { + # This configuration option has an automatic default value. + # lvdisplay_shows_full_device_path = 0 + ++ # Configuration option global/use_aio. ++ # Use async I/O when reading and writing devices. ++ # This configuration option has an automatic default value. ++ # use_aio = 1 ++ + # Configuration option global/use_lvmetad. + # Use lvmetad to cache metadata and reduce disk scanning. + # When enabled (and running), lvmetad provides LVM commands with VG diff --git a/SOURCES/lvm2-2_02_183-dmsetup-fix-stats-report-command-output.patch b/SOURCES/lvm2-2_02_183-dmsetup-fix-stats-report-command-output.patch new file mode 100644 index 0000000..82039d4 --- /dev/null +++ b/SOURCES/lvm2-2_02_183-dmsetup-fix-stats-report-command-output.patch @@ -0,0 +1,28 @@ + tools/dmsetup.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/tools/dmsetup.c b/tools/dmsetup.c +index 3cdf862..0b5b808 100644 +--- a/tools/dmsetup.c ++++ b/tools/dmsetup.c +@@ -910,17 +910,13 @@ static int _display_info_cols(struct dm_task *dmt, struct dm_info *info) + if (!(obj.stats = dm_stats_create(DM_STATS_PROGRAM_ID))) + goto_out; + +- if (!dm_stats_get_nr_regions(obj.stats)) { +- log_debug("Skipping %s with no regions.", dm_task_get_name(dmt)); ++ dm_stats_bind_devno(obj.stats, info->major, info->minor); ++ ++ if (!dm_stats_populate(obj.stats, _program_id, DM_STATS_REGIONS_ALL)) { + r = 1; + goto out; + } + +- dm_stats_bind_devno(obj.stats, info->major, info->minor); +- +- if (!dm_stats_populate(obj.stats, _program_id, DM_STATS_REGIONS_ALL)) +- goto_out; +- + /* Update timestamps and handle end-of-interval accounting. */ + _update_interval_times(); + diff --git a/SOURCES/lvm2-2_02_183-io-use-sync-io-if-aio-fails.patch b/SOURCES/lvm2-2_02_183-io-use-sync-io-if-aio-fails.patch new file mode 100644 index 0000000..d44b1ee --- /dev/null +++ b/SOURCES/lvm2-2_02_183-io-use-sync-io-if-aio-fails.patch @@ -0,0 +1,192 @@ + lib/commands/toolcontext.c | 2 ++ + lib/config/config_settings.h | 3 +++ + lib/config/defaults.h | 1 + + lib/device/bcache.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + lib/label/label.c | 17 +++++++++++++---- + lib/misc/lvm-globals.c | 11 +++++++++++ + lib/misc/lvm-globals.h | 2 ++ + 7 files changed, 74 insertions(+), 4 deletions(-) + +diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c +index 2b72645..4d3f744 100644 +--- a/lib/commands/toolcontext.c ++++ b/lib/commands/toolcontext.c +@@ -341,6 +341,8 @@ static void _init_logging(struct cmd_context *cmd) + find_config_tree_bool(cmd, global_test_CFG, NULL); + init_test(cmd->default_settings.test); + ++ init_use_aio(find_config_tree_bool(cmd, global_use_aio_CFG, NULL)); ++ + /* Settings for logging to file */ + if (find_config_tree_bool(cmd, log_overwrite_CFG, NULL)) + append = 0; +diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h +index 6d79087..2de3fd4 100644 +--- a/lib/config/config_settings.h ++++ b/lib/config/config_settings.h +@@ -947,6 +947,9 @@ cfg(global_lvdisplay_shows_full_device_path_CFG, "lvdisplay_shows_full_device_pa + "Previously this was always shown as /dev/vgname/lvname even when that\n" + "was never a valid path in the /dev filesystem.\n") + ++cfg(global_use_aio_CFG, "use_aio", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_AIO, vsn(2, 2, 183), NULL, 0, NULL, ++ "Use async I/O when reading and writing devices.\n") ++ + cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_LVMETAD, vsn(2, 2, 93), "@DEFAULT_USE_LVMETAD@", 0, NULL, + "Use lvmetad to cache metadata and reduce disk scanning.\n" + "When enabled (and running), lvmetad provides LVM commands with VG\n" +diff --git a/lib/config/defaults.h b/lib/config/defaults.h +index 1a11009..b3e6c34 100644 +--- a/lib/config/defaults.h ++++ b/lib/config/defaults.h +@@ -59,6 +59,7 @@ + #define DEFAULT_METADATA_READ_ONLY 0 + #define DEFAULT_LVDISPLAY_SHOWS_FULL_DEVICE_PATH 0 + #define DEFAULT_UNKNOWN_DEVICE_NAME "[unknown]" ++#define DEFAULT_USE_AIO 1 + + #define DEFAULT_SANLOCK_LV_EXTEND_MB 256 + +diff --git a/lib/device/bcache.c b/lib/device/bcache.c +index 5ac2558..1cb1b2f 100644 +--- a/lib/device/bcache.c ++++ b/lib/device/bcache.c +@@ -380,6 +380,48 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd, + return false; + } + ++ /* ++ * If bcache block goes past where lvm wants to write, then clamp it. ++ */ ++ if ((d == DIR_WRITE) && _last_byte_offset && (fd == _last_byte_fd)) { ++ uint64_t offset = where; ++ uint64_t nbytes = len; ++ sector_t limit_nbytes = 0; ++ sector_t extra_nbytes = 0; ++ ++ if (offset > _last_byte_offset) { ++ log_error("Limit write at %llu len %llu beyond last byte %llu", ++ (unsigned long long)offset, ++ (unsigned long long)nbytes, ++ (unsigned long long)_last_byte_offset); ++ return false; ++ } ++ ++ if (offset + nbytes > _last_byte_offset) { ++ limit_nbytes = _last_byte_offset - offset; ++ if (limit_nbytes % _last_byte_sector_size) ++ extra_nbytes = _last_byte_sector_size - (limit_nbytes % _last_byte_sector_size); ++ ++ if (extra_nbytes) { ++ log_debug("Limit write at %llu len %llu to len %llu rounded to %llu", ++ (unsigned long long)offset, ++ (unsigned long long)nbytes, ++ (unsigned long long)limit_nbytes, ++ (unsigned long long)(limit_nbytes + extra_nbytes)); ++ nbytes = limit_nbytes + extra_nbytes; ++ } else { ++ log_debug("Limit write at %llu len %llu to len %llu", ++ (unsigned long long)offset, ++ (unsigned long long)nbytes, ++ (unsigned long long)limit_nbytes); ++ nbytes = limit_nbytes; ++ } ++ } ++ ++ where = offset; ++ len = nbytes; ++ } ++ + while (len) { + do { + if (d == DIR_READ) +diff --git a/lib/label/label.c b/lib/label/label.c +index d2cfe62..e7e3997 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -797,7 +797,7 @@ out: + + static int _setup_bcache(int cache_blocks) + { +- struct io_engine *ioe; ++ struct io_engine *ioe = NULL; + + if (cache_blocks < MIN_BCACHE_BLOCKS) + cache_blocks = MIN_BCACHE_BLOCKS; +@@ -805,9 +805,18 @@ static int _setup_bcache(int cache_blocks) + if (cache_blocks > MAX_BCACHE_BLOCKS) + cache_blocks = MAX_BCACHE_BLOCKS; + +- if (!(ioe = create_async_io_engine())) { +- log_error("Failed to create bcache io engine."); +- return 0; ++ if (use_aio()) { ++ if (!(ioe = create_async_io_engine())) { ++ log_warn("Failed to set up async io, using sync io."); ++ init_use_aio(0); ++ } ++ } ++ ++ if (!ioe) { ++ if (!(ioe = create_sync_io_engine())) { ++ log_error("Failed to set up sync io."); ++ return 0; ++ } + } + + if (!(scan_bcache = bcache_create(BCACHE_BLOCK_SIZE_IN_SECTORS, cache_blocks, ioe))) { +diff --git a/lib/misc/lvm-globals.c b/lib/misc/lvm-globals.c +index 9941489..82c5706 100644 +--- a/lib/misc/lvm-globals.c ++++ b/lib/misc/lvm-globals.c +@@ -24,6 +24,7 @@ + static int _verbose_level = VERBOSE_BASE_LEVEL; + static int _silent = 0; + static int _test = 0; ++static int _use_aio = 0; + static int _md_filtering = 0; + static int _internal_filtering = 0; + static int _fwraid_filtering = 0; +@@ -71,6 +72,11 @@ void init_test(int level) + _test = level; + } + ++void init_use_aio(int use_aio) ++{ ++ _use_aio = use_aio; ++} ++ + void init_md_filtering(int level) + { + _md_filtering = level; +@@ -227,6 +233,11 @@ int test_mode(void) + return _test; + } + ++int use_aio(void) ++{ ++ return _use_aio; ++} ++ + int md_filtering(void) + { + return _md_filtering; +diff --git a/lib/misc/lvm-globals.h b/lib/misc/lvm-globals.h +index b383891..f985cfa 100644 +--- a/lib/misc/lvm-globals.h ++++ b/lib/misc/lvm-globals.h +@@ -25,6 +25,7 @@ enum dev_ext_e; + void init_verbose(int level); + void init_silent(int silent); + void init_test(int level); ++void init_use_aio(int use_aio); + void init_md_filtering(int level); + void init_internal_filtering(int level); + void init_fwraid_filtering(int level); +@@ -58,6 +59,7 @@ const char *get_cmd_name(void); + void set_sysfs_dir_path(const char *path); + + int test_mode(void); ++int use_aio(void); + int md_filtering(void); + int internal_filtering(void); + int fwraid_filtering(void); diff --git a/SOURCES/lvm2-2_02_183-libdm-stats-move-no-regions-warning-after-dm_stats_l.patch b/SOURCES/lvm2-2_02_183-libdm-stats-move-no-regions-warning-after-dm_stats_l.patch new file mode 100644 index 0000000..0244645 --- /dev/null +++ b/SOURCES/lvm2-2_02_183-libdm-stats-move-no-regions-warning-after-dm_stats_l.patch @@ -0,0 +1,31 @@ + libdm/libdm-stats.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/libdm/libdm-stats.c b/libdm/libdm-stats.c +index 94ad380..6b4e3d8 100644 +--- a/libdm/libdm-stats.c ++++ b/libdm/libdm-stats.c +@@ -2336,11 +2336,6 @@ int dm_stats_populate(struct dm_stats *dms, const char *program_id, + return 0; + } + +- if (!dms->nr_regions) { +- log_error("No regions registered."); +- return 0; +- } +- + /* allow zero-length program_id for populate */ + if (!program_id) + program_id = dms->program_id; +@@ -2352,6 +2347,11 @@ int dm_stats_populate(struct dm_stats *dms, const char *program_id, + goto_bad; + } + ++ if (!dms->nr_regions) { ++ log_verbose("No stats regions registered: %s", dms->name); ++ return 0; ++ } ++ + dms->walk_flags = DM_STATS_WALK_REGION; + dm_stats_walk_start(dms); + do { diff --git a/SOURCES/lvm2-2_02_183-pvscan-lvmetad-use-full-md-filter-when-md-1.0-device.patch b/SOURCES/lvm2-2_02_183-pvscan-lvmetad-use-full-md-filter-when-md-1.0-device.patch new file mode 100644 index 0000000..6c2b4f1 --- /dev/null +++ b/SOURCES/lvm2-2_02_183-pvscan-lvmetad-use-full-md-filter-when-md-1.0-device.patch @@ -0,0 +1,47 @@ + tools/pvscan.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/tools/pvscan.c b/tools/pvscan.c +index d9ad097..47ad0f1 100644 +--- a/tools/pvscan.c ++++ b/tools/pvscan.c +@@ -18,6 +18,8 @@ + #include "lvmetad.h" + #include "lvmcache.h" + ++extern int use_full_md_check; ++ + struct pvscan_params { + int new_pvs_found; + int pvs_found; +@@ -302,6 +304,7 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv) + struct dm_list found_vgnames; + struct device *dev; + struct device_list *devl; ++ struct dev_iter *iter; + const char *pv_name; + const char *reason = NULL; + int32_t major = -1; +@@ -443,6 +446,22 @@ static int _pvscan_cache(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(); + ++ /* See the same check in label_scan() to handle md 0.9/1.0 components. */ ++ if (!(iter = dev_iter_create(cmd->full_filter, 0))) { ++ log_error("Scanning failed to get devices."); ++ return 0; ++ } ++ while ((dev = dev_iter_get(iter))) { ++ if (dev_is_md_with_end_superblock(cmd->dev_types, dev)) { ++ cmd->use_full_md_check = 1; ++ use_full_md_check = 1; ++ log_debug("Found md with end superblock %s", dev_name(dev)); ++ } ++ } ++ dev_iter_destroy(iter); ++ if (!use_full_md_check) ++ log_debug("No md devs with end superblock"); ++ + dm_list_init(&single_devs); + + while (argc--) { diff --git a/SOURCES/lvm2-2_02_183-pvscan-lvmetad-use-udev-info-to-improve-md-component.patch b/SOURCES/lvm2-2_02_183-pvscan-lvmetad-use-udev-info-to-improve-md-component.patch new file mode 100644 index 0000000..23ba093 --- /dev/null +++ b/SOURCES/lvm2-2_02_183-pvscan-lvmetad-use-udev-info-to-improve-md-component.patch @@ -0,0 +1,183 @@ + lib/device/dev-md.c | 14 ++++++++++-- + lib/device/dev-type.c | 62 +++++++++++++++++++++++++++++++++++++++++---------- + lib/device/dev-type.h | 1 + + tools/pvscan.c | 3 ++- + 4 files changed, 65 insertions(+), 15 deletions(-) + +diff --git a/lib/device/dev-md.c b/lib/device/dev-md.c +index 185499b..9728507 100644 +--- a/lib/device/dev-md.c ++++ b/lib/device/dev-md.c +@@ -190,14 +190,24 @@ out: + + int dev_is_md(struct device *dev, uint64_t *offset_found, int full) + { ++ int ret; + + /* + * If non-native device status source is selected, use it + * only if offset_found is not requested as this + * information is not in udev db. + */ +- if ((dev->ext.src == DEV_EXT_NONE) || offset_found) +- return _native_dev_is_md(dev, offset_found, full); ++ if ((dev->ext.src == DEV_EXT_NONE) || offset_found) { ++ ret = _native_dev_is_md(dev, offset_found, full); ++ ++ if (!full) { ++ if (!ret || (ret == -EAGAIN)) { ++ if (udev_dev_is_md_component(dev)) ++ return 1; ++ } ++ } ++ return ret; ++ } + + if (dev->ext.src == DEV_EXT_UDEV) + return _udev_dev_is_md(dev); +diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c +index eda7982..331fe07 100644 +--- a/lib/device/dev-type.c ++++ b/lib/device/dev-type.c +@@ -1003,25 +1003,23 @@ int dev_is_rotational(struct dev_types *dt, struct device *dev) + * failed already due to timeout in udev - in both cases the + * udev_device_get_is_initialized returns 0. + */ +-#define UDEV_DEV_IS_MPATH_COMPONENT_ITERATION_COUNT 100 +-#define UDEV_DEV_IS_MPATH_COMPONENT_USLEEP 100000 ++#define UDEV_DEV_IS_COMPONENT_ITERATION_COUNT 100 ++#define UDEV_DEV_IS_COMPONENT_USLEEP 100000 + +-int udev_dev_is_mpath_component(struct device *dev) ++static struct udev_device *_udev_get_dev(struct device *dev) + { + struct udev *udev_context = udev_get_library_context(); + struct udev_device *udev_device = NULL; +- const char *value; + int initialized = 0; + unsigned i = 0; +- int ret = 0; + + if (!udev_context) { + log_warn("WARNING: No udev context available to check if device %s is multipath component.", dev_name(dev)); +- return 0; ++ return NULL; + } + + while (1) { +- if (i >= UDEV_DEV_IS_MPATH_COMPONENT_ITERATION_COUNT) ++ if (i >= UDEV_DEV_IS_COMPONENT_ITERATION_COUNT) + break; + + if (udev_device) +@@ -1029,7 +1027,7 @@ int udev_dev_is_mpath_component(struct device *dev) + + if (!(udev_device = udev_device_new_from_devnum(udev_context, 'b', dev->dev))) { + log_warn("WARNING: Failed to get udev device handler for device %s.", dev_name(dev)); +- return 0; ++ return NULL; + } + + #ifdef HAVE_LIBUDEV_UDEV_DEVICE_GET_IS_INITIALIZED +@@ -1041,19 +1039,32 @@ int udev_dev_is_mpath_component(struct device *dev) + #endif + + log_debug("Device %s not initialized in udev database (%u/%u, %u microseconds).", dev_name(dev), +- i + 1, UDEV_DEV_IS_MPATH_COMPONENT_ITERATION_COUNT, +- i * UDEV_DEV_IS_MPATH_COMPONENT_USLEEP); ++ i + 1, UDEV_DEV_IS_COMPONENT_ITERATION_COUNT, ++ i * UDEV_DEV_IS_COMPONENT_USLEEP); + +- usleep(UDEV_DEV_IS_MPATH_COMPONENT_USLEEP); ++ usleep(UDEV_DEV_IS_COMPONENT_USLEEP); + i++; + } + + if (!initialized) { + log_warn("WARNING: Device %s not initialized in udev database even after waiting %u microseconds.", +- dev_name(dev), i * UDEV_DEV_IS_MPATH_COMPONENT_USLEEP); ++ dev_name(dev), i * UDEV_DEV_IS_COMPONENT_USLEEP); + goto out; + } + ++out: ++ return udev_device; ++} ++ ++int udev_dev_is_mpath_component(struct device *dev) ++{ ++ struct udev_device *udev_device; ++ const char *value; ++ int ret = 0; ++ ++ if (!(udev_device = _udev_get_dev(dev))) ++ return 0; ++ + value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_BLKID_TYPE); + if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_MPATH)) { + log_debug("Device %s is multipath component based on blkid variable in udev db (%s=\"%s\").", +@@ -1073,6 +1084,28 @@ out: + udev_device_unref(udev_device); + return ret; + } ++ ++int udev_dev_is_md_component(struct device *dev) ++{ ++ struct udev_device *udev_device; ++ const char *value; ++ int ret = 0; ++ ++ if (!(udev_device = _udev_get_dev(dev))) ++ return 0; ++ ++ value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_BLKID_TYPE); ++ if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID)) { ++ log_debug("Device %s is md raid component based on blkid variable in udev db (%s=\"%s\").", ++ dev_name(dev), DEV_EXT_UDEV_BLKID_TYPE, value); ++ ret = 1; ++ goto out; ++ } ++out: ++ udev_device_unref(udev_device); ++ return ret; ++} ++ + #else + + int udev_dev_is_mpath_component(struct device *dev) +@@ -1080,4 +1113,9 @@ int udev_dev_is_mpath_component(struct device *dev) + return 0; + } + ++int udev_dev_is_md_component(struct device *dev) ++{ ++ return 0; ++} ++ + #endif +diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h +index f629a02..2644383 100644 +--- a/lib/device/dev-type.h ++++ b/lib/device/dev-type.h +@@ -62,6 +62,7 @@ int dev_is_swap(struct device *dev, uint64_t *signature, int full); + int dev_is_luks(struct device *dev, uint64_t *signature, int full); + int dasd_is_cdl_formatted(struct device *dev); + int udev_dev_is_mpath_component(struct device *dev); ++int udev_dev_is_md_component(struct device *dev); + + int dev_is_lvm1(struct device *dev, char *buf, int buflen); + int dev_is_pool(struct device *dev, char *buf, int buflen); +diff --git a/tools/pvscan.c b/tools/pvscan.c +index 47ad0f1..cdccfb5 100644 +--- a/tools/pvscan.c ++++ b/tools/pvscan.c +@@ -455,7 +455,8 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv) + if (dev_is_md_with_end_superblock(cmd->dev_types, dev)) { + cmd->use_full_md_check = 1; + use_full_md_check = 1; +- log_debug("Found md with end superblock %s", dev_name(dev)); ++ log_debug("Found md component in sysfs with end superblock %s", dev_name(dev)); ++ break; + } + } + dev_iter_destroy(iter); diff --git a/SOURCES/lvm2-2_02_183-scan-md-metadata-version-0.90-is-at-the-end-of-disk.patch b/SOURCES/lvm2-2_02_183-scan-md-metadata-version-0.90-is-at-the-end-of-disk.patch new file mode 100644 index 0000000..ce15ee0 --- /dev/null +++ b/SOURCES/lvm2-2_02_183-scan-md-metadata-version-0.90-is-at-the-end-of-disk.patch @@ -0,0 +1,44 @@ + lib/device/dev-md.c | 2 +- + lib/filters/filter-md.c | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/lib/device/dev-md.c b/lib/device/dev-md.c +index 7196dc0..185499b 100644 +--- a/lib/device/dev-md.c ++++ b/lib/device/dev-md.c +@@ -422,7 +422,7 @@ int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev) + log_very_verbose("Device %s %s is %s.", + dev_name(dev), attribute, version_string); + +- if (!strcmp(version_string, "1.0")) ++ if (!strcmp(version_string, "1.0") || !strcmp(version_string, "0.90")) + return 1; + return 0; + } +diff --git a/lib/filters/filter-md.c b/lib/filters/filter-md.c +index e03ff50..2011e1d 100644 +--- a/lib/filters/filter-md.c ++++ b/lib/filters/filter-md.c +@@ -47,7 +47,7 @@ extern int use_full_md_check; + * 3. use udev to detect components + * + * mode 1 will not detect and exclude components of md devices +- * that use superblock version 1.0 which is at the end of the device. ++ * that use superblock version 0.9 or 1.0 which is at the end of the device. + * + * mode 2 will detect these, but mode 2 doubles the i/o done by label + * scan, since there's a read at both the start and end of every device. +@@ -60,11 +60,11 @@ extern int use_full_md_check; + * + * - the command is pvcreate/vgcreate/vgextend, which format new + * devices, and if the user ran these commands on a component +- * device of an md device 1.0, then it would cause problems. ++ * device of an md device 0.9 or 1.0, then it would cause problems. + * FIXME: this would only really need to scan the end of the + * devices being formatted, not all devices. + * +- * - it sees an md device on the system using version 1.0. ++ * - it sees an md device on the system using version 0.9 or 1.0. + * The point of this is just to avoid displaying md components + * from the 'pvs' command. + * FIXME: the cost (double i/o) may not be worth the benefit diff --git a/SPECS/lvm2.spec b/SPECS/lvm2.spec index 8cd3401..85346e9 100644 --- a/SPECS/lvm2.spec +++ b/SPECS/lvm2.spec @@ -27,7 +27,7 @@ %global boom_pkgname lvm2-python-boom %global boom_version 0.9 -%global boom_release 13 +%global boom_release 14 %global boom_summary A set of libraries and tools for managing boot loader entries %global boom_dir boom-%{boom_version} @@ -67,7 +67,7 @@ Summary: Userland logical volume management tools Name: lvm2 Epoch: 7 Version: 2.02.180 -Release: 10%{?dist}.2%{?scratch} +Release: 10%{?dist}.3%{?scratch} License: GPLv2 Group: System Environment/Base URL: http://sources.redhat.com/lvm2 @@ -104,6 +104,22 @@ Patch27: lvm2-2_02_182-lvconvert-avoid-superfluous-interim-raid-type.patch Patch28: lvm2-2_02_182-lvconvert-fix-interim-segtype-regression-on-raid6-co.patch Patch29: lvm2-2_02_182-fix-clustered-mirror-repair.patch Patch30: lvm2-2_02_182-metadata-prevent-writing-beyond-metadata-area.patch +# BZ 1647718: +Patch31: lvm2-2_02_183-libdm-stats-move-no-regions-warning-after-dm_stats_l.patch +Patch32: lvm2-2_02_183-dmsetup-fix-stats-report-command-output.patch +# BZ 1656498: +Patch33: lvm2-2_02_183-io-use-sync-io-if-aio-fails.patch +Patch34: lvm2-2_02_183-bcache-sync-io-fixes.patch +Patch35: lvm2-2_02_183-WHATS_NEW-sync-io.patch +# BZ 1657640: +Patch36: lvm2-2_02_182-scan-use-full-md-filter-when-md-1.0-devices-are-pres.patch +Patch37: lvm2-2_02_182-scan-enable-full-md-filter-when-md-1.0-devices-are-p.patch +Patch38: lvm2-2_02_183-scan-md-metadata-version-0.90-is-at-the-end-of-disk.patch +Patch39: lvm2-2_02_183-pvscan-lvmetad-use-full-md-filter-when-md-1.0-device.patch +Patch40: lvm2-2_02_183-pvscan-lvmetad-use-udev-info-to-improve-md-component.patch +# Overhead: +Patch41: lvm2-2_02_183-build-make-generate.patch +Patch42: lvm2-2_02_183-WHATS_NEW.patch BuildRequires: libselinux-devel >= %{libselinux_version}, libsepol-devel BuildRequires: libblkid-devel >= %{util_linux_version} @@ -187,6 +203,18 @@ or more physical volumes and creating one or more logical volumes %patch28 -p1 -b .fix_interim_segtype_on_raid6 %patch29 -p1 -b .fix_clvmd_mirror %patch30 -p1 -b .prevent_writing_beyond_MDA +%patch31 -p1 -b .libdm_stats_move_no_regions_warning_after_dm_stats_l +%patch32 -p1 -b .dmsetup_fix_stats_report_command_output +%patch33 -p1 -b .io_use_sync_io_if_aio_fails +%patch34 -p1 -b .bcache_sync_io_fixes +%patch35 -p1 -b .WHATS_NEW_sync_io +%patch36 -p1 -b .scan_use_full_md_filter_when_md_1_0_devices_are_pres +%patch37 -p1 -b .scan_enable_full_md_filter_when_md_1_0_devices_are_p +%patch38 -p1 -b .scan_md_metadata_version_0_90_is_at_the_end_of_disk +%patch39 -p1 -b .pvscan_lvmetad_use_full_md_filter_when_md_1_0_device +%patch40 -p1 -b .pvscan_lvmetad_use_udev_info_to_improve_md_component +%patch41 -p1 -b .build_make_generate2 +%patch42 -p1 -b .WHATS_NEW2 %build %global _default_pid_dir /run @@ -965,6 +993,11 @@ This package provides the python2 version of boom. %endif %changelog +* Mon Dec 17 2018 Marian Csontos - 7:2.02.180-10.el7_6.3 +- Fix component detection for MD RAID version 1.0 and 0.90. +- Use sync io if async io_setup fails, or when use_aio=0 is set in config. +- Fix dmstats report printing no output. + * Wed Oct 31 2018 Marian Csontos - 7:2.02.180-10.el7_6.2 - Fix possible write beyond metadata area.