1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-02 01:18:26 +03:00

Move lvmcache data structures behind an API (making the structures private to

lvmcache.c). No functional change.
This commit is contained in:
Petr Rockai 2012-02-10 01:28:27 +00:00
parent 5fa417a9c0
commit 8e5f7cf3dc
18 changed files with 891 additions and 518 deletions

368
lib/cache/lvmcache.c vendored
View File

@ -28,6 +28,43 @@
#include "format1.h"
#include "config.h"
#define CACHE_INVALID 0x00000001
#define CACHE_LOCKED 0x00000002
/* One per device */
struct lvmcache_info {
struct dm_list list; /* Join VG members together */
struct dm_list mdas; /* list head for metadata areas */
struct dm_list das; /* list head for data areas */
struct lvmcache_vginfo *vginfo; /* NULL == unknown */
struct label *label;
const struct format_type *fmt;
struct device *dev;
uint64_t device_size; /* Bytes */
uint32_t status;
};
/* One per VG */
struct lvmcache_vginfo {
struct dm_list list; /* Join these vginfos together */
struct dm_list infos; /* List head for lvmcache_infos */
const struct format_type *fmt;
char *vgname; /* "" == orphan */
uint32_t status;
char vgid[ID_LEN + 1];
char _padding[7];
struct lvmcache_vginfo *next; /* Another VG with same name? */
char *creation_host;
size_t vgmetadata_size;
char *vgmetadata; /* Copy of VG metadata as format_text string */
struct dm_config_tree *cft; /* Config tree created from vgmetadata */
/* Lifetime is directly tied to vgmetadata */
struct volume_group *cached_vg;
unsigned holders;
unsigned vg_use_count; /* Counter of vg reusage */
unsigned precommitted; /* Is vgmetadata live or precommitted? */
};
static struct dm_hash_table *_pvid_hash = NULL;
static struct dm_hash_table *_vgid_hash = NULL;
static struct dm_hash_table *_vgname_hash = NULL;
@ -104,7 +141,7 @@ static void _store_metadata(struct volume_group *vg, unsigned precommitted)
char *data;
size_t size;
if (!(vginfo = vginfo_from_vgid((const char *)&vg->id))) {
if (!(vginfo = lvmcache_vginfo_from_vgid((const char *)&vg->id))) {
stack;
return;
}
@ -147,7 +184,7 @@ static void _update_cache_info_lock_state(struct lvmcache_info *info,
* Cache becomes invalid whenever lock state changes unless
* exclusive VG_GLOBAL is held (i.e. while scanning).
*/
if (!vgname_is_locked(VG_GLOBAL) && (was_locked != locked)) {
if (!lvmcache_vgname_is_locked(VG_GLOBAL) && (was_locked != locked)) {
info->status |= CACHE_INVALID;
*cached_vgmetadata_valid = 0;
}
@ -176,7 +213,7 @@ static void _update_cache_lock_state(const char *vgname, int locked)
{
struct lvmcache_vginfo *vginfo;
if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
return;
_update_cache_vginfo_lock_state(vginfo, locked);
@ -187,7 +224,7 @@ static void _drop_metadata(const char *vgname, int drop_precommitted)
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
return;
/*
@ -220,7 +257,7 @@ void lvmcache_commit_metadata(const char *vgname)
{
struct lvmcache_vginfo *vginfo;
if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
return;
if (vginfo->precommitted) {
@ -240,7 +277,7 @@ void lvmcache_drop_metadata(const char *vgname, int drop_precommitted)
/* Indicate that PVs could now be missing from the cache */
init_full_scan_done(0);
} else if (!vgname_is_locked(VG_GLOBAL))
} else if (!lvmcache_vgname_is_locked(VG_GLOBAL))
_drop_metadata(vgname, drop_precommitted);
}
@ -317,7 +354,7 @@ void lvmcache_lock_vgname(const char *vgname, int read_only __attribute__((unuse
_vgs_locked++;
}
int vgname_is_locked(const char *vgname)
int lvmcache_vgname_is_locked(const char *vgname)
{
if (!_lock_hash)
return 0;
@ -340,7 +377,7 @@ void lvmcache_unlock_vgname(const char *vgname)
dev_close_all();
}
int vgs_locked(void)
int lvmcache_vgs_locked(void)
{
return _vgs_locked;
}
@ -366,12 +403,12 @@ static void _vginfo_detach_info(struct lvmcache_info *info)
}
/* If vgid supplied, require a match. */
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname, const char *vgid)
{
struct lvmcache_vginfo *vginfo;
if (!vgname)
return vginfo_from_vgid(vgid);
return lvmcache_vginfo_from_vgid(vgid);
if (!_vgname_hash)
return NULL;
@ -388,7 +425,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, unsigned revalidate_labels)
const struct format_type *lvmcache_fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels)
{
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
@ -398,7 +435,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid,
struct device_list *devl;
char vgid_found[ID_LEN + 1] __attribute__((aligned(8)));
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
return NULL;
/*
@ -431,7 +468,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid,
}
/* If vginfo changed, caller needs to rescan */
if (!(vginfo = vginfo_from_vgname(vgname, vgid_found)) ||
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid_found)) ||
strncmp(vginfo->vgid, vgid_found, ID_LEN))
return NULL;
@ -439,7 +476,7 @@ out:
return vginfo->fmt;
}
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid)
{
struct lvmcache_vginfo *vginfo;
char id[ID_LEN + 1] __attribute__((aligned(8)));
@ -457,12 +494,12 @@ struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
return vginfo;
}
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid)
{
struct lvmcache_vginfo *vginfo;
const char *vgname = NULL;
if ((vginfo = vginfo_from_vgid(vgid)))
if ((vginfo = lvmcache_vginfo_from_vgid(vgid)))
vgname = vginfo->vgname;
if (mem && vgname)
@ -483,7 +520,7 @@ static int _info_is_valid(struct lvmcache_info *info)
* So if the VG appears to be unlocked here, it should be safe
* to use the cached value.
*/
if (info->vginfo && !vgname_is_locked(info->vginfo->vgname))
if (info->vginfo && !lvmcache_vgname_is_locked(info->vginfo->vgname))
return 1;
if (!(info->status & CACHE_LOCKED))
@ -520,7 +557,7 @@ static int _vginfo_is_invalid(struct lvmcache_vginfo *vginfo)
* If valid_only is set, data will only be returned if the cached data is
* known still to be valid.
*/
struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only)
struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, int valid_only)
{
struct lvmcache_info *info;
char id[ID_LEN + 1] __attribute__((aligned(8)));
@ -545,12 +582,12 @@ char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid)
struct lvmcache_info *info;
char *vgname;
if (!device_from_pvid(cmd, (const struct id *)pvid, NULL, NULL)) {
if (!lvmcache_device_from_pvid(cmd, (const struct id *)pvid, NULL, NULL)) {
log_error("Couldn't find device with uuid %s.", pvid);
return NULL;
}
info = info_from_pvid(pvid, 0);
info = lvmcache_info_from_pvid(pvid, 0);
if (!info)
return_NULL;
@ -644,7 +681,7 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
struct format_instance *fid;
struct format_instance_ctx fic;
if (!vgid || !(vginfo = vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
if (!vgid || !(vginfo = lvmcache_vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
return NULL;
if (!_vginfo_is_valid(vginfo))
@ -708,7 +745,8 @@ bad:
return NULL;
}
int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo)
// #if 0
int lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo)
{
log_debug("VG %s decrementing %d holder(s) at %p.",
vginfo->cached_vg->name, vginfo->holders, vginfo->cached_vg);
@ -731,6 +769,7 @@ int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo)
return 1;
}
// #endif
struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd,
int include_internal)
@ -798,7 +837,7 @@ struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
return NULL;
}
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
return pvids;
dm_list_iterate_items(info, &vginfo->infos) {
@ -818,7 +857,7 @@ static struct device *_device_from_pvid(const struct id *pvid,
struct lvmcache_info *info;
struct label *label;
if ((info = info_from_pvid((const char *) pvid, 0))) {
if ((info = lvmcache_info_from_pvid((const char *) pvid, 0))) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid)) {
@ -831,7 +870,7 @@ static struct device *_device_from_pvid(const struct id *pvid,
return NULL;
}
struct device *device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
unsigned *scan_done_once, uint64_t *label_sector)
{
struct device *dev;
@ -863,7 +902,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
return NULL;
}
const char *pvid_from_devname(struct cmd_context *cmd,
const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
const char *devname)
{
struct device *dev;
@ -889,7 +928,7 @@ static int _free_vginfo(struct lvmcache_vginfo *vginfo)
_free_cached_vgmetadata(vginfo);
vginfo2 = primary_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
vginfo2 = primary_vginfo = lvmcache_vginfo_from_vgname(vginfo->vgname, NULL);
if (vginfo == primary_vginfo) {
dm_hash_remove(_vgname_hash, vginfo->vgname);
@ -910,7 +949,7 @@ static int _free_vginfo(struct lvmcache_vginfo *vginfo)
dm_free(vginfo->creation_host);
if (*vginfo->vgid && _vgid_hash &&
vginfo_from_vgid(vginfo->vgid) == vginfo)
lvmcache_vginfo_from_vgid(vginfo->vgid) == vginfo)
dm_hash_remove(_vgid_hash, vginfo->vgid);
dm_list_del(&vginfo->list);
@ -959,6 +998,7 @@ static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
/*
* Nothing to do if already stored with same pvid.
*/
if (((dm_hash_lookup(_pvid_hash, pvid)) == info) &&
!strcmp(info->dev->pvid, pvid))
return 1;
@ -1110,7 +1150,7 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
_drop_vginfo(info, info->vginfo);
/* Get existing vginfo or create new one */
if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
/*** FIXME - vginfo ends up duplicated instead of renamed.
// Renaming? This lookup fails.
if ((vginfo = vginfo_from_vgid(vgid))) {
@ -1162,9 +1202,9 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
* If we're scanning and there's an invalidated entry, remove it.
* Otherwise we risk bogus warnings of duplicate VGs.
*/
while ((primary_vginfo = vginfo_from_vgname(vgname, NULL)) &&
while ((primary_vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)) &&
_scanning_in_progress && _vginfo_is_invalid(primary_vginfo)) {
orphan_vginfo = vginfo_from_vgname(primary_vginfo->fmt->orphan_vg_name, NULL);
orphan_vginfo = lvmcache_vginfo_from_vgname(primary_vginfo->fmt->orphan_vg_name, NULL);
if (!orphan_vginfo) {
log_error(INTERNAL_ERROR "Orphan vginfo %s lost from cache.",
primary_vginfo->fmt->orphan_vg_name);
@ -1212,7 +1252,7 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
else if (!_lvmcache_update_vgid(NULL, vginfo, vgid)) /* Orphans */
return_0;
_update_cache_vginfo_lock_state(vginfo, vgname_is_locked(vgname));
_update_cache_vginfo_lock_state(vginfo, lvmcache_vgname_is_locked(vgname));
/* FIXME Check consistency of list! */
vginfo->fmt = fmt;
@ -1282,6 +1322,8 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
const char *vgname, const char *vgid,
uint32_t vgstatus, const char *creation_host)
{
log_error("lvmcache_update_vgname_and_id: %s -> %s", dev_name(info->dev), vgname);
if (!vgname && !info->vginfo) {
log_error(INTERNAL_ERROR "NULL vgname handed to cache");
/* FIXME Remove this */
@ -1319,7 +1361,7 @@ int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
dm_list_iterate_items(pvl, &vg->pvs) {
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
/* FIXME Could pvl->pv->dev->pvid ever be different? */
if ((info = info_from_pvid(pvid_s, 0)) &&
if ((info = lvmcache_info_from_pvid(pvid_s, 0)) &&
!lvmcache_update_vgname_and_id(info, vg->name,
(char *) &vg->id,
vg->status, NULL))
@ -1350,8 +1392,8 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
strncpy(pvid_s, pvid, sizeof(pvid_s) - 1);
pvid_s[sizeof(pvid_s) - 1] = '\0';
if (!(existing = info_from_pvid(pvid_s, 0)) &&
!(existing = info_from_pvid(dev->pvid, 0))) {
if (!(existing = lvmcache_info_from_pvid(pvid_s, 0)) &&
!(existing = lvmcache_info_from_pvid(dev->pvid, 0))) {
if (!(label = label_create(labeller)))
return_NULL;
if (!(info = dm_zalloc(sizeof(*info)))) {
@ -1520,3 +1562,259 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans)
if (retain_orphans)
init_lvmcache_orphans(cmd);
}
int lvmcache_pvid_is_locked(const char *pvid) {
struct lvmcache_info *info;
info = lvmcache_info_from_pvid(pvid, 0);
if (!info || !info->vginfo)
return 0;
return lvmcache_vgname_is_locked(info->vginfo->vgname);
}
int lvmcache_fid_add_mdas(struct lvmcache_info *info, struct format_instance *fid,
const char *id, int id_len)
{
return fid_add_mdas(fid, &info->mdas, id, id_len);
}
int lvmcache_fid_add_mdas_pv(struct lvmcache_info *info, struct format_instance *fid)
{
return lvmcache_fid_add_mdas(info, fid, info->dev->pvid, ID_LEN);
}
int lvmcache_fid_add_mdas_vg(struct lvmcache_vginfo *vginfo, struct format_instance *fid)
{
struct lvmcache_info *info;
dm_list_iterate_items(info, &vginfo->infos) {
if (!lvmcache_fid_add_mdas_pv(info, fid))
return_0;
}
return 1;
}
static int _get_pv_if_in_vg(struct lvmcache_info *info,
struct physical_volume *pv)
{
char vgname[NAME_LEN + 1];
char vgid[ID_LEN + 1];
if (info->vginfo && info->vginfo->vgname &&
!is_orphan_vg(info->vginfo->vgname)) {
/*
* get_pv_from_vg_by_id() may call
* lvmcache_label_scan() and drop cached
* vginfo so make a local copy of string.
*/
strcpy(vgname, info->vginfo->vgname);
memcpy(vgid, info->vginfo->vgid, sizeof(vgid));
if (get_pv_from_vg_by_id(info->fmt, vgname, vgid,
info->dev->pvid, pv))
return 1;
}
return 0;
}
int lvmcache_populate_pv_fields(struct lvmcache_info *info,
struct physical_volume *pv,
int scan_label_only)
{
struct data_area_list *da;
/* Have we already cached vgname? */
if (!scan_label_only && _get_pv_if_in_vg(info, pv))
return 1;
/* Perform full scan (just the first time) and try again */
if (!scan_label_only && !critical_section() && !full_scan_done()) {
lvmcache_label_scan(info->fmt->cmd, 2);
if (_get_pv_if_in_vg(info, pv))
return 1;
}
/* Orphan */
pv->dev = info->dev;
pv->fmt = info->fmt;
pv->size = info->device_size >> SECTOR_SHIFT;
pv->vg_name = FMT_TEXT_ORPHAN_VG_NAME;
memcpy(&pv->id, &info->dev->pvid, sizeof(pv->id));
/* Currently only support exactly one data area */
if (dm_list_size(&info->das) != 1) {
log_error("Must be exactly one data area (found %d) on PV %s",
dm_list_size(&info->das), dev_name(info->dev));
return 0;
}
dm_list_iterate_items(da, &info->das)
pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
return 1;
}
int lvmcache_check_format(struct lvmcache_info *info, const struct format_type *fmt)
{
if (info->fmt != fmt) {
log_error("PV %s is a different format (seqno %s)",
dev_name(info->dev), info->fmt->name);
return 0;
}
return 1;
}
void lvmcache_del_mdas(struct lvmcache_info *info)
{
if (info->mdas.n)
del_mdas(&info->mdas);
dm_list_init(&info->mdas);
}
void lvmcache_del_das(struct lvmcache_info *info)
{
if (info->das.n)
del_das(&info->das);
dm_list_init(&info->das);
}
int lvmcache_add_mda(struct lvmcache_info *info, struct device *dev,
uint64_t start, uint64_t size, unsigned ignored)
{
return add_mda(info->fmt, NULL, &info->mdas, dev, start, size, ignored);
}
int lvmcache_add_da(struct lvmcache_info *info, uint64_t start, uint64_t size)
{
return add_da(NULL, &info->das, start, size);
}
void lvmcache_update_pv(struct lvmcache_info *info, struct physical_volume *pv,
const struct format_type *fmt)
{
info->device_size = pv->size << SECTOR_SHIFT;
info->fmt = fmt;
}
int lvmcache_update_das(struct lvmcache_info *info, struct physical_volume *pv)
{
struct data_area_list *da;
if (info->das.n) {
if (!pv->pe_start)
dm_list_iterate_items(da, &info->das)
pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
del_das(&info->das);
} else
dm_list_init(&info->das);
if (!add_da(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
return_0;
return 1;
}
int lvmcache_foreach_pv(struct lvmcache_vginfo *vginfo,
int (*fun)(struct lvmcache_info *, void *),
void *baton)
{
struct lvmcache_info *info;
dm_list_iterate_items(info, &vginfo->infos) {
if (!fun(info, baton))
return_0;
}
return 1;
}
int lvmcache_foreach_mda(struct lvmcache_info *info,
int (*fun)(struct metadata_area *, void *),
void *baton)
{
struct metadata_area *mda;
dm_list_iterate_items(mda, &info->mdas) {
if (!fun(mda, baton))
return_0;
}
return 1;
}
int lvmcache_mda_count(struct lvmcache_info *info)
{
return dm_list_size(&info->mdas);
}
int lvmcache_foreach_da(struct lvmcache_info *info,
int (*fun)(struct data_area_list *, void *),
void *baton)
{
struct data_area_list *da;
dm_list_iterate_items(da, &info->das) {
if (!fun(da, baton))
return_0;
}
return 1;
}
/*
* The lifetime of the label returned is tied to the lifetime of the
* lvmcache_info which is the same as lvmcache itself.
*/
struct label *lvmcache_get_label(struct lvmcache_info *info) {
return info->label;
}
void lvmcache_make_valid(struct lvmcache_info *info) {
info->status &= ~CACHE_INVALID;
}
uint64_t lvmcache_device_size(struct lvmcache_info *info) {
return info->device_size;
}
void lvmcache_set_device_size(struct lvmcache_info *info, uint64_t size) {
info->device_size = size;
}
struct device *lvmcache_device(struct lvmcache_info *info) {
return info->dev;
}
int lvmcache_is_orphan(struct lvmcache_info *info) {
if (!info->vginfo)
return 1; /* FIXME? */
return is_orphan_vg(info->vginfo->vgname);
}
int lvmcache_vgid_is_cached(const char *vgid) {
struct lvmcache_vginfo *vginfo;
vginfo = lvmcache_vginfo_from_vgid(vgid);
if (!vginfo || !vginfo->vgname)
return 0;
if (is_orphan_vg(vginfo->vgname))
return 0;
return 1;
}
/*
* Return true iff it is impossible to find out from this info alone whether the
* PV in question is or is not an orphan.
*/
int lvmcache_uncertain_ownership(struct lvmcache_info *info) {
return mdas_empty_or_ignored(&info->mdas);
}
int lvmcache_smallest_mda_size(struct lvmcache_info *info)
{
return find_min_mda_size(&info->mdas);
}
const struct format_type *lvmcache_fmt(struct lvmcache_info *info) {
return info->fmt;
}

105
lib/cache/lvmcache.h vendored
View File

@ -24,50 +24,19 @@
#define ORPHAN_PREFIX VG_ORPHANS
#define ORPHAN_VG_NAME(fmt) ORPHAN_PREFIX "_" fmt
#define CACHE_INVALID 0x00000001
#define CACHE_LOCKED 0x00000002
/* LVM specific per-volume info */
/* Eventual replacement for struct physical_volume perhaps? */
struct cmd_context;
struct format_type;
struct volume_group;
struct physical_volume;
struct dm_config_tree;
struct format_instance;
struct metadata_area;
struct data_area_list;
/* One per VG */
struct lvmcache_vginfo {
struct dm_list list; /* Join these vginfos together */
struct dm_list infos; /* List head for lvmcache_infos */
const struct format_type *fmt;
char *vgname; /* "" == orphan */
uint32_t status;
char vgid[ID_LEN + 1];
char _padding[7];
struct lvmcache_vginfo *next; /* Another VG with same name? */
char *creation_host;
size_t vgmetadata_size;
char *vgmetadata; /* Copy of VG metadata as format_text string */
struct dm_config_tree *cft; /* Config tree created from vgmetadata */
/* Lifetime is directly tied to vgmetadata */
struct volume_group *cached_vg;
unsigned holders;
unsigned vg_use_count; /* Counter of vg reusage */
unsigned precommitted; /* Is vgmetadata live or precommitted? */
};
/* One per device */
struct lvmcache_info {
struct dm_list list; /* Join VG members together */
struct dm_list mdas; /* list head for metadata areas */
struct dm_list das; /* list head for data areas */
struct lvmcache_vginfo *vginfo; /* NULL == unknown */
struct label *label;
const struct format_type *fmt;
struct device *dev;
uint64_t device_size; /* Bytes */
uint32_t status;
};
struct lvmcache_vginfo;
int lvmcache_init(void);
void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans);
@ -95,21 +64,23 @@ 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, unsigned revalidate_labels);
const struct format_type *lvmcache_fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels);
/* Decrement and test if there are still vg holders in vginfo. */
int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo);
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
int lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo);
struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname,
const char *vgid);
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only);
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
struct device *device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid);
struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, int valid_only);
const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid);
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
unsigned *scan_done_once, uint64_t *label_sector);
const char *pvid_from_devname(struct cmd_context *cmd,
const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
const char *dev_name);
char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid);
int vgs_locked(void);
int vgname_is_locked(const char *vgname);
int lvmcache_vgs_locked(void);
int lvmcache_vgname_is_locked(const char *vgname);
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
/* If include_internal is not set, return only proper vg names. */
@ -130,4 +101,46 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted);
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
void lvmcache_commit_metadata(const char *vgname);
int lvmcache_pvid_is_locked(const char *pvid);
int lvmcache_fid_add_mdas(struct lvmcache_info *info, struct format_instance *fid,
const char *id, int id_len);
int lvmcache_fid_add_mdas_pv(struct lvmcache_info *info, struct format_instance *fid);
int lvmcache_fid_add_mdas_vg(struct lvmcache_vginfo *vginfo, struct format_instance *fid);
int lvmcache_populate_pv_fields(struct lvmcache_info *info,
struct physical_volume *pv,
int scan_label_only);
int lvmcache_check_format(struct lvmcache_info *info, const struct format_type *fmt);
void lvmcache_del_mdas(struct lvmcache_info *info);
void lvmcache_del_das(struct lvmcache_info *info);
int lvmcache_add_mda(struct lvmcache_info *info, struct device *dev,
uint64_t start, uint64_t size, unsigned ignored);
int lvmcache_add_da(struct lvmcache_info *info, uint64_t start, uint64_t size);
const struct format_type *lvmcache_fmt(struct lvmcache_info *info);
struct label *lvmcache_get_label(struct lvmcache_info *info);
void lvmcache_update_pv(struct lvmcache_info *info, struct physical_volume *pv,
const struct format_type *fmt);
int lvmcache_update_das(struct lvmcache_info *info, struct physical_volume *pv);
int lvmcache_foreach_mda(struct lvmcache_info *info,
int (*fun)(struct metadata_area *, void *),
void *baton);
int lvmcache_foreach_da(struct lvmcache_info *info,
int (*fun)(struct data_area_list *, void *),
void *baton);
int lvmcache_foreach_pv(struct lvmcache_vginfo *vg,
int (*fun)(struct lvmcache_info *, void *), void * baton);
uint64_t lvmcache_device_size(struct lvmcache_info *info);
void lvmcache_set_device_size(struct lvmcache_info *info, uint64_t size);
struct device *lvmcache_device(struct lvmcache_info *info);
void lvmcache_make_valid(struct lvmcache_info *info);
int lvmcache_is_orphan(struct lvmcache_info *info);
int lvmcache_uncertain_ownership(struct lvmcache_info *info);
int lvmcache_mda_count(struct lvmcache_info *info);
int lvmcache_vgid_is_cached(const char *vgid);
int lvmcache_smallest_mda_size(struct lvmcache_info *info);
#endif

View File

@ -586,7 +586,6 @@ static void _close(struct device *dev)
static int _dev_close(struct device *dev, int immediate)
{
struct lvmcache_info *info;
if (dev->fd < 0) {
log_error("Attempt to close device '%s' "
@ -608,10 +607,7 @@ static int _dev_close(struct device *dev, int immediate)
/* Close unless device is known to belong to a locked VG */
if (immediate ||
(dev->open_count < 1 &&
(!(info = info_from_pvid(dev->pvid, 0)) ||
!info->vginfo ||
!vgname_is_locked(info->vginfo->vgname))))
(dev->open_count < 1 && !lvmcache_pvid_is_locked(dev->pvid)))
_close(dev);
return 1;

View File

@ -335,9 +335,9 @@ static void __update_lvmcache(const struct format_type *fmt,
return;
}
info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
dm_list_init(&info->mdas);
info->status &= ~CACHE_INVALID;
lvmcache_set_device_size(info, xlate32(dl->pvd.pv_size) << SECTOR_SHIFT);
lvmcache_del_mdas(info);
lvmcache_make_valid(info);
}
static struct disk_list *__read_disk(const struct format_type *fmt,
@ -451,6 +451,28 @@ static void _add_pv_to_list(struct dm_list *head, struct disk_list *data)
dm_list_add(head, &data->list);
}
struct _read_pvs_in_vg_baton {
const char *vg_name;
struct dm_list *head;
struct disk_list *data;
struct dm_pool *mem;
int empty;
};
static int _read_pv_in_vg(struct lvmcache_info *info, void *baton)
{
struct _read_pvs_in_vg_baton *b = baton;
b->empty = 0;
if (!lvmcache_device(info) ||
!(b->data = read_disk(lvmcache_fmt(info), lvmcache_device(info), b->mem, b->vg_name)))
return 0; /* stop here */
_add_pv_to_list(b->head, b->data);
return 1;
}
/*
* Build a list of pv_d's structures, allocated from mem.
* We keep track of the first object allocated from the pool
@ -462,30 +484,32 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
{
struct dev_iter *iter;
struct device *dev;
struct disk_list *data = NULL;
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
struct _read_pvs_in_vg_baton baton;
baton.head = head;
baton.empty = 1;
baton.data = NULL;
baton.mem = mem;
baton.vg_name = vg_name;
/* Fast path if we already saw this VG and cached the list of PVs */
if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
vginfo->infos.n) {
dm_list_iterate_items(info, &vginfo->infos) {
dev = info->dev;
if (!dev || !(data = read_disk(fmt, dev, mem, vg_name)))
break;
_add_pv_to_list(head, data);
}
if (vg_name && (vginfo = lvmcache_vginfo_from_vgname(vg_name, NULL))) {
lvmcache_foreach_pv(vginfo, _read_pv_in_vg, &baton);
if (!baton.empty) {
/* Did we find the whole VG? */
if (!vg_name || is_orphan_vg(vg_name) ||
(data && *data->pvd.vg_name &&
dm_list_size(head) == data->vgd.pv_cur))
(baton.data && *baton.data->pvd.vg_name &&
dm_list_size(head) == baton.data->vgd.pv_cur))
return 1;
/* Failed */
dm_list_init(head);
/* vgcache_del(vg_name); */
}
}
if (!(iter = dev_iter_create(filter, 1))) {
log_error("read_pvs_in_vg: dev_iter_create failed");
@ -494,8 +518,8 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
/* Otherwise do a complete scan */
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
if ((data = read_disk(fmt, dev, mem, vg_name))) {
_add_pv_to_list(head, data);
if ((baton.data = read_disk(fmt, dev, mem, vg_name))) {
_add_pv_to_list(head, baton.data);
}
}
dev_iter_destroy(iter);

View File

@ -413,10 +413,8 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
pv->vg_name, NULL, 0)))
return_0;
info->device_size = pv->size << SECTOR_SHIFT;
info->fmt = fmt;
dm_list_init(&info->mdas);
lvmcache_update_pv(info, pv, fmt);
lvmcache_del_mdas(info);
dm_list_init(&pvs);

View File

@ -77,12 +77,11 @@ static int _lvm1_read(struct labeller *l, struct device *dev, void *buf,
if (!(info = lvmcache_add(l, (char *)pvd->pv_uuid, dev, vgname, vgid,
exported)))
return_0;
*label = info->label;
*label = lvmcache_get_label(info);
info->device_size = xlate32(pvd->pv_size) << SECTOR_SHIFT;
dm_list_init(&info->mdas);
info->status &= ~CACHE_INVALID;
lvmcache_set_device_size(info, xlate32(pvd->pv_size) << SECTOR_SHIFT);
lvmcache_del_mdas(info);
lvmcache_make_valid(info);
return 1;
}

View File

@ -101,12 +101,11 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
(char *) &vgid, 0)))
return_0;
if (label)
*label = info->label;
*label = lvmcache_get_label(info);
info->device_size = xlate32_be(pd->pl_blocks) << SECTOR_SHIFT;
dm_list_init(&info->mdas);
info->status &= ~CACHE_INVALID;
lvmcache_set_device_size(info, xlate32_be(pd->pl_blocks) << SECTOR_SHIFT);
lvmcache_del_mdas(info);
lvmcache_make_valid(info);
pl->dev = dev;
pl->pv = NULL;
@ -236,68 +235,92 @@ void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid)
}
static int _read_vg_pds(const struct format_type *fmt, struct dm_pool *mem,
struct lvmcache_vginfo *vginfo, struct dm_list *head,
uint32_t *devcount)
struct _read_pool_pv_baton {
const struct format_type *fmt;
struct dm_pool *mem, *tmpmem;
struct pool_list *pl;
struct dm_list *head;
const char *vgname;
uint32_t *sp_devs;
int sp_count;
int failed;
int empty;
};
static int _read_pool_pv(struct lvmcache_info *info, void *baton)
{
struct lvmcache_info *info;
struct pool_list *pl = NULL;
struct dm_pool *tmpmem;
struct _read_pool_pv_baton *b = baton;
uint32_t sp_count = 0;
uint32_t *sp_devs = NULL;
uint32_t i;
b->empty = 0;
/* FIXME: maybe should return a different error in memory
* allocation failure */
if (!(tmpmem = dm_pool_create("pool read_vg", 512)))
return_0;
if (lvmcache_device(info) &&
!(b->pl = read_pool_disk(b->fmt, lvmcache_device(info), b->mem, b->vgname)))
return 0;
dm_list_iterate_items(info, &vginfo->infos) {
if (info->dev &&
!(pl = read_pool_disk(fmt, info->dev, mem, vginfo->vgname)))
break;
/*
* We need to keep track of the total expected number
* of devices per subpool
*/
if (!sp_count) {
if (!b->sp_count) {
/* FIXME pl left uninitialised if !info->dev */
if (!pl) {
if (!b->pl) {
log_error(INTERNAL_ERROR "device is missing");
dm_pool_destroy(tmpmem);
dm_pool_destroy(b->tmpmem);
b->failed = 1;
return 0;
}
sp_count = pl->pd.pl_subpools;
if (!(sp_devs =
dm_pool_zalloc(tmpmem,
sizeof(uint32_t) * sp_count))) {
b->sp_count = b->pl->pd.pl_subpools;
if (!(b->sp_devs =
dm_pool_zalloc(b->tmpmem,
sizeof(uint32_t) * b->sp_count))) {
log_error("Unable to allocate %d 32-bit uints",
sp_count);
dm_pool_destroy(tmpmem);
b->sp_count);
dm_pool_destroy(b->tmpmem);
b->failed = 1;
return 0;
}
}
/*
* watch out for a pool label with a different subpool
* count than the original - give up if it does
*/
if (sp_count != pl->pd.pl_subpools)
break;
if (b->sp_count != b->pl->pd.pl_subpools)
return 0;
_add_pl_to_list(head, pl);
_add_pl_to_list(b->head, b->pl);
if (sp_count > pl->pd.pl_sp_id && sp_devs[pl->pd.pl_sp_id] == 0)
sp_devs[pl->pd.pl_sp_id] = pl->pd.pl_sp_devs;
}
if (b->sp_count > b->pl->pd.pl_sp_id && b->sp_devs[b->pl->pd.pl_sp_id] == 0)
b->sp_devs[b->pl->pd.pl_sp_id] = b->pl->pd.pl_sp_devs;
return 1;
}
static int _read_vg_pds(struct _read_pool_pv_baton *b,
struct lvmcache_vginfo *vginfo,
uint32_t *devcount)
{
uint32_t i;
b->sp_count = 0;
b->sp_devs = NULL;
b->failed = 0;
b->pl = NULL;
/* FIXME: maybe should return a different error in memory
* allocation failure */
if (!(b->tmpmem = dm_pool_create("pool read_vg", 512)))
return_0;
lvmcache_foreach_pv(vginfo, _read_pool_pv, b);
*devcount = 0;
for (i = 0; i < sp_count; i++)
*devcount += sp_devs[i];
for (i = 0; i < b->sp_count; i++)
*devcount += b->sp_devs[i];
dm_pool_destroy(tmpmem);
dm_pool_destroy(b->tmpmem);
if (pl && *pl->pd.pl_pool_name)
if (b->pl && *b->pl->pd.pl_pool_name)
return 1;
return 0;
@ -311,29 +334,36 @@ int read_pool_pds(const struct format_type *fmt, const char *vg_name,
uint32_t totaldevs;
int full_scan = -1;
struct _read_pool_pv_baton baton;
baton.vgname = vg_name;
baton.mem = mem;
baton.fmt = fmt;
baton.head = pdhead;
baton.empty = 1;
do {
/*
* If the cache scanning doesn't work, this will never work
*/
if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
vginfo->infos.n) {
if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {
if (vg_name && (vginfo = lvmcache_vginfo_from_vgname(vg_name, NULL)) &&
_read_vg_pds(&baton, vginfo, &totaldevs) && !baton.empty)
{
/*
* If we found all the devices we were
* expecting, return success
* If we found all the devices we were expecting, return
* success
*/
if (dm_list_size(pdhead) == totaldevs)
return 1;
/*
* accept partial pool if we've done a full
* rescan of the cache
* accept partial pool if we've done a full rescan of
* the cache
*/
if (full_scan > 0)
return 1;
}
}
/* Failed */
dm_list_init(pdhead);

View File

@ -432,7 +432,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
"not match expected name %s.", vgname);
bad:
if ((info = info_from_pvid(dev_area->dev->pvid, 0)))
if ((info = lvmcache_info_from_pvid(dev_area->dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, FMT_TEXT_ORPHAN_VG_NAME,
FMT_TEXT_ORPHAN_VG_NAME, 0, NULL);
@ -1251,6 +1251,33 @@ static int _text_scan(const struct format_type *fmt, const char *vgname)
return (_scan_file(fmt, vgname) & _scan_raw(fmt, vgname));
}
struct _write_single_mda_baton {
const struct format_type *fmt;
struct physical_volume *pv;
};
static int _write_single_mda(struct metadata_area *mda, void *baton)
{
struct _write_single_mda_baton *p = baton;
struct mda_context *mdac;
char buf[MDA_HEADER_SIZE] __attribute__((aligned(8)));
struct mda_header *mdah = (struct mda_header *) buf;
mdac = mda->metadata_locn;
memset(&buf, 0, sizeof(buf));
mdah->size = mdac->area.size;
rlocn_set_ignored(mdah->raw_locns, mda_is_ignored(mda));
if (!_raw_write_mda_header(p->fmt, mdac->area.dev,
mdac->area.start, mdah)) {
if (!dev_close(p->pv->dev))
stack;
return_0;
}
return 1;
}
/* Only for orphans */
static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv)
{
@ -1260,27 +1287,21 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
struct lvmcache_info *info;
struct mda_context *mdac;
struct metadata_area *mda;
struct _write_single_mda_baton baton;
unsigned mda_index;
char buf[MDA_HEADER_SIZE] __attribute__((aligned(8)));
struct mda_header *mdah = (struct mda_header *) buf;
struct data_area_list *da;
/* Add a new cache entry with PV info or update existing one. */
if (!(info = lvmcache_add(fmt->labeller, (const char *) &pv->id,
pv->dev, pv->vg_name, NULL, 0)))
return_0;
label = info->label;
label = lvmcache_get_label(info);
label->sector = pv->label_sector;
info->device_size = pv->size << SECTOR_SHIFT;
info->fmt = fmt;
lvmcache_update_pv(info, pv, fmt);
/* Flush all cached metadata areas, we will reenter new/modified ones. */
if (info->mdas.n)
del_mdas(&info->mdas);
else
dm_list_init(&info->mdas);
lvmcache_del_mdas(info);
/*
* Add all new or modified metadata areas for this PV stored in
@ -1299,7 +1320,9 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
dev_name(mdac->area.dev),
mdac->area.start >> SECTOR_SHIFT,
mdac->area.size >> SECTOR_SHIFT);
add_mda(fmt, NULL, &info->mdas, mdac->area.dev,
// if fmt is not the same as info->fmt we are in trouble
lvmcache_add_mda(info, mdac->area.dev,
mdac->area.start, mdac->area.size, mda_is_ignored(mda));
}
@ -1318,34 +1341,20 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
* pvcreate --restorefile. However, we can can have this value in
* metadata which will override the value in the PV header.
*/
if (info->das.n) {
if (!pv->pe_start)
dm_list_iterate_items(da, &info->das)
pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
del_das(&info->das);
} else
dm_list_init(&info->das);
if (!add_da(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
if (!lvmcache_update_das(info, pv))
return_0;
if (!dev_open(pv->dev))
return_0;
dm_list_iterate_items(mda, &info->mdas) {
mdac = mda->metadata_locn;
memset(&buf, 0, sizeof(buf));
mdah->size = mdac->area.size;
rlocn_set_ignored(mdah->raw_locns, mda_is_ignored(mda));
if (!_raw_write_mda_header(fmt, mdac->area.dev,
mdac->area.start, mdah)) {
if (!dev_close(pv->dev))
stack;
return_0;
}
}
baton.pv = pv;
baton.fmt = fmt;
if (!label_write(pv->dev, info->label)) {
if (!lvmcache_foreach_mda(info, _write_single_mda, &baton))
return_0;
if (!label_write(pv->dev, label)) {
dev_close(pv->dev);
return_0;
}
@ -1384,68 +1393,6 @@ static int _add_raw(struct dm_list *raw_list, struct device_area *dev_area)
return 1;
}
static int _get_pv_if_in_vg(struct lvmcache_info *info,
struct physical_volume *pv)
{
char vgname[NAME_LEN + 1];
char vgid[ID_LEN + 1];
if (info->vginfo && info->vginfo->vgname &&
!is_orphan_vg(info->vginfo->vgname)) {
/*
* get_pv_from_vg_by_id() may call
* lvmcache_label_scan() and drop cached
* vginfo so make a local copy of string.
*/
strcpy(vgname, info->vginfo->vgname);
memcpy(vgid, info->vginfo->vgid, sizeof(vgid));
if (get_pv_from_vg_by_id(info->fmt, vgname, vgid,
info->dev->pvid, pv))
return 1;
}
return 0;
}
static int _populate_pv_fields(struct lvmcache_info *info,
struct physical_volume *pv,
int scan_label_only)
{
struct data_area_list *da;
/* Have we already cached vgname? */
if (!scan_label_only && _get_pv_if_in_vg(info, pv))
return 1;
/* Perform full scan (just the first time) and try again */
if (!scan_label_only && !critical_section() && !full_scan_done()) {
lvmcache_label_scan(info->fmt->cmd, 2);
if (_get_pv_if_in_vg(info, pv))
return 1;
}
/* Orphan */
pv->dev = info->dev;
pv->fmt = info->fmt;
pv->size = info->device_size >> SECTOR_SHIFT;
pv->vg_name = FMT_TEXT_ORPHAN_VG_NAME;
memcpy(&pv->id, &info->dev->pvid, sizeof(pv->id));
/* Currently only support exactly one data area */
if (dm_list_size(&info->das) != 1) {
log_error("Must be exactly one data area (found %d) on PV %s",
dm_list_size(&info->das), dev_name(info->dev));
return 0;
}
dm_list_iterate_items(da, &info->das)
pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
return 1;
}
/*
* Copy constructor for a metadata_locn.
*/
@ -1485,16 +1432,14 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
{
struct label *label;
struct device *dev;
struct lvmcache_info *info;
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
return_0;
if (!(label_read(dev, &label, UINT64_C(0))))
return_0;
info = (struct lvmcache_info *) label->info;
if (!_populate_pv_fields(info, pv, scan_label_only))
if (!lvmcache_populate_pv_fields(label->info, pv, scan_label_only))
return 0;
return 1;
@ -1670,18 +1615,15 @@ static int _text_pv_setup(const struct format_type *fmt,
* reread PV mda information from the cache and add it to vg->fid.
*/
else {
if (!(info = info_from_pvid(pv->dev->pvid, 0))) {
if (!(info = lvmcache_info_from_pvid(pv->dev->pvid, 0))) {
log_error("PV %s missing from cache", pv_dev_name(pv));
return 0;
}
if (fmt != info->fmt) {
log_error("PV %s is a different format (seqno %s)",
pv_dev_name(pv), info->fmt->name);
return 0;
}
if (!lvmcache_check_format(info, fmt))
return_0;
if (!fid_add_mdas(vg->fid, &info->mdas, pvid, ID_LEN))
if (!lvmcache_fid_add_mdas_pv(info, fid))
return_0;
}
@ -1736,8 +1678,8 @@ static int _create_pv_text_instance(struct format_instance *fid,
}
if (fic->type & FMT_INSTANCE_MDAS &&
(info = info_from_pvid(fic->context.pv_id, 0)))
fid_add_mdas(fid, &info->mdas, fic->context.pv_id, ID_LEN);
(info = lvmcache_info_from_pvid(fic->context.pv_id, 0)))
lvmcache_fid_add_mdas_pv(info, fid);
return 1;
}
@ -1801,7 +1743,6 @@ static int _create_vg_text_instance(struct format_instance *fid,
struct dm_list *dir_list, *raw_list;
struct text_context tc;
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
const char *vg_name, *vg_id;
if (!(fidtc = (struct text_fid_context *)
@ -1873,12 +1814,10 @@ static int _create_vg_text_instance(struct format_instance *fid,
if (type & FMT_INSTANCE_MDAS) {
/* Scan PVs in VG for any further MDAs */
lvmcache_label_scan(fid->fmt->cmd, 0);
if (!(vginfo = vginfo_from_vgname(vg_name, vg_id)))
if (!(vginfo = lvmcache_vginfo_from_vgname(vg_name, vg_id)))
goto_out;
if (!lvmcache_fid_add_mdas_vg(vginfo, fid))
goto_out;
dm_list_iterate_items(info, &vginfo->infos) {
if (!fid_add_mdas(fid, &info->mdas, info->dev->pvid, ID_LEN))
return_0;
}
}
/* FIXME Check raw metadata area count - rescan if required */
@ -2314,7 +2253,7 @@ static int _get_config_disk_area(struct cmd_context *cmd,
return 0;
}
if (!(dev_area.dev = device_from_pvid(cmd, &id, NULL, NULL))) {
if (!(dev_area.dev = lvmcache_device_from_pvid(cmd, &id, NULL, NULL))) {
char buffer[64] __attribute__((aligned(8)));
if (!id_write_format(&id, buffer, sizeof(buffer)))

View File

@ -62,4 +62,16 @@ int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct dm_list *
struct device *dev, uint64_t start, uint64_t size, unsigned ignored);
void del_mdas(struct dm_list *mdas);
/* On disk */
struct disk_locn {
uint64_t offset; /* Offset in bytes to start sector */
uint64_t size; /* Bytes */
} __attribute__ ((packed));
/* Data areas (holding PEs) */
struct data_area_list {
struct dm_list list;
struct disk_locn disk_locn;
};
#endif

View File

@ -190,7 +190,7 @@ static int _read_pv(struct format_instance *fid,
/*
* Convert the uuid into a device.
*/
if (!(pv->dev = device_from_pvid(fid->fmt->cmd, &pv->id, scan_done_once,
if (!(pv->dev = lvmcache_device_from_pvid(fid->fmt->cmd, &pv->id, scan_done_once,
&pv->label_sector))) {
char buffer[64] __attribute__((aligned(8)));

View File

@ -21,17 +21,7 @@
#include "metadata.h"
#include "uuid.h"
/* On disk */
struct disk_locn {
uint64_t offset; /* Offset in bytes to start sector */
uint64_t size; /* Bytes */
} __attribute__ ((packed));
/* Data areas (holding PEs) */
struct data_area_list {
struct dm_list list;
struct disk_locn disk_locn;
};
/* disk_locn and data_area_list are defined in format-text.h */
/* Fields with the suffix _xl should be xlate'd wherever they appear */
/* On disk */

View File

@ -35,15 +35,41 @@ static int _text_can_handle(struct labeller *l __attribute__((unused)),
return 0;
}
struct _da_setup_baton {
struct disk_locn *pvh_dlocn_xl;
struct device *dev;
};
static int _da_setup(struct data_area_list *da, void *baton)
{
struct _da_setup_baton *p = baton;
p->pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset);
p->pvh_dlocn_xl->size = xlate64(da->disk_locn.size);
p->pvh_dlocn_xl++;
return 1;
}
static int _mda_setup(struct metadata_area *mda, void *baton)
{
struct _da_setup_baton *p = baton;
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
if (mdac->area.dev != p->dev)
return 1;
p->pvh_dlocn_xl->offset = xlate64(mdac->area.start);
p->pvh_dlocn_xl->size = xlate64(mdac->area.size);
p->pvh_dlocn_xl++;
return 1;
}
static int _text_write(struct label *label, void *buf)
{
struct label_header *lh = (struct label_header *) buf;
struct pv_header *pvhdr;
struct lvmcache_info *info;
struct disk_locn *pvh_dlocn_xl;
struct metadata_area *mda;
struct mda_context *mdac;
struct data_area_list *da;
struct _da_setup_baton baton;
char buffer[64] __attribute__((aligned(8)));
int da1, mda1, mda2;
@ -54,43 +80,31 @@ static int _text_write(struct label *label, void *buf)
pvhdr = (struct pv_header *) ((char *) buf + xlate32(lh->offset_xl));
info = (struct lvmcache_info *) label->info;
pvhdr->device_size_xl = xlate64(info->device_size);
memcpy(pvhdr->pv_uuid, &info->dev->pvid, sizeof(struct id));
pvhdr->device_size_xl = xlate64(lvmcache_device_size(info));
memcpy(pvhdr->pv_uuid, &lvmcache_device(info)->pvid, sizeof(struct id));
if (!id_write_format((const struct id *)pvhdr->pv_uuid, buffer,
sizeof(buffer))) {
stack;
buffer[0] = '\0';
}
pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
baton.dev = lvmcache_device(info);
/* List of data areas (holding PEs) */
dm_list_iterate_items(da, &info->das) {
pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset);
pvh_dlocn_xl->size = xlate64(da->disk_locn.size);
pvh_dlocn_xl++;
}
baton.pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
lvmcache_foreach_da(info, _da_setup, &baton);
/* NULL-termination */
pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
pvh_dlocn_xl->size = xlate64(UINT64_C(0));
pvh_dlocn_xl++;
baton.pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
baton.pvh_dlocn_xl->size = xlate64(UINT64_C(0));
baton.pvh_dlocn_xl++;
/* List of metadata area header locations */
dm_list_iterate_items(mda, &info->mdas) {
mdac = (struct mda_context *) mda->metadata_locn;
if (mdac->area.dev != info->dev)
continue;
pvh_dlocn_xl->offset = xlate64(mdac->area.start);
pvh_dlocn_xl->size = xlate64(mdac->area.size);
pvh_dlocn_xl++;
}
lvmcache_foreach_mda(info, _mda_setup, &baton);
/* NULL-termination */
pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
pvh_dlocn_xl->size = xlate64(UINT64_C(0));
baton.pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
baton.pvh_dlocn_xl->size = xlate64(UINT64_C(0));
/* Create debug message with da and mda locations */
if (xlate64(pvhdr->disk_areas_xl[0].offset) ||
@ -113,7 +127,7 @@ static int _text_write(struct label *label, void *buf)
"%s%.*" PRIu64 "%s%.*" PRIu64 "%s"
"%s%.*" PRIu64 "%s%.*" PRIu64 "%s"
"%s%.*" PRIu64 "%s%.*" PRIu64 "%s",
dev_name(info->dev), buffer, info->device_size,
dev_name(lvmcache_device(info)), buffer, lvmcache_device_size(info),
(da1 > -1) ? " da1 (" : "",
(da1 > -1) ? 1 : 0,
(da1 > -1) ? xlate64(pvhdr->disk_areas_xl[da1].offset) >> SECTOR_SHIFT : 0,
@ -138,7 +152,7 @@ static int _text_write(struct label *label, void *buf)
if (da1 < 0) {
log_error(INTERNAL_ERROR "%s label header currently requires "
"a data area.", dev_name(info->dev));
"a data area.", dev_name(lvmcache_device(info)));
return 0;
}
@ -250,67 +264,33 @@ static int _text_initialise_label(struct labeller *l __attribute__((unused)),
return 1;
}
static int _text_read(struct labeller *l, struct device *dev, void *buf,
struct label **label)
{
struct label_header *lh = (struct label_header *) buf;
struct pv_header *pvhdr;
struct _update_mda_baton {
struct lvmcache_info *info;
struct disk_locn *dlocn_xl;
uint64_t offset;
struct metadata_area *mda;
struct id vgid;
struct mda_context *mdac;
struct label *label;
};
static int _update_mda(struct metadata_area *mda, void *baton)
{
struct _update_mda_baton *p = baton;
const struct format_type *fmt = p->label->labeller->private; // Oh dear.
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct mda_header *mdah;
const char *vgname;
struct id vgid;
uint64_t vgstatus;
char *creation_host;
struct mda_header *mdah;
pvhdr = (struct pv_header *) ((char *) buf + xlate32(lh->offset_xl));
if (!(info = lvmcache_add(l, (char *)pvhdr->pv_uuid, dev,
FMT_TEXT_ORPHAN_VG_NAME,
FMT_TEXT_ORPHAN_VG_NAME, 0)))
return_0;
*label = info->label;
info->device_size = xlate64(pvhdr->device_size_xl);
if (info->das.n)
del_das(&info->das);
dm_list_init(&info->das);
if (info->mdas.n)
del_mdas(&info->mdas);
dm_list_init(&info->mdas);
/* Data areas holding the PEs */
dlocn_xl = pvhdr->disk_areas_xl;
while ((offset = xlate64(dlocn_xl->offset))) {
add_da(NULL, &info->das, offset,
xlate64(dlocn_xl->size));
dlocn_xl++;
}
/* Metadata area headers */
dlocn_xl++;
while ((offset = xlate64(dlocn_xl->offset))) {
add_mda(info->fmt, NULL, &info->mdas, dev, offset,
xlate64(dlocn_xl->size), 0);
dlocn_xl++;
}
dm_list_iterate_items(mda, &info->mdas) {
mdac = (struct mda_context *) mda->metadata_locn;
if (!dev_open_readonly(mdac->area.dev)) {
mda_set_ignored(mda, 1);
stack;
continue;
return 1;
}
if (!(mdah = raw_read_mda_header(info->fmt, &mdac->area))) {
if (!(mdah = raw_read_mda_header(fmt, &mdac->area))) {
stack;
goto close_dev;
}
mda_set_ignored(mda, rlocn_is_ignored(mdah->raw_locns));
if (mda_is_ignored(mda)) {
@ -319,26 +299,71 @@ static int _text_read(struct labeller *l, struct device *dev, void *buf,
mdac->area.start);
if (!dev_close(mdac->area.dev))
stack;
continue;
return 1;
}
if ((vgname = vgname_from_mda(info->fmt, mdah,
if ((vgname = vgname_from_mda(fmt, mdah,
&mdac->area,
&vgid, &vgstatus, &creation_host,
&mdac->free_sectors)) &&
!lvmcache_update_vgname_and_id(info, vgname,
!lvmcache_update_vgname_and_id(p->info, vgname,
(char *) &vgid, vgstatus,
creation_host)) {
if (!dev_close(mdac->area.dev))
stack;
return_0;
}
close_dev:
close_dev:
if (!dev_close(mdac->area.dev))
stack;
return 1;
}
static int _text_read(struct labeller *l, struct device *dev, void *buf,
struct label **label)
{
struct label_header *lh = (struct label_header *) buf;
struct pv_header *pvhdr;
struct lvmcache_info *info;
struct disk_locn *dlocn_xl;
uint64_t offset;
struct _update_mda_baton baton;
pvhdr = (struct pv_header *) ((char *) buf + xlate32(lh->offset_xl));
if (!(info = lvmcache_add(l, (char *)pvhdr->pv_uuid, dev,
FMT_TEXT_ORPHAN_VG_NAME,
FMT_TEXT_ORPHAN_VG_NAME, 0)))
return_0;
/* this one is leaked forever */
*label = lvmcache_get_label(info);
lvmcache_set_device_size(info, xlate64(pvhdr->device_size_xl));
lvmcache_del_das(info);
lvmcache_del_mdas(info);
/* Data areas holding the PEs */
dlocn_xl = pvhdr->disk_areas_xl;
while ((offset = xlate64(dlocn_xl->offset))) {
lvmcache_add_da(info, offset, xlate64(dlocn_xl->size));
dlocn_xl++;
}
info->status &= ~CACHE_INVALID;
/* Metadata area headers */
dlocn_xl++;
while ((offset = xlate64(dlocn_xl->offset))) {
lvmcache_add_mda(info, dev, offset, xlate64(dlocn_xl->size), 0);
dlocn_xl++;
}
baton.info = info;
baton.label = *label;
lvmcache_foreach_mda(info, _update_mda, &baton);
lvmcache_make_valid(info);
return 1;
}
@ -348,10 +373,8 @@ static void _text_destroy_label(struct labeller *l __attribute__((unused)),
{
struct lvmcache_info *info = (struct lvmcache_info *) label->info;
if (info->mdas.n)
del_mdas(&info->mdas);
if (info->das.n)
del_das(&info->das);
lvmcache_del_mdas(info);
lvmcache_del_das(info);
}
static void _fmt_text_destroy(struct labeller *l)

View File

@ -172,9 +172,9 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
out:
if (!found) {
if ((info = info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
info->fmt->orphan_vg_name,
if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
lvmcache_fmt(info)->orphan_vg_name,
0, NULL);
log_very_verbose("%s: No label detected", dev_name(dev));
}
@ -261,18 +261,18 @@ int label_read(struct device *dev, struct label **result,
struct lvmcache_info *info;
int r = 0;
if ((info = info_from_pvid(dev->pvid, 1))) {
if ((info = lvmcache_info_from_pvid(dev->pvid, 1))) {
log_debug("Using cached label for %s", dev_name(dev));
*result = info->label;
*result = lvmcache_get_label(info); /* leaked */
return 1;
}
if (!dev_open_readonly(dev)) {
stack;
if ((info = info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
info->fmt->orphan_vg_name,
if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
lvmcache_fmt(info)->orphan_vg_name,
0, NULL);
return r;
@ -348,9 +348,9 @@ int label_verify(struct device *dev)
int r = 0;
if (!dev_open_readonly(dev)) {
if ((info = info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
info->fmt->orphan_vg_name,
if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
lvmcache_fmt(info)->orphan_vg_name,
0, NULL);
return_0;

View File

@ -1504,7 +1504,7 @@ struct physical_volume * pvcreate_single(struct cmd_context *cmd,
pp = &default_pp;
if (pp->idp) {
if ((dev = device_from_pvid(cmd, pp->idp, NULL, NULL)) &&
if ((dev = lvmcache_device_from_pvid(cmd, pp->idp, NULL, NULL)) &&
(dev != dev_cache_get(pv_name, cmd->filter))) {
if (!id_write_format((const struct id*)&pp->idp->uuid,
buffer, sizeof(buffer)))
@ -2671,7 +2671,7 @@ int vg_commit(struct volume_group *vg)
{
int cache_updated = 0;
if (!vgname_is_locked(vg->name)) {
if (!lvmcache_vgname_is_locked(vg->name)) {
log_error(INTERNAL_ERROR "Attempt to write new VG metadata "
"without locking %s", vg->name);
return cache_updated;
@ -2717,6 +2717,31 @@ void vg_revert(struct volume_group *vg)
remote_revert_cached_metadata(vg);
}
struct _vg_read_orphan_baton {
struct volume_group *vg;
int warnings;
};
static int _vg_read_orphan_pv(struct lvmcache_info *info, void *baton)
{
struct _vg_read_orphan_baton *b = baton;
struct physical_volume *pv = NULL;
struct pv_list *pvl;
if (!(pv = _pv_read(b->vg->cmd, b->vg->vgmem, dev_name(lvmcache_device(info)),
b->vg->fid, b->warnings, 0))) {
return 1;
}
if (!(pvl = dm_pool_zalloc(b->vg->vgmem, sizeof(*pvl)))) {
log_error("pv_list allocation failed");
free_pv_fid(pv);
return 0;
}
pvl->pv = pv;
add_pvl_to_vgs(b->vg, pvl);
return 1;
}
/* Make orphan PVs look like a VG */
static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
int warnings,
@ -2724,15 +2749,17 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
{
struct format_instance_ctx fic;
struct format_instance *fid;
const struct format_type *fmt;
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
struct pv_list *pvl;
struct volume_group *vg = NULL;
struct physical_volume *pv = NULL;
struct _vg_read_orphan_baton baton;
lvmcache_label_scan(cmd, 0);
if (!(vginfo = vginfo_from_vgname(orphan_vgname, NULL)))
if (!(vginfo = lvmcache_vginfo_from_vgname(orphan_vgname, NULL)))
return_NULL;
if (!(fmt = lvmcache_fmt_from_vgname(orphan_vgname, NULL, 0)))
return_NULL;
if (!(vg = alloc_vg("vg_read_orphans", cmd, orphan_vgname)))
@ -2742,28 +2769,18 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
fic.type = FMT_INSTANCE_VG | FMT_INSTANCE_AUX_MDAS;
fic.context.vg_ref.vg_name = orphan_vgname;
fic.context.vg_ref.vg_id = NULL;
if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt, &fic))) {
if (!(fid = fmt->ops->create_instance(fmt, &fic))) {
log_error("Failed to create format instance");
goto bad;
}
vg_set_fid(vg, fid);
dm_list_iterate_items(info, &vginfo->infos) {
if (!(pv = _pv_read(cmd, vg->vgmem, dev_name(info->dev),
vg->fid, warnings, 0))) {
continue;
}
if (!(pvl = dm_pool_zalloc(vg->vgmem, sizeof(*pvl)))) {
log_error("pv_list allocation failed");
goto bad;
}
pvl->pv = pv;
add_pvl_to_vgs(vg, pvl);
}
baton.warnings = warnings;
baton.vg = vg;
lvmcache_foreach_pv(vginfo, _vg_read_orphan_pv, &baton);
return vg;
bad:
free_pv_fid(pv);
release_vg(vg);
return NULL;
}
@ -2848,6 +2865,15 @@ static void check_reappeared_pv(struct volume_group *correct_vg,
"on it, remove volumes and consider vgreduce --removemissing.");
}
}
static int _check_mda_in_use(struct metadata_area *mda, void *_in_use)
{
int *in_use = _in_use;
if (!mda_is_ignored(mda))
*in_use = 1;
return 1;
}
/* Caller sets consistent to 1 if it's safe for vg_read_internal to correct
* inconsistent metadata on disk (i.e. the VG write lock is held).
* This guarantees only consistent metadata is returned.
@ -2913,20 +2939,20 @@ 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, 1))) {
if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 1))) {
lvmcache_label_scan(cmd, 0);
if (!(fmt = fmt_from_vgname(vgname, vgid, 1))) {
if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 1))) {
/* Independent MDAs aren't supported under low memory */
if (!cmd->independent_metadata_areas && critical_section())
return_NULL;
lvmcache_label_scan(cmd, 2);
if (!(fmt = fmt_from_vgname(vgname, vgid, 0)))
if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 0)))
return_NULL;
}
}
/* Now determine the correct vgname if none was supplied */
if (!vgname && !(vgname = vgname_from_vgid(cmd->mem, vgid)))
if (!vgname && !(vgname = lvmcache_vgname_from_vgid(cmd->mem, vgid)))
return_NULL;
if (use_precommitted && !(fmt->features & FMT_PRECOMMIT))
@ -3016,14 +3042,13 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
* Check it's an orphan without metadata area
* not ignored.
*/
if (!(info = info_from_pvid(pvl->pv->dev->pvid, 1)) ||
!info->vginfo || !is_orphan_vg(info->vginfo->vgname)) {
if (!(info = lvmcache_info_from_pvid(pvl->pv->dev->pvid, 1)) ||
!lvmcache_is_orphan(info)) {
inconsistent_pvs = 1;
break;
}
if (dm_list_size(&info->mdas)) {
if (!fid_add_mdas(fid, &info->mdas,
info->dev->pvid, ID_LEN)) {
if (lvmcache_mda_count(info)) {
if (!lvmcache_fid_add_mdas_pv(info, fid)) {
release_vg(correct_vg);
return_NULL;
}
@ -3037,11 +3062,8 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
* If any newly-added mdas are in-use then their
* metadata needs updating.
*/
dm_list_iterate_items(mda, &info->mdas)
if (!mda_is_ignored(mda)) {
inconsistent_mdas = 1;
break;
}
lvmcache_foreach_mda(info, _check_mda_in_use,
&inconsistent_mdas);
}
}
@ -3110,7 +3132,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
if (!cmd->independent_metadata_areas && critical_section())
return_NULL;
lvmcache_label_scan(cmd, 2);
if (!(fmt = fmt_from_vgname(vgname, vgid, 0)))
if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 0)))
return_NULL;
if (precommitted && !(fmt->features & FMT_PRECOMMIT))
@ -3383,13 +3405,11 @@ static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
const char *vgname;
struct dm_list *vgnames;
struct volume_group *vg;
struct lvmcache_vginfo *vginfo;
struct str_list *strl;
int consistent = 0;
/* Is corresponding vgname already cached? */
if ((vginfo = vginfo_from_vgid(vgid)) &&
vginfo->vgname && !is_orphan_vg(vginfo->vgname)) {
if (lvmcache_vgid_is_cached(vgid)) {
if ((vg = _vg_read(cmd, NULL, vgid, 1,
&consistent, precommitted)) &&
id_equal(&vg->id, (const struct id *)vgid)) {
@ -3480,7 +3500,7 @@ const char *find_vgname_from_pvid(struct cmd_context *cmd,
vgname = lvmcache_vgname_from_pvid(cmd, pvid);
if (is_orphan_vg(vgname)) {
if (!(info = info_from_pvid(pvid, 0))) {
if (!(info = lvmcache_info_from_pvid(pvid, 0))) {
return_NULL;
}
/*
@ -3490,7 +3510,7 @@ const char *find_vgname_from_pvid(struct cmd_context *cmd,
* Detecting this means checking every VG by scanning
* every PV on the system.
*/
if (mdas_empty_or_ignored(&info->mdas)) {
if (lvmcache_uncertain_ownership(info)) {
if (!scan_vgs_for_pvs(cmd, 1)) {
log_error("Rescan for PVs without "
"metadata areas failed.");
@ -3512,7 +3532,7 @@ const char *find_vgname_from_pvname(struct cmd_context *cmd,
{
const char *pvid;
pvid = pvid_from_devname(cmd, pvname);
pvid = lvmcache_pvid_from_devname(cmd, pvname);
if (!pvid)
/* Not a PV */
return NULL;
@ -3576,7 +3596,7 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
pv->label_sector = label->sector;
/* FIXME Move more common code up here */
if (!(info->fmt->ops->pv_read(info->fmt, pv_name, pv, scan_label_only))) {
if (!(lvmcache_fmt(info)->ops->pv_read(lvmcache_fmt(info), pv_name, pv, scan_label_only))) {
log_error("Failed to read existing physical volume '%s'",
pv_name);
goto bad;
@ -3589,7 +3609,7 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
goto_bad;
if (fid)
fid_add_mdas(fid, &info->mdas, (const char *) &pv->id, ID_LEN);
lvmcache_fid_add_mdas(info, fid, (const char *) &pv->id, ID_LEN);
else {
fic.type = FMT_INSTANCE_PV | FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
fic.context.pv_id = (const char *) &pv->id;
@ -3656,7 +3676,7 @@ static int _get_pvs(struct cmd_context *cmd, int warnings, struct dm_list **pvsl
if (!vgid)
continue; /* FIXME Unnecessary? */
consistent = 0;
if (!(vgname = vgname_from_vgid(NULL, vgid))) {
if (!(vgname = lvmcache_vgname_from_vgid(NULL, vgid))) {
stack;
continue;
}
@ -3777,6 +3797,13 @@ int is_real_vg(const char *vg_name)
return (vg_name && *vg_name != '#');
}
static int _analyze_mda(struct metadata_area *mda, void *baton)
{
const struct format_type *fmt = baton;
mda->ops->pv_analyze_mda(fmt, mda);
return 1;
}
/*
* Returns:
* 0 - fail
@ -3787,7 +3814,6 @@ int pv_analyze(struct cmd_context *cmd, const char *pv_name,
{
struct label *label;
struct device *dev;
struct metadata_area *mda;
struct lvmcache_info *info;
dev = dev_cache_get(pv_name, cmd->filter);
@ -3813,8 +3839,7 @@ int pv_analyze(struct cmd_context *cmd, const char *pv_name,
* Next, loop through metadata areas
*/
info = label->info;
dm_list_iterate_items(mda, &info->mdas)
mda->ops->pv_analyze_mda(info->fmt, mda);
lvmcache_foreach_mda(info, _analyze_mda, (void *)lvmcache_fmt(info));
return 1;
}
@ -3932,7 +3957,7 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
return NULL;
}
already_locked = vgname_is_locked(vg_name);
already_locked = lvmcache_vgname_is_locked(vg_name);
if (!already_locked && !(misc_flags & READ_WITHOUT_LOCK) &&
!lock_vol(cmd, vg_name, lock_flags)) {
@ -4096,9 +4121,9 @@ 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, 1)) {
if (!lvmcache_fmt_from_vgname(vgname, NULL, 1)) {
lvmcache_label_scan(cmd, 0);
if (!fmt_from_vgname(vgname, NULL, 1)) {
if (!lvmcache_fmt_from_vgname(vgname, NULL, 1)) {
/* Independent MDAs aren't supported under low memory */
if (!cmd->independent_metadata_areas && critical_section()) {
/*
@ -4109,7 +4134,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, 0)) {
if (!lvmcache_fmt_from_vgname(vgname, NULL, 0)) {
/* vgname not found after scanning */
return SUCCESS;
}

View File

@ -143,23 +143,27 @@ uint32_t pv_mda_count(const struct physical_volume *pv)
{
struct lvmcache_info *info;
info = info_from_pvid((const char *)&pv->id.uuid, 0);
return info ? dm_list_size(&info->mdas) : UINT64_C(0);
info = lvmcache_info_from_pvid((const char *)&pv->id.uuid, 0);
return info ? lvmcache_mda_count(info) : UINT64_C(0);
}
static int _count_unignored(struct metadata_area *mda, void *baton)
{
uint32_t *count = baton;
if (!mda_is_ignored(mda))
(*count) ++;
return 1;
}
uint32_t pv_mda_used_count(const struct physical_volume *pv)
{
struct lvmcache_info *info;
struct metadata_area *mda;
uint32_t used_count=0;
info = info_from_pvid((const char *)&pv->id.uuid, 0);
info = lvmcache_info_from_pvid((const char *)&pv->id.uuid, 0);
if (!info)
return 0;
dm_list_iterate_items(mda, &info->mdas) {
if (!mda_is_ignored(mda))
used_count++;
}
lvmcache_foreach_mda(info, _count_unignored, &used_count);
return used_count;
}
@ -209,29 +213,36 @@ uint64_t pv_mda_size(const struct physical_volume *pv)
const char *pvid = (const char *)(&pv->id.uuid);
/* PVs could have 2 mdas of different sizes (rounding effect) */
if ((info = info_from_pvid(pvid, 0)))
min_mda_size = find_min_mda_size(&info->mdas);
if ((info = lvmcache_info_from_pvid(pvid, 0)))
min_mda_size = lvmcache_smallest_mda_size(info);
return min_mda_size;
}
static int _pv_mda_free(struct metadata_area *mda, void *baton) {
uint64_t mda_free;
uint64_t *freespace = baton;
if (!mda->ops->mda_free_sectors)
return 1;
mda_free = mda->ops->mda_free_sectors(mda);
if (mda_free < *freespace)
*freespace = mda_free;
return 1;
}
uint64_t pv_mda_free(const struct physical_volume *pv)
{
struct lvmcache_info *info;
uint64_t freespace = UINT64_MAX, mda_free;
uint64_t freespace = UINT64_MAX;
const char *pvid = (const char *)&pv->id.uuid;
struct metadata_area *mda;
if ((info = info_from_pvid(pvid, 0)))
dm_list_iterate_items(mda, &info->mdas) {
if (!mda->ops->mda_free_sectors)
continue;
mda_free = mda->ops->mda_free_sectors(mda);
if (mda_free < freespace)
freespace = mda_free;
}
if ((info = lvmcache_info_from_pvid(pvid, 0)))
lvmcache_foreach_mda(info, _pv_mda_free, &freespace);
if (freespace == UINT64_MAX)
freespace = UINT64_C(0);
return freespace;
}
@ -246,22 +257,51 @@ uint64_t pv_used(const struct physical_volume *pv)
return used;
}
struct _pv_mda_set_ignored_baton {
unsigned mda_ignored;
struct dm_list *mdas_in_use, *mdas_ignored, *mdas_to_change;
};
static int _pv_mda_set_ignored_one(struct metadata_area *mda, void *baton)
{
struct _pv_mda_set_ignored_baton *b = baton;
struct metadata_area *vg_mda, *tmda;
if (mda_is_ignored(mda) && !b->mda_ignored) {
/* Changing an ignored mda to one in_use requires moving it */
dm_list_iterate_items_safe(vg_mda, tmda, b->mdas_ignored)
if (mda_locns_match(mda, vg_mda)) {
mda_set_ignored(vg_mda, b->mda_ignored);
dm_list_move(b->mdas_in_use, &vg_mda->list);
}
}
dm_list_iterate_items_safe(vg_mda, tmda, b->mdas_in_use)
if (mda_locns_match(mda, vg_mda))
/* Don't move mda: needs writing to disk. */
mda_set_ignored(vg_mda, b->mda_ignored);
mda_set_ignored(mda, b->mda_ignored);
return 1;
}
unsigned pv_mda_set_ignored(const struct physical_volume *pv, unsigned mda_ignored)
{
struct lvmcache_info *info;
struct metadata_area *mda, *vg_mda, *tmda;
struct dm_list *mdas_in_use, *mdas_ignored, *mdas_to_change;
struct _pv_mda_set_ignored_baton baton;
struct metadata_area *mda;
if (!(info = info_from_pvid((const char *)&pv->id.uuid, 0)))
if (!(info = lvmcache_info_from_pvid((const char *)&pv->id.uuid, 0)))
return_0;
mdas_in_use = &pv->fid->metadata_areas_in_use;
mdas_ignored = &pv->fid->metadata_areas_ignored;
mdas_to_change = mda_ignored ? mdas_in_use : mdas_ignored;
baton.mda_ignored = mda_ignored;
baton.mdas_in_use = &pv->fid->metadata_areas_in_use;
baton.mdas_ignored = &pv->fid->metadata_areas_ignored;
baton.mdas_to_change = baton.mda_ignored ? baton.mdas_in_use : baton.mdas_ignored;
if (is_orphan(pv)) {
dm_list_iterate_items(mda, mdas_to_change)
mda_set_ignored(mda, mda_ignored);
dm_list_iterate_items(mda, baton.mdas_to_change)
mda_set_ignored(mda, baton.mda_ignored);
return 1;
}
@ -288,22 +328,8 @@ unsigned pv_mda_set_ignored(const struct physical_volume *pv, unsigned mda_ignor
/* FIXME: Try not to update the cache here! Also, try to iterate over
* PV mdas only using the format instance's index somehow
* (i.e. try to avoid using mda_locn_match call). */
dm_list_iterate_items(mda, &info->mdas) {
if (mda_is_ignored(mda) && !mda_ignored)
/* Changing an ignored mda to one in_use requires moving it */
dm_list_iterate_items_safe(vg_mda, tmda, mdas_ignored)
if (mda_locns_match(mda, vg_mda)) {
mda_set_ignored(vg_mda, mda_ignored);
dm_list_move(mdas_in_use, &vg_mda->list);
}
dm_list_iterate_items_safe(vg_mda, tmda, mdas_in_use)
if (mda_locns_match(mda, vg_mda))
/* Don't move mda: needs writing to disk. */
mda_set_ignored(vg_mda, mda_ignored);
mda_set_ignored(mda, mda_ignored);
}
lvmcache_foreach_mda(info, _pv_mda_set_ignored_one, &baton);
return 1;
}

View File

@ -84,7 +84,7 @@ void release_vg(struct volume_group *vg)
/* Check if there are any vginfo holders */
if (vg->vginfo &&
!vginfo_holders_dec_and_test_for_zero(vg->vginfo))
!lvmcache_vginfo_holders_dec_and_test_for_zero(vg->vginfo))
return;
_free_vg(vg);

View File

@ -587,7 +587,7 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
}
dm_list_iterate_items(sl, vgids) {
vgid = sl->str;
if (!(vgid) || !(vg_name = vgname_from_vgid(cmd->mem, vgid)))
if (!(vgid) || !(vg_name = lvmcache_vgname_from_vgid(cmd->mem, vgid)))
continue;
ret_max = _process_one_vg(cmd, vg_name, vgid, &tags,
&arg_vgnames,

View File

@ -87,7 +87,7 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
dm_list_iterate_items(sl, vgids) {
vgid = sl->str;
if (!vgid || !(vg_name = vgname_from_vgid(NULL, vgid)))
if (!vgid || !(vg_name = lvmcache_vgname_from_vgid(NULL, vgid)))
continue;
if (!strcmp(vg_name, vg_name_old)) {
if (match) {
@ -102,7 +102,7 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
log_suppress(2);
found_id = id_read_format(&id, vg_name_old);
log_suppress(0);
if (found_id && (vg_name = vgname_from_vgid(cmd->mem, (char *)id.uuid))) {
if (found_id && (vg_name = lvmcache_vgname_from_vgid(cmd->mem, (char *)id.uuid))) {
vg_name_old = vg_name;
vgid = (char *)id.uuid;
} else