summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlasdair Kergon <agk@redhat.com>2010-12-10 22:39:52 +0000
committerAlasdair Kergon <agk@redhat.com>2010-12-10 22:39:52 +0000
commitacb037657cf4ffb5b36e20881bdffd954e6249cf (patch)
treef7189777eb7cc0baa63f7ca30c3cce26fb888147
parent706edf60d564996ea018573e495c5946872d9062 (diff)
downloadlvm2-acb037657cf4ffb5b36e20881bdffd954e6249cf.tar.gz
lvm2-acb037657cf4ffb5b36e20881bdffd954e6249cf.tar.xz
lvm2-acb037657cf4ffb5b36e20881bdffd954e6249cf.zip
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.
-rw-r--r--WHATS_NEW4
-rw-r--r--lib/cache/lvmcache.c23
-rw-r--r--lib/cache/lvmcache.h2
-rw-r--r--lib/commands/toolcontext.c3
-rw-r--r--lib/commands/toolcontext.h2
-rw-r--r--lib/format_text/format-text.c31
-rw-r--r--lib/metadata/metadata.c23
-rw-r--r--lib/metadata/metadata.h2
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.