diff options
author | David Teigland <teigland@redhat.com> | 2017-11-06 12:09:52 -0600 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2017-11-09 15:29:32 -0600 |
commit | a3e311e58a22e4db60e67cb4bcfd36e7b594f691 (patch) | |
tree | 577bfb051d79a5548082984a42f866b8c0df3060 | |
parent | dea1829dc07ea8c34fec977ee820c5bc61dc719e (diff) | |
download | lvm2-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.c | 51 | ||||
-rw-r--r-- | lib/cache/lvmcache.h | 4 | ||||
-rw-r--r-- | lib/format_text/format-text.c | 31 | ||||
-rw-r--r-- | lib/metadata/metadata.c | 150 | ||||
-rw-r--r-- | lib/metadata/metadata.h | 6 |
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); |