commit 982b051619f5da8a94a9c0299edc587c18866f96 Author: overweight <5324761+overweight@user.noreply.gitee.com> Date: Mon Sep 30 11:03:04 2019 -0400 Package init diff --git a/0000-lvm2-set-default-preferred_names.patch b/0000-lvm2-set-default-preferred_names.patch new file mode 100644 index 0000000..1c44605 --- /dev/null +++ b/0000-lvm2-set-default-preferred_names.patch @@ -0,0 +1,30 @@ + conf/example.conf.in | 2 +- + lib/config/config_settings.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/conf/example.conf.in b/conf/example.conf.in +index c0afcb7..ec12918 100644 +--- a/conf/example.conf.in ++++ b/conf/example.conf.in +@@ -106,7 +106,7 @@ devices { + # Example + # preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ] + # +- # This configuration option does not have a default value defined. ++ preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ] + + # Configuration option devices/filter. + # Limit the block devices that are used by LVM commands. +diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h +index 9017043..c06b6f0 100644 +--- a/lib/config/config_settings.h ++++ b/lib/config/config_settings.h +@@ -205,7 +205,7 @@ cfg(devices_external_device_info_source_CFG, "external_device_info_source", devi + " compiled with udev support.\n" + "#\n") + +-cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED , CFG_TYPE_STRING, NULL, vsn(1, 2, 19), NULL, 0, NULL, ++cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#S^/dev/mpath/#S^/dev/mapper/mpath#S^/dev/[hs]d", vsn(1, 2, 19), NULL, 0, NULL, + "Select which path name to display for a block device.\n" + "If multiple path names exist for a block device, and LVM needs to\n" + "display a name for the device, the path names are matched against\n" diff --git a/0001-lvm2-lvmetad-timeout.patch b/0001-lvm2-lvmetad-timeout.patch new file mode 100644 index 0000000..dc5eb75 --- /dev/null +++ b/0001-lvm2-lvmetad-timeout.patch @@ -0,0 +1,16 @@ + scripts/lvm2_lvmetad_systemd_red_hat.service.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/lvm2_lvmetad_systemd_red_hat.service.in b/scripts/lvm2_lvmetad_systemd_red_hat.service.in +index 8f4c60d..a1cedd2 100644 +--- a/scripts/lvm2_lvmetad_systemd_red_hat.service.in ++++ b/scripts/lvm2_lvmetad_systemd_red_hat.service.in +@@ -9,7 +9,7 @@ Conflicts=shutdown.target + [Service] + Type=simple + NonBlocking=true +-ExecStart=@SBINDIR@/lvmetad -f ++ExecStart=@SBINDIR@/lvmetad -f -t 3600 + Environment=SD_ACTIVATION=1 + Restart=on-abort + PIDFile=@LVMETAD_PIDFILE@ diff --git a/6000-mirrors-fix-read_only_volume_list.patch b/6000-mirrors-fix-read_only_volume_list.patch new file mode 100644 index 0000000..74a34c0 --- /dev/null +++ b/6000-mirrors-fix-read_only_volume_list.patch @@ -0,0 +1,34 @@ +From 873e27006829b4973ac39db86499f4579325500a Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 11:19:18 +0800 +Subject: [PATCH 01/17] mirrors: fix read_only_volume_list + +If a mirror LV is listed in read_only_volume_list, it would +still be activated rw. The activation would initially be +readonly, but the monitoring function would immediately +change it to rw. This was a regression from commit + +fade45b1d14c mirror: improve table update + +The monitoring function needs to copy the read_only setting +into the new set of mirror activation options it uses. +--- + lib/activate/activate.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/activate/activate.c b/lib/activate/activate.c +index 56ec732..70cce30 100644 +--- a/lib/activate/activate.c ++++ b/lib/activate/activate.c +@@ -1851,6 +1851,8 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume + + if (!laopts) + laopts = &zlaopts; ++ else ++ mirr_laopts.read_only = laopts->read_only; + + /* skip dmeventd code altogether */ + if (dmeventd_monitor_mode() == DMEVENTD_MONITOR_IGNORE) +-- +2.19.1 + diff --git a/6001-bcache-reduce-MAX_IO-to-256.patch b/6001-bcache-reduce-MAX_IO-to-256.patch new file mode 100644 index 0000000..275de5c --- /dev/null +++ b/6001-bcache-reduce-MAX_IO-to-256.patch @@ -0,0 +1,39 @@ +From 400ffe97d5db1a3a06de77851d44813ff48ebb9a Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 11:27:13 +0800 +Subject: [PATCH 02/17] bcache: reduce MAX_IO to 256 + +This is the number of concurrent async io requests that +the scan layer will submit to the bcache layer. There +will be an open fd for each of these, so it is best to +keep this well below the default limit for max open files +(1024), otherwise lvm may get EMFILE from open(2) when +there are around 1024 devices to scan on the system. +--- + lib/device/bcache.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/lib/device/bcache.c b/lib/device/bcache.c +index b1f7d2a..531d83b 100644 +--- a/lib/device/bcache.c ++++ b/lib/device/bcache.c +@@ -196,7 +196,15 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd, + return true; + } + +-#define MAX_IO 1024 ++/* ++ * MAX_IO is returned to the layer above via bcache_max_prefetches() which ++ * tells the caller how many devices to submit io for concurrently. There will ++ * be an open file descriptor for each of these, so keep it low enough to avoid ++ * reaching the default max open file limit (1024) when there are over 1024 ++ * devices being scanned. ++ */ ++ ++#define MAX_IO 256 + #define MAX_EVENT 64 + + static bool _async_wait(struct io_engine *ioe, io_complete_fn fn) +-- +2.19.1 + diff --git a/6002-lvmetad-fix-pvs-for-many-devices.patch b/6002-lvmetad-fix-pvs-for-many-devices.patch new file mode 100644 index 0000000..122a82e --- /dev/null +++ b/6002-lvmetad-fix-pvs-for-many-devices.patch @@ -0,0 +1,118 @@ +From 0b14fe20d0aac79e99832bc53010abb5d8c6812c Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 11:32:01 +0800 +Subject: [PATCH 03/17] lvmetad: fix pvs for many devices + +When using lvmetad, 'pvs' still evaluates full filters +on all devices (lvmetad only provides info about PVs, +but pvs needs to report info about all devices, at +least sometimes.) + +Because some filters read the devices, pvs still reads +every device, even with lvmetad (i.e. lvmetad is no help +for the pvs command.) Because the device reads are not +being managed by the standard label scan layer, but only +happen incidentally through the filters, there is nothing +to control and limit the bcache content and the open file +descriptors for the devices. When there are a lot of devs +on the system, the number of open fd's excedes the limit +and all opens begin failing. + +The proper solution for this would be for pvs to really +use lvmetad and not scan devs, or for pvs to do a proper +label scan even when lvmetad is enabled. To avoid any +major changes to the way this has worked, just work around +this problem by dropping bcache and closing the fd after +pvs evaluates the filter on each device. +--- + tools/toollib.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 59 insertions(+), 1 deletion(-) + +diff --git a/tools/toollib.c b/tools/toollib.c +index 413937f..01686b0 100644 +--- a/tools/toollib.c ++++ b/tools/toollib.c +@@ -3931,7 +3931,7 @@ static int _get_arg_devices(struct cmd_context *cmd, + return ret_max; + } + +-static int _get_all_devices(struct cmd_context *cmd, struct dm_list *all_devices) ++static int _get_all_devices_lvmetad(struct cmd_context *cmd, struct dm_list *all_devices) + { + struct dev_iter *iter; + struct device *dev; +@@ -3947,6 +3947,56 @@ static int _get_all_devices(struct cmd_context *cmd, struct dm_list *all_devices + return ECMD_FAILED; + } + ++ /* ++ * The dev_iter_get applies the filter, which means it reads the device ++ * (since some filters read devices). The read is called from the ++ * filter, and done without label_scan_open, so the dev_read_bytes does ++ * the open. Since the open and read are not done from the label scan ++ * layer, there's nothing to do label_scan_invalidate and close devs ++ * that are not lvms. Hack around this by doing label_scan_invalidate ++ * here. It's dumb that we are reading all disks here when we're meant ++ * to be using lvmetad. process_each_pv with lvmetad should either ++ * just do a proper label_scan or find a way to not need to read devs ++ * at all. If we didn't close each dev here, all devs would remain ++ * open and lvm will have too many open fds. It's all because we're ++ * not using the label scan layer to do the scanning, but pretending a ++ * label scan isn't needed (because of lvmetad) and then secretly doing ++ * a scan anyway hidden down in the filters. ++ */ ++ ++ while ((dev = dev_iter_get(iter))) { ++ if (!(dil = dm_pool_alloc(cmd->mem, sizeof(*dil)))) { ++ log_error("device_id_list alloc failed."); ++ goto out; ++ } ++ ++ strncpy(dil->pvid, dev->pvid, ID_LEN); ++ dil->dev = dev; ++ dm_list_add(all_devices, &dil->list); ++ ++ label_scan_invalidate(dev); ++ } ++ ++ r = ECMD_PROCESSED; ++out: ++ dev_iter_destroy(iter); ++ return r; ++} ++ ++static int _get_all_devices_normal(struct cmd_context *cmd, struct dm_list *all_devices) ++{ ++ struct dev_iter *iter; ++ struct device *dev; ++ struct device_id_list *dil; ++ int r = ECMD_FAILED; ++ ++ log_debug("Getting list of all devices"); ++ ++ if (!(iter = dev_iter_create(cmd->full_filter, 1))) { ++ log_error("dev_iter creation failed."); ++ return ECMD_FAILED; ++ } ++ + while ((dev = dev_iter_get(iter))) { + if (!(dil = dm_pool_alloc(cmd->mem, sizeof(*dil)))) { + log_error("device_id_list alloc failed."); +@@ -3964,6 +4014,14 @@ out: + return r; + } + ++static int _get_all_devices(struct cmd_context *cmd, struct dm_list *all_devices) ++{ ++ if (lvmetad_used()) ++ return _get_all_devices_lvmetad(cmd, all_devices); ++ else ++ return _get_all_devices_normal(cmd, all_devices); ++} ++ + static int _device_list_remove(struct dm_list *devices, struct device *dev) + { + struct device_id_list *dil; +-- +2.19.1 + diff --git a/6003-dmeventd-lvm2-plugin-uses-envvar-registry.patch b/6003-dmeventd-lvm2-plugin-uses-envvar-registry.patch new file mode 100644 index 0000000..9bbe61c --- /dev/null +++ b/6003-dmeventd-lvm2-plugin-uses-envvar-registry.patch @@ -0,0 +1,113 @@ +From bb468b6d7593b2ebbb541ceda240e115a8b8545c Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:05:42 +0800 +Subject: [PATCH 04/17] dmeventd: lvm2 plugin uses envvar registry + +Thin plugin started to use configuble setting to allow to configure +usage of external scripts - however to read this value it needed to +execute internal command as dmeventd itself has no access to lvm.conf +and the API for dmeventd plugin has been kept stable. + +The call of command itself was not normally 'a big issue' until users +started to use higher number of monitored LVs and execution of command +got stuck because other monitored resource already started to execute +some other lvm2 command and become blocked waiting on VG lock. + +This scenario revealed necesity to somehow avoid calling lvm2 command +during resource registration - but this requires bigger changes - so +meanwhile this patch tries to minimize the possibility to hit this race +by obtaining any configurable setting just once - such patch is small +and covers majority of problem - yet better solution needs to be +introduced likely with bigger rework of dmeventd. + +TODO: Avoid blocking registration of resource with execution of lvm2 +commands since those can get stuck waiting on mutexes. +--- + daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c | 49 +++++++++++++++----- + 1 file changed, 38 insertions(+), 11 deletions(-) + +diff --git a/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c b/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c +index 930f9fc..5be11f1 100644 +--- a/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c ++++ b/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c +@@ -31,6 +31,13 @@ static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER; + static int _register_count = 0; + static struct dm_pool *_mem_pool = NULL; + static void *_lvm_handle = NULL; ++static DM_LIST_INIT(_env_registry); ++ ++struct env_data { ++ struct dm_list list; ++ const char *cmd; ++ const char *data; ++}; + + DM_EVENT_LOG_FN("#lvm") + +@@ -100,6 +107,7 @@ void dmeventd_lvm2_exit(void) + lvm2_run(_lvm_handle, "_memlock_dec"); + dm_pool_destroy(_mem_pool); + _mem_pool = NULL; ++ dm_list_init(&_env_registry); + lvm2_exit(_lvm_handle); + _lvm_handle = NULL; + log_debug("lvm plugin exited."); +@@ -124,6 +132,8 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size, + static char _internal_prefix[] = "_dmeventd_"; + char *vg = NULL, *lv = NULL, *layer; + int r; ++ struct env_data *env_data; ++ const char *env = NULL; + + if (!dm_split_lvm_name(mem, device, &vg, &lv, &layer)) { + log_error("Unable to determine VG name from %s.", +@@ -137,18 +147,35 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size, + *layer = '\0'; + + if (!strncmp(cmd, _internal_prefix, sizeof(_internal_prefix) - 1)) { +- dmeventd_lvm2_lock(); +- /* output of internal command passed via env var */ +- if (!dmeventd_lvm2_run(cmd)) +- cmd = NULL; +- else if ((cmd = getenv(cmd))) +- cmd = dm_pool_strdup(mem, cmd); /* copy with lock */ +- dmeventd_lvm2_unlock(); +- +- if (!cmd) { +- log_error("Unable to find configured command."); +- return 0; ++ /* check if ENVVAR wasn't already resolved */ ++ dm_list_iterate_items(env_data, &_env_registry) ++ if (!strcmp(cmd, env_data->cmd)) { ++ env = env_data->data; ++ break; ++ } ++ ++ if (!env) { ++ /* run lvm2 command to find out setting value */ ++ dmeventd_lvm2_lock(); ++ if (!dmeventd_lvm2_run(cmd) || ++ !(env = getenv(cmd))) { ++ log_error("Unable to find configured command."); ++ return 0; ++ } ++ /* output of internal command passed via env var */ ++ env = dm_pool_strdup(_mem_pool, env); /* copy with lock */ ++ dmeventd_lvm2_unlock(); ++ if (!env || ++ !(env_data = dm_pool_zalloc(_mem_pool, sizeof(*env_data))) || ++ !(env_data->cmd = dm_pool_strdup(_mem_pool, cmd))) { ++ log_error("Unable to allocate env memory."); ++ return 0; ++ } ++ env_data->data = env; ++ /* add to ENVVAR registry */ ++ dm_list_add(&_env_registry, &env_data->list); + } ++ cmd = env; + } + + r = dm_snprintf(buffer, size, "%s %s/%s", cmd, vg, lv); +-- +2.19.1 + diff --git a/6004-metadata-prevent-writing-beyond-metadata-area.patch b/6004-metadata-prevent-writing-beyond-metadata-area.patch new file mode 100644 index 0000000..a9be32f --- /dev/null +++ b/6004-metadata-prevent-writing-beyond-metadata-area.patch @@ -0,0 +1,336 @@ +From f4f4a850ea6f992beadd07288ddcb83343c30d27 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:07:23 +0800 +Subject: [PATCH 05/17] metadata: prevent writing beyond metadata area + +lvm uses a bcache block size of 128K. A bcache block +at the end of the metadata area will overlap the PEs +from which LVs are allocated. How much depends on +alignments. When lvm reads and writes one of these +bcache blocks to update VG metadata, it can also be +reading and writing PEs that belong to an LV. + +If these overlapping PEs are being written to by the +LV user (e.g. filesystem) at the same time that lvm +is modifying VG metadata in the overlapping bcache +block, then the user's updates to the PEs can be lost. + +This patch is a quick hack to prevent lvm from writing +past the end of the metadata area. +--- + lib/device/bcache.c | 79 ++++++++++++++++++++++++++++++++++- + lib/device/bcache.h | 3 ++ + lib/format_text/format-text.c | 10 +++++ + lib/label/label.c | 35 +++++++++++++++- + lib/label/label.h | 2 + + lib/metadata/mirror.c | 4 ++ + 6 files changed, 130 insertions(+), 3 deletions(-) + +diff --git a/lib/device/bcache.c b/lib/device/bcache.c +index 531d83b..6235256 100644 +--- a/lib/device/bcache.c ++++ b/lib/device/bcache.c +@@ -156,6 +156,10 @@ static void _async_destroy(struct io_engine *ioe) + dm_free(e); + } + ++static int _last_byte_fd; ++static uint64_t _last_byte_offset; ++static int _last_byte_sector_size; ++ + static bool _async_issue(struct io_engine *ioe, enum dir d, int fd, + sector_t sb, sector_t se, void *data, void *context) + { +@@ -163,12 +167,53 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd, + struct iocb *cb_array[1]; + struct control_block *cb; + struct async_engine *e = _to_async(ioe); ++ sector_t offset; ++ sector_t nbytes; ++ sector_t limit_nbytes; ++ sector_t extra_nbytes = 0; + + if (((uintptr_t) data) & e->page_mask) { + log_warn("misaligned data buffer"); + return false; + } + ++ offset = sb << SECTOR_SHIFT; ++ nbytes = (se - sb) << SECTOR_SHIFT; ++ ++ /* ++ * If bcache block goes past where lvm wants to write, then clamp it. ++ */ ++ if ((d == DIR_WRITE) && _last_byte_offset && (fd == _last_byte_fd)) { ++ 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; ++ } ++ } ++ } ++ + cb = _cb_alloc(e->cbs, context); + if (!cb) { + log_warn("couldn't allocate control block"); +@@ -179,10 +224,22 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd, + + cb->cb.aio_fildes = (int) fd; + cb->cb.u.c.buf = data; +- cb->cb.u.c.offset = sb << SECTOR_SHIFT; +- cb->cb.u.c.nbytes = (se - sb) << SECTOR_SHIFT; ++ cb->cb.u.c.offset = offset; ++ cb->cb.u.c.nbytes = nbytes; + cb->cb.aio_lio_opcode = (d == DIR_READ) ? IO_CMD_PREAD : IO_CMD_PWRITE; + ++#if 0 ++ if (d == DIR_READ) { ++ log_debug("io R off %llu bytes %llu", ++ (unsigned long long)cb->cb.u.c.offset, ++ (unsigned long long)cb->cb.u.c.nbytes); ++ } else { ++ log_debug("io W off %llu bytes %llu", ++ (unsigned long long)cb->cb.u.c.offset, ++ (unsigned long long)cb->cb.u.c.nbytes); ++ } ++#endif ++ + cb_array[0] = &cb->cb; + do { + r = io_submit(e->aio_context, 1, cb_array); +@@ -1153,3 +1210,21 @@ bool bcache_invalidate_fd(struct bcache *cache, int fd) + + //---------------------------------------------------------------- + ++void bcache_set_last_byte(struct bcache *cache, int fd, uint64_t offset, int sector_size) ++{ ++ _last_byte_fd = fd; ++ _last_byte_offset = offset; ++ _last_byte_sector_size = sector_size; ++ if (!sector_size) ++ _last_byte_sector_size = 512; ++} ++ ++void bcache_unset_last_byte(struct bcache *cache, int fd) ++{ ++ if (_last_byte_fd == fd) { ++ _last_byte_fd = 0; ++ _last_byte_offset = 0; ++ _last_byte_sector_size = 0; ++ } ++} ++ +diff --git a/lib/device/bcache.h b/lib/device/bcache.h +index b0aebb4..cb902ef 100644 +--- a/lib/device/bcache.h ++++ b/lib/device/bcache.h +@@ -158,6 +158,9 @@ bool bcache_write_bytes(struct bcache *cache, int fd, uint64_t start, size_t len + bool bcache_zero_bytes(struct bcache *cache, int fd, uint64_t start, size_t len); + bool bcache_set_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, uint8_t val); + ++void bcache_set_last_byte(struct bcache *cache, int fd, uint64_t offset, int sector_size); ++void bcache_unset_last_byte(struct bcache *cache, int fd); ++ + //---------------------------------------------------------------- + + #endif +diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c +index 5c7b72f..4160ba8 100644 +--- a/lib/format_text/format-text.c ++++ b/lib/format_text/format-text.c +@@ -400,10 +400,14 @@ static int _raw_write_mda_header(const struct format_type *fmt, + MDA_HEADER_SIZE - + sizeof(mdah->checksum_xl))); + ++ dev_set_last_byte(dev, start_byte + MDA_HEADER_SIZE); ++ + if (!dev_write_bytes(dev, start_byte, MDA_HEADER_SIZE, mdah)) { ++ dev_unset_last_byte(dev); + log_error("Failed to write mda header to %s fd %d", dev_name(dev), dev->bcache_fd); + return 0; + } ++ dev_unset_last_byte(dev); + + return 1; + } +@@ -677,10 +681,13 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg, + (unsigned long long)(mdac->rlocn.size - new_wrap), + (unsigned long long)new_wrap); + ++ dev_set_last_byte(mdac->area.dev, mdac->area.start + mdah->size); ++ + if (!dev_write_bytes(mdac->area.dev, mdac->area.start + mdac->rlocn.offset, + (size_t) (mdac->rlocn.size - new_wrap), + fidtc->raw_metadata_buf)) { + log_error("Failed to write metadata to %s fd %d", dev_name(mdac->area.dev), mdac->area.dev->bcache_fd); ++ dev_unset_last_byte(mdac->area.dev); + goto out; + } + +@@ -694,10 +701,13 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg, + (size_t) new_wrap, + fidtc->raw_metadata_buf + mdac->rlocn.size - new_wrap)) { + log_error("Failed to write metadata wrap to %s fd %d", dev_name(mdac->area.dev), mdac->area.dev->bcache_fd); ++ dev_unset_last_byte(mdac->area.dev); + goto out; + } + } + ++ dev_unset_last_byte(mdac->area.dev); ++ + mdac->rlocn.checksum = calc_crc(INITIAL_CRC, (uint8_t *)fidtc->raw_metadata_buf, + (uint32_t) (mdac->rlocn.size - + new_wrap)); +diff --git a/lib/label/label.c b/lib/label/label.c +index ac37713..e86b54b 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -172,6 +172,7 @@ int label_write(struct device *dev, struct label *label) + { + char buf[LABEL_SIZE] __attribute__((aligned(8))); + struct label_header *lh = (struct label_header *) buf; ++ uint64_t offset; + int r = 1; + + if (!label->labeller->ops->write) { +@@ -206,11 +207,17 @@ int label_write(struct device *dev, struct label *label) + return 0; + } + +- if (!dev_write_bytes(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf)) { ++ offset = label->sector << SECTOR_SHIFT; ++ ++ dev_set_last_byte(dev, offset + LABEL_SIZE); ++ ++ if (!dev_write_bytes(dev, offset, LABEL_SIZE, buf)) { + log_debug_devs("Failed to write label to %s", dev_name(dev)); + r = 0; + } + ++ dev_unset_last_byte(dev); ++ + return r; + } + +@@ -1256,9 +1263,12 @@ bool dev_write_zeros(struct device *dev, uint64_t start, size_t len) + } + } + ++ dev_set_last_byte(dev, start + len); ++ + if (!bcache_zero_bytes(scan_bcache, dev->bcache_fd, start, len)) { + log_error("Error writing device %s at %llu length %u.", + dev_name(dev), (unsigned long long)start, (uint32_t)len); ++ dev_unset_last_byte(dev); + label_scan_invalidate(dev); + return false; + } +@@ -1266,9 +1276,11 @@ bool dev_write_zeros(struct device *dev, uint64_t start, size_t len) + if (!bcache_flush(scan_bcache)) { + log_error("Error writing device %s at %llu length %u.", + dev_name(dev), (unsigned long long)start, (uint32_t)len); ++ dev_unset_last_byte(dev); + label_scan_invalidate(dev); + return false; + } ++ dev_unset_last_byte(dev); + return true; + } + +@@ -1302,9 +1314,12 @@ bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val) + } + } + ++ dev_set_last_byte(dev, start + len); ++ + if (!bcache_set_bytes(scan_bcache, dev->bcache_fd, start, len, val)) { + log_error("Error writing device %s at %llu length %u.", + dev_name(dev), (unsigned long long)start, (uint32_t)len); ++ dev_unset_last_byte(dev); + label_scan_invalidate(dev); + return false; + } +@@ -1312,9 +1327,27 @@ bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val) + if (!bcache_flush(scan_bcache)) { + log_error("Error writing device %s at %llu length %u.", + dev_name(dev), (unsigned long long)start, (uint32_t)len); ++ dev_unset_last_byte(dev); + label_scan_invalidate(dev); + return false; + } ++ ++ dev_unset_last_byte(dev); + return true; + } + ++void dev_set_last_byte(struct device *dev, uint64_t offset) ++{ ++ unsigned int phys_block_size = 0; ++ unsigned int block_size = 0; ++ ++ dev_get_block_size(dev, &phys_block_size, &block_size); ++ ++ bcache_set_last_byte(scan_bcache, dev->bcache_fd, offset, phys_block_size); ++} ++ ++void dev_unset_last_byte(struct device *dev) ++{ ++ bcache_unset_last_byte(scan_bcache, dev->bcache_fd); ++} ++ +diff --git a/lib/label/label.h b/lib/label/label.h +index 5ed8bc8..e2b8263 100644 +--- a/lib/label/label.h ++++ b/lib/label/label.h +@@ -125,5 +125,7 @@ bool dev_read_bytes(struct device *dev, uint64_t start, size_t len, void *data); + bool dev_write_bytes(struct device *dev, uint64_t start, size_t len, void *data); + bool dev_write_zeros(struct device *dev, uint64_t start, size_t len); + 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); ++void dev_unset_last_byte(struct device *dev); + + #endif +diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c +index 7f38d4f..b2a4dfb 100644 +--- a/lib/metadata/mirror.c ++++ b/lib/metadata/mirror.c +@@ -302,10 +302,14 @@ static int _write_log_header(struct cmd_context *cmd, struct logical_volume *lv) + return 0; + } + ++ dev_set_last_byte(dev, sizeof(log_header)); ++ + if (!dev_write_bytes(dev, UINT64_C(0), sizeof(log_header), &log_header)) { ++ dev_unset_last_byte(dev); + log_error("Failed to write log header to %s.", name); + return 0; + } ++ dev_unset_last_byte(dev); + + label_scan_invalidate(dev); + +-- +2.19.1 + diff --git a/6005-libdm-stats-move-no-regions-warning-after-dm_stats_l.patch b/6005-libdm-stats-move-no-regions-warning-after-dm_stats_l.patch new file mode 100644 index 0000000..d79d3e0 --- /dev/null +++ b/6005-libdm-stats-move-no-regions-warning-after-dm_stats_l.patch @@ -0,0 +1,45 @@ +From 4493c6a45c334751ab99428ca0f072f7486e3b2c Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:13:16 +0800 +Subject: [PATCH 06/17] libdm-stats: move no regions warning after + dm_stats_list() + +It doesn't make sense to test or warn about the region count until +the stats handle has been listed: at this point it may or may not +contain valid information (but is guaranteed to be correct after +the list). +--- + 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 { +-- +2.19.1 + diff --git a/6006-dmsetup-fix-stats-report-command-output.patch b/6006-dmsetup-fix-stats-report-command-output.patch new file mode 100644 index 0000000..f2ad6dc --- /dev/null +++ b/6006-dmsetup-fix-stats-report-command-output.patch @@ -0,0 +1,48 @@ +From fcae18ceb9a6db7182abbbea379d45cebb901313 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:14:43 +0800 +Subject: [PATCH 07/17] dmsetup: fix stats report command output + +Since the stats handle is neither bound nor listed before the +attempt to call dm_stats_get_nr_regions(), it will always return +zero: this prevents reporting of any dmstats regions on any +device. + +Remove the dm_stats_get_nr_regions() check and instead rely on +the correct return status from dm_stats_populate() which only +returns 0 in the case that there are regions to inspect (and +which logs a specific error for all other cases). + +Reported-by: Bryan Gurney +--- + tools/dmsetup.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/tools/dmsetup.c b/tools/dmsetup.c +index af70a02..aca595d 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(); + +-- +2.19.1 + diff --git a/6007-io-use-sync-io-if-aio-fails.patch b/6007-io-use-sync-io-if-aio-fails.patch new file mode 100644 index 0000000..117a111 --- /dev/null +++ b/6007-io-use-sync-io-if-aio-fails.patch @@ -0,0 +1,216 @@ +From 541efb3a013eed7dda561be66a66a11a3d500c78 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:16:56 +0800 +Subject: [PATCH 08/17] io: use sync io if aio fails + +io_setup() for aio may fail if a system has reached the +aio request limit. In this case, fall back to using +sync io. Also, lvm use of aio can be disabled entirely +with config setting global/use_aio=0. + +The system limit for aio requests can be seen from + /proc/sys/fs/aio-max-nr + +The current usage of aio requests can be seen from + /proc/sys/fs/aio-nr + +The system limit for aio requests can be increased by +setting fs.aio-max-nr using sysctl. + +Also add last-byte limit to the sync io code. +--- + 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 c9596e2..ecd8fd7 100644 +--- a/lib/commands/toolcontext.c ++++ b/lib/commands/toolcontext.c +@@ -333,6 +333,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 e98ca6d..f8a577f 100644 +--- a/lib/config/config_settings.h ++++ b/lib/config/config_settings.h +@@ -935,6 +935,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 7cebd84..fc2f603 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 6235256..571ee7a 100644 +--- a/lib/device/bcache.c ++++ b/lib/device/bcache.c +@@ -388,6 +388,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 e86b54b..5114959 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); +-- +2.19.1 + diff --git a/6008-bcache-sync-io-fixes.patch b/6008-bcache-sync-io-fixes.patch new file mode 100644 index 0000000..4da5455 --- /dev/null +++ b/6008-bcache-sync-io-fixes.patch @@ -0,0 +1,126 @@ +From 7152c76a6b8949df3ed4ace7dd9148c5ef91a74f Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:21:50 +0800 +Subject: [PATCH 09/17] bcache: sync io fixes + +fix lseek error check +fix read/write error checks +handle zero return from read and write +don't return an error for short io +fix partial read/write loop +--- + 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 571ee7a..7384a32 100644 +--- a/lib/device/bcache.c ++++ b/lib/device/bcache.c +@@ -328,7 +328,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; + } +@@ -371,8 +371,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) { +@@ -381,11 +384,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; + } + + /* +@@ -430,28 +439,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; ++ */ + } + + +-- +2.19.1 + diff --git a/6009-lvmanip-uninitialized-members-in-struct-pv_list-10.patch b/6009-lvmanip-uninitialized-members-in-struct-pv_list-10.patch new file mode 100644 index 0000000..c0c06c8 --- /dev/null +++ b/6009-lvmanip-uninitialized-members-in-struct-pv_list-10.patch @@ -0,0 +1,37 @@ +From c04042cf7b7d4de3d892c6078787af8e29fd3c8a Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:23:39 +0800 +Subject: [PATCH 10/17] lvmanip: uninitialized members in struct pv_list (#10) + +Scenario: Given an existed LV `lvol0`, I want to create another LV +on the PVs used by `lvol0`. + +I use `build_parallel_areas_from_lv()` to obtain the `pv_list` of each segments. +However, the returned `pv_list` is not properly initialized, which causes +segfault in subsequent operations. + +(cherry picked from commit 859feb81e5b61ac2109b1d7850844ccf1ce3e5bf) +(cherry picked from commit 219ba4f54a462c175f5e9acaa0558afac94d5ff7) + +Conflicts: + WHATS_NEW +--- + lib/metadata/lv_manip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c +index e4293cc..d1389e7 100644 +--- a/lib/metadata/lv_manip.c ++++ b/lib/metadata/lv_manip.c +@@ -5860,7 +5860,7 @@ static int _add_pvs(struct cmd_context *cmd, struct pv_segment *peg, + if (find_pv_in_pv_list(&spvs->pvs, peg->pv)) + return 1; + +- if (!(pvl = dm_pool_alloc(cmd->mem, sizeof(*pvl)))) { ++ if (!(pvl = dm_pool_zalloc(cmd->mem, sizeof(*pvl)))) { + log_error("pv_list allocation failed"); + return 0; + } +-- +2.19.1 + diff --git a/6010-apply-obtain_device_list_from_udev-to-all-libudev-us.patch b/6010-apply-obtain_device_list_from_udev-to-all-libudev-us.patch new file mode 100644 index 0000000..9fa7c2e --- /dev/null +++ b/6010-apply-obtain_device_list_from_udev-to-all-libudev-us.patch @@ -0,0 +1,34 @@ +From bc10f60bdc1076b8b3405e9ce18a088cd770b268 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:39:13 +0800 +Subject: [PATCH 11/17] apply obtain_device_list_from_udev to all libudev usage + +udev_dev_is_md_component and udev_dev_is_mpath_component +are not used for obtaining the device list, but they still +use libudev for device info. When there are problems with +udev, these functions can get stuck. So, use the existing +obtain_device_list_from_udev config setting to also control +whether these "is component" functions are used, which gives +us a way to avoid using libudev entirely when it's causing +problems. +--- + lib/device/dev-type.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c +index af4b407..e1671fa 100644 +--- a/lib/device/dev-type.c ++++ b/lib/device/dev-type.c +@@ -1016,6 +1016,9 @@ int udev_dev_is_mpath_component(struct device *dev) + unsigned i = 0; + int ret = 0; + ++ if (!obtain_device_list_from_udev()) ++ return 0; ++ + if (!udev_context) { + log_warn("WARNING: No udev context available to check if device %s is multipath component.", dev_name(dev)); + return 0; +-- +2.19.1 + diff --git a/6011-cov-dmstats-check-for-failing-malloc.patch b/6011-cov-dmstats-check-for-failing-malloc.patch new file mode 100644 index 0000000..a39c31c --- /dev/null +++ b/6011-cov-dmstats-check-for-failing-malloc.patch @@ -0,0 +1,31 @@ +From 1e02c1dc7986800b92ec2662b74ebbf0e1e82f4c Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:41:41 +0800 +Subject: [PATCH 12/17] cov: dmstats check for failing malloc + +Add missing check for allocation success. + +Backported from: 9b7121226258f7dfe759cc1f8625cbfb80fec161 +--- + tools/dmsetup.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/tools/dmsetup.c b/tools/dmsetup.c +index aca595d..d47484b 100644 +--- a/tools/dmsetup.c ++++ b/tools/dmsetup.c +@@ -5228,7 +5228,10 @@ static int _do_stats_create_regions(struct dm_stats *dms, + if (!segments || (info.target_count == 1)) + region_ids = ®ion_id; + else +- region_ids = dm_malloc(info.target_count * sizeof(*region_ids)); ++ if (!(region_ids = dm_malloc(info.target_count * sizeof(*region_ids)))) { ++ log_error("Failed to allocated region IDs."); ++ goto out; ++ } + + do { + uint64_t segment_start, segment_len; +-- +2.19.1 + diff --git a/6012-cov-ensure-vars-are-set.patch b/6012-cov-ensure-vars-are-set.patch new file mode 100644 index 0000000..ad195e8 --- /dev/null +++ b/6012-cov-ensure-vars-are-set.patch @@ -0,0 +1,32 @@ +From 8b4941a9ebc83b49d25215ae914169db8441aafd Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:42:59 +0800 +Subject: [PATCH 13/17] cov: ensure vars are set + +Make sure, tmp_begin and tmp_end are always set, even for blind +coverity. + +(cherry picked from commit 251366146727aac97af5de2eef855860d14910ca) + +Conflicts: + device_mapper/libdm-report.c +--- + libdm/libdm-report.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c +index 6d140af..0401f9c 100644 +--- a/libdm/libdm-report.c ++++ b/libdm/libdm-report.c +@@ -2380,7 +2380,7 @@ static const char *_get_reserved(struct dm_report *rh, unsigned type, + { + const struct dm_report_reserved_value *iter = implicit ? NULL : rh->reserved_values; + const struct dm_report_field_reserved_value *frv; +- const char *tmp_begin, *tmp_end, *tmp_s = s; ++ const char *tmp_begin = NULL, *tmp_end = NULL, *tmp_s = s; + const char *name = NULL; + char c; + +-- +2.19.1 + diff --git a/6013-libdm-add-memory-barrier.patch b/6013-libdm-add-memory-barrier.patch new file mode 100644 index 0000000..f793a20 --- /dev/null +++ b/6013-libdm-add-memory-barrier.patch @@ -0,0 +1,43 @@ +From 673ff3585880ccacc53abaea01df027859ed5c1b Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:44:36 +0800 +Subject: [PATCH 14/17] libdm: add memory barrier + +Just for case ensure compiler is not able to optimize +memset() away for resources that are released. + +This idea of using memory barrier is taken from openssl. + +Other options would be to check for 'explicit_bzero' function. + +(cherry picked from commit 55a8d6c86b4c6c6c707cfcc3dd887bca0632114f) + +Conflicts: + device_mapper/ioctl/libdm-iface.c +--- + libdm/ioctl/libdm-iface.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libdm/ioctl/libdm-iface.c b/libdm/ioctl/libdm-iface.c +index 769b69c..7f48e37 100644 +--- a/libdm/ioctl/libdm-iface.c ++++ b/libdm/ioctl/libdm-iface.c +@@ -466,6 +466,7 @@ static void _dm_zfree_string(char *string) + { + if (string) { + memset(string, 0, strlen(string)); ++ asm volatile ("" ::: "memory"); /* Compiler barrier. */ + dm_free(string); + } + } +@@ -474,6 +475,7 @@ static void _dm_zfree_dmi(struct dm_ioctl *dmi) + { + if (dmi) { + memset(dmi, 0, dmi->data_size); ++ asm volatile ("" ::: "memory"); /* Compiler barrier. */ + dm_free(dmi); + } + } +-- +2.19.1 + diff --git a/6014-stats-fix-error-path-when-region-is-NULL.patch b/6014-stats-fix-error-path-when-region-is-NULL.patch new file mode 100644 index 0000000..e17c661 --- /dev/null +++ b/6014-stats-fix-error-path-when-region-is-NULL.patch @@ -0,0 +1,51 @@ +From ebb978b547c4593de34d259e745824f12672614d Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:46:45 +0800 +Subject: [PATCH 15/17] stats: fix error path when region is NULL + +We should not call _stats_cleanup_region_ids() when regions +are NULL. +Also add backtracing for goto. + +(cherry picked from commit 3750b0cff5ab1c41076afdf8275e3fa20aa756d0) +--- + 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 6b4e3d8..ec9801a 100644 +--- a/libdm/libdm-stats.c ++++ b/libdm/libdm-stats.c +@@ -4867,24 +4867,24 @@ uint64_t *dm_stats_update_regions_from_fd(struct dm_stats *dms, int fd, + group_id, &count, ®roup); + + if (!regions) +- goto bad; ++ goto_out; + + if (!dm_stats_list(dms, NULL)) +- goto bad; ++ goto_bad; + + /* regroup if there are regions to group */ + if (regroup && (*regions != DM_STATS_REGION_NOT_PRESENT)) + if (!_stats_group_file_regions(dms, regions, count, alias)) +- goto bad; ++ goto_bad; + + dm_free(bounds); + dm_free((char *) alias); + return regions; + bad: + _stats_cleanup_region_ids(dms, regions, count); +- dm_free(bounds); +- dm_free(regions); + out: ++ dm_free(regions); ++ dm_free(bounds); + dm_free((char *) alias); + return NULL; + } +-- +2.19.1 + diff --git a/6015-stats-initilize-regions-to-NULL.patch b/6015-stats-initilize-regions-to-NULL.patch new file mode 100644 index 0000000..415e476 --- /dev/null +++ b/6015-stats-initilize-regions-to-NULL.patch @@ -0,0 +1,29 @@ +From b6dae8eae08f85705248bc98120609d19d4424cf Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:47:57 +0800 +Subject: [PATCH 16/17] stats: initilize regions to NULL + +Commit 3750b0cff5ab1c41076afdf8275e3fa20aa756d0 used bad: error +path in more occasions thus it now needs regions defined as NULL. + +(cherry picked from commit 83c6f7e7e6e76199d836bf694266c78e3cbc12f1) +--- + libdm/libdm-stats.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libdm/libdm-stats.c b/libdm/libdm-stats.c +index ec9801a..5d90231 100644 +--- a/libdm/libdm-stats.c ++++ b/libdm/libdm-stats.c +@@ -4807,7 +4807,7 @@ uint64_t *dm_stats_update_regions_from_fd(struct dm_stats *dms, int fd, + { + struct dm_histogram *bounds = NULL; + int nr_bins, precise, regroup; +- uint64_t *regions, count = 0; ++ uint64_t *regions = NULL, count = 0; + const char *alias = NULL; + + if (!dms->regions || !dm_stats_group_present(dms, group_id)) { +-- +2.19.1 + diff --git a/6016-dmsetup-Fix-multi-line-concise-table-parsing.patch b/6016-dmsetup-Fix-multi-line-concise-table-parsing.patch new file mode 100644 index 0000000..611c8a5 --- /dev/null +++ b/6016-dmsetup-Fix-multi-line-concise-table-parsing.patch @@ -0,0 +1,31 @@ +From d10584888038afb855099feebb117492c48d156c Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 14:49:08 +0800 +Subject: [PATCH 17/17] dmsetup: Fix multi-line concise table parsing + +Use the correct loop variable within the loop, instead of reusing the +initial value. Table lines after the first don't get terminated in +the right place. + +Signed-off-by: Kurt Garloff +(cherry picked from commit ccfbd505fea2f259f7c89dc23b020b838363a611) +--- + tools/dmsetup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/dmsetup.c b/tools/dmsetup.c +index d47484b..55fbd95 100644 +--- a/tools/dmsetup.c ++++ b/tools/dmsetup.c +@@ -367,7 +367,7 @@ static int _parse_table_lines(struct dm_task *dmt) + + do { + /* Identify and terminate each line */ +- if ((next_pos = strchr(_table, '\n'))) ++ if ((next_pos = strchr(pos, '\n'))) + *next_pos++ = '\0'; + if (!_parse_line(dmt, pos, "", ++line)) + return_0; +-- +2.19.1 + diff --git a/6017-Remove-VG-lock-ordering-check.patch b/6017-Remove-VG-lock-ordering-check.patch new file mode 100644 index 0000000..935551c --- /dev/null +++ b/6017-Remove-VG-lock-ordering-check.patch @@ -0,0 +1,194 @@ +From 80f7f6e0fdd7672a3bbb781b5edbc73c0699c539 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 17:13:26 +0800 +Subject: [PATCH 01/19] Remove VG lock ordering check + +Four commands lock two VGs at a time: + +- vgsplit and vgmerge already have their own logic to + acquire the locks in the correct order. + +- vgimportclone and vgrename disable this ordering check. +--- + lib/cache/lvmcache.c | 66 ------------------------------------------- + lib/cache/lvmcache.h | 1 - + lib/locking/locking.c | 5 ---- + tools/toollib.c | 8 ------ + tools/vgimportclone.c | 4 --- + tools/vgrename.c | 5 ---- + 6 files changed, 89 deletions(-) + +diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c +index 3e681a2..1a2e987 100644 +--- a/lib/cache/lvmcache.c ++++ b/lib/cache/lvmcache.c +@@ -105,7 +105,6 @@ static int _has_scanned = 0; + static int _vgs_locked = 0; + static int _vg_global_lock_held = 0; /* Global lock held when cache wiped? */ + static int _found_duplicate_pvs = 0; /* If we never see a duplicate PV we can skip checking for them later. */ +-static int _suppress_lock_ordering = 0; + + int lvmcache_init(struct cmd_context *cmd) + { +@@ -547,71 +546,6 @@ void lvmcache_drop_metadata(const char *vgname, int drop_precommitted) + _drop_metadata(vgname, drop_precommitted); + } + +-/* +- * Ensure vgname2 comes after vgname1 alphabetically. +- * Orphan locks come last. +- * VG_GLOBAL comes first. +- */ +-static int _vgname_order_correct(const char *vgname1, const char *vgname2) +-{ +- if (is_global_vg(vgname1)) +- return 1; +- +- if (is_global_vg(vgname2)) +- return 0; +- +- if (is_orphan_vg(vgname1)) +- return 0; +- +- if (is_orphan_vg(vgname2)) +- return 1; +- +- if (strcmp(vgname1, vgname2) < 0) +- return 1; +- +- return 0; +-} +- +-void lvmcache_lock_ordering(int enable) +-{ +- _suppress_lock_ordering = !enable; +-} +- +-/* +- * Ensure VG locks are acquired in alphabetical order. +- */ +-int lvmcache_verify_lock_order(const char *vgname) +-{ +- struct dm_hash_node *n; +- const char *vgname2; +- +- if (_suppress_lock_ordering) +- return 1; +- +- if (!_lock_hash) +- return 1; +- +- dm_hash_iterate(n, _lock_hash) { +- if (!dm_hash_get_data(_lock_hash, n)) +- return_0; +- +- if (!(vgname2 = dm_hash_get_key(_lock_hash, n))) { +- log_error(INTERNAL_ERROR "VG lock %s hits NULL.", +- vgname); +- return 0; +- } +- +- if (!_vgname_order_correct(vgname2, vgname)) { +- log_errno(EDEADLK, INTERNAL_ERROR "VG lock %s must " +- "be requested before %s, not after.", +- vgname, vgname2); +- return 0; +- } +- } +- +- return 1; +-} +- + void lvmcache_lock_vgname(const char *vgname, int read_only __attribute__((unused))) + { + if (dm_hash_lookup(_lock_hash, vgname)) +diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h +index bf976e9..e9e6932 100644 +--- a/lib/cache/lvmcache.h ++++ b/lib/cache/lvmcache.h +@@ -87,7 +87,6 @@ int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted); + + void lvmcache_lock_vgname(const char *vgname, int read_only); + void lvmcache_unlock_vgname(const char *vgname); +-int lvmcache_verify_lock_order(const char *vgname); + + /* Queries */ + const struct format_type *lvmcache_fmt_from_vgname(struct cmd_context *cmd, const char *vgname, const char *vgid, unsigned revalidate_labels); +diff --git a/lib/locking/locking.c b/lib/locking/locking.c +index 2584227..093dbbd 100644 +--- a/lib/locking/locking.c ++++ b/lib/locking/locking.c +@@ -319,11 +319,6 @@ int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags, const str + /* Global VG_ORPHANS lock covers all orphan formats. */ + if (is_orphan_vg(vol)) + vol = VG_ORPHANS; +- /* VG locks alphabetical, ORPHAN lock last */ +- if ((lck_type != LCK_UNLOCK) && +- !(flags & LCK_CACHE) && +- !lvmcache_verify_lock_order(vol)) +- return_0; + + if ((flags == LCK_VG_DROP_CACHE) || + (strcmp(vol, VG_GLOBAL) && strcmp(vol, VG_SYNC_NAMES))) { +diff --git a/tools/toollib.c b/tools/toollib.c +index 01686b0..ce877cc 100644 +--- a/tools/toollib.c ++++ b/tools/toollib.c +@@ -5514,14 +5514,6 @@ int pvcreate_each_device(struct cmd_context *cmd, + dm_list_add(&pp->arg_devices, &pd->list); + } + +- /* +- * This function holds the orphans lock while reading VGs to look for +- * devices. This means the orphans lock is held while VG locks are +- * acquired, which is against lvmcache lock ordering rules, so disable +- * the lvmcache lock ordering checks. +- */ +- lvmcache_lock_ordering(0); +- + /* + * Clear the cache before acquiring the orphan lock. (Clearing the + * cache with locks held is an error.) We want the orphan lock +diff --git a/tools/vgimportclone.c b/tools/vgimportclone.c +index c4c5d4c..087078a 100644 +--- a/tools/vgimportclone.c ++++ b/tools/vgimportclone.c +@@ -342,9 +342,6 @@ retry_name: + + log_debug("Changing VG %s to %s.", vp.old_vgname, vp.new_vgname); + +- /* We don't care if the new name comes before the old in lock order. */ +- lvmcache_lock_ordering(0); +- + if (!lock_vol(cmd, vp.new_vgname, LCK_VG_WRITE, NULL)) { + log_error("Can't get lock for new VG name %s", vp.new_vgname); + goto out; +@@ -363,7 +360,6 @@ out: + unlock_vg(cmd, NULL, VG_GLOBAL); + internal_filter_clear(); + init_internal_filtering(0); +- lvmcache_lock_ordering(1); + destroy_processing_handle(cmd, handle); + + /* Enable lvmetad again if no duplicates are left. */ +diff --git a/tools/vgrename.c b/tools/vgrename.c +index 4f2a08b..bbc3087 100644 +--- a/tools/vgrename.c ++++ b/tools/vgrename.c +@@ -99,13 +99,8 @@ static int _vgrename_single(struct cmd_context *cmd, const char *vg_name, + * this uuid-for-name case. + */ + if (vp->lock_vg_old_first || vp->old_name_is_uuid) { +- if (vp->old_name_is_uuid) +- lvmcache_lock_ordering(0); +- + if (!_lock_new_vg_for_rename(cmd, vp->vg_name_new)) + return ECMD_FAILED; +- +- lvmcache_lock_ordering(1); + } + + dev_dir = cmd->dev_dir; +-- +2.19.1 + diff --git a/6018-Fix-use-of-orphan-lock-in-commands.patch b/6018-Fix-use-of-orphan-lock-in-commands.patch new file mode 100644 index 0000000..454fb11 --- /dev/null +++ b/6018-Fix-use-of-orphan-lock-in-commands.patch @@ -0,0 +1,223 @@ +From b71954e7599a651470e51020c9aa9205a1551ad5 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 17:23:43 +0800 +Subject: [PATCH 02/19] Fix use of orphan lock in commands + +vgreduce, vgremove and vgcfgrestore were acquiring +the orphan lock in the midst of command processing +instead of at the start of the command. (The orphan +lock moved to being acquired at the start of the +command back when pvcreate/vgcreate/vgextend were +reworked based on pvcreate_each_device.) + +vgsplit also needed a small update to avoid reacquiring +a VG lock that it already held (for the new VG name). +--- + lib/metadata/metadata-exported.h | 4 ++++ + lib/metadata/metadata.c | 10 ++-------- + lib/metadata/vg.c | 14 ++++++-------- + tools/vgcfgrestore.c | 12 ++++++------ + tools/vgreduce.c | 7 +++++++ + tools/vgremove.c | 7 +++++++ + tools/vgsplit.c | 2 ++ + 7 files changed, 34 insertions(+), 22 deletions(-) + +diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h +index f4fb112..e2fe76b 100644 +--- a/lib/metadata/metadata-exported.h ++++ b/lib/metadata/metadata-exported.h +@@ -704,6 +704,10 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, + const char *vgid, uint32_t read_flags, uint32_t lockd_state); + struct volume_group *vg_read_for_update(struct cmd_context *cmd, const char *vg_name, + const char *vgid, uint32_t read_flags, uint32_t lockd_state); ++struct volume_group *vg_read_orphans(struct cmd_context *cmd, ++ uint32_t warn_flags, ++ const char *orphan_vgname, ++ int *consistent); + + /* + * Test validity of a VG handle. +diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c +index 2292568..2c81623 100644 +--- a/lib/metadata/metadata.c ++++ b/lib/metadata/metadata.c +@@ -600,14 +600,8 @@ int vg_remove(struct volume_group *vg) + { + int ret; + +- if (!lock_vol(vg->cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) { +- log_error("Can't get lock for orphan PVs"); +- return 0; +- } +- + ret = vg_remove_direct(vg); + +- unlock_vg(vg->cmd, vg, VG_ORPHANS); + return ret; + } + +@@ -3377,7 +3371,7 @@ static int _vg_read_orphan_pv(struct lvmcache_info *info, void *baton) + } + + /* Make orphan PVs look like a VG. */ +-static struct volume_group *_vg_read_orphans(struct cmd_context *cmd, ++struct volume_group *vg_read_orphans(struct cmd_context *cmd, + uint32_t warn_flags, + const char *orphan_vgname, + int *consistent) +@@ -3768,7 +3762,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, + "with pre-commit."); + return NULL; + } +- return _vg_read_orphans(cmd, warn_flags, vgname, consistent); ++ return vg_read_orphans(cmd, warn_flags, vgname, consistent); + } + + uuid[0] = '\0'; +diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c +index b8b1501..3bde1fd 100644 +--- a/lib/metadata/vg.c ++++ b/lib/metadata/vg.c +@@ -722,6 +722,7 @@ int vgreduce_single(struct cmd_context *cmd, struct volume_group *vg, + { + struct pv_list *pvl; + struct volume_group *orphan_vg = NULL; ++ int consistent; + int r = 0; + const char *name = pv_dev_name(pv); + +@@ -730,6 +731,8 @@ int vgreduce_single(struct cmd_context *cmd, struct volume_group *vg, + return r; + } + ++ log_debug("vgreduce_single VG %s PV %s", vg->name, pv_dev_name(pv)); ++ + if (pv_pe_alloc_count(pv)) { + log_error("Physical volume \"%s\" still in use", name); + return r; +@@ -741,11 +744,6 @@ int vgreduce_single(struct cmd_context *cmd, struct volume_group *vg, + return r; + } + +- if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) { +- log_error("Can't get lock for orphan PVs"); +- return r; +- } +- + pvl = find_pv_in_vg(vg, name); + + if (!archive(vg)) +@@ -767,8 +765,8 @@ int vgreduce_single(struct cmd_context *cmd, struct volume_group *vg, + vg->free_count -= pv_pe_count(pv) - pv_pe_alloc_count(pv); + vg->extent_count -= pv_pe_count(pv); + +- orphan_vg = vg_read_for_update(cmd, vg->fid->fmt->orphan_vg_name, +- NULL, 0, 0); ++ /* FIXME: we don't need to vg_read the orphan vg here */ ++ orphan_vg = vg_read_orphans(cmd, 0, vg->fid->fmt->orphan_vg_name, &consistent); + + if (vg_read_error(orphan_vg)) + goto bad; +@@ -806,6 +804,6 @@ bad: + /* If we are committing here or we had an error then we will free fid */ + if (pvl && (commit || r != 1)) + free_pv_fid(pvl->pv); +- unlock_and_release_vg(cmd, orphan_vg, VG_ORPHANS); ++ release_vg(orphan_vg); + return r; + } +diff --git a/tools/vgcfgrestore.c b/tools/vgcfgrestore.c +index 48a2fa4..37df8cf 100644 +--- a/tools/vgcfgrestore.c ++++ b/tools/vgcfgrestore.c +@@ -136,14 +136,14 @@ int vgcfgrestore(struct cmd_context *cmd, int argc, char **argv) + lvmetad_rescan = 1; + } + +- if (!lock_vol(cmd, vg_name, LCK_VG_WRITE, NULL)) { +- log_error("Unable to lock volume group %s", vg_name); ++ if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) { ++ log_error("Unable to lock orphans."); + return ECMD_FAILED; + } + +- if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) { +- log_error("Unable to lock orphans"); +- unlock_vg(cmd, NULL, vg_name); ++ if (!lock_vol(cmd, vg_name, LCK_VG_WRITE, NULL)) { ++ log_error("Unable to lock volume group %s.", vg_name); ++ unlock_vg(cmd, NULL, VG_ORPHANS); + return ECMD_FAILED; + } + +@@ -156,8 +156,8 @@ int vgcfgrestore(struct cmd_context *cmd, int argc, char **argv) + arg_str_value(cmd, file_ARG, ""), + arg_count(cmd, force_long_ARG)) : + backup_restore(cmd, vg_name, arg_count(cmd, force_long_ARG)))) { +- unlock_vg(cmd, NULL, VG_ORPHANS); + unlock_vg(cmd, NULL, vg_name); ++ unlock_vg(cmd, NULL, VG_ORPHANS); + log_error("Restore failed."); + ret = ECMD_FAILED; + goto rescan; +diff --git a/tools/vgreduce.c b/tools/vgreduce.c +index e8479a8..aa35453 100644 +--- a/tools/vgreduce.c ++++ b/tools/vgreduce.c +@@ -231,9 +231,16 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv) + handle->custom_handle = &vp; + + if (!repairing) { ++ if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) { ++ log_error("Can't get lock for orphan PVs"); ++ ret = ECMD_FAILED; ++ goto out; ++ } ++ + /* FIXME: Pass private struct through to all these functions */ + /* and update in batch afterwards? */ + ret = process_each_pv(cmd, argc, argv, vg_name, 0, READ_FOR_UPDATE, handle, _vgreduce_single); ++ unlock_vg(cmd, NULL, VG_ORPHANS); + goto out; + } + +diff --git a/tools/vgremove.c b/tools/vgremove.c +index 8bf3841..5010e7d 100644 +--- a/tools/vgremove.c ++++ b/tools/vgremove.c +@@ -108,10 +108,17 @@ int vgremove(struct cmd_context *cmd, int argc, char **argv) + */ + cmd->lockd_gl_disable = 1; + ++ if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) { ++ log_error("Can't get lock for orphan PVs"); ++ return ECMD_FAILED; ++ } ++ + cmd->handles_missing_pvs = 1; + ret = process_each_vg(cmd, argc, argv, NULL, NULL, + READ_FOR_UPDATE, 0, + NULL, &_vgremove_single); + ++ unlock_vg(cmd, NULL, VG_ORPHANS); ++ + return ret; + } +diff --git a/tools/vgsplit.c b/tools/vgsplit.c +index 2d39111..fb1fb6b 100644 +--- a/tools/vgsplit.c ++++ b/tools/vgsplit.c +@@ -749,8 +749,10 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv) + + /* + * Finally, remove the EXPORTED flag from the new VG and write it out. ++ * We need to unlock vg_to because vg_read_for_update wants to lock it. + */ + 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); +-- +2.19.1 + diff --git a/6019-metadata-remove-an-unused-and-incorrect-overflow-che.patch b/6019-metadata-remove-an-unused-and-incorrect-overflow-che.patch new file mode 100644 index 0000000..f4099be --- /dev/null +++ b/6019-metadata-remove-an-unused-and-incorrect-overflow-che.patch @@ -0,0 +1,54 @@ +From d5b2f439a1a36938b4f7659bc7c40870db928c4a Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 17:38:14 +0800 +Subject: [PATCH 03/19] metadata: remove an unused and incorrect overflow check + +Remove another instance of an invalid check for metadata +overflow during read. The previous instance was removed +in commit 5fb15b193. + +This was checking for metadata that that overflowed the +circular disk metadata buffer during read, but such metadata +cannot be written, so it shouldn't be possible to find see. +Also, the check was incorrect and could trigger when there +was no overflow. +--- + lib/format_text/format-text.c | 15 --------------- + 1 file changed, 15 deletions(-) + +diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c +index 4160ba8..4e5b08e 100644 +--- a/lib/format_text/format-text.c ++++ b/lib/format_text/format-text.c +@@ -553,14 +553,6 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid, + if (rlocn->offset + rlocn->size > mdah->size) + wrap = (uint32_t) ((rlocn->offset + rlocn->size) - mdah->size); + +- if (wrap > rlocn->offset) { +- log_error("Metadata for VG %s on %s at %llu size %llu is too large for circular buffer.", +- vgname, dev_name(area->dev), +- (unsigned long long)(area->start + rlocn->offset), +- (unsigned long long)rlocn->size); +- goto out; +- } +- + vg = text_read_metadata(fid, NULL, vg_fmtdata, use_previous_vg, area->dev, primary_mda, + (off_t) (area->start + rlocn->offset), + (uint32_t) (rlocn->size - wrap), +@@ -1249,13 +1241,6 @@ int read_metadata_location_summary(const struct format_type *fmt, + if (rlocn->offset + rlocn->size > mdah->size) + wrap = (uint32_t) ((rlocn->offset + rlocn->size) - mdah->size); + +- if (wrap > rlocn->offset) { +- log_error("Metadata location on %s at %llu is too large for circular buffer.", +- dev_name(dev_area->dev), +- (unsigned long long)(dev_area->start + rlocn->offset)); +- return 0; +- } +- + /* + * Did we see this metadata before? + * Look in lvmcache to see if there is vg info matching +-- +2.19.1 + diff --git a/6020-cov-dmeventd-plugin-fix-memleak.patch b/6020-cov-dmeventd-plugin-fix-memleak.patch new file mode 100644 index 0000000..f6f5c87 --- /dev/null +++ b/6020-cov-dmeventd-plugin-fix-memleak.patch @@ -0,0 +1,41 @@ +From 3d3b47975f25027b0dbc454f64fddea04a8c01f8 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 19:35:31 +0800 +Subject: [PATCH 04/19] cov: dmeventd plugin fix memleak + +Fix memory leak when policy command fails too frequently and +plugin decided to skip it. +--- + daemons/dmeventd/plugins/thin/dmeventd_thin.c | 2 +- + daemons/dmeventd/plugins/vdo/dmeventd_vdo.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/daemons/dmeventd/plugins/thin/dmeventd_thin.c b/daemons/dmeventd/plugins/thin/dmeventd_thin.c +index 29b0391..0330947 100644 +--- a/daemons/dmeventd/plugins/thin/dmeventd_thin.c ++++ b/daemons/dmeventd/plugins/thin/dmeventd_thin.c +@@ -286,7 +286,7 @@ void process_event(struct dm_task *dmt, + if (state->fails++ <= state->max_fails) { + log_debug("Postponing frequently failing policy (%u <= %u).", + state->fails - 1, state->max_fails); +- return; ++ goto out; + } + if (state->max_fails < MAX_FAILS) + state->max_fails <<= 1; +diff --git a/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c b/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c +index 389632c..6b35b2f 100644 +--- a/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c ++++ b/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c +@@ -261,7 +261,7 @@ void process_event(struct dm_task *dmt, + if (state->fails++ <= state->max_fails) { + log_debug("Postponing frequently failing policy (%u <= %u).", + state->fails - 1, state->max_fails); +- return; ++ goto out; + } + if (state->max_fails < MAX_FAILS) + state->max_fails <<= 1; +-- +2.19.1 + diff --git a/6021-cov-fix-missing-null-allocation-check.patch b/6021-cov-fix-missing-null-allocation-check.patch new file mode 100644 index 0000000..cc462e6 --- /dev/null +++ b/6021-cov-fix-missing-null-allocation-check.patch @@ -0,0 +1,26 @@ +From 0b3d3a5250810ace1770ca29afba9fc3bc0ca000 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 19:43:49 +0800 +Subject: [PATCH 05/19] cov: fix missing null allocation check + +--- + base/data-struct/radix-tree.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/base/data-struct/radix-tree.c b/base/data-struct/radix-tree.c +index 222b350..52066eb 100644 +--- a/base/data-struct/radix-tree.c ++++ b/base/data-struct/radix-tree.c +@@ -261,7 +261,8 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, uint8_t + if (kb[i] != pc->prefix[i]) + break; + +- pc2 = zalloc(sizeof(*pc2) + pc->len - i); ++ if (!(pc2 = zalloc(sizeof(*pc2) + pc->len - i))) ++ return false; + pc2->len = pc->len - i; + memmove(pc2->prefix, pc->prefix + i, pc2->len); + pc2->child = pc->child; +-- +2.19.1 + diff --git a/6022-cov-add-check-for-positive-value.patch b/6022-cov-add-check-for-positive-value.patch new file mode 100644 index 0000000..c7573d8 --- /dev/null +++ b/6022-cov-add-check-for-positive-value.patch @@ -0,0 +1,30 @@ +From 0049b42891ac6e095b91643320743a3c0a3ae882 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 19:47:31 +0800 +Subject: [PATCH 06/19] cov: add check for positive value + +As pgsize parameter for _init_free_list() can't be negative, +report problem in case for any reason we would get negative number. +--- + lib/device/bcache.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/lib/device/bcache.c b/lib/device/bcache.c +index 7384a32..0fc7364 100644 +--- a/lib/device/bcache.c ++++ b/lib/device/bcache.c +@@ -1039,6 +1039,11 @@ struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks, + unsigned max_io = engine->max_io(engine); + long pgsize = sysconf(_SC_PAGESIZE); + ++ if (pgsize < 0) { ++ log_warn("WARNING: _SC_PAGESIZE returns negative value."); ++ return NULL; ++ } ++ + if (!nr_cache_blocks) { + log_warn("bcache must have at least one cache block"); + return NULL; +-- +2.19.1 + diff --git a/6023-cov-fix-failing-filter-initialization.patch b/6023-cov-fix-failing-filter-initialization.patch new file mode 100644 index 0000000..70a43fb --- /dev/null +++ b/6023-cov-fix-failing-filter-initialization.patch @@ -0,0 +1,43 @@ +From 494d1fdc82fa4c5a8ae0c976ea0076f9347ee800 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 19:55:12 +0800 +Subject: [PATCH 07/19] cov: fix failing filter initialization + +When persistent_filter_create() fails, the existing passed filter +should be preserved, so it could be properly deleted on +error path - so new pfilter is assigned instead. +--- + lib/commands/toolcontext.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c +index ecd8fd7..df9ca75 100644 +--- a/lib/commands/toolcontext.c ++++ b/lib/commands/toolcontext.c +@@ -1197,7 +1197,7 @@ bad: + int init_filters(struct cmd_context *cmd, unsigned load_persistent_cache) + { + const char *dev_cache; +- struct dev_filter *filter = NULL, *filter_components[2] = {0}; ++ struct dev_filter *pfilter, *filter = NULL, *filter_components[2] = {0}; + int nr_filt; + struct stat st; + const struct dm_config_node *cn; +@@ -1250,12 +1250,12 @@ int init_filters(struct cmd_context *cmd, unsigned load_persistent_cache) + if (!(dev_cache = find_config_tree_str(cmd, devices_cache_CFG, NULL))) + goto_bad; + +- if (!(filter = persistent_filter_create(cmd->dev_types, filter, dev_cache))) { ++ if (!(pfilter = persistent_filter_create(cmd->dev_types, filter, dev_cache))) { + log_verbose("Failed to create persistent device filter."); + goto bad; + } + +- cmd->filter = filter; ++ cmd->filter = filter = pfilter; + + if (lvmetad_used()) { + nr_filt = 0; +-- +2.19.1 + diff --git a/6024-cov-check-dev_close_immediate.patch b/6024-cov-check-dev_close_immediate.patch new file mode 100644 index 0000000..4a27c4a --- /dev/null +++ b/6024-cov-check-dev_close_immediate.patch @@ -0,0 +1,53 @@ +From 71860814428050f4f180e9a264bab34c1916f15d Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 20:05:35 +0800 +Subject: [PATCH 08/19] cov: check dev_close_immediate + +Function can report log_error() on fail path. +--- + lib/device/dev-cache.c | 4 ++-- + lib/device/dev-io.c | 6 ++++-- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c +index c866ff9..8af1de9 100644 +--- a/lib/device/dev-cache.c ++++ b/lib/device/dev-cache.c +@@ -1344,8 +1344,8 @@ static int _check_for_open_devices(int close_immediate) + log_error("Device '%s' has been left open (%d remaining references).", + dev_name(dev), dev->open_count); + num_open++; +- if (close_immediate) +- dev_close_immediate(dev); ++ if (close_immediate && !dev_close_immediate(dev)) ++ stack; + } + } + +diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c +index 2a4967f..8bf1847 100644 +--- a/lib/device/dev-io.c ++++ b/lib/device/dev-io.c +@@ -510,7 +510,8 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet) + /* dev_close_immediate will decrement this */ + dev->open_count++; + +- dev_close_immediate(dev); ++ if (!dev_close_immediate(dev)) ++ return_0; + // FIXME: dev with DEV_ALLOCED is released + // but code is referencing it + } +@@ -591,7 +592,8 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet) + if (!(dev->flags & DEV_REGULAR) && + ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) { + log_error("%s: fstat failed: Has device name changed?", name); +- dev_close_immediate(dev); ++ if (!dev_close_immediate(dev)) ++ stack; + return 0; + } + +-- +2.19.1 + diff --git a/6025-cov-make-sure-label-scans-valid-lvinfo.patch b/6025-cov-make-sure-label-scans-valid-lvinfo.patch new file mode 100644 index 0000000..7fd35a1 --- /dev/null +++ b/6025-cov-make-sure-label-scans-valid-lvinfo.patch @@ -0,0 +1,26 @@ +From 50e44b8fd06cd3af952b253249ab8e144d3296ec Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 20:09:56 +0800 +Subject: [PATCH 09/19] cov: make sure label scans valid lvinfo + +--- + lib/label/label.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/lib/label/label.c b/lib/label/label.c +index 5114959..86c84d8 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -991,7 +991,8 @@ void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv + struct device *dev; + dev_t devt; + +- lv_info(cmd, lv, 0, &lvinfo, 0, 0); ++ if (!lv_info(cmd, lv, 0, &lvinfo, 0, 0)) ++ return; + devt = MKDEV(lvinfo.major, lvinfo.minor); + if ((dev = dev_cache_get_by_devt(devt, NULL))) + label_scan_invalidate(dev); +-- +2.19.1 + diff --git a/6026-cov-add-missing-error-path-check-for-label_scan_open.patch b/6026-cov-add-missing-error-path-check-for-label_scan_open.patch new file mode 100644 index 0000000..289c6fc --- /dev/null +++ b/6026-cov-add-missing-error-path-check-for-label_scan_open.patch @@ -0,0 +1,29 @@ +From ce4e728a2d7b9fd8fda7cb8cabb0af763abac886 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 20:14:33 +0800 +Subject: [PATCH 10/19] cov: add missing error path check for label_scan_open + +--- + lib/label/label.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/lib/label/label.c b/lib/label/label.c +index 86c84d8..63300d2 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -1087,7 +1087,11 @@ int label_read_sector(struct device *dev, uint64_t read_sector) + block_sector = block_num * BCACHE_BLOCK_SIZE_IN_SECTORS; + start_sector = read_sector % BCACHE_BLOCK_SIZE_IN_SECTORS; + +- label_scan_open(dev); ++ if (!label_scan_open(dev)) { ++ log_error("Error opening device %s for prefetch %llu sector.", ++ dev_name(dev), (unsigned long long)block_num); ++ return false; ++ } + + bcache_prefetch(scan_bcache, dev->bcache_fd, block_num); + +-- +2.19.1 + diff --git a/6027-cov-pvscan-ensure-sigle_devs-list-is-always-initiali.patch b/6027-cov-pvscan-ensure-sigle_devs-list-is-always-initiali.patch new file mode 100644 index 0000000..0b05d15 --- /dev/null +++ b/6027-cov-pvscan-ensure-sigle_devs-list-is-always-initiali.patch @@ -0,0 +1,34 @@ +From 8ff7d5679a2300d09e9296f7fdfa0a0db90043e9 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 20:21:54 +0800 +Subject: [PATCH 11/19] cov: pvscan ensure sigle_devs list is always + initialized + +--- + tools/pvscan.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/tools/pvscan.c b/tools/pvscan.c +index 2915db5..5a43069 100644 +--- a/tools/pvscan.c ++++ b/tools/pvscan.c +@@ -315,6 +315,7 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv) + int add_errors = 0; + int ret = ECMD_PROCESSED; + ++ dm_list_init(&single_devs); + dm_list_init(&found_vgnames); + dm_list_init(&pp.changed_vgnames); + +@@ -443,8 +444,6 @@ 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(); + +- dm_list_init(&single_devs); +- + while (argc--) { + pv_name = *argv++; + if (pv_name[0] == '/') { +-- +2.19.1 + diff --git a/6028-fix-cov-missed-return-value-test.patch b/6028-fix-cov-missed-return-value-test.patch new file mode 100644 index 0000000..4553de0 --- /dev/null +++ b/6028-fix-cov-missed-return-value-test.patch @@ -0,0 +1,65 @@ +From 73d1f273084f7a50c26f1ebc9586dbbffd3d082b Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 21:33:22 +0800 +Subject: [PATCH 12/19] fix: cov: missed return value test + +use the existing error paths +--- + lib/format_text/format-text.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c +index 4e5b08e..1a6c3a3 100644 +--- a/lib/format_text/format-text.c ++++ b/lib/format_text/format-text.c +@@ -468,12 +468,14 @@ static struct raw_locn *_read_metadata_location_vg(struct device_area *dev_area, + */ + memset(vgnamebuf, 0, sizeof(vgnamebuf)); + +- dev_read_bytes(dev_area->dev, dev_area->start + rlocn->offset, NAME_LEN, vgnamebuf); ++ if (!dev_read_bytes(dev_area->dev, dev_area->start + rlocn->offset, NAME_LEN, vgnamebuf)) ++ goto fail; + + if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) && + (isspace(vgnamebuf[len]) || vgnamebuf[len] == '{')) + return rlocn; + ++fail: + log_error("Metadata on %s at %llu has wrong VG name \"%s\" expected %s.", + dev_name(dev_area->dev), + (unsigned long long)(dev_area->start + rlocn->offset), +@@ -1196,7 +1198,7 @@ int read_metadata_location_summary(const struct format_type *fmt, + struct raw_locn *rlocn; + uint32_t wrap = 0; + unsigned int len = 0; +- char buf[NAME_LEN + 1] __attribute__((aligned(8))); ++ char namebuf[NAME_LEN + 1] __attribute__((aligned(8))); + uint64_t buffer_size, current_usage; + + if (mda_free_sectors) +@@ -1221,16 +1223,17 @@ int read_metadata_location_summary(const struct format_type *fmt, + return 0; + } + +- dev_read_bytes(dev_area->dev, dev_area->start + rlocn->offset, NAME_LEN, buf); +- +- while (buf[len] && !isspace(buf[len]) && buf[len] != '{' && ++ memset(namebuf, 0, sizeof(namebuf)); ++ if (!dev_read_bytes(dev_area->dev, dev_area->start + rlocn->offset, NAME_LEN, namebuf)) ++ stack; ++ while (namebuf[len] && !isspace(namebuf[len]) && namebuf[len] != '{' && + len < (NAME_LEN - 1)) + len++; + +- buf[len] = '\0'; ++ namebuf[len] = '\0'; + + /* Ignore this entry if the characters aren't permissible */ +- if (!validate_name(buf)) { ++ if (!validate_name(namebuf)) { + log_error("Metadata location on %s at %llu begins with invalid VG name.", + dev_name(dev_area->dev), + (unsigned long long)(dev_area->start + rlocn->offset)); +-- +2.19.1 + diff --git a/6029-cov-trace-failing-pthread_kill.patch b/6029-cov-trace-failing-pthread_kill.patch new file mode 100644 index 0000000..9b8e494 --- /dev/null +++ b/6029-cov-trace-failing-pthread_kill.patch @@ -0,0 +1,44 @@ +From 24d0326e17b1088751d005cf60783bc05114733b Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 21:54:28 +0800 +Subject: [PATCH 13/19] cov: trace failing pthread_kill + +--- + daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c b/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c +index 93697a0..d4614b5 100644 +--- a/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c ++++ b/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c +@@ -175,6 +175,7 @@ void process_event(struct dm_task *dmt, + const char *device = dm_task_get_name(dmt); + int percent; + struct dm_info info; ++ int ret; + + /* No longer monitoring, waiting for remove */ + if (!state->percent_check) +@@ -205,7 +206,8 @@ void process_event(struct dm_task *dmt, + /* Maybe configurable ? */ + _remove(dm_task_get_uuid(dmt)); + #endif +- pthread_kill(pthread_self(), SIGALRM); ++ if ((ret = pthread_kill(pthread_self(), SIGALRM)) && (ret != ESRCH)) ++ log_sys_error("pthread_kill", "self"); + goto out; + } + +@@ -213,7 +215,8 @@ void process_event(struct dm_task *dmt, + /* TODO eventually recognize earlier when room is enough */ + log_info("Dropping monitoring of fully provisioned snapshot %s.", + device); +- pthread_kill(pthread_self(), SIGALRM); ++ if ((ret = pthread_kill(pthread_self(), SIGALRM)) && (ret != ESRCH)) ++ log_sys_error("pthread_kill", "self"); + goto out; + } + +-- +2.19.1 + diff --git a/6030-cov-avoid-unsing-unchecked-label_scan_open.patch b/6030-cov-avoid-unsing-unchecked-label_scan_open.patch new file mode 100644 index 0000000..5d47e75 --- /dev/null +++ b/6030-cov-avoid-unsing-unchecked-label_scan_open.patch @@ -0,0 +1,29 @@ +From 8630d2363be3b57569acff6d323f7d8a8c3d3ce9 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 21:56:11 +0800 +Subject: [PATCH 14/19] cov: avoid unsing unchecked label_scan_open + +Drop extra call too label_scan_open() without checking return value, +and let code go through next call bellow. +--- + lib/label/label.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/lib/label/label.c b/lib/label/label.c +index 63300d2..8efc89e 100644 +--- a/lib/label/label.c ++++ b/lib/label/label.c +@@ -1313,9 +1313,7 @@ bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val) + log_debug("Close and reopen to write %s", dev_name(dev)); + bcache_invalidate_fd(scan_bcache, dev->bcache_fd); + _scan_dev_close(dev); +- +- dev->flags |= DEV_BCACHE_WRITE; +- label_scan_open(dev); ++ /* goes to label_scan_open() since bcache_fd < 0 */ + } + + if (dev->bcache_fd <= 0) { +-- +2.19.1 + diff --git a/6031-lvmlockd-fix-missing-LV-lock-for-lvconvert-repair.patch b/6031-lvmlockd-fix-missing-LV-lock-for-lvconvert-repair.patch new file mode 100644 index 0000000..29f1a70 --- /dev/null +++ b/6031-lvmlockd-fix-missing-LV-lock-for-lvconvert-repair.patch @@ -0,0 +1,48 @@ +From ec6ba10081488699edaba1c80ef69f5a14bced00 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 22:20:42 +0800 +Subject: [PATCH 15/19] lvmlockd: fix missing LV lock for lvconvert repair + +Add missing lvmlockd LV lock for lvconvert repair +on mirror and thin/cache pools. +--- + tools/lvconvert.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/tools/lvconvert.c b/tools/lvconvert.c +index d7a618d..794877e 100644 +--- a/tools/lvconvert.c ++++ b/tools/lvconvert.c +@@ -3461,6 +3461,18 @@ static int _lvconvert_repair_pvs_mirror(struct cmd_context *cmd, struct logical_ + struct lvinfo info; + int ret; + ++ /* ++ * We want to allow cmirror active on multiple nodes to be repaired, ++ * but normal mirror to only be repaired if active exclusively here. ++ * If the LV is active it already has the necessary lock, but if not ++ * active, then require ex since we cannot know the active state on ++ * other hosts. ++ */ ++ if (!lv_is_active(lv)) { ++ if (!lockd_lv(cmd, lv, "ex", 0)) ++ return_0; ++ } ++ + /* + * FIXME: temporary use of lp because _lvconvert_mirrors_repair() + * and _aux() still use lp fields everywhere. +@@ -3594,6 +3606,10 @@ static int _lvconvert_repair_cachepool_thinpool(struct cmd_context *cmd, struct + int poolmetadataspare = arg_int_value(cmd, poolmetadataspare_ARG, DEFAULT_POOL_METADATA_SPARE); + struct dm_list *use_pvh; + ++ /* ensure it's not active elsewhere. */ ++ if (!lockd_lv(cmd, lv, "ex", 0)) ++ return_0; ++ + if (cmd->position_argc > 1) { + /* First pos arg is required LV, remaining are optional PVs. */ + if (!(use_pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc - 1, cmd->position_argv + 1, 0))) +-- +2.19.1 + diff --git a/6032-lvconvert-ensure-proper-init-of-pv_list.patch b/6032-lvconvert-ensure-proper-init-of-pv_list.patch new file mode 100644 index 0000000..fce91ab --- /dev/null +++ b/6032-lvconvert-ensure-proper-init-of-pv_list.patch @@ -0,0 +1,25 @@ +From 9b898dc260048071fb5f0ab2d85580c73225e9d3 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 22:30:24 +0800 +Subject: [PATCH 16/19] lvconvert: ensure proper init of pv_list + +--- + tools/lvconvert.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/lvconvert.c b/tools/lvconvert.c +index 794877e..9e9029e 100644 +--- a/tools/lvconvert.c ++++ b/tools/lvconvert.c +@@ -483,7 +483,7 @@ static struct dm_list *_failed_pv_list(struct volume_group *vg) + if (pvl->pv->pe_alloc_count == 0) + continue; + +- if (!(new_pvl = dm_pool_alloc(vg->vgmem, sizeof(*new_pvl)))) { ++ if (!(new_pvl = dm_pool_zalloc(vg->vgmem, sizeof(*new_pvl)))) { + log_error("Allocation of failed_pvs list entry failed."); + return NULL; + } +-- +2.19.1 + diff --git a/6033-dmeventd-unlock-lvm2-lock-on-error-path.patch b/6033-dmeventd-unlock-lvm2-lock-on-error-path.patch new file mode 100644 index 0000000..fe488a2 --- /dev/null +++ b/6033-dmeventd-unlock-lvm2-lock-on-error-path.patch @@ -0,0 +1,26 @@ +From 769dca1377ecbac623d78ca86a7e3c80b2d4d4f1 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 22:34:11 +0800 +Subject: [PATCH 17/19] dmeventd: unlock lvm2 lock on error path + +New code missed to unlock locked lvm2 on error path when +command is not configured. +--- + daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c b/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c +index 5be11f1..be58aac 100644 +--- a/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c ++++ b/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c +@@ -159,6 +159,7 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size, + dmeventd_lvm2_lock(); + if (!dmeventd_lvm2_run(cmd) || + !(env = getenv(cmd))) { ++ dmeventd_lvm2_unlock(); + log_error("Unable to find configured command."); + return 0; + } +-- +2.19.1 + diff --git a/6034-mangenerator-check-strdup-was-successfull.patch b/6034-mangenerator-check-strdup-was-successfull.patch new file mode 100644 index 0000000..b1841c4 --- /dev/null +++ b/6034-mangenerator-check-strdup-was-successfull.patch @@ -0,0 +1,27 @@ +From a805a5254b06f30574f8d322fa451763335c1ee1 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 22:37:32 +0800 +Subject: [PATCH 18/19] mangenerator: check strdup was successfull + +Check for strdup != NULL +and drop unneeded zeroing when buffer is overwritten. +--- + tools/command.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/command.c b/tools/command.c +index f2a2722..9516fde 100644 +--- a/tools/command.c ++++ b/tools/command.c +@@ -1465,7 +1465,7 @@ int define_commands(struct cmd_context *cmdtool, const char *run_name) + + if (_is_desc_line(line_argv[0]) && !skip && cmd) { + char *desc = dm_pool_strdup(cmdtool->libmem, line_orig); +- if (cmd->desc) { ++ if (cmd->desc && desc) { + int newlen = strlen(cmd->desc) + strlen(desc) + 2; + char *newdesc = dm_pool_alloc(cmdtool->libmem, newlen); + if (newdesc) { +-- +2.19.1 + diff --git a/6035-cov-ensure-lock_type-is-not-NULL.patch b/6035-cov-ensure-lock_type-is-not-NULL.patch new file mode 100644 index 0000000..66d84c1 --- /dev/null +++ b/6035-cov-ensure-lock_type-is-not-NULL.patch @@ -0,0 +1,43 @@ +From 3ac89d45f3b5091fa3864248a50a4d15ebacb6d9 Mon Sep 17 00:00:00 2001 +From: root +Date: Wed, 13 Mar 2019 22:51:19 +0800 +Subject: [PATCH 19/19] cov: ensure lock_type is not NULL + +--- + tools/vgchange.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/vgchange.c b/tools/vgchange.c +index 623517b..40c3c4d 100644 +--- a/tools/vgchange.c ++++ b/tools/vgchange.c +@@ -932,7 +932,7 @@ static int _vgchange_locktype(struct cmd_context *cmd, struct volume_group *vg) + int lv_lock_count = 0; + + /* Special recovery case. */ +- if (lockopt && !strcmp(lock_type, "none") && !strcmp(lockopt, "force")) { ++ if (lock_type && lockopt && !strcmp(lock_type, "none") && !strcmp(lockopt, "force")) { + vg->status &= ~CLUSTERED; + vg->lock_type = "none"; + vg->lock_args = NULL; +@@ -997,7 +997,7 @@ static int _vgchange_locktype(struct cmd_context *cmd, struct volume_group *vg) + } + + /* none to clvm */ +- if (!strcmp(vg->lock_type, "none") && !strcmp(lock_type, "clvm")) { ++ if (lock_type && !strcmp(vg->lock_type, "none") && !strcmp(lock_type, "clvm")) { + log_warn("New clvm lock type will not be usable with lvmlockd."); + vg->status |= CLUSTERED; + vg->lock_type = "clvm"; /* this is optional */ +@@ -1110,7 +1110,7 @@ static int _vgchange_locktype(struct cmd_context *cmd, struct volume_group *vg) + } + + /* ... to none */ +- if (!strcmp(lock_type, "none")) { ++ if (lock_type && !strcmp(lock_type, "none")) { + vg->lock_type = NULL; + vg->system_id = cmd->system_id ? dm_pool_strdup(vg->vgmem, cmd->system_id) : NULL; + return 1; +-- +2.19.1 + diff --git a/6036-Remove-checking-for-locked-VGs.patch b/6036-Remove-checking-for-locked-VGs.patch new file mode 100644 index 0000000..05f9dcd --- /dev/null +++ b/6036-Remove-checking-for-locked-VGs.patch @@ -0,0 +1,411 @@ +From afb4ce9833dd60220f48a273c7b50c692c900164 Mon Sep 17 00:00:00 2001 +From: root +Date: Sat, 23 Mar 2019 18:25:27 +0800 +Subject: [PATCH] Remove checking for locked VGs + +A few places were calling a function to check if a +VG lock was held. The only place it was actually +needed is for pvcreate which wants to do its own +locking (and scanning) around process_each_pv. + +The locking/scanning exceptions for pvcreate in +process_each_pv/vg_read can be enabled by just passing +a couple of flags instead of checking if the VG is +already locked. This also means that these special +cases won't be enabled unknowingly in other places +where they shouldn't be used. +--- + lib/cache/lvmcache.c | 13 ----- + lib/cache/lvmcache.h | 1 - + lib/metadata/metadata-exported.h | 2 + + lib/metadata/metadata.c | 18 ++---- + liblvm/lvm_vg.c | 2 - + tools/toollib.c | 94 +++++++++----------------------- + tools/vgreduce.c | 2 +- + 7 files changed, 35 insertions(+), 97 deletions(-) + +diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c +index 1a2e987..a48c5e7 100644 +--- a/lib/cache/lvmcache.c ++++ b/lib/cache/lvmcache.c +@@ -536,9 +536,6 @@ void lvmcache_drop_metadata(const char *vgname, int drop_precommitted) + if (!_saved_vg_hash) + return; + +- if (lvmcache_vgname_is_locked(VG_GLOBAL)) +- return; +- + /* For VG_ORPHANS, we need to invalidate all labels on orphan PVs. */ + if (!strcmp(vgname, VG_ORPHANS)) { + _drop_metadata(FMT_TEXT_ORPHAN_VG_NAME, 0); +@@ -561,14 +558,6 @@ void lvmcache_lock_vgname(const char *vgname, int read_only __attribute__((unuse + } + } + +-int lvmcache_vgname_is_locked(const char *vgname) +-{ +- if (!_lock_hash) +- return 0; +- +- return dm_hash_lookup(_lock_hash, is_orphan_vg(vgname) ? VG_ORPHANS : vgname) ? 1 : 0; +-} +- + void lvmcache_unlock_vgname(const char *vgname) + { + if (!dm_hash_lookup(_lock_hash, vgname)) +@@ -1997,8 +1986,6 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info, + else if (!_lvmcache_update_vgid(NULL, vginfo, vgid)) /* Orphans */ + return_0; + +- _update_cache_vginfo_lock_state(vginfo, lvmcache_vgname_is_locked(vgname)); +- + /* FIXME Check consistency of list! */ + vginfo->fmt = fmt; + +diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h +index e9e6932..0567a81 100644 +--- a/lib/cache/lvmcache.h ++++ b/lib/cache/lvmcache.h +@@ -107,7 +107,6 @@ char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid); + const char *lvmcache_vgname_from_info(struct lvmcache_info *info); + const struct format_type *lvmcache_fmt_from_info(struct lvmcache_info *info); + int lvmcache_vgs_locked(void); +-int lvmcache_vgname_is_locked(const char *vgname); + + void lvmcache_seed_infos_from_lvmetad(struct cmd_context *cmd); + +diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h +index e2fe76b..a4ca17f 100644 +--- a/lib/metadata/metadata-exported.h ++++ b/lib/metadata/metadata-exported.h +@@ -178,6 +178,8 @@ + #define READ_OK_NOTFOUND 0x00040000U + #define READ_WARN_INCONSISTENT 0x00080000U + #define READ_FOR_UPDATE 0x00100000U /* A meta-flag, useful with toollib for_each_* functions. */ ++#define PROCESS_SKIP_SCAN 0x00200000U /* skip lvmcache_label_scan in process_each_pv */ ++#define PROCESS_SKIP_ORPHAN_LOCK 0x00400000U /* skip lock_vol(VG_ORPHAN) in vg_read */ + + /* vg's "read_status" field */ + #define FAILED_INCONSISTENT 0x00000001U +diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c +index 2c81623..237e57b 100644 +--- a/lib/metadata/metadata.c ++++ b/lib/metadata/metadata.c +@@ -3118,12 +3118,6 @@ int vg_commit(struct volume_group *vg) + int cache_updated = 0; + struct pv_list *pvl; + +- if (!lvmcache_vgname_is_locked(vg->name)) { +- log_error(INTERNAL_ERROR "Attempt to write new VG metadata " +- "without locking %s", vg->name); +- return cache_updated; +- } +- + cache_updated = _vg_commit_mdas(vg); + + set_vg_notify(vg->cmd); +@@ -5465,8 +5459,8 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha + uint32_t failure = 0; + uint32_t warn_flags = 0; + int is_shared = 0; +- int already_locked; + int write_lock_held = (lock_flags == LCK_VG_WRITE); ++ int skip_lock = is_orphan_vg(vg_name) && (read_flags & PROCESS_SKIP_ORPHAN_LOCK); + + if ((read_flags & READ_ALLOW_INCONSISTENT) || (lock_flags != LCK_VG_WRITE)) + consistent = 0; +@@ -5477,15 +5471,13 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha + return NULL; + } + +- already_locked = lvmcache_vgname_is_locked(vg_name); +- +- if (!already_locked && ++ if (!skip_lock && + !lock_vol(cmd, vg_name, lock_flags, NULL)) { + log_error("Can't get lock for %s", vg_name); + return _vg_make_handle(cmd, vg, FAILED_LOCKING); + } + +- if (already_locked) ++ if (skip_lock) + log_very_verbose("Locking %s already done", vg_name); + + if (is_orphan_vg(vg_name)) +@@ -5553,13 +5545,13 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha + goto_bad; + + if (!(vg = _vg_make_handle(cmd, vg, failure)) || vg_read_error(vg)) +- if (!already_locked) ++ if (!skip_lock) + unlock_vg(cmd, vg, vg_name); + + return vg; + + bad: +- if (!already_locked) ++ if (!skip_lock) + unlock_vg(cmd, vg, vg_name); + + bad_no_unlock: +diff --git a/liblvm/lvm_vg.c b/liblvm/lvm_vg.c +index ee6fa4e..616c78f 100644 +--- a/liblvm/lvm_vg.c ++++ b/liblvm/lvm_vg.c +@@ -186,8 +186,6 @@ int lvm_vg_close(vg_t vg) + struct saved_env e = store_user_env(vg->cmd); + if (vg_read_error(vg) == FAILED_LOCKING) + release_vg(vg); +- else if (!lvmcache_vgname_is_locked(vg->name)) +- release_vg(vg); + else + unlock_and_release_vg(vg->cmd, vg, vg->name); + restore_user_env(&e); +diff --git a/tools/toollib.c b/tools/toollib.c +index ce877cc..3210e28 100644 +--- a/tools/toollib.c ++++ b/tools/toollib.c +@@ -1969,7 +1969,6 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t read_flags, + int skip; + int notfound; + int process_all = 0; +- int already_locked; + int do_report_ret_code = 1; + + log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_VG); +@@ -2012,8 +2011,6 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t read_flags, + continue; + } + +- already_locked = lvmcache_vgname_is_locked(vg_name); +- + vg = vg_read(cmd, vg_name, vg_uuid, read_flags, lockd_state); + if (_ignore_vg(vg, vg_name, arg_vgnames, read_flags, &skip, ¬found)) { + stack; +@@ -2041,7 +2038,7 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t read_flags, + ret_max = ret; + } + +- if (!vg_read_error(vg) && !already_locked) ++ if (!vg_read_error(vg)) + unlock_vg(cmd, vg, vg_name); + endvg: + release_vg(vg); +@@ -3681,8 +3678,6 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t read_flag + continue; + } + +- already_locked = lvmcache_vgname_is_locked(vg_name); +- + vg = vg_read(cmd, vg_name, vg_uuid, read_flags, lockd_state); + if (_ignore_vg(vg, vg_name, arg_vgnames, read_flags, &skip, ¬found)) { + stack; +@@ -3701,8 +3696,7 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t read_flag + if (ret > ret_max) + ret_max = ret; + +- if (!already_locked) +- unlock_vg(cmd, vg, vg_name); ++ unlock_vg(cmd, vg, vg_name); + endvg: + release_vg(vg); + if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state)) +@@ -4400,7 +4394,7 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t read_flags, + int ret; + int skip; + int notfound; +- int already_locked; ++ int skip_lock; + int do_report_ret_code = 1; + + log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_VG); +@@ -4434,7 +4428,7 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t read_flags, + + log_debug("Processing PVs in VG %s", vg_name); + +- already_locked = lvmcache_vgname_is_locked(vg_name); ++ skip_lock = is_orphan_vg(vg_name) && (read_flags & PROCESS_SKIP_ORPHAN_LOCK); + + vg = vg_read(cmd, vg_name, vg_uuid, read_flags, lockd_state); + if (_ignore_vg(vg, vg_name, NULL, read_flags, &skip, ¬found)) { +@@ -4462,7 +4456,7 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t read_flags, + if (ret > ret_max) + ret_max = ret; + +- if (!skip && !already_locked) ++ if (!skip && !skip_lock) + unlock_vg(cmd, vg, vg->name); + endvg: + release_vg(vg); +@@ -4501,7 +4495,6 @@ int process_each_pv(struct cmd_context *cmd, + struct device_id_list *dil; + int process_all_pvs; + int process_all_devices; +- int orphans_locked; + int ret_max = ECMD_PROCESSED; + int ret; + +@@ -4549,8 +4542,6 @@ int process_each_pv(struct cmd_context *cmd, + return ECMD_FAILED; + } + +- orphans_locked = lvmcache_vgname_is_locked(VG_ORPHANS); +- + process_all_pvs = dm_list_empty(&arg_pvnames) && dm_list_empty(&arg_tags); + + process_all_devices = process_all_pvs && (cmd->cname->flags & ENABLE_ALL_DEVS) && all_is_set; +@@ -4561,22 +4552,8 @@ int process_each_pv(struct cmd_context *cmd, + goto_out; + } + +- /* +- * This full scan would be done by _get_all_devices() if +- * it were not done here first. It's called here first +- * so that get_vgnameids() will look at any new devices. +- * When orphans is already locked, these steps are done +- * before process_each_pv is called. +- */ +- if (!trust_cache() && !orphans_locked) { +- lvmcache_destroy(cmd, 1, 0); +- +- /* +- * Scan all devices to populate lvmcache with initial +- * list of PVs and VGs. +- */ ++ if (!(read_flags & PROCESS_SKIP_SCAN)) + lvmcache_label_scan(cmd); +- } + + if (!get_vgnameids(cmd, &all_vgnameids, only_this_vgname, 1)) { + ret_max = ret; +@@ -4647,11 +4624,9 @@ int process_each_pv(struct cmd_context *cmd, + ret_max = ret; + + /* +- * If the orphans lock was held, there shouldn't be missed devices. If +- * there were, we cannot clear the cache while holding the orphans lock +- * anyway. ++ * If the orphans lock was held, there shouldn't be missed devices. + */ +- if (orphans_locked) ++ if (read_flags & PROCESS_SKIP_ORPHAN_LOCK) + goto skip_missed; + + /* +@@ -4678,12 +4653,7 @@ int process_each_pv(struct cmd_context *cmd, + + log_verbose("Some PVs were not found in first search, retrying."); + +- lvmcache_destroy(cmd, 0, 0); +- if (!lvmcache_init(cmd)) { +- log_error("Failed to initalize lvm cache."); +- ret_max = ECMD_FAILED; +- goto out; +- } ++ lvmcache_label_scan(cmd); + lvmcache_seed_infos_from_lvmetad(cmd); + + ret = _process_pvs_in_vgs(cmd, read_flags, &all_vgnameids, &all_devices, +@@ -5514,25 +5484,16 @@ int pvcreate_each_device(struct cmd_context *cmd, + dm_list_add(&pp->arg_devices, &pd->list); + } + +- /* +- * Clear the cache before acquiring the orphan lock. (Clearing the +- * cache with locks held is an error.) We want the orphan lock +- * acquired before process_each_pv. If the orphan lock is not held +- * when process_each_pv is called, then process_each_pv clears the +- * cache. +- */ +- lvmcache_destroy(cmd, 1, 0); +- +- /* +- * If no prompts require a user response, this orphan lock is held +- * throughout, and pvcreate_each_device() returns with it held so that +- * vgcreate/vgextend use the PVs created here to add to a VG. +- */ + if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) { + log_error("Can't get lock for orphan PVs."); + return 0; + } + ++ /* ++ * Scan before calling process_each_pv so we can set up the PV args ++ * first. We can then skip the scan that would normally occur at the ++ * beginning of process_each_pv. ++ */ + lvmcache_label_scan(cmd); + + /* +@@ -5556,9 +5517,8 @@ int pvcreate_each_device(struct cmd_context *cmd, + * If it's added to arg_process but needs a prompt or force option, then + * a corresponding prompt entry is added to pp->prompts. + */ +- process_each_pv(cmd, 0, NULL, NULL, 1, 0, handle, +- pp->is_remove ? _pvremove_check_single : _pvcreate_check_single); +- ++ process_each_pv(cmd, 0, NULL, NULL, 1, PROCESS_SKIP_SCAN | PROCESS_SKIP_ORPHAN_LOCK, ++ handle, pp->is_remove ? _pvremove_check_single : _pvcreate_check_single); + /* + * A fatal error was found while checking. + */ +@@ -5639,9 +5599,11 @@ int pvcreate_each_device(struct cmd_context *cmd, + goto do_command; + + /* +- * Prompts require asking the user, so release the orphans lock, ask +- * the questions, reacquire the orphans lock, verify that the PVs were +- * not used during the questions, then do the create steps. ++ * Prompts require asking the user and make take some time, during ++ * which we don't want to block other commands. So, release the lock ++ * to prevent blocking other commands while we wait. After a response ++ * from the user, reacquire the lock, verify that the PVs were not used ++ * during the wait, then do the create steps. + */ + unlock_vg(cmd, NULL, VG_ORPHANS); + +@@ -5676,14 +5638,11 @@ int pvcreate_each_device(struct cmd_context *cmd, + } + + /* +- * Clear the cache, reacquire the orphans write lock, then check again +- * that the devices can still be used. If the second loop finds them +- * changed, or can't find them any more, then they aren't used. +- * Clear the cache here before locking orphans, since it won't be +- * done by process_each_pv with orphans already locked. ++ * Reacquire the lock that was released above before waiting, then ++ * check again that the devices can still be used. If the second loop ++ * finds them changed, or can't find them any more, then they aren't ++ * used. + */ +- lvmcache_destroy(cmd, 1, 0); +- + if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) { + log_error("Can't get lock for orphan PVs."); + goto out; +@@ -5705,7 +5664,8 @@ int pvcreate_each_device(struct cmd_context *cmd, + */ + dm_list_splice(&pp->arg_confirm, &pp->arg_process); + +- process_each_pv(cmd, 0, NULL, NULL, 1, 0, handle, _pv_confirm_single); ++ process_each_pv(cmd, 0, NULL, NULL, 1, PROCESS_SKIP_SCAN | PROCESS_SKIP_ORPHAN_LOCK, ++ handle, _pv_confirm_single); + + dm_list_iterate_items(pd, &pp->arg_confirm) + log_error("Device %s %s.", pd->name, dev_cache_filtered_reason(pd->name)); +diff --git a/tools/vgreduce.c b/tools/vgreduce.c +index aa35453..aa68f0f 100644 +--- a/tools/vgreduce.c ++++ b/tools/vgreduce.c +@@ -239,7 +239,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv) + + /* FIXME: Pass private struct through to all these functions */ + /* and update in batch afterwards? */ +- ret = process_each_pv(cmd, argc, argv, vg_name, 0, READ_FOR_UPDATE, handle, _vgreduce_single); ++ ret = process_each_pv(cmd, argc, argv, vg_name, 0, READ_FOR_UPDATE | PROCESS_SKIP_ORPHAN_LOCK, handle, _vgreduce_single); + unlock_vg(cmd, NULL, VG_ORPHANS); + goto out; + } +-- +2.19.1 + diff --git a/6037-lvm2-default-allow-changes-with-duplicate-pvs.patch b/6037-lvm2-default-allow-changes-with-duplicate-pvs.patch new file mode 100644 index 0000000..0bf0618 --- /dev/null +++ b/6037-lvm2-default-allow-changes-with-duplicate-pvs.patch @@ -0,0 +1,30 @@ + conf/example.conf.in | 2 +- + lib/config/defaults.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/conf/example.conf.in b/conf/example.conf.in +index 4894d04..48afbd1 100644 +--- a/conf/example.conf.in ++++ b/conf/example.conf.in +@@ -311,7 +311,7 @@ devices { + # or activating LVs in it while a PV appears on multiple devices. + # Enabling this setting allows the VG to be used as usual even with + # uncertain devices. +- allow_changes_with_duplicate_pvs = 0 ++ allow_changes_with_duplicate_pvs = 1 + } + + # Configuration section allocation. +diff --git a/lib/config/defaults.h b/lib/config/defaults.h +index d9e19d9..894b979 100644 +--- a/lib/config/defaults.h ++++ b/lib/config/defaults.h +@@ -45,7 +45,7 @@ + #define DEFAULT_DATA_ALIGNMENT_DETECTION 1 + #define DEFAULT_ISSUE_DISCARDS 0 + #define DEFAULT_PV_MIN_SIZE_KB 2048 +-#define DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS 0 ++#define DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS 1 + + #define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so" + #define DEFAULT_ERROR_WHEN_FULL 0 diff --git a/9000-bugfix-lvm2-add-SSD.patch b/9000-bugfix-lvm2-add-SSD.patch new file mode 100644 index 0000000..ba364ad --- /dev/null +++ b/9000-bugfix-lvm2-add-SSD.patch @@ -0,0 +1,26 @@ +From 0f30a9d3c2619cbaba323524f7aa9c9c4b01bcdd Mon Sep 17 00:00:00 2001 +From: geruijun +Date: Thu, 14 Feb 2019 04:55:01 -0500 +Subject: [PATCH] lvm2: add 0002-bugfix-lvm2-add-SSD.patch + +DTS/AR: +reason: +--- + conf/example.conf.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/conf/example.conf.in b/conf/example.conf.in +index 32267e7..1f7b264 100644 +--- a/conf/example.conf.in ++++ b/conf/example.conf.in +@@ -149,6 +149,7 @@ devices { + # global_filter are not opened by LVM. + # This configuration option has an automatic default value. + # global_filter = [ "a|.*/|" ] ++ types = [ "hio", 16 ] + + # Configuration option devices/cache_dir. + # Directory in which to store the device cache file. +-- +1.8.3.1 + diff --git a/9001-bugfix-add-timeout-when-fail-to-wait-udev.patch b/9001-bugfix-add-timeout-when-fail-to-wait-udev.patch new file mode 100644 index 0000000..bc7bc40 --- /dev/null +++ b/9001-bugfix-add-timeout-when-fail-to-wait-udev.patch @@ -0,0 +1,110 @@ +diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c +index 40b366b..0b03106 100644 +--- a/libdm/libdm-common.c ++++ b/libdm/libdm-common.c +@@ -59,6 +59,7 @@ union semun + #endif + #endif + ++#define UDEV_SEM_TIMEOUT 300 + static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR; + static char _sysfs_dir[PATH_MAX] = "/sys/"; + static char _path0[PATH_MAX]; /* path buffer, safe 4kB on stack */ +@@ -2611,6 +2612,9 @@ static int _udev_wait(uint32_t cookie, int *nowait) + int semid; + struct sembuf sb = {0, 0, 0}; + int val; ++ struct timespec timeout; ++ timeout.tv_sec = UDEV_SEM_TIMEOUT; ++ timeout.tv_nsec = 0; + + if (!cookie || !dm_udev_get_sync_support()) + return 1; +@@ -2646,7 +2650,7 @@ static int _udev_wait(uint32_t cookie, int *nowait) + cookie, semid); + + repeat_wait: +- if (semop(semid, &sb, 1) < 0) { ++ if (semtimedop(semid, &sb, 1,&timeout) < 0) { + if (errno == EINTR) + goto repeat_wait; + else if (errno == EIDRM) +diff --git a/tools/dmsetup.c b/tools/dmsetup.c +index 3cdf862..af70a02 100644 +--- a/tools/dmsetup.c ++++ b/tools/dmsetup.c +@@ -1131,6 +1131,7 @@ out: + static int _create_one_device(const char *name, const char *file) + { + int r = 0; ++ int udev_wait_r = 1; + struct dm_task *dmt; + uint32_t cookie = 0; + uint16_t udev_flags = 0; +@@ -1203,13 +1204,16 @@ static int _create_one_device(const char *name, const char *file) + + out: + if (!_udev_cookie) +- (void) dm_udev_wait(cookie); ++ udev_wait_r = dm_udev_wait(cookie); + + if (r && _switches[VERBOSE_ARG]) + r = _display_info(dmt); + + dm_task_destroy(dmt); + ++ if(!udev_wait_r) ++ return 0; ++ + return r; + } + +@@ -1430,6 +1434,7 @@ static int _create(CMD_ARGS) + + static int _do_rename(const char *name, const char *new_name, const char *new_uuid) { + int r = 0; ++ int udev_wait_r = 1; + struct dm_task *dmt; + uint32_t cookie = 0; + uint16_t udev_flags = 0; +@@ -1474,10 +1479,13 @@ static int _do_rename(const char *name, const char *new_name, const char *new_uu + + out: + if (!_udev_cookie) +- (void) dm_udev_wait(cookie); ++ udev_wait_r = dm_udev_wait(cookie); + + dm_task_destroy(dmt); + ++ if (!udev_wait_r) ++ return 0; ++ + return r; + } + +@@ -1997,6 +2005,7 @@ static int _simple(int task, const char *name, uint32_t event_nr, int display) + int udev_wait_flag = task == DM_DEVICE_RESUME || + task == DM_DEVICE_REMOVE; + int r = 0; ++ int udev_wait_r = 1; + + struct dm_task *dmt; + +@@ -2056,13 +2065,16 @@ static int _simple(int task, const char *name, uint32_t event_nr, int display) + + out: + if (!_udev_cookie && udev_wait_flag) +- (void) dm_udev_wait(cookie); ++ udev_wait_r = dm_udev_wait(cookie); + + if (r && display && _switches[VERBOSE_ARG]) + r = _display_info(dmt); + + dm_task_destroy(dmt); + ++ if(!udev_wait_r) ++ return 0; ++ + return r; + } + diff --git a/9002-bugfix-fix-the-code-maybe-lead-to-buffer-over-bound-access.patch b/9002-bugfix-fix-the-code-maybe-lead-to-buffer-over-bound-access.patch new file mode 100644 index 0000000..bc7e1bd --- /dev/null +++ b/9002-bugfix-fix-the-code-maybe-lead-to-buffer-over-bound-access.patch @@ -0,0 +1,28 @@ +diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c +index a1ab41a..e743a58 100644 +--- a/lib/cache/lvmetad.c ++++ b/lib/cache/lvmetad.c +@@ -1467,7 +1467,9 @@ int lvmetad_get_vgnameids(struct cmd_context *cmd, struct dm_list *vgnameids) + return 0; + } + +- vgnl->vgid = dm_pool_strdup(cmd->mem, (char *)&vgid); ++ char vgid_buffer[ID_LEN+1] = {0x0}; ++ memcpy(vgid_buffer, vgid.uuid, ID_LEN); ++ vgnl->vgid = dm_pool_strdup(cmd->mem, vgid_buffer); + vgnl->vg_name = dm_pool_strdup(cmd->mem, vg_name); + + if (!vgnl->vgid || !vgnl->vg_name) { +diff --git a/tools/command.c b/tools/command.c +index 377d03f..f2a2722 100644 +--- a/tools/command.c ++++ b/tools/command.c +@@ -1364,7 +1364,7 @@ static int _copy_line(char *line, int max_line, int *position) + + memset(line, 0, max_line); + +- while (1) { ++ while ( p < strlen(_command_input) ) { + line[i] = _command_input[p]; + i++; + p++; diff --git a/9003-enhancement-modify-default-log-level-to-error-level.patch b/9003-enhancement-modify-default-log-level-to-error-level.patch new file mode 100644 index 0000000..01db1f1 --- /dev/null +++ b/9003-enhancement-modify-default-log-level-to-error-level.patch @@ -0,0 +1,25 @@ +From 2a0100ad8fd91ff367948fb79d7a2430380e1cb8 Mon Sep 17 00:00:00 2001 +From: root +Date: Tue, 19 Mar 2019 15:44:17 +0800 +Subject: [PATCH 1/2] modify default log level to error level + +--- + conf/example.conf.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/conf/example.conf.in b/conf/example.conf.in +index 1f7b264..9a465ca 100644 +--- a/conf/example.conf.in ++++ b/conf/example.conf.in +@@ -585,7 +585,7 @@ log { + # The level of log messages that are sent to the log file or syslog. + # There are 6 syslog-like log levels currently in use: 2 to 7 inclusive. + # 7 is the most verbose (LOG_DEBUG). +- level = 0 ++ level = 3 + + # Configuration option log/indent. + # Indent messages according to their severity. +-- +2.19.1 + diff --git a/9004-enhancement-add-dfx-log.patch b/9004-enhancement-add-dfx-log.patch new file mode 100644 index 0000000..fb9ee83 --- /dev/null +++ b/9004-enhancement-add-dfx-log.patch @@ -0,0 +1,252 @@ +From 2f257461191b97e47a716f0cd0374e174041ddef Mon Sep 17 00:00:00 2001 +From: root +Date: Tue, 19 Mar 2019 16:43:16 +0800 +Subject: [PATCH 2/2] add dfx log when error occur, or lvm resource change, it + will print the cmdline and ppid + +--- + conf/example.conf.in | 5 +++++ + lib/commands/toolcontext.c | 16 ++++++++++++++++ + lib/commands/toolcontext.h | 4 ++++ + lib/config/config_settings.h | 5 +++++ + lib/log/log.c | 21 +++++++++++++++++++-- + lib/log/log.h | 4 +++- + lib/misc/lvm-globals.c | 11 +++++++++++ + lib/misc/lvm-globals.h | 2 ++ + tools/lvmcmdline.c | 1 + + 9 files changed, 66 insertions(+), 3 deletions(-) + +diff --git a/conf/example.conf.in b/conf/example.conf.in +index 9a465ca..4f2abae 100644 +--- a/conf/example.conf.in ++++ b/conf/example.conf.in +@@ -587,6 +587,11 @@ log { + # 7 is the most verbose (LOG_DEBUG). + level = 3 + ++ #When the level of log messages is set as 2 or 3, set log_unless_silent ++ #to 1, it will also log some important warning level messages, such as, ++ #create/delete/change a lv/vg/pv, 0 is close this option. ++ log_unless_silent = 1 ++ + # Configuration option log/indent. + # Indent messages according to their severity. + indent = 1 +diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c +index df9ca75..b1ecf77 100644 +--- a/lib/commands/toolcontext.c ++++ b/lib/commands/toolcontext.c +@@ -49,6 +49,8 @@ + + static const size_t _linebuffer_size = 4096; + ++char *global_cmdline = NULL; ++ + /* + * Copy the input string, removing invalid characters. + */ +@@ -314,6 +316,9 @@ static void _init_logging(struct cmd_context *cmd) + find_config_tree_bool(cmd, log_silent_CFG, NULL); + init_silent(cmd->default_settings.silent); + ++ cmd->default_settings.log_unless_silent = find_config_tree_bool(cmd, log_unless_silent_CFG, NULL); ++ init_log_unless_silent(cmd->default_settings.log_unless_silent); ++ + /* Verbose level for tty output */ + cmd->default_settings.verbose = find_config_tree_int(cmd, log_verbose_CFG, NULL); + init_verbose(cmd->default_settings.verbose + VERBOSE_BASE_LEVEL); +@@ -2240,6 +2245,7 @@ void destroy_toolcontext(struct cmd_context *cmd) + _destroy_segtypes(&cmd->segtypes); + _destroy_formats(cmd, &cmd->formats); + _destroy_filters(cmd); ++ set_global_cmdline(NULL); + if (cmd->mem) + dm_pool_destroy(cmd->mem); + dev_cache_exit(); +@@ -2293,3 +2299,13 @@ void destroy_toolcontext(struct cmd_context *cmd) + fin_syslog(); + reset_lvm_errno(0); + } ++ ++char *get_global_cmdline() ++{ ++ return global_cmdline; ++} ++ ++void set_global_cmdline(char *cmdline) ++{ ++ global_cmdline = cmdline; ++} +diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h +index da5d582..345dcc8 100644 +--- a/lib/commands/toolcontext.h ++++ b/lib/commands/toolcontext.h +@@ -48,6 +48,7 @@ struct config_info { + mode_t umask; + char unit_type; + char _padding[1]; ++ int log_unless_silent; + }; + + struct dm_config_tree; +@@ -267,4 +268,7 @@ struct format_type *get_format_by_name(struct cmd_context *cmd, const char *form + + const char *system_id_from_string(struct cmd_context *cmd, const char *str); + ++char *get_global_cmdline(); ++ ++void set_global_cmdline(char *cmdline); + #endif +diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h +index f8a577f..b637eb0 100644 +--- a/lib/config/config_settings.h ++++ b/lib/config/config_settings.h +@@ -686,6 +686,11 @@ cfg(log_level_CFG, "level", log_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_LOGLEVEL, + "There are 6 syslog-like log levels currently in use: 2 to 7 inclusive.\n" + "7 is the most verbose (LOG_DEBUG).\n") + ++cfg(log_unless_silent_CFG, "log_unless_silent", log_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 2, 178), NULL, 0, NULL, ++ "When the level of log messages is set as 2 or 3, set log_unless_silent\n" ++ "to 1, it will also log some important warning level messages, such as,\n" ++ "create/delete/change a lv/vg/pv, 0 is close this option.\n") ++ + cfg(log_indent_CFG, "indent", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_INDENT, vsn(1, 0, 0), NULL, 0, NULL, + "Indent messages according to their severity.\n") + +diff --git a/lib/log/log.c b/lib/log/log.c +index 79fbd7a..d34e160 100644 +--- a/lib/log/log.c ++++ b/lib/log/log.c +@@ -19,6 +19,7 @@ + #include "defaults.h" + #include "report.h" + #include "lvm-file.h" ++#include "toolcontext.h" + + #include + #include +@@ -478,6 +479,7 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c + const char *trformat; /* Translated format string */ + char *newbuf; + int use_stderr = log_stderr(level); ++ int force_syslog = (level & _LOG_IMPORTANT_TO_SYSLOG) ? 1 : 0; + int log_once = log_once(level); + int log_bypass_report = log_bypass_report(level); + int fatal_internal_error = 0; +@@ -490,7 +492,9 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c + struct dm_report *orig_report; + int logged_via_report = 0; + ++ static int printcmdline = 1; + level = log_level(level); ++ force_syslog = (level!=0 && get_log_unless_silent()) ? force_syslog : 0; + + if (_abort_on_internal_errors_env_present < 0) { + if ((env_str = getenv("DM_ABORT_ON_INTERNAL_ERRORS"))) { +@@ -632,8 +636,8 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c + va_end(ap); + } + +- if ((level > debug_level()) || +- (level >= _LOG_DEBUG && !debug_class_is_logged(dm_errno_or_class))) { ++ if (!force_syslog && ((level > debug_level()) || ++ (level >= _LOG_DEBUG && !debug_class_is_logged(dm_errno_or_class)))) { + if (fatal_internal_error) + abort(); + return; +@@ -661,6 +665,19 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c + + if (_syslog && (_log_while_suspended || !critical_section())) { + va_copy(ap, orig_ap); ++ ++ if (level <= _LOG_WARN && printcmdline) { ++ char *cmdline = get_global_cmdline(); ++ if (cmdline) { ++ printcmdline = 0; ++ char msg_addcmd[4096] = {0}; ++ ++ snprintf(msg_addcmd, sizeof(msg_addcmd), ++ "ppid=%lu, cmdline:%s", getppid(), cmdline); ++ syslog(level, "%s", msg_addcmd); ++ } ++ } ++ + vsyslog(level, trformat, ap); + va_end(ap); + } +diff --git a/lib/log/log.h b/lib/log/log.h +index 256fed0..7c22859 100644 +--- a/lib/log/log.h ++++ b/lib/log/log.h +@@ -50,6 +50,8 @@ + #define _LOG_STDERR 0x0080 /* force things to go to stderr, even if loglevel would make them go to stdout */ + #define _LOG_ONCE 0x0100 /* downgrade to NOTICE if this has been already logged */ + #define _LOG_BYPASS_REPORT 0x0200 /* do not log through report even if report available */ ++#define _LOG_IMPORTANT_TO_SYSLOG 0x10000 /*log to syslog even if loglevel number is bigger than _debug_level configuration, ++ unless _debug_level is 0*/ + #define log_level(x) ((x) & 0x0f) /* obtain message level */ + #define log_stderr(x) ((x) & _LOG_STDERR) /* obtain stderr bit */ + #define log_once(x) ((x) & _LOG_ONCE) /* obtain once bit */ +@@ -100,7 +102,7 @@ + #define log_very_verbose(args...) log_info(args) + #define log_verbose(args...) log_notice(args) + #define log_print(args...) LOG_LINE(_LOG_WARN, args) +-#define log_print_unless_silent(args...) LOG_LINE(silent_mode() ? _LOG_NOTICE : _LOG_WARN, args) ++#define log_print_unless_silent(args...) LOG_LINE(silent_mode() ? _LOG_NOTICE : _LOG_WARN | _LOG_IMPORTANT_TO_SYSLOG, args) + #define log_error(args...) log_err(args) + #define log_error_suppress(s, args...) log_err_suppress(s, args) + #define log_error_once(args...) log_err_once(args) +diff --git a/lib/misc/lvm-globals.c b/lib/misc/lvm-globals.c +index 82c5706..2cb471e 100644 +--- a/lib/misc/lvm-globals.c ++++ b/lib/misc/lvm-globals.c +@@ -54,12 +54,23 @@ static char _sysfs_dir_path[PATH_MAX] = ""; + static int _dev_disable_after_error_count = DEFAULT_DISABLE_AFTER_ERROR_COUNT; + static uint64_t _pv_min_size = (DEFAULT_PV_MIN_SIZE_KB * 1024L >> SECTOR_SHIFT); + static const char *_unknown_device_name = DEFAULT_UNKNOWN_DEVICE_NAME; ++static int _log_unless_silent = 1; + + void init_verbose(int level) + { + _verbose_level = level; + } + ++void init_log_unless_silent(int unless_silent) ++{ ++ _log_unless_silent = unless_silent; ++} ++ ++int get_log_unless_silent(void) ++{ ++ return _log_unless_silent; ++} ++ + void init_silent(int silent) + { + _silent = silent; +diff --git a/lib/misc/lvm-globals.h b/lib/misc/lvm-globals.h +index f985cfa..3374d0d 100644 +--- a/lib/misc/lvm-globals.h ++++ b/lib/misc/lvm-globals.h +@@ -93,4 +93,6 @@ int dmeventd_monitor_mode(void); + #define NO_DEV_ERROR_COUNT_LIMIT 0 + int dev_disable_after_error_count(void); + ++void init_log_unless_silent(int unless_silent); ++int get_log_unless_silent(void); + #endif +diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c +index 298ead7..0b1a9b2 100644 +--- a/tools/lvmcmdline.c ++++ b/tools/lvmcmdline.c +@@ -2807,6 +2807,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) + /* The cmd_line string is only used for logging, not processing. */ + if (!(cmd->cmd_line = _copy_command_line(cmd, argc, argv))) + return_ECMD_FAILED; ++ set_global_cmdline(cmd->cmd_line); + + /* Look up command - will be NULL if not recognised */ + if (!(cmd->cname = _find_command_name(cmd->name))) +-- +2.19.1 + diff --git a/LVM2.2.02.181.tgz b/LVM2.2.02.181.tgz new file mode 100644 index 0000000..e7a659d Binary files /dev/null and b/LVM2.2.02.181.tgz differ diff --git a/lvm2.spec b/lvm2.spec new file mode 100644 index 0000000..2db28da --- /dev/null +++ b/lvm2.spec @@ -0,0 +1,538 @@ +%global use_cluster 1 +%global use_cmirror 1 +%global use_lockd_sanlock 1 +%global use_lockd_dlm 1 +%ifnarch i686 x86_64 + %global use_cluster 0 + %global use_cmirror 0 + %global use_lockd_dlm 0 +%endif + +%ifnarch x86_64 aarch64 + %global use_lockd_sanlock 0 +%endif + +%if %{use_cluster} + %global configure_cluster --with-cluster=internal --with-clvmd=corosync + %if %{use_cmirror} + %global configure_cmirror --enable-cmirrord + %endif +%else + %global configure_cluster --with-cluster=internal --with-clvmd=none +%endif + +%if %{use_lockd_dlm} +%global configure_lockd_dlm --enable-lvmlockd-dlm +%endif + +%if %{use_lockd_sanlock} +%global configure_lockd_sanlock --enable-lvmlockd-sanlock +%endif + +%global libselinux_version 1.30.19-4 +%global persistent_data_version 0.7.0-0.1.rc6 +%global sanlock_version 3.3.0-2 +%global device_mapper_version 1.02.150 +%global systemd_version 189-3 +%global dracut_version 002-18 +%global util_linux_version 2.24 +%global bash_version 4.0 +%global corosync_version 1.99.9-1 +%global resource_agents_version 3.9.5-12 +%global dlm_version 4.0.6-2 + +Name: lvm2 +Version: 2.02.181 +Release: 2 +Epoch: 8 +Summary: Tools for logical volume management +License: GPLv2 and LGPLv2 +URL: http://sourceware.org/lvm2 +Source0: ftp://sourceware.org/pub/lvm2/releases/LVM2.%{version}.tgz +Patch0000: 0000-lvm2-set-default-preferred_names.patch +Patch0001: 0001-lvm2-lvmetad-timeout.patch + +Patch6000: 6000-mirrors-fix-read_only_volume_list.patch +Patch6001: 6001-bcache-reduce-MAX_IO-to-256.patch +Patch6002: 6002-lvmetad-fix-pvs-for-many-devices.patch +Patch6003: 6003-dmeventd-lvm2-plugin-uses-envvar-registry.patch +Patch6004: 6004-metadata-prevent-writing-beyond-metadata-area.patch +Patch6005: 6005-libdm-stats-move-no-regions-warning-after-dm_stats_l.patch +Patch6006: 6006-dmsetup-fix-stats-report-command-output.patch +Patch6007: 6007-io-use-sync-io-if-aio-fails.patch +Patch6008: 6008-bcache-sync-io-fixes.patch +Patch6009: 6009-lvmanip-uninitialized-members-in-struct-pv_list-10.patch +Patch6010: 6010-apply-obtain_device_list_from_udev-to-all-libudev-us.patch +Patch6011: 6011-cov-dmstats-check-for-failing-malloc.patch +Patch6012: 6012-cov-ensure-vars-are-set.patch +Patch6013: 6013-libdm-add-memory-barrier.patch +Patch6014: 6014-stats-fix-error-path-when-region-is-NULL.patch +Patch6015: 6015-stats-initilize-regions-to-NULL.patch +Patch6016: 6016-dmsetup-Fix-multi-line-concise-table-parsing.patch +Patch6017: 6017-Remove-VG-lock-ordering-check.patch +Patch6018: 6018-Fix-use-of-orphan-lock-in-commands.patch +Patch6019: 6019-metadata-remove-an-unused-and-incorrect-overflow-che.patch +Patch6020: 6020-cov-dmeventd-plugin-fix-memleak.patch +Patch6021: 6021-cov-fix-missing-null-allocation-check.patch +Patch6022: 6022-cov-add-check-for-positive-value.patch +Patch6023: 6023-cov-fix-failing-filter-initialization.patch +Patch6024: 6024-cov-check-dev_close_immediate.patch +Patch6025: 6025-cov-make-sure-label-scans-valid-lvinfo.patch +Patch6026: 6026-cov-add-missing-error-path-check-for-label_scan_open.patch +Patch6027: 6027-cov-pvscan-ensure-sigle_devs-list-is-always-initiali.patch +Patch6028: 6028-fix-cov-missed-return-value-test.patch +Patch6029: 6029-cov-trace-failing-pthread_kill.patch +Patch6030: 6030-cov-avoid-unsing-unchecked-label_scan_open.patch +Patch6031: 6031-lvmlockd-fix-missing-LV-lock-for-lvconvert-repair.patch +Patch6032: 6032-lvconvert-ensure-proper-init-of-pv_list.patch +Patch6033: 6033-dmeventd-unlock-lvm2-lock-on-error-path.patch +Patch6034: 6034-mangenerator-check-strdup-was-successfull.patch +Patch6035: 6035-cov-ensure-lock_type-is-not-NULL.patch +Patch6036: 6036-Remove-checking-for-locked-VGs.patch +Patch6037: 6037-lvm2-default-allow-changes-with-duplicate-pvs.patch + +Patch9000: 9000-bugfix-lvm2-add-SSD.patch +Patch9001: 9001-bugfix-add-timeout-when-fail-to-wait-udev.patch +Patch9002: 9002-bugfix-fix-the-code-maybe-lead-to-buffer-over-bound-access.patch +Patch9003: 9003-enhancement-modify-default-log-level-to-error-level.patch +Patch9004: 9004-enhancement-add-dfx-log.patch + +BuildRequires: gcc +BuildRequires: gcc-c++ +BuildRequires: libselinux-devel >= %{libselinux_version}, libsepol-devel +BuildRequires: libblkid-devel >= %{util_linux_version} +BuildRequires: ncurses-devel +BuildRequires: readline-devel +BuildRequires: libaio-devel +BuildRequires: module-init-tools +BuildRequires: pkgconfig +BuildRequires: systemd-devel +BuildRequires: systemd-units +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-dbus +BuildRequires: python3-pyudev +BuildRequires: device-mapper-persistent-data >= %{persistent_data_version} + +%if %{use_cluster} +BuildRequires: corosynclib-devel >= %{corosync_version} +%endif +%if %{use_cluster} || %{use_lockd_dlm} +BuildRequires: dlm-devel >= %{dlm_version} +%endif +%if %{use_lockd_sanlock} +BuildRequires: sanlock-devel >= %{sanlock_version} +%endif + +Requires: bash >= %{bash_version} +Requires: module-init-tools +Requires: device-mapper-persistent-data >= %{persistent_data_version} +Requires: device-mapper-event = %{?epoch}:%{device_mapper_version}-%{release} +Requires(post): systemd-units >= %{systemd_version}, systemd-sysv +Requires(preun): systemd-units >= %{systemd_version} +Requires(postun): systemd-units >= %{systemd_version} + +Provides: %{name}-libs +Obsoletes: %{name}-libs + +%description +lvm2 refers to the userspace toolset that provide logical volume management facilities on linux. + +%package devel +Summary: lvm2 devel files +License: LGPLv2 +Requires: %{name} = %{?epoch}:%{version}-%{release} +Requires: pkgconfig +Requires: device-mapper = %{?epoch}:%{device_mapper_version}-%{release} +Provides: device-mapper-devel = %{?epoch}:%{device_mapper_version}-%{release} +Obsoletes: device-mapper-devel +Provides: device-mapper-event-devel = %{?epoch}:%{device_mapper_version}-%{release} +Obsoletes: device-mapper-event-devel + +%description devel +This package contains all include files, libraries files needed to develop programs that use lvm2. + +%package help +Summary: Including man files for lvm2 +Requires: man +BuildArch: noarch + +%description help +This contains man files for the using of lvm2. + +%package -n python3-lvm-deprecated +Summary: Python 3 api to lvm +License: LGPLv2 +Provides: python3-lvm = %{?epoch}:%{version}-%{release} +%{?python_provide:%python_provide python3-lvm} +Provides: %{name}-python3-libs = %{?epoch}:%{version}-%{release} +Obsoletes: %{name}-python3-libs < %{?epoch}:%{version}-%{release} +Requires: %{name}-libs = %{?epoch}:%{version}-%{release} + +%description -n python3-lvm-deprecated +Support python 3 to use lvm. + +%if %{use_lockd_dlm} || %{use_lockd_sanlock} +%package lockd +Summary: LVM locking daemon +Requires: lvm2 = %{?epoch}:%{version}-%{release} +%if %{use_lockd_sanlock} +Requires: sanlock-lib >= %{sanlock_version} +%endif +%if %{use_lockd_dlm} +Requires: dlm-lib >= %{dlm_version} +%endif +Requires(post): systemd-units >= %{systemd_version} +Requires(preun): systemd-units >= %{systemd_version} +Requires(postun): systemd-units >= %{systemd_version} + +%description lockd +LVM commands use lvmlockd to coordinate access to shared storage. +%endif + +%if %{use_cluster} +%package cluster +Summary: cluster LVM daemon tools +License: GPLv2 +Requires: lvm2 = %{?epoch}:%{version}-%{release} +Requires(preun): device-mapper >= %{?epoch}:%{device_mapper_version} +Requires(preun): lvm2 >= 2.02 +Requires: corosync >= %{corosync_version} +Requires: dlm >= %{dlm_version} +Requires: resource-agents >= %{resource_agents_version} +Provides: cluster-standalone +Obsoletes: cluster-standalone + +%description cluster +cluster distributes LVM metadata updates around a cluster. +%endif + +%if %{use_cluster} && %{use_cmirror} +%package -n cmirror +Summary: cluster mirror log daemon +License: GPLv2 +Requires: corosync >= %{corosync_version} +Requires: device-mapper = %{?epoch}:%{device_mapper_version}-%{release} +Requires: resource-agents >= %{resource_agents_version} +Provides: cmirror-standalone +Obsoletes: cmirror-standalone + +%description -n cmirror +cmirror tracks mirror log information in a cluster. +%endif + +%package dbusd +Summary: LVM2 D-Bus daemon +License: GPLv2 +Requires: lvm2 >= %{?epoch}:%{version}-%{release} +Requires: dbus +Requires: python3-dbus +Requires: python3-pyudev +Requires: python3-gobject-base +Requires(post): systemd-units >= %{systemd_version} +Requires(preun): systemd-units >= %{systemd_version} +Requires(postun): systemd-units >= %{systemd_version} + +%description dbusd +dbusd is a service which provides a D-Bus API to the logical volume manager. + +%package test +Summary: Testsuite for lvm2 +License: LGPLv2 and GPLv2 and BSD-2-Clause +Provides: %{name}-testsuite +Obsoletes: %{name}-testsuite + +%description test +An extensive functional testsuite for LVM2. + +%prep +%autosetup -n LVM2.%{version} -p1 + +%package -n device-mapper +Summary: Low level logical volume management +Version: %{device_mapper_version} +License: LGPLv2 +URL: http://sources.redhat.com/dm +Requires: util-linux >= %{util_linux_version} +Requires: systemd >= %{systemd_version} +Provides: device-mapper-libs = %{?epoch}:%{device_mapper_version}-%{release} +Obsoletes: device-mapper-libs +Conflicts: dracut < %{dracut_version} + +%description -n device-mapper +Manages logical devices that use the device-mapper driver. + +%package -n device-mapper-event +Summary: Handle device-mapper events +Version: %{device_mapper_version} +Requires: device-mapper = %{?epoch}:%{device_mapper_version}-%{release} +Requires: systemd-units +Provides: device-mapper-event-libs = %{?epoch}:%{device_mapper_version}-%{release} +Obsoletes: device-mapper-event-libs + +%description -n device-mapper-event +It contains tthe event monitoring daemon for device-mapper devices. Library plugins +can register and carryout actions triggered when particular events occur. + +%build +%configure --with-default-dm-run-dir=/run --with-default-run-dir=/run/lvm --with-default-pid-dir=/run --with-default-locking-dir=/run/lock/lvm --with-usrlibdir=%{_libdir} --enable-fsadm --enable-write_install --with-user= --with-group= --with-device-uid=0 --with-device-gid=6 --with-device-mode=0660 --enable-pkgconfig --enable-applib --enable-cmdlib --enable-dmeventd --enable-blkid_wiping --enable-python3-bindings %{?configure_cluster} %{?configure_cmirror} --with-udevdir=%{_prefix}/lib/udev/rules.d --enable-udev_sync --with-thin=internal --enable-lvmetad --with-thin=internal --enable-lvmpolld %{?configure_lockd_dlm} %{?configure_lockd_sanlock} --enable-dbus-service --enable-notify-dbus --enable-dmfilemapd +make %{?_smp_mflags} + +%install +make install DESTDIR=%{buildroot} +make install_system_dirs DESTDIR=%{buildroot} +make install_systemd_units DESTDIR=%{buildroot} +make install_systemd_generators DESTDIR=%{buildroot} +make install_tmpfiles_configuration DESTDIR=%{buildroot} +make -C test install DESTDIR=%{buildroot} + +%post +/sbin/ldconfig +%systemd_post blk-availability.service lvm2-monitor.service +if [ "$1" = "1" ] ; then + systemctl enable lvm2-monitor.service + systemctl start lvm2-monitor.service >/dev/null 2>&1 || : +fi +%systemd_post lvm2-lvmetad.socket +systemctl start lvm2-lvmetad.socket >/dev/null 2>&1 || : + +%systemd_post lvm2-lvmpolld.socket +systemctl enable lvm2-lvmpolld.socket +systemctl start lvm2-lvmpolld.socket >/dev/null 2>&1 || : + +%preun +%systemd_preun blk-availability.service lvm2-monitor.service +%systemd_preun lvm2-lvmetad.service lvm2-lvmetad.socket +%systemd_preun lvm2-lvmpolld.service lvm2-lvmpolld.socket + +%postun +%systemd_postun lvm2-monitor.service +%systemd_postun_with_restart lvm2-lvmetad.service +%systemd_postun_with_restart lvm2-lvmpolld.service +/sbin/ldconfig + +%post -n device-mapper +/sbin/ldconfig + +%postun -n device-mapper +/sbin/ldconfig + +%post -n device-mapper-event +/sbin/ldconfig +%systemd_post dm-event.socket +systemctl enable dm-event.socket +systemctl start dm-event.socket >/dev/null 2>&1 || : +if [ -e %{_default_pid_dir}/dmeventd.pid ]; then + %{_sbindir}/dmeventd -R || echo "Failed to start dmeventd." +fi + +%preun -n device-mapper-event +%systemd_preun dm-event.service dm-event.socket + +%postun -n device-mapper-event +/sbin/ldconfig + +%if %{use_lockd_dlm} || %{use_lockd_sanlock} +%post lockd +%systemd_post lvm2-lvmlockd.service lvm2-lvmlocking.service + +%preun lockd +%systemd_preun lvm2-lvmlockd.service lvm2-lvmlocking.service + +%postun lockd +%systemd_postun lvm2-lvmlockd.service lvm2-lvmlocking.service +%endif + +%if %{use_cluster} +%post cluster +if [ -e /run/clvmd.pid ]; then + /usr/sbin/clvmd -S || echo "Failed to start clvmd." +fi +%systemd_post lvm2-clvmd.service lvm2-cluster-activation.service + +%preun cluster +if [ "$1" = "0" ]; then + /sbin/lvmconf --disable-cluster +fi +%systemd_preun lvm2-clvmd.service lvm2-cluster-activation.service + +%postun cluster +%systemd_postun lvm2-clvmd.service lvm2-cluster-activation.service +%endif + +%if %{use_cluster} && %{use_cmirror} +%post -n cmirror +%systemd_post lvm2-cmirrord.service + +%preun -n cmirror +%systemd_preun lvm2-cmirrord.service + +%postun -n cmirror +%systemd_postun lvm2-cmirrord.service +%endif + +%post dbusd +%systemd_post lvm2-lvmdbusd.service + +%preun dbusd +%systemd_preun lvm2-lvmdbusd.service + +%postun dbusd +%systemd_postun lvm2-lvmdbusd.service + +%files +%license COPYING COPYING.LIB + +%defattr(555,root,root,-) +%{_sbindir}/fsadm +%{_sbindir}/lvm +%{_sbindir}/lvmconf +%{_sbindir}/lvmconfig +%{_sbindir}/lvmdump +%{_sbindir}/lvmetad +%{_sbindir}/lvmpolld +%{_libdir}/liblvm2app.so.* +%{_libdir}/liblvm2cmd.so.* +%{_libdir}/libdevmapper-event-lvm2.so.* + +%defattr(444,root,root,-) +%{_sbindir}/lvchange +%{_sbindir}/lvconvert +%{_sbindir}/lvcreate +%{_sbindir}/lvdisplay +%{_sbindir}/lvextend +%{_sbindir}/lvmdiskscan +%{_sbindir}/lvmsadc +%{_sbindir}/lvmsar +%{_sbindir}/lvreduce +%{_sbindir}/lvremove +%{_sbindir}/lvrename +%{_sbindir}/lvresize +%{_sbindir}/lvs +%{_sbindir}/lvscan +%{_sbindir}/pv* +%{_sbindir}/vg* + +%{_prefix}/lib/udev/rules.d/69-dm-lvm-metad.rules +%{_prefix}/lib/udev/rules.d/11-dm-lvm.rules + +%dir %{_sysconfdir}/lvm +%ghost %{_sysconfdir}/lvm/cache/.cache +%attr(644, -, -) %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/lvm.conf +%attr(644, -, -) %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/lvmlocal.conf +%dir %{_sysconfdir}/lvm/profile +%{_sysconfdir}/lvm/profile/* +%dir %{_sysconfdir}/lvm/backup +%dir %{_sysconfdir}/lvm/cache +%dir %{_sysconfdir}/lvm/archive +%ghost %dir /run/lock/lvm +%ghost %dir /run/lvm +%dir %{_libdir}/device-mapper +%{_libdir}/device-mapper/* +%{_libdir}/libdevmapper-event-lvm2mirror.so +%{_libdir}/libdevmapper-event-lvm2snapshot.so +%{_libdir}/libdevmapper-event-lvm2raid.so +%{_libdir}/libdevmapper-event-lvm2thin.so +%{_libdir}/libdevmapper-event-lvm2vdo.so +%{_tmpfilesdir}/%{name}.conf +%{_unitdir}/blk-availability.service +%{_unitdir}/lvm2-monitor.service +%attr(555, -, -) %{_prefix}/lib/systemd/system-generators/lvm2-activation-generator +%{_unitdir}/lvm2-lvmetad.socket +%{_unitdir}/lvm2-lvmetad.service +%{_unitdir}/lvm2-pvscan@.service +%{_unitdir}/lvm2-lvmpolld.socket +%{_unitdir}/lvm2-lvmpolld.service + +%files -n device-mapper +%license COPYING COPYING.LIB +%doc udev/12-dm-permissions.rules +%defattr(555,root,root,-) +%{_sbindir}/dmsetup +%{_sbindir}/blkdeactivate +%{_sbindir}/dmstats +%{_sbindir}/dmfilemapd +%{_libdir}/libdevmapper.so.* +%defattr(444,root,root,-) +%{_prefix}/lib/udev/rules.d/10-dm.rules +%{_prefix}/lib/udev/rules.d/13-dm-disk.rules +%{_prefix}/lib/udev/rules.d/95-dm-notify.rules + +%files -n device-mapper-event +%license COPYING.LIB +%defattr(555,root,root,-) +%{_sbindir}/dmeventd +%{_libdir}/libdevmapper-event.so.* +%defattr(444,root,root,-) +%{_unitdir}/dm-event.socket +%{_unitdir}/dm-event.service + +%files devel +%defattr(444,root,root,-) +%{_libdir}/liblvm2app.so +%{_libdir}/liblvm2cmd.so +%{_libdir}/libdevmapper-event-lvm2.so +%{_libdir}/libdevmapper.so +%{_libdir}/libdevmapper-event.so +%{_includedir}/lvm2app.h +%{_includedir}/lvm2cmd.h +%{_includedir}/libdevmapper.h +%{_includedir}/libdevmapper-event.h +%{_libdir}/pkgconfig/lvm2app.pc +%{_libdir}/pkgconfig/devmapper.pc +%{_libdir}/pkgconfig/devmapper-event.pc + +%files help +%{_mandir}/man5/* +%{_mandir}/man7/* +%{_mandir}/man8/* + +%files -n python3-lvm-deprecated +%{python3_sitearch}/*.so +%{python3_sitearch}/*.egg-info + +%if %{use_lockd_dlm} || %{use_lockd_sanlock} +%files lockd +%defattr(444,root,root,-) +%%attr(555, -, -) %{_sbindir}/lvmlockd +%%attr(555, -, -) %{_sbindir}/lvmlockctl +%{_unitdir}/lvm2-lvmlockd.service +%{_unitdir}/lvm2-lvmlocking.service +%endif + +%if %{use_cluster} +%files cluster +%defattr(555,root,root,-) +%{_sbindir}/clvmd +%{_prefix}/lib/systemd/lvm2-cluster-activation +%defattr(444,root,root,-) +%{_unitdir}/lvm2-clvmd.service +%{_unitdir}/lvm2-cluster-activation.service +%endif + +%if %{use_cluster} && %{use_cmirror} +%files -n cmirror +%defattr(555,root,root,-) +%{_sbindir}/cmirrord +%{_unitdir}/lvm2-cmirrord.service +%endif + +%files dbusd +%defattr(555,root,root,-) +%{_sbindir}/lvmdbusd +%defattr(444,root,root,-) +%{_sysconfdir}/dbus-1/system.d/com.redhat.lvmdbus1.conf +%{_datadir}/dbus-1/system-services/com.redhat.lvmdbus1.service +%{_unitdir}/lvm2-lvmdbusd.service +%{python3_sitelib}/lvmdbusd/* + +%files test +%license COPYING COPYING.LIB COPYING.BSD +%{_datadir}/lvm2-testsuite/ +%{_libexecdir}/lvm2-testsuite/ +%{_bindir}/lvm2-testsuite + + +%changelog +* Fri Sep 06 2019 wangjufeng - 2.02.181-2 +- Package init