Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=63169594385ed4b02d93c…
Commit: 63169594385ed4b02d93c2e8f422bbeb0b8225af
Parent: 125da10d47f4c1f72d3df99f2451c1eb031b9f3a
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed Oct 28 16:50:47 2020 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Oct 28 16:50:47 2020 -0500
pvck: fix previous commit
line to setup bcache was misplaced in
commit 5a94126e7a28
---
tools/pvck.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/pvck.c b/tools/pvck.c
index 06fd01733..c36e18216 100644
--- a/tools/pvck.c
+++ b/tools/pvck.c
@@ -3064,11 +3064,11 @@ int pvck(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
+ label_scan_setup_bcache();
+
if (dev) {
char buf[4096];
- label_scan_setup_bcache();
-
/*
* This buf is not used, but bcache data is used for subsequent
* reads in the filters and by _read_bytes for other disk structs.
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=5a94126e7a2824387c36d…
Commit: 5a94126e7a2824387c36d87f5ede97702a82cdda
Parent: c96645781ceb88c625dfae73e5baa08f1ce0e07e
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Oct 27 15:42:08 2020 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Tue Oct 27 15:43:15 2020 -0500
pvck: fix dev filtering
filters needing io weren't being run because bcache
wasn't set up. Read the first 4k of the device
before doing filtering or reading ondisk structs to
reduce reads.
---
tools/pvck.c | 31 +++++++++++++++++++++----------
1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/tools/pvck.c b/tools/pvck.c
index 39692e3de..06fd01733 100644
--- a/tools/pvck.c
+++ b/tools/pvck.c
@@ -1039,13 +1039,6 @@ static int _dump_label_and_pv_header(struct cmd_context *cmd, uint64_t labelsect
return 0;
}
- /*
- * Not invalidating this range can cause an error reading
- * a larger range that overlaps this.
- */
- if (dev && !dev_invalidate_bytes(dev, lh_offset, 512))
- stack;
-
lh = (struct label_header *)buf;
if (print_fields) {
@@ -3040,7 +3033,7 @@ int pvck(struct cmd_context *cmd, int argc, char **argv)
clear_hint_file(cmd);
- if (!(dev = dev_cache_get(cmd, pv_name, cmd->filter))) {
+ if (!(dev = dev_cache_get(cmd, pv_name, NULL))) {
log_error("Cannot use %s: %s.", pv_name, devname_error_reason(pv_name));
return ECMD_FAILED;
}
@@ -3049,7 +3042,7 @@ int pvck(struct cmd_context *cmd, int argc, char **argv)
if (arg_is_set(cmd, dump_ARG)) {
pv_name = argv[0];
- dev = dev_cache_get(cmd, pv_name, cmd->filter);
+ dev = dev_cache_get(cmd, pv_name, NULL);
if (!dev)
def = get_devicefile(pv_name);
@@ -3071,7 +3064,25 @@ int pvck(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- label_scan_setup_bcache();
+ if (dev) {
+ char buf[4096];
+
+ label_scan_setup_bcache();
+
+ /*
+ * This buf is not used, but bcache data is used for subsequent
+ * reads in the filters and by _read_bytes for other disk structs.
+ */
+ if (!dev_read_bytes(dev, 0, 4096, buf)) {
+ log_error("Failed to read the first 4096 bytes of device %s.", dev_name(dev));
+ return ECMD_FAILED;
+ }
+
+ if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, NULL)) {
+ log_error("Cannot use %s: %s.", pv_name, dev_filtered_reason(dev));
+ return ECMD_FAILED;
+ }
+ }
if ((dump = arg_str_value(cmd, dump_ARG, NULL))) {
cmd->use_hints = 0;
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=c96645781ceb88c625dfa…
Commit: c96645781ceb88c625dfae73e5baa08f1ce0e07e
Parent: 020d1edaa06e5e05b58e8d39530408f86a22d1b8
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Oct 27 14:28:54 2020 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Tue Oct 27 14:28:54 2020 -0500
pvck: handle first mda at non-4096 offset
It's possible for a machine with a non-4k page size
to create a PV with an mda_header at an offset other
than 4k. Fix pvck --dump to work with these other
mda offsets. pvck --repair will write a new first
mda at 4096 but lvm with other page sizes will work
with this.
---
tools/pvck.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/tools/pvck.c b/tools/pvck.c
index 7ae4976e5..39692e3de 100644
--- a/tools/pvck.c
+++ b/tools/pvck.c
@@ -1406,9 +1406,10 @@ static int _dump_headers(struct cmd_context *cmd, const char *dump, struct setti
}
/*
- * The first mda is always 4096 bytes from the start of the device.
+ * The first mda is usually 4096 bytes from the start of the device.
+ * (If created by a machine with larger pages it could be 8k/16k/64k.)
*/
- if (!_dump_mda_header(cmd, set, 1, 0, 0, NULL, dev, def, 4096, mda1_size, &mda1_checksum, NULL))
+ if (!_dump_mda_header(cmd, set, 1, 0, 0, NULL, dev, def, mda1_offset, mda1_size, &mda1_checksum, NULL))
bad++;
if (mda2_offset) {
@@ -1463,7 +1464,7 @@ static int _dump_metadata(struct cmd_context *cmd, const char *dump, struct sett
* The first mda is always 4096 bytes from the start of the device.
*/
if (mda_num == 1) {
- if (!_dump_mda_header(cmd, set, 0, print_metadata, print_area, tofile, dev, def, 4096, mda1_size, &mda1_checksum, NULL))
+ if (!_dump_mda_header(cmd, set, 0, print_metadata, print_area, tofile, dev, def, mda1_offset, mda1_size, &mda1_checksum, NULL))
bad++;
} else if (mda_num == 2) {
if (!mda2_offset) {
@@ -1497,7 +1498,7 @@ static int _dump_found(struct cmd_context *cmd, struct settings *set, uint64_t l
bad++;
if (found_label && mda1_offset) {
- if (!_dump_mda_header(cmd, set, 0, 0, 0, NULL, dev, NULL, 4096, mda1_size, &mda1_checksum, &found_header1))
+ if (!_dump_mda_header(cmd, set, 0, 0, 0, NULL, dev, NULL, mda1_offset, mda1_size, &mda1_checksum, &found_header1))
bad++;
}
@@ -1681,7 +1682,7 @@ static int _dump_search(struct cmd_context *cmd, const char *dump, struct settin
*/
if ((mda_num == 1) && found_label && mda1_offset && mda1_size) {
/* use header values when available */
- mda_offset = 4096;
+ mda_offset = mda1_offset;
mda_size = mda1_size;
} else if (mda_num == 1) {
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=2c319398274b930a38278…
Commit: 2c319398274b930a38278e635e9171ce663f2bab
Parent: 7bafae48bb7b7bf1e7adc420bf83d0c5acaf0aac
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Oct 23 13:53:52 2020 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Mon Oct 26 11:13:27 2020 -0500
pvcreate: clean up opening and filtering of args
The args for pvcreate/pvremove (and vgcreate/vgextend
when applicable) were not efficiently opened, scanned,
and filtered. This change reorganizes the opening
and filtering in the following steps:
- label scan and filter all devs
. open ro
. standard label scan at the start of command
- label scan and filter dev args
. open ro
. uses full md component check
. typically the first scan and filter of pvcreate devs
- close and reopen dev args
. open rw and excl
- repeat label scan and filter dev args
. using reopened rw excl fd
- wipe and write new headers
. using reopened rw excl fd
---
lib/label/label.c | 24 ++++++-----
lib/label/label.h | 2 +-
tools/lvmcmdline.c | 9 +---
tools/toollib.c | 124 ++++++++++++++++++++++++++++++++++++++++++++---------
4 files changed, 120 insertions(+), 39 deletions(-)
diff --git a/lib/label/label.c b/lib/label/label.c
index 36eab19f3..e067a6bed 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -669,7 +669,7 @@ static void _invalidate_di(struct bcache *cache, int di)
*/
static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
- struct dm_list *devs, int *failed)
+ struct dm_list *devs, int want_other_devs, int *failed)
{
struct dm_list wait_devs;
struct dm_list done_devs;
@@ -759,9 +759,11 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
* Keep the bcache block of lvm devices we have processed so
* that the vg_read phase can reuse it. If bcache failed to
* read the block, or the device does not belong to lvm, then
- * drop it from bcache.
+ * drop it from bcache. When "want_other_devs" is set, it
+ * means the caller wants to scan and keep open non-lvm devs,
+ * e.g. to pvcreate them.
*/
- if (!is_lvm_device) {
+ if (!is_lvm_device && !want_other_devs) {
_invalidate_di(scan_bcache, devl->dev->bcache_di);
_scan_dev_close(devl->dev);
}
@@ -1146,7 +1148,7 @@ int label_scan(struct cmd_context *cmd)
/*
* Do the main scan.
*/
- _scan_list(cmd, cmd->filter, &scan_devs, NULL);
+ _scan_list(cmd, cmd->filter, &scan_devs, 0, NULL);
/*
* Metadata could be larger than total size of bcache, and bcache
@@ -1193,7 +1195,7 @@ int label_scan(struct cmd_context *cmd)
if (using_hints) {
if (!validate_hints(cmd, &hints_list)) {
log_debug("Will scan %d remaining devices", dm_list_size(&all_devs));
- _scan_list(cmd, cmd->filter, &all_devs, NULL);
+ _scan_list(cmd, cmd->filter, &all_devs, 0, NULL);
free_hints(&hints_list);
using_hints = 0;
create_hints = 0;
@@ -1312,7 +1314,7 @@ int label_scan_devs_cached(struct cmd_context *cmd, struct dev_filter *f, struct
if (!scan_bcache)
return 0;
- _scan_list(cmd, f, devs, NULL);
+ _scan_list(cmd, f, devs, 0, NULL);
return 1;
}
@@ -1339,7 +1341,7 @@ int label_scan_devs(struct cmd_context *cmd, struct dev_filter *f, struct dm_lis
_invalidate_di(scan_bcache, devl->dev->bcache_di);
}
- _scan_list(cmd, f, devs, NULL);
+ _scan_list(cmd, f, devs, 0, NULL);
return 1;
}
@@ -1359,12 +1361,12 @@ int label_scan_devs_rw(struct cmd_context *cmd, struct dev_filter *f, struct dm_
devl->dev->flags |= DEV_BCACHE_WRITE;
}
- _scan_list(cmd, f, devs, NULL);
+ _scan_list(cmd, f, devs, 0, NULL);
return 1;
}
-int label_scan_devs_excl(struct dm_list *devs)
+int label_scan_devs_excl(struct cmd_context *cmd, struct dev_filter *f, struct dm_list *devs)
{
struct device_list *devl;
int failed = 0;
@@ -1379,7 +1381,7 @@ int label_scan_devs_excl(struct dm_list *devs)
devl->dev->flags |= DEV_BCACHE_WRITE;
}
- _scan_list(NULL, NULL, devs, &failed);
+ _scan_list(cmd, f, devs, 1, &failed);
if (failed)
return 0;
@@ -1472,7 +1474,7 @@ int label_scan_dev(struct device *dev)
label_scan_invalidate(dev);
- _scan_list(NULL, NULL, &one_dev, &failed);
+ _scan_list(NULL, NULL, &one_dev, 0, &failed);
free(devl);
diff --git a/lib/label/label.h b/lib/label/label.h
index a98ba32e3..78724c1ce 100644
--- a/lib/label/label.h
+++ b/lib/label/label.h
@@ -106,7 +106,7 @@ int label_scan(struct cmd_context *cmd);
int label_scan_devs(struct cmd_context *cmd, struct dev_filter *f, struct dm_list *devs);
int label_scan_devs_cached(struct cmd_context *cmd, struct dev_filter *f, struct dm_list *devs);
int label_scan_devs_rw(struct cmd_context *cmd, struct dev_filter *f, struct dm_list *devs);
-int label_scan_devs_excl(struct dm_list *devs);
+int label_scan_devs_excl(struct cmd_context *cmd, struct dev_filter *f, struct dm_list *devs);
int label_scan_dev(struct device *dev);
void label_scan_invalidate(struct device *dev);
void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv);
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 3a2ce93b5..b84a9a014 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -2900,13 +2900,8 @@ static void _init_md_checks(struct cmd_context *cmd)
if (!strcmp(cmd->md_component_checks, "full"))
cmd->use_full_md_check = 1;
- else if (!strcmp(cmd->md_component_checks, "auto")) {
- /* use_full_md_check can also be set later */
- if (!strcmp(cmd->name, "pvcreate") ||
- !strcmp(cmd->name, "vgcreate") ||
- !strcmp(cmd->name, "vgextend"))
- cmd->use_full_md_check = 1;
- }
+
+ /* use_full_md_check can also be set later */
log_debug("Using md_component_checks %s use_full_md_check %d",
cmd->md_component_checks, cmd->use_full_md_check);
diff --git a/tools/toollib.c b/tools/toollib.c
index 0fbb0b6ec..d9295bb82 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -4884,16 +4884,6 @@ static int _pvcreate_check_used(struct cmd_context *cmd,
log_debug("Checking %s for pvcreate %.32s.",
dev_name(pd->dev), pd->dev->pvid[0] ? pd->dev->pvid : "");
- /*
- * Since the device is likely not a PV yet, it was probably not
- * scanned by label_scan at the start of the command, so that
- * needs to be done first to find if there's a PV label or metadata
- * on it. If there's a PV label, it sets dev->pvid.
- * If a VG is using the dev, it adds basic VG info for it to
- * lvmcache.
- */
- label_scan_dev(pd->dev);
-
if (!pd->dev->pvid[0]) {
log_debug("Check pvcreate arg %s no PVID found", dev_name(pd->dev));
pd->is_not_pv = 1;
@@ -5189,6 +5179,31 @@ fail:
* This function returns 1 (success) if the caller requires all specified
* devices to be created, and all are created, or if the caller does not
* require all specified devices to be created and one or more were created.
+ *
+ * Process of opening, scanning and filtering:
+ *
+ * - label scan and filter all devs
+ * . open ro
+ * . standard label scan at the start of command
+ * . done prior to this function
+ *
+ * - label scan and filter dev args
+ * . label_scan_devs(&scan_devs) in this function
+ * . open ro
+ * . uses full md component check
+ * . typically the first scan and filter of pvcreate devs
+ *
+ * - close and reopen dev args
+ * . open rw and excl
+ * . done by label_scan_devs_excl
+ *
+ * - repeat label scan and filter dev args
+ * . using reopened rw excl fd
+ * . since something could have used dev
+ * in the small window between close and reopen
+ *
+ * - wipe and write new headers
+ * . using reopened rw excl fd
*/
int pvcreate_each_device(struct cmd_context *cmd,
@@ -5201,6 +5216,7 @@ int pvcreate_each_device(struct cmd_context *cmd,
struct volume_group *orphan_vg;
struct dm_list remove_duplicates;
struct dm_list arg_sort;
+ struct dm_list scan_devs;
struct dm_list rescan_devs;
struct pv_list *pvl;
struct pv_list *vgpvl;
@@ -5217,6 +5233,7 @@ int pvcreate_each_device(struct cmd_context *cmd,
dm_list_init(&remove_duplicates);
dm_list_init(&arg_sort);
+ dm_list_init(&scan_devs);
dm_list_init(&rescan_devs);
handle->custom_handle = pp;
@@ -5244,10 +5261,60 @@ int pvcreate_each_device(struct cmd_context *cmd,
/*
* Translate arg names into struct device's.
+ *
+ * lvmcache_label_scan has already been run by the caller.
+ * It has likely found and filtered pvremove args, but often
+ * not pvcreate args, since pvcreate args are not typically PVs
+ * yet (but may be.)
+ *
+ * We call label_scan_devs on the args, using the full
+ * md filter (the previous scan likely did not use the
+ * full md filter - we really only need to check the
+ * command args to ensure they are not md components.)
*/
+
dm_list_iterate_items_safe(pd, pd2, &pp->arg_devices) {
- pd->dev = dev_cache_get(cmd, pd->name, cmd->filter);
- if (!pd->dev) {
+ struct device *dev;
+
+ /* No filter used here */
+ if (!(dev = dev_cache_get(cmd, pd->name, NULL))) {
+ log_error("No device found for %s.", pd->name);
+ dm_list_del(&pd->list);
+ dm_list_add(&pp->arg_fail, &pd->list);
+ continue;
+ }
+
+ if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl))))
+ goto bad;
+
+ devl->dev = dev;
+ pd->dev = dev;
+
+ dm_list_add(&scan_devs, &devl->list);
+ }
+
+ if (dm_list_empty(&pp->arg_devices))
+ goto_bad;
+
+ /*
+ * Clear the filtering results from lvmcache_label_scan because we are
+ * going to rerun the filters and don't want to get the results saved
+ * by the prior filtering. The filtering in label scan will use full
+ * md filter.
+ */
+ dm_list_iterate_items(devl, &scan_devs)
+ cmd->filter->wipe(cmd, cmd->filter, devl->dev, NULL);
+
+ cmd->use_full_md_check = 1;
+
+ log_debug("Scanning and filtering device args.");
+ label_scan_devs(cmd, cmd->filter, &scan_devs);
+
+ /*
+ * Check if the filtering done by label scan excluded any devices.
+ */
+ dm_list_iterate_items_safe(pd, pd2, &pp->arg_devices) {
+ if (!cmd->filter->passes_filter(cmd, cmd->filter, pd->dev, NULL)) {
log_error("Cannot use %s: %s", pd->name, devname_error_reason(pd->name));
dm_list_del(&pd->list);
dm_list_add(&pp->arg_fail, &pd->list);
@@ -5455,12 +5522,35 @@ do_command:
dm_list_add(&rescan_devs, &devl->list);
}
- log_debug("Rescanning devices with exclusive open");
- if (!label_scan_devs_excl(&rescan_devs)) {
+ /*
+ * We want label_scan excl to repeat the filter check in case something
+ * changed to filter out a dev before we were able to get exclusive.
+ */
+ dm_list_iterate_items(devl, &rescan_devs)
+ cmd->filter->wipe(cmd, cmd->filter, devl->dev, NULL);
+
+ log_debug("Rescanning and filtering device args with exclusive open");
+ if (!label_scan_devs_excl(cmd, cmd->filter, &rescan_devs)) {
log_debug("Failed to rescan devs excl");
goto bad;
}
+ dm_list_iterate_items_safe(pd, pd2, &pp->arg_process) {
+ if (!cmd->filter->passes_filter(cmd, cmd->filter, pd->dev, NULL)) {
+ log_error("Cannot use %s: %s", pd->name, devname_error_reason(pd->name));
+ dm_list_del(&pd->list);
+ dm_list_add(&pp->arg_fail, &pd->list);
+ }
+ }
+
+ if (dm_list_empty(&pp->arg_process) && dm_list_empty(&remove_duplicates)) {
+ log_debug("No devices to process.");
+ goto bad;
+ }
+
+ if (!dm_list_empty(&pp->arg_fail) && must_use_all)
+ goto_bad;
+
/*
* If the global lock was unlocked to wait for prompts, then
* devs could have changed while unlocked, so confirm that
@@ -5498,9 +5588,6 @@ do_command:
* Wipe signatures on devices being created.
*/
dm_list_iterate_items_safe(pd, pd2, &pp->arg_create) {
- /* FIXME: won't all already be open excl from label_scan_devs_excl above? */
- label_scan_open_excl(pd->dev);
-
log_verbose("Wiping signatures on new PV %s.", pd->name);
if (!wipe_known_signatures(cmd, pd->dev, pd->name, TYPE_LVM1_MEMBER | TYPE_LVM2_MEMBER,
@@ -5578,9 +5665,6 @@ do_command:
pv_name = pd->name;
- /* FIXME: won't all already be open excl from label_scan_devs_excl above? */
- label_scan_open_excl(pd->dev);
-
log_debug("Creating a new PV on %s.", pv_name);
if (!(pv = pv_create(cmd, pd->dev, &pp->pva))) {