mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-30 17:18:21 +03:00
lib: avoid reparsing same metadata
When reading VG mda from multiple PVs - do all the validation only when mda is seen for the first time and when mda checksum and length is same just return already existing VG pointer. (i.e. using 300PVs for a VG would lead to create and destroy 300 config trees....)
This commit is contained in:
parent
6a2ae250ff
commit
7e7411966a
@ -1,5 +1,6 @@
|
||||
Version 2.02.118 -
|
||||
=================================
|
||||
Avoid reparsing same metadata when reading same metadata from multiple PVs.
|
||||
Save extra device open/close when scanning device for size.
|
||||
Fix seg_monitor field to report status also for mirrors and thick snapshots.
|
||||
|
||||
|
@ -478,9 +478,15 @@ int override_config_tree_from_profile(struct cmd_context *cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* When skip_parse is set, the checksum of buffer is only matched
|
||||
* and function avoids parsing of mda into config tree which
|
||||
* remains unmodified and should not be used.
|
||||
*/
|
||||
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
|
||||
off_t offset, size_t size, off_t offset2, size_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum)
|
||||
checksum_fn_t checksum_fn, uint32_t checksum,
|
||||
int skip_parse)
|
||||
{
|
||||
char *fb, *fe;
|
||||
int r = 0;
|
||||
@ -529,9 +535,11 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
fe = fb + size + size2;
|
||||
if (!dm_config_parse(cft, fb, fe))
|
||||
goto_out;
|
||||
if (!skip_parse) {
|
||||
fe = fb + size + size2;
|
||||
if (!dm_config_parse(cft, fb, fe))
|
||||
goto_out;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
@ -575,7 +583,7 @@ int config_file_read(struct dm_config_tree *cft)
|
||||
}
|
||||
|
||||
r = config_file_read_fd(cft, cf->dev, 0, (size_t) info.st_size, 0, 0,
|
||||
(checksum_fn_t) NULL, 0);
|
||||
(checksum_fn_t) NULL, 0, 0);
|
||||
|
||||
if (!cf->keep_open) {
|
||||
if (!dev_close(cf->dev))
|
||||
|
@ -205,7 +205,8 @@ typedef uint32_t (*checksum_fn_t) (uint32_t initial, const uint8_t *buf, uint32_
|
||||
struct dm_config_tree *config_open(config_source_t source, const char *filename, int keep_open);
|
||||
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
|
||||
off_t offset, size_t size, off_t offset2, size_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum);
|
||||
checksum_fn_t checksum_fn, uint32_t checksum,
|
||||
int skip_parse);
|
||||
int config_file_read(struct dm_config_tree *cft);
|
||||
struct dm_config_tree *config_file_open_and_read(const char *config_file, config_source_t source,
|
||||
struct cmd_context *cmd);
|
||||
|
@ -51,7 +51,7 @@ const char *text_vgname_import(const struct format_type *fmt,
|
||||
|
||||
if ((!dev && !config_file_read(cft)) ||
|
||||
(dev && !config_file_read_fd(cft, dev, offset, size,
|
||||
offset2, size2, checksum_fn, checksum))) {
|
||||
offset2, size2, checksum_fn, checksum, 0))) {
|
||||
log_error("Couldn't read volume group metadata.");
|
||||
goto out;
|
||||
}
|
||||
@ -88,6 +88,7 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
struct volume_group *vg = NULL;
|
||||
struct dm_config_tree *cft;
|
||||
struct text_vg_version_ops **vsn;
|
||||
int skip_parse;
|
||||
|
||||
_init_text_import();
|
||||
|
||||
@ -97,11 +98,20 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
if (!(cft = config_open(CONFIG_FILE_SPECIAL, file, 0)))
|
||||
return_NULL;
|
||||
|
||||
skip_parse = fid->vg && (fid->mda_checksum == checksum) &&
|
||||
(fid->mda_size == (size + size2));
|
||||
|
||||
if ((!dev && !config_file_read(cft)) ||
|
||||
(dev && !config_file_read_fd(cft, dev, offset, size,
|
||||
offset2, size2, checksum_fn, checksum)))
|
||||
offset2, size2, checksum_fn, checksum,
|
||||
skip_parse)))
|
||||
goto_out;
|
||||
|
||||
if (skip_parse) {
|
||||
vg = fid->vg;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a set of version functions that can read this file
|
||||
*/
|
||||
@ -116,6 +126,16 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
break;
|
||||
}
|
||||
|
||||
if (vg && (!fid->vg || (vg->seqno > fid->vg->seqno))) {
|
||||
/*
|
||||
* Remember vg pointer to newest VG for reuse.
|
||||
* NOTE: _vg_read() will not release same VG
|
||||
*/
|
||||
fid->vg = vg;
|
||||
fid->mda_size = (size + size2);
|
||||
fid->mda_checksum = checksum;
|
||||
}
|
||||
|
||||
out:
|
||||
config_destroy(cft);
|
||||
return vg;
|
||||
|
@ -324,6 +324,11 @@ struct format_instance {
|
||||
struct dm_list metadata_areas_ignored;
|
||||
struct dm_hash_table *metadata_areas_index;
|
||||
|
||||
/* Remember last vg to avoid parsing same mda content for multiple PVs */
|
||||
struct volume_group *vg;
|
||||
uint32_t mda_checksum;
|
||||
size_t mda_size;
|
||||
|
||||
void *private;
|
||||
};
|
||||
|
||||
|
@ -3365,6 +3365,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
if (vg != correct_vg)
|
||||
/* NOTE: tied to fid->vg logic in text_vg_import_fd() */
|
||||
release_vg(vg);
|
||||
}
|
||||
fid->ref_count--;
|
||||
|
Loading…
Reference in New Issue
Block a user