summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2017-11-06 12:09:52 -0600
committerDavid Teigland <teigland@redhat.com>2017-11-09 15:29:32 -0600
commita3e311e58a22e4db60e67cb4bcfd36e7b594f691 (patch)
tree577bfb051d79a5548082984a42f866b8c0df3060
parentdea1829dc07ea8c34fec977ee820c5bc61dc719e (diff)
downloadlvm2-a3e311e58a22e4db60e67cb4bcfd36e7b594f691.tar.gz
label_scan: remove extra label scan and read for orphan PVs
When process_each_pv() calls vg_read() on the orphan VG, the internal implementation was doing an unnecessary lvmcache_label_scan() and two unnecessary label_read() calls on each orphan. Some of those unnecessary label scans/reads would sometimes be skipped due to caching, but the code was always doing at least one unnecessary read on each orphan. The common format_text case was also unecessarily calling into the format-specific pv_read() function which actually did nothing. By analyzing each case in which vg_read() was being called on the orphan VG, we can say that all of the label scans/reads in vg_read_orphans are unnecessary: 1. reporting commands: the information saved in lvmcache by the original label scan can be reported. There is no advantage to repeating the label scan on the orphans a second time before reporting it. 2. pvcreate/vgcreate/vgextend: these all share a common implementation in pvcreate_each_device(). That function already rescans labels after acquiring the orphan VG lock, which ensures that the command is using valid lvmcache information.
-rw-r--r--lib/cache/lvmcache.c51
-rw-r--r--lib/cache/lvmcache.h4
-rw-r--r--lib/format_text/format-text.c31
-rw-r--r--lib/metadata/metadata.c150
-rw-r--r--lib/metadata/metadata.h6
5 files changed, 54 insertions, 188 deletions
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 8253fd237..d536311b9 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -2459,56 +2459,29 @@ int lvmcache_fid_add_mdas_vg(struct lvmcache_vginfo *vginfo, struct format_insta
return 1;
}
-static int _get_pv_if_in_vg(struct lvmcache_info *info,
- struct physical_volume *pv)
-{
- char vgname[NAME_LEN + 1];
- char vgid[ID_LEN + 1];
-
- if (info->vginfo && info->vginfo->vgname &&
- !is_orphan_vg(info->vginfo->vgname)) {
- /*
- * get_pv_from_vg_by_id() may call
- * lvmcache_label_scan() and drop cached
- * vginfo so make a local copy of string.
- */
- (void) dm_strncpy(vgname, info->vginfo->vgname, sizeof(vgname));
- memcpy(vgid, info->vginfo->vgid, sizeof(vgid));
-
- if (get_pv_from_vg_by_id(info->fmt, vgname, vgid,
- info->dev->pvid, pv))
- return 1;
- }
-
- return 0;
-}
-
int lvmcache_populate_pv_fields(struct lvmcache_info *info,
- struct physical_volume *pv,
- int scan_label_only)
+ struct volume_group *vg,
+ struct physical_volume *pv)
{
struct data_area_list *da;
-
- /* Have we already cached vgname? */
- if (!scan_label_only && _get_pv_if_in_vg(info, pv))
- return 1;
-
- /* Perform full scan (just the first time) and try again */
- if (!scan_label_only && !critical_section() && !full_scan_done()) {
- lvmcache_force_next_label_scan();
- lvmcache_label_scan(info->fmt->cmd);
-
- if (_get_pv_if_in_vg(info, pv))
- return 1;
+
+ if (!info->label) {
+ log_error("No cached label for orphan PV %s", pv_dev_name(pv));
+ return 0;
}
- /* Orphan */
+ pv->label_sector = info->label->sector;
pv->dev = info->dev;
pv->fmt = info->fmt;
pv->size = info->device_size >> SECTOR_SHIFT;
pv->vg_name = FMT_TEXT_ORPHAN_VG_NAME;
memcpy(&pv->id, &info->dev->pvid, sizeof(pv->id));
+ if (!pv->size) {
+ log_error("PV %s size is zero.", dev_name(info->dev));
+ return 0;
+ }
+
/* Currently only support exactly one data area */
if (dm_list_size(&info->das) != 1) {
log_error("Must be exactly one data area (found %d) on PV %s",
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index abdea30b2..676071f5c 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -145,8 +145,8 @@ int lvmcache_fid_add_mdas(struct lvmcache_info *info, struct format_instance *fi
int lvmcache_fid_add_mdas_pv(struct lvmcache_info *info, struct format_instance *fid);
int lvmcache_fid_add_mdas_vg(struct lvmcache_vginfo *vginfo, struct format_instance *fid);
int lvmcache_populate_pv_fields(struct lvmcache_info *info,
- struct physical_volume *pv,
- int scan_label_only);
+ struct volume_group *vg,
+ struct physical_volume *pv);
int lvmcache_check_format(struct lvmcache_info *info, const struct format_type *fmt);
void lvmcache_del_mdas(struct lvmcache_info *info);
void lvmcache_del_das(struct lvmcache_info *info);
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index ced056237..c6422dfb3 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1600,36 +1600,6 @@ static uint64_t _metadata_locn_offset_raw(void *metadata_locn)
return mdac->area.start;
}
-static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
- struct physical_volume *pv, int scan_label_only)
-{
- struct lvmcache_info *info;
- struct device *dev;
-
- if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
- return_0;
-
- if (lvmetad_used()) {
- info = lvmcache_info_from_pvid(dev->pvid, dev, 0);
- if (!info && !lvmetad_pv_lookup_by_dev(fmt->cmd, dev, NULL))
- return 0;
- info = lvmcache_info_from_pvid(dev->pvid, dev, 0);
- } else {
- struct label *label;
- if (!(label_read(dev, &label, UINT64_C(0))))
- return_0;
- info = label->info;
- }
-
- if (!info)
- return_0;
-
- if (!lvmcache_populate_pv_fields(info, pv, scan_label_only))
- return 0;
-
- return 1;
-}
-
static int _text_pv_initialise(const struct format_type *fmt,
struct pv_create_args *pva,
struct physical_volume *pv)
@@ -2478,7 +2448,6 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
static struct format_handler _text_handler = {
.scan = _text_scan,
- .pv_read = _text_pv_read,
.pv_initialise = _text_pv_initialise,
.pv_setup = _text_pv_setup,
.pv_add_metadata_area = _text_pv_add_metadata_area,
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index ff22277fc..5ef3a48b6 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -40,10 +40,9 @@
#include <sys/param.h>
static struct physical_volume *_pv_read(struct cmd_context *cmd,
- struct dm_pool *pvmem,
- const char *pv_name,
- struct format_instance *fid,
- uint32_t warn_flags, int scan_label_only);
+ const struct format_type *fmt,
+ struct volume_group *vg,
+ struct lvmcache_info *info);
static int _alignment_overrides_default(unsigned long data_alignment,
unsigned long default_pe_align)
@@ -332,37 +331,6 @@ bad:
return NULL;
}
-int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
- const char *vgid, const char *pvid,
- struct physical_volume *pv)
-{
- struct volume_group *vg;
- struct pv_list *pvl;
- uint32_t warn_flags = WARN_PV_READ | WARN_INCONSISTENT;
- int r = 0, consistent = 0;
-
- if (!(vg = vg_read_internal(fmt->cmd, vg_name, vgid, warn_flags, &consistent))) {
- log_error("get_pv_from_vg_by_id: vg_read_internal failed to read VG %s",
- vg_name);
- return 0;
- }
-
- dm_list_iterate_items(pvl, &vg->pvs) {
- if (id_equal(&pvl->pv->id, (const struct id *) pvid)) {
- if (!_copy_pv(fmt->cmd->mem, pv, pvl->pv)) {
- log_error("internal PV duplication failed");
- r = 0;
- goto out;
- }
- r = 1;
- goto out;
- }
- }
-out:
- release_vg(vg);
- return r;
-}
-
static int _move_pv(struct volume_group *vg_from, struct volume_group *vg_to,
const char *pv_name, int enforce_pv_from_source)
{
@@ -3254,9 +3222,7 @@ static int _check_mda_in_use(struct metadata_area *mda, void *_in_use)
struct _vg_read_orphan_baton {
struct cmd_context *cmd;
struct volume_group *vg;
- uint32_t warn_flags;
- int consistent;
- int repair;
+ const struct format_type *fmt;
};
/*
@@ -3353,8 +3319,7 @@ static int _vg_read_orphan_pv(struct lvmcache_info *info, void *baton)
uint32_t ext_version;
uint32_t ext_flags;
- if (!(pv = _pv_read(b->vg->cmd, b->vg->vgmem, dev_name(lvmcache_device(info)),
- b->vg->fid, b->warn_flags, 0))) {
+ if (!(pv = _pv_read(b->cmd, b->fmt, b->vg, info))) {
stack;
return 1;
}
@@ -3461,10 +3426,22 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
vg->free_count = 0;
baton.cmd = cmd;
- baton.warn_flags = warn_flags;
+ baton.fmt = fmt;
baton.vg = vg;
- baton.consistent = 1;
- baton.repair = *consistent;
+
+ /*
+ * vg_read for a normal VG will rescan labels for all the devices
+ * in the VG, in case something changed on disk between the initial
+ * label scan and acquiring the VG lock. We don't rescan labels
+ * here because this is only called in two ways:
+ *
+ * 1. for reporting, in which case it doesn't matter if something
+ * changed between the label scan and printing the PVs here
+ *
+ * 2. pvcreate_each_device() for pvcreate//vgcreate/vgextend,
+ * which already does the label rescan after taking the
+ * orphan lock.
+ */
while ((pvl = (struct pv_list *) dm_list_first(&head.list))) {
dm_list_del(&pvl->list);
@@ -3476,7 +3453,6 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
if (!lvmcache_foreach_pv(vginfo, _vg_read_orphan_pv, &baton))
return_NULL;
- *consistent = baton.consistent;
return vg;
}
@@ -4689,86 +4665,40 @@ const char *find_vgname_from_pvname(struct cmd_context *cmd,
return find_vgname_from_pvid(cmd, pvid);
}
-/* FIXME Use label functions instead of PV functions */
static struct physical_volume *_pv_read(struct cmd_context *cmd,
- struct dm_pool *pvmem,
- const char *pv_name,
- struct format_instance *fid,
- uint32_t warn_flags, int scan_label_only)
+ const struct format_type *fmt,
+ struct volume_group *vg,
+ struct lvmcache_info *info)
{
struct physical_volume *pv;
- struct label *label;
- struct lvmcache_info *info;
- struct device *dev;
- const struct format_type *fmt;
- int found;
-
- if (!(dev = dev_cache_get(pv_name, cmd->filter)))
- return_NULL;
-
- if (lvmetad_used()) {
- info = lvmcache_info_from_pvid(dev->pvid, dev, 0);
- if (!info) {
- if (!lvmetad_pv_lookup_by_dev(cmd, dev, &found))
- return_NULL;
- if (!found) {
- if (warn_flags & WARN_PV_READ)
- log_error("No physical volume found in lvmetad cache for %s",
- pv_name);
- return NULL;
- }
- if (!(info = lvmcache_info_from_pvid(dev->pvid, dev, 0))) {
- if (warn_flags & WARN_PV_READ)
- log_error("No cache info in lvmetad cache for %s.",
- pv_name);
- return NULL;
- }
- }
- label = lvmcache_get_label(info);
- } else {
- if (!(label_read(dev, &label, UINT64_C(0)))) {
- if (warn_flags & WARN_PV_READ)
- log_error("No physical volume label read from %s",
- pv_name);
- return NULL;
- }
- info = (struct lvmcache_info *) label->info;
- }
+ struct device *dev = lvmcache_device(info);
- fmt = lvmcache_fmt(info);
-
- pv = _alloc_pv(pvmem, dev);
- if (!pv) {
- log_error("pv allocation for '%s' failed", pv_name);
+ if (!(pv = _alloc_pv(vg->vgmem, NULL))) {
+ log_error("pv allocation failed");
return NULL;
}
- pv->label_sector = label->sector;
-
- /* FIXME Move more common code up here */
- if (!(lvmcache_fmt(info)->ops->pv_read(lvmcache_fmt(info), pv_name, pv, scan_label_only))) {
- log_error("Failed to read existing physical volume '%s'",
- pv_name);
- goto bad;
+ if (fmt->ops->pv_read) {
+ /* format1 and pool */
+ if (!(fmt->ops->pv_read(fmt, dev_name(dev), pv, 0))) {
+ log_error("Failed to read existing physical volume '%s'", dev_name(dev));
+ goto bad;
+ }
+ } else {
+ /* format text */
+ if (!lvmcache_populate_pv_fields(info, vg, pv))
+ goto_bad;
}
- if (!pv->size)
- goto bad;
-
- if (!alloc_pv_segment_whole_pv(pvmem, pv))
+ if (!alloc_pv_segment_whole_pv(vg->vgmem, pv))
goto_bad;
- if (fid)
- lvmcache_fid_add_mdas(info, fid, (const char *) &pv->id, ID_LEN);
- else {
- lvmcache_fid_add_mdas(info, fmt->orphan_vg->fid, (const char *) &pv->id, ID_LEN);
- pv_set_fid(pv, fmt->orphan_vg->fid);
- }
-
+ lvmcache_fid_add_mdas(info, vg->fid, (const char *) &pv->id, ID_LEN);
+ pv_set_fid(pv, vg->fid);
return pv;
bad:
free_pv_fid(pv);
- dm_pool_free(pvmem, pv);
+ dm_pool_free(vg->vgmem, pv);
return NULL;
}
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 145d0428a..94fb04a6c 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -368,12 +368,6 @@ uint32_t vg_bad_status_bits(const struct volume_group *vg, uint64_t status);
int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
struct physical_volume *pv, int new_pv);
-
-/* Find a PV within a given VG */
-int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
- const char *vgid, const char *pvid,
- struct physical_volume *pv);
-
struct logical_volume *find_lv_in_vg_by_lvid(struct volume_group *vg,
const union lvid *lvid);