From acb037657cf4ffb5b36e20881bdffd954e6249cf Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Fri, 10 Dec 2010 22:39:52 +0000 Subject: Fix scanning of VGs without in-PV mdas. Set cmd->independent_metadata_areas if metadata/dirs or disk_areas in use. - Identify and record this state. Don't skip full scan when independent mdas are present even if memlock is set. - Clusters and OOM aren't supported, so no problem doing the proper scans. Avoid revalidating the label cache immediately after scanning. - A simple optimisation. Support scanning for a single VG in independent mdas. - Not used by the fix but I left it in anyway as later patches might use it. --- WHATS_NEW | 4 ++++ lib/cache/lvmcache.c | 23 ++++++++++++++++------- lib/cache/lvmcache.h | 2 +- lib/commands/toolcontext.c | 3 +++ lib/commands/toolcontext.h | 2 ++ lib/format_text/format-text.c | 31 +++++++++++++++++++------------ lib/metadata/metadata.c | 23 +++++++++++++---------- lib/metadata/metadata.h | 2 +- 8 files changed, 59 insertions(+), 31 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 2dfaf243..2d23413c 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,9 @@ Version 2.02.79 - =================================== + Avoid revalidating the label cache immediately after scanning. + Support scanning for a single VG in independent mdas. + Don't skip full scan when independent mdas are present even if memlock is set. + Set cmd->independent_metadata_areas if metadata/dirs or disk_areas in use. Cope better with an undefined target_percent operation in _percent_run. Fix write to released memory in vg_release and rename to free_vg. (2.02.78) diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c index ab16536c..d5455631 100644 --- a/lib/cache/lvmcache.c +++ b/lib/cache/lvmcache.c @@ -366,7 +366,7 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid) return vginfo; } -const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid) +const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels) { struct lvmcache_vginfo *vginfo; struct lvmcache_info *info; @@ -379,8 +379,16 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid) if (!(vginfo = vginfo_from_vgname(vgname, vgid))) return NULL; - /* This function is normally called before reading metadata so - * we check cached labels here. Unfortunately vginfo is volatile. */ + /* + * If this function is called repeatedly, only the first one needs to revalidate. + */ + if (!revalidate_labels) + goto out; + + /* + * This function is normally called before reading metadata so + * we check cached labels here. Unfortunately vginfo is volatile. + */ dm_list_init(&devs); dm_list_iterate_items(info, &vginfo->infos) { if (!(devl = dm_malloc(sizeof(*devl)))) { @@ -405,6 +413,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid) strncmp(vginfo->vgid, vgid_found, ID_LEN)) return NULL; +out: return vginfo->fmt; } @@ -588,10 +597,10 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan) _has_scanned = 1; /* Perform any format-specific scanning e.g. text files */ - dm_list_iterate_items(fmt, &cmd->formats) { - if (fmt->ops->scan && !fmt->ops->scan(fmt)) - goto out; - } + if (cmd->independent_metadata_areas) + dm_list_iterate_items(fmt, &cmd->formats) + if (fmt->ops->scan && !fmt->ops->scan(fmt, NULL)) + goto out; /* * If we are a long-lived process, write out the updated persistent diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h index 28f85418..06838dc8 100644 --- a/lib/cache/lvmcache.h +++ b/lib/cache/lvmcache.h @@ -88,7 +88,7 @@ void lvmcache_unlock_vgname(const char *vgname); int lvmcache_verify_lock_order(const char *vgname); /* Queries */ -const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid); +const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels); struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid); struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid); diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index 8dd7d6f8..c59238de 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -1138,6 +1138,7 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived, cmd->is_long_lived = is_long_lived; cmd->handles_missing_pvs = 0; cmd->handles_unknown_segments = 0; + cmd->independent_metadata_areas = 0; cmd->hosttags = 0; dm_list_init(&cmd->arg_value_groups); dm_list_init(&cmd->formats); @@ -1246,6 +1247,8 @@ static void _destroy_formats(struct cmd_context *cmd, struct dm_list *formats) dlclose(lib); #endif } + + cmd->independent_metadata_areas = 0; } static void _destroy_segtypes(struct dm_list *segtypes) diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h index 04fd755c..4628c7c2 100644 --- a/lib/commands/toolcontext.h +++ b/lib/commands/toolcontext.h @@ -78,6 +78,8 @@ struct cmd_context { unsigned si_unit_consistency:1; unsigned metadata_read_only:1; + unsigned independent_metadata_areas:1; /* Active formats have MDAs outside PVs */ + struct dev_filter *filter; int dump_filter; /* Dump filter when exiting? */ diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c index 13a8482d..4828e219 100644 --- a/lib/format_text/format-text.c +++ b/lib/format_text/format-text.c @@ -1045,7 +1045,7 @@ static int _vg_remove_file(struct format_instance *fid __attribute__((unused)), return 1; } -static int _scan_file(const struct format_type *fmt) +static int _scan_file(const struct format_type *fmt, const char *vgname) { struct dirent *dirent; struct dir_list *dl; @@ -1055,7 +1055,7 @@ static int _scan_file(const struct format_type *fmt) struct volume_group *vg; struct format_instance *fid; char path[PATH_MAX]; - char *vgname; + char *scanned_vgname; dir_list = &((struct mda_lists *) fmt->private)->dirs; @@ -1070,18 +1070,23 @@ static int _scan_file(const struct format_type *fmt) (!(tmp = strstr(dirent->d_name, ".tmp")) || tmp != dirent->d_name + strlen(dirent->d_name) - 4)) { - vgname = dirent->d_name; + scanned_vgname = dirent->d_name; + + /* If vgname supplied, only scan that one VG */ + if (vgname && strcmp(vgname, scanned_vgname)) + continue; + if (dm_snprintf(path, PATH_MAX, "%s/%s", - dl->dir, vgname) < 0) { + dl->dir, scanned_vgname) < 0) { log_error("Name too long %s/%s", - dl->dir, vgname); + dl->dir, scanned_vgname); break; } /* FIXME stat file to see if it's changed */ fid = _text_create_text_instance(fmt, NULL, NULL, NULL); - if ((vg = _vg_read_file_name(fid, vgname, + if ((vg = _vg_read_file_name(fid, scanned_vgname, path))) { /* FIXME Store creation host in vg */ lvmcache_update_vg(vg, 0); @@ -1195,11 +1200,11 @@ const char *vgname_from_mda(const struct format_type *fmt, return vgname; } -static int _scan_raw(const struct format_type *fmt) +static int _scan_raw(const struct format_type *fmt, const char *vgname __attribute__((unused))) { struct raw_list *rl; struct dm_list *raw_list; - const char *vgname; + const char *scanned_vgname; struct volume_group *vg; struct format_instance fid; struct id vgid; @@ -1224,10 +1229,10 @@ static int _scan_raw(const struct format_type *fmt) goto close_dev; } - if ((vgname = vgname_from_mda(fmt, mdah, + if ((scanned_vgname = vgname_from_mda(fmt, mdah, &rl->dev_area, &vgid, &vgstatus, NULL, NULL))) { - vg = _vg_read_raw_area(&fid, vgname, &rl->dev_area, 0); + vg = _vg_read_raw_area(&fid, scanned_vgname, &rl->dev_area, 0); if (vg) lvmcache_update_vg(vg, 0); @@ -1240,9 +1245,9 @@ static int _scan_raw(const struct format_type *fmt) return 1; } -static int _text_scan(const struct format_type *fmt) +static int _text_scan(const struct format_type *fmt, const char *vgname) { - return (_scan_file(fmt) & _scan_raw(fmt)); + return (_scan_file(fmt, vgname) & _scan_raw(fmt, vgname)); } /* For orphan, creates new mdas according to policy. @@ -2181,6 +2186,7 @@ struct format_type *create_text_format(struct cmd_context *cmd) "metadata directory list ", cv->v.str); goto err; } + cmd->independent_metadata_areas = 1; } } @@ -2188,6 +2194,7 @@ struct format_type *create_text_format(struct cmd_context *cmd) for (cn = cn->child; cn; cn = cn->sib) { if (!_get_config_disk_area(cmd, cn, &mda_lists->raws)) goto err; + cmd->independent_metadata_areas = 1; } } diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 3b7061c5..ab9cee9c 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -2706,13 +2706,14 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, /* Find the vgname in the cache */ /* If it's not there we must do full scan to be completely sure */ - if (!(fmt = fmt_from_vgname(vgname, vgid))) { + if (!(fmt = fmt_from_vgname(vgname, vgid, 1))) { lvmcache_label_scan(cmd, 0); - if (!(fmt = fmt_from_vgname(vgname, vgid))) { - if (memlock()) + if (!(fmt = fmt_from_vgname(vgname, vgid, 1))) { + /* Independent MDAs aren't supported under low memory */ + if (!cmd->independent_metadata_areas && memlock()) return_NULL; lvmcache_label_scan(cmd, 2); - if (!(fmt = fmt_from_vgname(vgname, vgid))) + if (!(fmt = fmt_from_vgname(vgname, vgid, 0))) return_NULL; } } @@ -2868,10 +2869,11 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, if (!correct_vg) { inconsistent = 0; - if (memlock()) + /* Independent MDAs aren't supported under low memory */ + if (!cmd->independent_metadata_areas && memlock()) return_NULL; lvmcache_label_scan(cmd, 2); - if (!(fmt = fmt_from_vgname(vgname, vgid))) + if (!(fmt = fmt_from_vgname(vgname, vgid, 0))) return_NULL; if (precommitted && !(fmt->features & FMT_PRECOMMIT)) @@ -3795,10 +3797,11 @@ uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname) /* Find the vgname in the cache */ /* If it's not there we must do full scan to be completely sure */ - if (!fmt_from_vgname(vgname, NULL)) { + if (!fmt_from_vgname(vgname, NULL, 1)) { lvmcache_label_scan(cmd, 0); - if (!fmt_from_vgname(vgname, NULL)) { - if (memlock()) { + if (!fmt_from_vgname(vgname, NULL, 1)) { + /* Independent MDAs aren't supported under low memory */ + if (!cmd->independent_metadata_areas && memlock()) { /* * FIXME: Disallow calling this function if * memlock() is true. @@ -3807,7 +3810,7 @@ uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname) return FAILED_LOCKING; } lvmcache_label_scan(cmd, 2); - if (!fmt_from_vgname(vgname, NULL)) { + if (!fmt_from_vgname(vgname, NULL, 0)) { /* vgname not found after scanning */ return SUCCESS; } diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index 5aa9c193..6ed467ed 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -227,7 +227,7 @@ struct format_handler { /* * Scan any metadata areas that aren't referenced in PV labels */ - int (*scan) (const struct format_type * fmt); + int (*scan) (const struct format_type * fmt, const char *vgname); /* * Return PV with given path. -- cgit