mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-02 01:18:26 +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 -
|
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.
|
Save extra device open/close when scanning device for size.
|
||||||
Fix seg_monitor field to report status also for mirrors and thick snapshots.
|
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;
|
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,
|
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,
|
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;
|
char *fb, *fe;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
@ -529,9 +535,11 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
fe = fb + size + size2;
|
if (!skip_parse) {
|
||||||
if (!dm_config_parse(cft, fb, fe))
|
fe = fb + size + size2;
|
||||||
goto_out;
|
if (!dm_config_parse(cft, fb, fe))
|
||||||
|
goto_out;
|
||||||
|
}
|
||||||
|
|
||||||
r = 1;
|
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,
|
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 (!cf->keep_open) {
|
||||||
if (!dev_close(cf->dev))
|
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);
|
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,
|
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,
|
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);
|
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 dm_config_tree *config_file_open_and_read(const char *config_file, config_source_t source,
|
||||||
struct cmd_context *cmd);
|
struct cmd_context *cmd);
|
||||||
|
@ -51,7 +51,7 @@ const char *text_vgname_import(const struct format_type *fmt,
|
|||||||
|
|
||||||
if ((!dev && !config_file_read(cft)) ||
|
if ((!dev && !config_file_read(cft)) ||
|
||||||
(dev && !config_file_read_fd(cft, dev, offset, size,
|
(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.");
|
log_error("Couldn't read volume group metadata.");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -88,6 +88,7 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
|||||||
struct volume_group *vg = NULL;
|
struct volume_group *vg = NULL;
|
||||||
struct dm_config_tree *cft;
|
struct dm_config_tree *cft;
|
||||||
struct text_vg_version_ops **vsn;
|
struct text_vg_version_ops **vsn;
|
||||||
|
int skip_parse;
|
||||||
|
|
||||||
_init_text_import();
|
_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)))
|
if (!(cft = config_open(CONFIG_FILE_SPECIAL, file, 0)))
|
||||||
return_NULL;
|
return_NULL;
|
||||||
|
|
||||||
|
skip_parse = fid->vg && (fid->mda_checksum == checksum) &&
|
||||||
|
(fid->mda_size == (size + size2));
|
||||||
|
|
||||||
if ((!dev && !config_file_read(cft)) ||
|
if ((!dev && !config_file_read(cft)) ||
|
||||||
(dev && !config_file_read_fd(cft, dev, offset, size,
|
(dev && !config_file_read_fd(cft, dev, offset, size,
|
||||||
offset2, size2, checksum_fn, checksum)))
|
offset2, size2, checksum_fn, checksum,
|
||||||
|
skip_parse)))
|
||||||
goto_out;
|
goto_out;
|
||||||
|
|
||||||
|
if (skip_parse) {
|
||||||
|
vg = fid->vg;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a set of version functions that can read this file
|
* 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;
|
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:
|
out:
|
||||||
config_destroy(cft);
|
config_destroy(cft);
|
||||||
return vg;
|
return vg;
|
||||||
|
@ -324,6 +324,11 @@ struct format_instance {
|
|||||||
struct dm_list metadata_areas_ignored;
|
struct dm_list metadata_areas_ignored;
|
||||||
struct dm_hash_table *metadata_areas_index;
|
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;
|
void *private;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3365,6 +3365,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vg != correct_vg)
|
if (vg != correct_vg)
|
||||||
|
/* NOTE: tied to fid->vg logic in text_vg_import_fd() */
|
||||||
release_vg(vg);
|
release_vg(vg);
|
||||||
}
|
}
|
||||||
fid->ref_count--;
|
fid->ref_count--;
|
||||||
|
Loading…
Reference in New Issue
Block a user