mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
scan: expand and update label scan comments
This commit is contained in:
parent
60bf9c9f33
commit
dc1e12dcd4
@ -847,8 +847,11 @@ static void _free_hints(struct dm_list *hints)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan and cache lvm data from all devices on the system.
|
* Scan devices on the system to discover which are LVM devices.
|
||||||
* The cache should be empty/reset before calling this.
|
* Info about the LVM devices (PVs) is saved in lvmcache in a
|
||||||
|
* basic/summary form (info/vginfo structs). The vg_read phase
|
||||||
|
* uses this summary info to know which PVs to look at for
|
||||||
|
* processing a given VG.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int label_scan(struct cmd_context *cmd)
|
int label_scan(struct cmd_context *cmd)
|
||||||
@ -860,7 +863,8 @@ int label_scan(struct cmd_context *cmd)
|
|||||||
struct device_list *devl, *devl2;
|
struct device_list *devl, *devl2;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
uint64_t max_metadata_size_bytes;
|
uint64_t max_metadata_size_bytes;
|
||||||
int newhints = 0;
|
int using_hints;
|
||||||
|
int create_hints = 0; /* NEWHINTS_NONE */
|
||||||
|
|
||||||
log_debug_devs("Finding devices to scan");
|
log_debug_devs("Finding devices to scan");
|
||||||
|
|
||||||
@ -869,20 +873,37 @@ int label_scan(struct cmd_context *cmd)
|
|||||||
dm_list_init(&hints_list);
|
dm_list_init(&hints_list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate through all the devices in dev-cache (block devs that appear
|
* dev_cache_scan() creates a list of devices on the system
|
||||||
* under /dev that could possibly hold a PV and are not excluded by
|
* (saved in in dev-cache) which we can iterate through to
|
||||||
* filters). Read each to see if it's an lvm device, and if so
|
* search for LVM devs. The dev cache list either comes from
|
||||||
* populate lvmcache with some basic info about the device and the VG
|
* looking at dev nodes under /dev, or from udev.
|
||||||
* on it. This info will be used by the vg_read() phase of the
|
|
||||||
* command.
|
|
||||||
*/
|
*/
|
||||||
dev_cache_scan();
|
dev_cache_scan();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up the iterator that is needed to step through each device in
|
||||||
|
* dev cache.
|
||||||
|
*/
|
||||||
if (!(iter = dev_iter_create(cmd->filter, 0))) {
|
if (!(iter = dev_iter_create(cmd->filter, 0))) {
|
||||||
log_error("Scanning failed to get devices.");
|
log_error("Scanning failed to get devices.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_debug_devs("Filtering devices to scan");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate through all devices in dev cache and apply filters
|
||||||
|
* to exclude devs that we do not need to scan. Those devs
|
||||||
|
* that pass the filters are returned by the iterator and
|
||||||
|
* saved in a list of devs that we will proceed to scan to
|
||||||
|
* check if they are LVM devs. IOW this loop is the
|
||||||
|
* application of filters (those that do not require reading
|
||||||
|
* the devs) to the list of all devices. It does that because
|
||||||
|
* the 'cmd->filter' is used above when setting up the iterator.
|
||||||
|
* Unfortunately, it's not obvious that this is what's happening
|
||||||
|
* here. filters that require reading the device are not applied
|
||||||
|
* here, but in process_block(), see DEV_FILTER_AFTER_SCAN.
|
||||||
|
*/
|
||||||
while ((dev = dev_iter_get(cmd, iter))) {
|
while ((dev = dev_iter_get(cmd, iter))) {
|
||||||
if (!(devl = zalloc(sizeof(*devl))))
|
if (!(devl = zalloc(sizeof(*devl))))
|
||||||
continue;
|
continue;
|
||||||
@ -901,13 +922,12 @@ int label_scan(struct cmd_context *cmd)
|
|||||||
/*
|
/*
|
||||||
* When md devices exist that use the old superblock at the
|
* When md devices exist that use the old superblock at the
|
||||||
* end of the device, then in order to detect and filter out
|
* end of the device, then in order to detect and filter out
|
||||||
* the component devices of those md devs, we need to enable
|
* the component devices of those md devs, we enable the full
|
||||||
* the full md filter which scans both the start and the end
|
* md filter which scans both the start and the end of every
|
||||||
* of every device. This doubles the amount of scanning i/o,
|
* device. This doubles the amount of scanning i/o, which we
|
||||||
* which we want to avoid. FIXME: it may not be worth the
|
* want to avoid. FIXME: this forces start+end scanning of
|
||||||
* cost of double i/o just to avoid displaying md component
|
* every device, but it would be more efficient to limit the
|
||||||
* devs in 'pvs', which is a pretty harmless effect from a
|
* end scan only to PVs.
|
||||||
* pretty uncommon situation.
|
|
||||||
*/
|
*/
|
||||||
if (dev_is_md_with_end_superblock(cmd->dev_types, dev))
|
if (dev_is_md_with_end_superblock(cmd->dev_types, dev))
|
||||||
cmd->use_full_md_check = 1;
|
cmd->use_full_md_check = 1;
|
||||||
@ -920,7 +940,10 @@ int label_scan(struct cmd_context *cmd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In some common cases we can avoid scanning all devices.
|
* In some common cases we can avoid scanning all devices
|
||||||
|
* by using hints which tell us which devices are PVs, which
|
||||||
|
* are the only devices we actually need to scan. Without
|
||||||
|
* hints we need to scan all devs to find which are PVs.
|
||||||
*
|
*
|
||||||
* TODO: if the command is using hints and a single vgname
|
* TODO: if the command is using hints and a single vgname
|
||||||
* arg, we can also take the vg lock here, prior to scanning.
|
* arg, we can also take the vg lock here, prior to scanning.
|
||||||
@ -930,10 +953,12 @@ int label_scan(struct cmd_context *cmd)
|
|||||||
* able to avoid rescan in vg_read, but locking early would
|
* able to avoid rescan in vg_read, but locking early would
|
||||||
* apply to more cases.)
|
* apply to more cases.)
|
||||||
*/
|
*/
|
||||||
if (!get_hints(cmd, &hints_list, &newhints, &all_devs, &scan_devs)) {
|
if (!get_hints(cmd, &hints_list, &create_hints, &all_devs, &scan_devs)) {
|
||||||
dm_list_splice(&scan_devs, &all_devs);
|
dm_list_splice(&scan_devs, &all_devs);
|
||||||
dm_list_init(&hints_list);
|
dm_list_init(&hints_list);
|
||||||
}
|
using_hints = 0;
|
||||||
|
} else
|
||||||
|
using_hints = 1;
|
||||||
|
|
||||||
log_debug("Will scan %d devices skip %d", dm_list_size(&scan_devs), dm_list_size(&all_devs));
|
log_debug("Will scan %d devices skip %d", dm_list_size(&scan_devs), dm_list_size(&all_devs));
|
||||||
|
|
||||||
@ -979,17 +1004,18 @@ int label_scan(struct cmd_context *cmd)
|
|||||||
|
|
||||||
dm_list_init(&cmd->hints);
|
dm_list_init(&cmd->hints);
|
||||||
|
|
||||||
if (!dm_list_empty(&hints_list)) {
|
/*
|
||||||
|
* If we're using hints to limit which devs we scanned, verify
|
||||||
|
* that those hints were valid, and if not we need to scan the
|
||||||
|
* rest of the devs.
|
||||||
|
*/
|
||||||
|
if (using_hints) {
|
||||||
if (!validate_hints(cmd, &hints_list)) {
|
if (!validate_hints(cmd, &hints_list)) {
|
||||||
/*
|
|
||||||
* We scanned a subset of all devices based on hints.
|
|
||||||
* With the results from the scan we may decide that
|
|
||||||
* the hints are not valid, so scan all others.
|
|
||||||
*/
|
|
||||||
log_debug("Will scan %d remaining devices", dm_list_size(&all_devs));
|
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, NULL);
|
||||||
_free_hints(&hints_list);
|
_free_hints(&hints_list);
|
||||||
newhints = 0;
|
using_hints = 0;
|
||||||
|
create_hints = 0;
|
||||||
} else {
|
} else {
|
||||||
/* The hints may be used by another device iteration. */
|
/* The hints may be used by another device iteration. */
|
||||||
dm_list_splice(&cmd->hints, &hints_list);
|
dm_list_splice(&cmd->hints, &hints_list);
|
||||||
@ -1006,8 +1032,15 @@ int label_scan(struct cmd_context *cmd)
|
|||||||
free(devl);
|
free(devl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newhints)
|
/*
|
||||||
write_hint_file(cmd, newhints);
|
* If hints were not available/usable, then we scanned all devs,
|
||||||
|
* and we now know which are PVs. Save this list of PVs we've
|
||||||
|
* identified as hints for the next command to use.
|
||||||
|
* (create_hints variable has NEWHINTS_X value which indicates
|
||||||
|
* the reason for creating the new hints.)
|
||||||
|
*/
|
||||||
|
if (create_hints)
|
||||||
|
write_hint_file(cmd, create_hints);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user