1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-18 10:04:20 +03:00

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.
This commit is contained in:
Alasdair Kergon 2010-12-10 22:39:52 +00:00
parent 706edf60d5
commit acb037657c
8 changed files with 59 additions and 31 deletions

View File

@ -1,5 +1,9 @@
Version 2.02.79 - 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. 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) Fix write to released memory in vg_release and rename to free_vg. (2.02.78)

23
lib/cache/lvmcache.c vendored
View File

@ -366,7 +366,7 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
return vginfo; 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_vginfo *vginfo;
struct lvmcache_info *info; 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))) if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
return NULL; 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_init(&devs);
dm_list_iterate_items(info, &vginfo->infos) { dm_list_iterate_items(info, &vginfo->infos) {
if (!(devl = dm_malloc(sizeof(*devl)))) { 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)) strncmp(vginfo->vgid, vgid_found, ID_LEN))
return NULL; return NULL;
out:
return vginfo->fmt; return vginfo->fmt;
} }
@ -588,10 +597,10 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
_has_scanned = 1; _has_scanned = 1;
/* Perform any format-specific scanning e.g. text files */ /* Perform any format-specific scanning e.g. text files */
dm_list_iterate_items(fmt, &cmd->formats) { if (cmd->independent_metadata_areas)
if (fmt->ops->scan && !fmt->ops->scan(fmt)) dm_list_iterate_items(fmt, &cmd->formats)
goto out; if (fmt->ops->scan && !fmt->ops->scan(fmt, NULL))
} goto out;
/* /*
* If we are a long-lived process, write out the updated persistent * If we are a long-lived process, write out the updated persistent

View File

@ -88,7 +88,7 @@ void lvmcache_unlock_vgname(const char *vgname);
int lvmcache_verify_lock_order(const char *vgname); int lvmcache_verify_lock_order(const char *vgname);
/* Queries */ /* 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, struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
const char *vgid); const char *vgid);
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid); struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);

View File

@ -1138,6 +1138,7 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
cmd->is_long_lived = is_long_lived; cmd->is_long_lived = is_long_lived;
cmd->handles_missing_pvs = 0; cmd->handles_missing_pvs = 0;
cmd->handles_unknown_segments = 0; cmd->handles_unknown_segments = 0;
cmd->independent_metadata_areas = 0;
cmd->hosttags = 0; cmd->hosttags = 0;
dm_list_init(&cmd->arg_value_groups); dm_list_init(&cmd->arg_value_groups);
dm_list_init(&cmd->formats); dm_list_init(&cmd->formats);
@ -1246,6 +1247,8 @@ static void _destroy_formats(struct cmd_context *cmd, struct dm_list *formats)
dlclose(lib); dlclose(lib);
#endif #endif
} }
cmd->independent_metadata_areas = 0;
} }
static void _destroy_segtypes(struct dm_list *segtypes) static void _destroy_segtypes(struct dm_list *segtypes)

View File

@ -78,6 +78,8 @@ struct cmd_context {
unsigned si_unit_consistency:1; unsigned si_unit_consistency:1;
unsigned metadata_read_only:1; unsigned metadata_read_only:1;
unsigned independent_metadata_areas:1; /* Active formats have MDAs outside PVs */
struct dev_filter *filter; struct dev_filter *filter;
int dump_filter; /* Dump filter when exiting? */ int dump_filter; /* Dump filter when exiting? */

View File

@ -1045,7 +1045,7 @@ static int _vg_remove_file(struct format_instance *fid __attribute__((unused)),
return 1; 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 dirent *dirent;
struct dir_list *dl; struct dir_list *dl;
@ -1055,7 +1055,7 @@ static int _scan_file(const struct format_type *fmt)
struct volume_group *vg; struct volume_group *vg;
struct format_instance *fid; struct format_instance *fid;
char path[PATH_MAX]; char path[PATH_MAX];
char *vgname; char *scanned_vgname;
dir_list = &((struct mda_lists *) fmt->private)->dirs; 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 = strstr(dirent->d_name, ".tmp")) ||
tmp != dirent->d_name + strlen(dirent->d_name) tmp != dirent->d_name + strlen(dirent->d_name)
- 4)) { - 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", if (dm_snprintf(path, PATH_MAX, "%s/%s",
dl->dir, vgname) < 0) { dl->dir, scanned_vgname) < 0) {
log_error("Name too long %s/%s", log_error("Name too long %s/%s",
dl->dir, vgname); dl->dir, scanned_vgname);
break; break;
} }
/* FIXME stat file to see if it's changed */ /* FIXME stat file to see if it's changed */
fid = _text_create_text_instance(fmt, NULL, NULL, fid = _text_create_text_instance(fmt, NULL, NULL,
NULL); NULL);
if ((vg = _vg_read_file_name(fid, vgname, if ((vg = _vg_read_file_name(fid, scanned_vgname,
path))) { path))) {
/* FIXME Store creation host in vg */ /* FIXME Store creation host in vg */
lvmcache_update_vg(vg, 0); lvmcache_update_vg(vg, 0);
@ -1195,11 +1200,11 @@ const char *vgname_from_mda(const struct format_type *fmt,
return vgname; 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 raw_list *rl;
struct dm_list *raw_list; struct dm_list *raw_list;
const char *vgname; const char *scanned_vgname;
struct volume_group *vg; struct volume_group *vg;
struct format_instance fid; struct format_instance fid;
struct id vgid; struct id vgid;
@ -1224,10 +1229,10 @@ static int _scan_raw(const struct format_type *fmt)
goto close_dev; goto close_dev;
} }
if ((vgname = vgname_from_mda(fmt, mdah, if ((scanned_vgname = vgname_from_mda(fmt, mdah,
&rl->dev_area, &vgid, &vgstatus, &rl->dev_area, &vgid, &vgstatus,
NULL, NULL))) { 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) if (vg)
lvmcache_update_vg(vg, 0); lvmcache_update_vg(vg, 0);
@ -1240,9 +1245,9 @@ static int _scan_raw(const struct format_type *fmt)
return 1; 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. /* 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); "metadata directory list ", cv->v.str);
goto err; 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) { for (cn = cn->child; cn; cn = cn->sib) {
if (!_get_config_disk_area(cmd, cn, &mda_lists->raws)) if (!_get_config_disk_area(cmd, cn, &mda_lists->raws))
goto err; goto err;
cmd->independent_metadata_areas = 1;
} }
} }

View File

@ -2706,13 +2706,14 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
/* Find the vgname in the cache */ /* Find the vgname in the cache */
/* If it's not there we must do full scan to be completely sure */ /* 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); lvmcache_label_scan(cmd, 0);
if (!(fmt = fmt_from_vgname(vgname, vgid))) { if (!(fmt = fmt_from_vgname(vgname, vgid, 1))) {
if (memlock()) /* Independent MDAs aren't supported under low memory */
if (!cmd->independent_metadata_areas && memlock())
return_NULL; return_NULL;
lvmcache_label_scan(cmd, 2); lvmcache_label_scan(cmd, 2);
if (!(fmt = fmt_from_vgname(vgname, vgid))) if (!(fmt = fmt_from_vgname(vgname, vgid, 0)))
return_NULL; return_NULL;
} }
} }
@ -2868,10 +2869,11 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
if (!correct_vg) { if (!correct_vg) {
inconsistent = 0; inconsistent = 0;
if (memlock()) /* Independent MDAs aren't supported under low memory */
if (!cmd->independent_metadata_areas && memlock())
return_NULL; return_NULL;
lvmcache_label_scan(cmd, 2); lvmcache_label_scan(cmd, 2);
if (!(fmt = fmt_from_vgname(vgname, vgid))) if (!(fmt = fmt_from_vgname(vgname, vgid, 0)))
return_NULL; return_NULL;
if (precommitted && !(fmt->features & FMT_PRECOMMIT)) 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 */ /* Find the vgname in the cache */
/* If it's not there we must do full scan to be completely sure */ /* 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); lvmcache_label_scan(cmd, 0);
if (!fmt_from_vgname(vgname, NULL)) { if (!fmt_from_vgname(vgname, NULL, 1)) {
if (memlock()) { /* Independent MDAs aren't supported under low memory */
if (!cmd->independent_metadata_areas && memlock()) {
/* /*
* FIXME: Disallow calling this function if * FIXME: Disallow calling this function if
* memlock() is true. * memlock() is true.
@ -3807,7 +3810,7 @@ uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname)
return FAILED_LOCKING; return FAILED_LOCKING;
} }
lvmcache_label_scan(cmd, 2); lvmcache_label_scan(cmd, 2);
if (!fmt_from_vgname(vgname, NULL)) { if (!fmt_from_vgname(vgname, NULL, 0)) {
/* vgname not found after scanning */ /* vgname not found after scanning */
return SUCCESS; return SUCCESS;
} }

View File

@ -227,7 +227,7 @@ struct format_handler {
/* /*
* Scan any metadata areas that aren't referenced in PV labels * 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. * Return PV with given path.