mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Cache VG metadata internally while VG lock is held.
This commit is contained in:
parent
33842916b0
commit
6e210a6c54
@ -1,5 +1,6 @@
|
||||
Version 2.02.34 -
|
||||
===================================
|
||||
Cache VG metadata internally while VG lock is held.
|
||||
Fix redundant lvresize message if vg doesn't exist.
|
||||
Fix another allocation bug with clvmd and large node IDs.
|
||||
Add find_lv_in_lv_list() and find_pv_in_pv_list().
|
||||
|
105
lib/cache/lvmcache.c
vendored
105
lib/cache/lvmcache.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -49,15 +49,53 @@ int lvmcache_init(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _update_cache_info_lock_state(struct lvmcache_info *info, int locked)
|
||||
/* Volume Group metadata cache functions */
|
||||
static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
if (!vginfo || !vginfo->vgmetadata)
|
||||
return;
|
||||
|
||||
dm_free(vginfo->vgmetadata);
|
||||
|
||||
vginfo->vgmetadata = NULL;
|
||||
vginfo->fid = NULL;
|
||||
|
||||
log_debug("Metadata cache: VG %s wiped.", vginfo->vgname);
|
||||
}
|
||||
|
||||
static void _store_metadata(struct lvmcache_vginfo *vginfo,
|
||||
struct volume_group *vg, unsigned precommitted)
|
||||
{
|
||||
int size;
|
||||
|
||||
if (vginfo->vgmetadata)
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
|
||||
if (!(size = export_vg_to_buffer(vg, &vginfo->vgmetadata))) {
|
||||
stack;
|
||||
return;
|
||||
}
|
||||
|
||||
vginfo->fid = vg->fid;
|
||||
vginfo->precommitted = precommitted;
|
||||
|
||||
log_debug("Metadata cache: VG %s stored (%d bytes%s).", vginfo->vgname,
|
||||
size, precommitted ? ", precommitted" : "");
|
||||
}
|
||||
|
||||
static void _update_cache_info_lock_state(struct lvmcache_info *info,
|
||||
int locked,
|
||||
int *cached_vgmetadata_valid)
|
||||
{
|
||||
int was_locked = (info->status & CACHE_LOCKED) ? 1 : 0;
|
||||
|
||||
/*
|
||||
* Cache becomes invalid whenever lock state changes
|
||||
*/
|
||||
if (was_locked != locked)
|
||||
if (was_locked != locked) {
|
||||
info->status |= CACHE_INVALID;
|
||||
*cached_vgmetadata_valid = 0;
|
||||
}
|
||||
|
||||
if (locked)
|
||||
info->status |= CACHE_LOCKED;
|
||||
@ -69,9 +107,14 @@ static void _update_cache_vginfo_lock_state(struct lvmcache_vginfo *vginfo,
|
||||
int locked)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
int cached_vgmetadata_valid = 1;
|
||||
|
||||
list_iterate_items(info, &vginfo->infos)
|
||||
_update_cache_info_lock_state(info, locked);
|
||||
_update_cache_info_lock_state(info, locked,
|
||||
&cached_vgmetadata_valid);
|
||||
|
||||
if (!cached_vgmetadata_valid)
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
}
|
||||
|
||||
static void _update_cache_lock_state(const char *vgname, int locked)
|
||||
@ -238,6 +281,17 @@ static int _info_is_valid(struct lvmcache_info *info)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _vginfo_is_valid(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
|
||||
list_iterate_items(info, &vginfo->infos)
|
||||
if (!_info_is_valid(info))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If valid_only is set, data will only be returned if the cached data is
|
||||
* known still to be valid.
|
||||
@ -329,6 +383,32 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
||||
return r;
|
||||
}
|
||||
|
||||
struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct volume_group *vg;
|
||||
|
||||
if (!vgid || !(vginfo = vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
|
||||
return NULL;
|
||||
|
||||
if (!_vginfo_is_valid(vginfo))
|
||||
return NULL;
|
||||
|
||||
if ((precommitted && !vginfo->precommitted) ||
|
||||
(!precommitted && vginfo->precommitted))
|
||||
return NULL;
|
||||
|
||||
if (!(vg = import_vg_from_buffer(vginfo->vgmetadata, vginfo->fid)) ||
|
||||
!vg_validate(vg)) {
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
log_debug("Using cached metadata for VG %s.", vginfo->vgname);
|
||||
|
||||
return vg;
|
||||
}
|
||||
|
||||
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
|
||||
{
|
||||
struct list *vgids;
|
||||
@ -490,20 +570,6 @@ void lvmcache_del(struct lvmcache_info *info)
|
||||
return;
|
||||
} */
|
||||
|
||||
int lvmcache_store_vg(struct lvmcache_vginfo *vginfo, struct volume_group *vg,
|
||||
unsigned precommitted)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void lvmcache_drop_vg(const char *vgname)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
|
||||
return;
|
||||
}
|
||||
|
||||
static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
|
||||
{
|
||||
if (!strcmp(info->dev->pvid, pvid))
|
||||
@ -803,7 +869,7 @@ int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
|
||||
|
||||
/* store text representation of vg to cache */
|
||||
if ((vginfo = vginfo_from_vgname(vg->name, NULL)))
|
||||
lvmcache_store_vg(vginfo, vg, precommitted);
|
||||
_store_metadata(vginfo, vg, precommitted);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -935,6 +1001,7 @@ static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
|
||||
dm_free(vginfo->vgname);
|
||||
if (vginfo->creation_host)
|
||||
dm_free(vginfo->creation_host);
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
dm_free(vginfo);
|
||||
} while ((vginfo = next));
|
||||
}
|
||||
|
3
lib/cache/lvmcache.h
vendored
3
lib/cache/lvmcache.h
vendored
@ -109,4 +109,7 @@ struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan);
|
||||
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||
const char *vgid);
|
||||
|
||||
/* Returns cached volume group metadata. */
|
||||
struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted);
|
||||
|
||||
#endif
|
||||
|
@ -742,5 +742,10 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf)
|
||||
return r;
|
||||
}
|
||||
|
||||
int export_vg_to_buffer(struct volume_group *vg, char **buf)
|
||||
{
|
||||
return text_vg_export_raw(vg, "", buf);
|
||||
}
|
||||
|
||||
#undef outf
|
||||
#undef outnl
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -130,3 +130,27 @@ struct volume_group *text_vg_import_file(struct format_instance *fid,
|
||||
return text_vg_import_fd(fid, file, NULL, (off_t)0, 0, (off_t)0, 0, NULL, 0,
|
||||
when, desc);
|
||||
}
|
||||
|
||||
struct volume_group *import_vg_from_buffer(char *buf,
|
||||
struct format_instance *fid)
|
||||
{
|
||||
struct volume_group *vg = NULL;
|
||||
struct config_tree *cft;
|
||||
struct text_vg_version_ops **vsn;
|
||||
|
||||
_init_text_import();
|
||||
|
||||
if (!(cft = create_config_tree_from_string(fid->fmt->cmd, buf)))
|
||||
return_NULL;
|
||||
|
||||
for (vsn = &_text_vsn_list[0]; *vsn; vsn++) {
|
||||
if (!(*vsn)->check_version(cft))
|
||||
continue;
|
||||
if (!(vg = (*vsn)->read_vg(fid, cft)))
|
||||
stack;
|
||||
break;
|
||||
}
|
||||
|
||||
destroy_config_tree(cft);
|
||||
return vg;
|
||||
}
|
||||
|
@ -1316,9 +1316,6 @@ int vg_commit(struct volume_group *vg)
|
||||
int cache_updated = 0;
|
||||
int failed = 0;
|
||||
|
||||
/* Forget all cached instances of vg and force reread */
|
||||
lvmcache_drop_vg(vg->name);
|
||||
|
||||
/* Commit to each copy of the metadata area */
|
||||
list_iterate_items(mda, &vg->fid->metadata_areas) {
|
||||
failed = 0;
|
||||
@ -1455,6 +1452,11 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
return _vg_read_orphans(cmd, vgname);
|
||||
}
|
||||
|
||||
if ((correct_vg = lvmcache_get_vg(vgid, precommitted))) {
|
||||
*consistent = 1;
|
||||
return correct_vg;
|
||||
}
|
||||
|
||||
/* 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))) {
|
||||
|
@ -312,6 +312,13 @@ int add_seg_to_segs_using_this_lv(struct logical_volume *lv, struct lv_segment *
|
||||
int remove_seg_from_segs_using_this_lv(struct logical_volume *lv, struct lv_segment *seg);
|
||||
struct lv_segment *get_only_segment_using_this_lv(struct logical_volume *lv);
|
||||
|
||||
/*
|
||||
* For internal metadata caching.
|
||||
*/
|
||||
int export_vg_to_buffer(struct volume_group *vg, char **buf);
|
||||
struct volume_group *import_vg_from_buffer(char *buf,
|
||||
struct format_instance *fid);
|
||||
|
||||
/*
|
||||
* Mirroring functions
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user