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:
parent
5fa417a9c0
commit
8e5f7cf3dc
368
lib/cache/lvmcache.c
vendored
368
lib/cache/lvmcache.c
vendored
@ -28,6 +28,43 @@
|
|||||||
#include "format1.h"
|
#include "format1.h"
|
||||||
#include "config.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 *_pvid_hash = NULL;
|
||||||
static struct dm_hash_table *_vgid_hash = NULL;
|
static struct dm_hash_table *_vgid_hash = NULL;
|
||||||
static struct dm_hash_table *_vgname_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;
|
char *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
if (!(vginfo = vginfo_from_vgid((const char *)&vg->id))) {
|
if (!(vginfo = lvmcache_vginfo_from_vgid((const char *)&vg->id))) {
|
||||||
stack;
|
stack;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -147,7 +184,7 @@ static void _update_cache_info_lock_state(struct lvmcache_info *info,
|
|||||||
* Cache becomes invalid whenever lock state changes unless
|
* Cache becomes invalid whenever lock state changes unless
|
||||||
* exclusive VG_GLOBAL is held (i.e. while scanning).
|
* 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;
|
info->status |= CACHE_INVALID;
|
||||||
*cached_vgmetadata_valid = 0;
|
*cached_vgmetadata_valid = 0;
|
||||||
}
|
}
|
||||||
@ -176,7 +213,7 @@ static void _update_cache_lock_state(const char *vgname, int locked)
|
|||||||
{
|
{
|
||||||
struct lvmcache_vginfo *vginfo;
|
struct lvmcache_vginfo *vginfo;
|
||||||
|
|
||||||
if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
|
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_update_cache_vginfo_lock_state(vginfo, locked);
|
_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_vginfo *vginfo;
|
||||||
struct lvmcache_info *info;
|
struct lvmcache_info *info;
|
||||||
|
|
||||||
if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
|
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -220,7 +257,7 @@ void lvmcache_commit_metadata(const char *vgname)
|
|||||||
{
|
{
|
||||||
struct lvmcache_vginfo *vginfo;
|
struct lvmcache_vginfo *vginfo;
|
||||||
|
|
||||||
if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
|
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (vginfo->precommitted) {
|
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 */
|
/* Indicate that PVs could now be missing from the cache */
|
||||||
init_full_scan_done(0);
|
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);
|
_drop_metadata(vgname, drop_precommitted);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,7 +354,7 @@ void lvmcache_lock_vgname(const char *vgname, int read_only __attribute__((unuse
|
|||||||
_vgs_locked++;
|
_vgs_locked++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vgname_is_locked(const char *vgname)
|
int lvmcache_vgname_is_locked(const char *vgname)
|
||||||
{
|
{
|
||||||
if (!_lock_hash)
|
if (!_lock_hash)
|
||||||
return 0;
|
return 0;
|
||||||
@ -340,7 +377,7 @@ void lvmcache_unlock_vgname(const char *vgname)
|
|||||||
dev_close_all();
|
dev_close_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
int vgs_locked(void)
|
int lvmcache_vgs_locked(void)
|
||||||
{
|
{
|
||||||
return _vgs_locked;
|
return _vgs_locked;
|
||||||
}
|
}
|
||||||
@ -366,12 +403,12 @@ static void _vginfo_detach_info(struct lvmcache_info *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If vgid supplied, require a match. */
|
/* 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;
|
struct lvmcache_vginfo *vginfo;
|
||||||
|
|
||||||
if (!vgname)
|
if (!vgname)
|
||||||
return vginfo_from_vgid(vgid);
|
return lvmcache_vginfo_from_vgid(vgid);
|
||||||
|
|
||||||
if (!_vgname_hash)
|
if (!_vgname_hash)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -388,7 +425,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, 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_vginfo *vginfo;
|
||||||
struct lvmcache_info *info;
|
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;
|
struct device_list *devl;
|
||||||
char vgid_found[ID_LEN + 1] __attribute__((aligned(8)));
|
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;
|
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 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))
|
strncmp(vginfo->vgid, vgid_found, ID_LEN))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -439,7 +476,7 @@ out:
|
|||||||
return vginfo->fmt;
|
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;
|
struct lvmcache_vginfo *vginfo;
|
||||||
char id[ID_LEN + 1] __attribute__((aligned(8)));
|
char id[ID_LEN + 1] __attribute__((aligned(8)));
|
||||||
@ -457,12 +494,12 @@ struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
|
|||||||
return vginfo;
|
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;
|
struct lvmcache_vginfo *vginfo;
|
||||||
const char *vgname = NULL;
|
const char *vgname = NULL;
|
||||||
|
|
||||||
if ((vginfo = vginfo_from_vgid(vgid)))
|
if ((vginfo = lvmcache_vginfo_from_vgid(vgid)))
|
||||||
vgname = vginfo->vgname;
|
vgname = vginfo->vgname;
|
||||||
|
|
||||||
if (mem && 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
|
* So if the VG appears to be unlocked here, it should be safe
|
||||||
* to use the cached value.
|
* 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;
|
return 1;
|
||||||
|
|
||||||
if (!(info->status & CACHE_LOCKED))
|
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
|
* If valid_only is set, data will only be returned if the cached data is
|
||||||
* known still to be valid.
|
* 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;
|
struct lvmcache_info *info;
|
||||||
char id[ID_LEN + 1] __attribute__((aligned(8)));
|
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;
|
struct lvmcache_info *info;
|
||||||
char *vgname;
|
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);
|
log_error("Couldn't find device with uuid %s.", pvid);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
info = info_from_pvid(pvid, 0);
|
info = lvmcache_info_from_pvid(pvid, 0);
|
||||||
if (!info)
|
if (!info)
|
||||||
return_NULL;
|
return_NULL;
|
||||||
|
|
||||||
@ -644,7 +681,7 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
|
|||||||
struct format_instance *fid;
|
struct format_instance *fid;
|
||||||
struct format_instance_ctx fic;
|
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;
|
return NULL;
|
||||||
|
|
||||||
if (!_vginfo_is_valid(vginfo))
|
if (!_vginfo_is_valid(vginfo))
|
||||||
@ -708,7 +745,8 @@ bad:
|
|||||||
return NULL;
|
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.",
|
log_debug("VG %s decrementing %d holder(s) at %p.",
|
||||||
vginfo->cached_vg->name, vginfo->holders, vginfo->cached_vg);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd,
|
struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd,
|
||||||
int include_internal)
|
int include_internal)
|
||||||
@ -798,7 +837,7 @@ struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
|
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
|
||||||
return pvids;
|
return pvids;
|
||||||
|
|
||||||
dm_list_iterate_items(info, &vginfo->infos) {
|
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 lvmcache_info *info;
|
||||||
struct label *label;
|
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))) {
|
if (label_read(info->dev, &label, UINT64_C(0))) {
|
||||||
info = (struct lvmcache_info *) label->info;
|
info = (struct lvmcache_info *) label->info;
|
||||||
if (id_equal(pvid, (struct id *) &info->dev->pvid)) {
|
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;
|
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)
|
unsigned *scan_done_once, uint64_t *label_sector)
|
||||||
{
|
{
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
@ -863,7 +902,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *pvid_from_devname(struct cmd_context *cmd,
|
const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
|
||||||
const char *devname)
|
const char *devname)
|
||||||
{
|
{
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
@ -889,7 +928,7 @@ static int _free_vginfo(struct lvmcache_vginfo *vginfo)
|
|||||||
|
|
||||||
_free_cached_vgmetadata(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) {
|
if (vginfo == primary_vginfo) {
|
||||||
dm_hash_remove(_vgname_hash, vginfo->vgname);
|
dm_hash_remove(_vgname_hash, vginfo->vgname);
|
||||||
@ -910,7 +949,7 @@ static int _free_vginfo(struct lvmcache_vginfo *vginfo)
|
|||||||
dm_free(vginfo->creation_host);
|
dm_free(vginfo->creation_host);
|
||||||
|
|
||||||
if (*vginfo->vgid && _vgid_hash &&
|
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_hash_remove(_vgid_hash, vginfo->vgid);
|
||||||
|
|
||||||
dm_list_del(&vginfo->list);
|
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.
|
* Nothing to do if already stored with same pvid.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (((dm_hash_lookup(_pvid_hash, pvid)) == info) &&
|
if (((dm_hash_lookup(_pvid_hash, pvid)) == info) &&
|
||||||
!strcmp(info->dev->pvid, pvid))
|
!strcmp(info->dev->pvid, pvid))
|
||||||
return 1;
|
return 1;
|
||||||
@ -1110,7 +1150,7 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
|||||||
_drop_vginfo(info, info->vginfo);
|
_drop_vginfo(info, info->vginfo);
|
||||||
|
|
||||||
/* Get existing vginfo or create new one */
|
/* 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.
|
/*** FIXME - vginfo ends up duplicated instead of renamed.
|
||||||
// Renaming? This lookup fails.
|
// Renaming? This lookup fails.
|
||||||
if ((vginfo = vginfo_from_vgid(vgid))) {
|
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.
|
* If we're scanning and there's an invalidated entry, remove it.
|
||||||
* Otherwise we risk bogus warnings of duplicate VGs.
|
* 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)) {
|
_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) {
|
if (!orphan_vginfo) {
|
||||||
log_error(INTERNAL_ERROR "Orphan vginfo %s lost from cache.",
|
log_error(INTERNAL_ERROR "Orphan vginfo %s lost from cache.",
|
||||||
primary_vginfo->fmt->orphan_vg_name);
|
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 */
|
else if (!_lvmcache_update_vgid(NULL, vginfo, vgid)) /* Orphans */
|
||||||
return_0;
|
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! */
|
/* FIXME Check consistency of list! */
|
||||||
vginfo->fmt = fmt;
|
vginfo->fmt = fmt;
|
||||||
@ -1282,6 +1322,8 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
|
|||||||
const char *vgname, const char *vgid,
|
const char *vgname, const char *vgid,
|
||||||
uint32_t vgstatus, const char *creation_host)
|
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) {
|
if (!vgname && !info->vginfo) {
|
||||||
log_error(INTERNAL_ERROR "NULL vgname handed to cache");
|
log_error(INTERNAL_ERROR "NULL vgname handed to cache");
|
||||||
/* FIXME Remove this */
|
/* FIXME Remove this */
|
||||||
@ -1319,7 +1361,7 @@ int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
|
|||||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||||
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
|
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
|
||||||
/* FIXME Could pvl->pv->dev->pvid ever be different? */
|
/* 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,
|
!lvmcache_update_vgname_and_id(info, vg->name,
|
||||||
(char *) &vg->id,
|
(char *) &vg->id,
|
||||||
vg->status, NULL))
|
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);
|
strncpy(pvid_s, pvid, sizeof(pvid_s) - 1);
|
||||||
pvid_s[sizeof(pvid_s) - 1] = '\0';
|
pvid_s[sizeof(pvid_s) - 1] = '\0';
|
||||||
|
|
||||||
if (!(existing = info_from_pvid(pvid_s, 0)) &&
|
if (!(existing = lvmcache_info_from_pvid(pvid_s, 0)) &&
|
||||||
!(existing = info_from_pvid(dev->pvid, 0))) {
|
!(existing = lvmcache_info_from_pvid(dev->pvid, 0))) {
|
||||||
if (!(label = label_create(labeller)))
|
if (!(label = label_create(labeller)))
|
||||||
return_NULL;
|
return_NULL;
|
||||||
if (!(info = dm_zalloc(sizeof(*info)))) {
|
if (!(info = dm_zalloc(sizeof(*info)))) {
|
||||||
@ -1520,3 +1562,259 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans)
|
|||||||
if (retain_orphans)
|
if (retain_orphans)
|
||||||
init_lvmcache_orphans(cmd);
|
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
105
lib/cache/lvmcache.h
vendored
@ -24,50 +24,19 @@
|
|||||||
#define ORPHAN_PREFIX VG_ORPHANS
|
#define ORPHAN_PREFIX VG_ORPHANS
|
||||||
#define ORPHAN_VG_NAME(fmt) ORPHAN_PREFIX "_" fmt
|
#define ORPHAN_VG_NAME(fmt) ORPHAN_PREFIX "_" fmt
|
||||||
|
|
||||||
#define CACHE_INVALID 0x00000001
|
|
||||||
#define CACHE_LOCKED 0x00000002
|
|
||||||
|
|
||||||
/* LVM specific per-volume info */
|
/* LVM specific per-volume info */
|
||||||
/* Eventual replacement for struct physical_volume perhaps? */
|
/* Eventual replacement for struct physical_volume perhaps? */
|
||||||
|
|
||||||
struct cmd_context;
|
struct cmd_context;
|
||||||
struct format_type;
|
struct format_type;
|
||||||
struct volume_group;
|
struct volume_group;
|
||||||
|
struct physical_volume;
|
||||||
struct dm_config_tree;
|
struct dm_config_tree;
|
||||||
|
struct format_instance;
|
||||||
|
struct metadata_area;
|
||||||
|
struct data_area_list;
|
||||||
|
|
||||||
/* One per VG */
|
struct lvmcache_vginfo;
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
int lvmcache_init(void);
|
int lvmcache_init(void);
|
||||||
void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans);
|
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);
|
int lvmcache_verify_lock_order(const char *vgname);
|
||||||
|
|
||||||
/* Queries */
|
/* 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. */
|
/* Decrement and test if there are still vg holders in vginfo. */
|
||||||
int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo);
|
int lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo);
|
||||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
|
|
||||||
|
struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname,
|
||||||
const char *vgid);
|
const char *vgid);
|
||||||
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
|
struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid);
|
||||||
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);
|
||||||
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 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);
|
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);
|
const char *dev_name);
|
||||||
char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid);
|
char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid);
|
||||||
int vgs_locked(void);
|
int lvmcache_vgs_locked(void);
|
||||||
int vgname_is_locked(const char *vgname);
|
int lvmcache_vgname_is_locked(const char *vgname);
|
||||||
|
|
||||||
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
|
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
|
||||||
/* If include_internal is not set, return only proper vg names. */
|
/* 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_drop_metadata(const char *vgname, int drop_precommitted);
|
||||||
void lvmcache_commit_metadata(const char *vgname);
|
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
|
#endif
|
||||||
|
@ -586,7 +586,6 @@ static void _close(struct device *dev)
|
|||||||
|
|
||||||
static int _dev_close(struct device *dev, int immediate)
|
static int _dev_close(struct device *dev, int immediate)
|
||||||
{
|
{
|
||||||
struct lvmcache_info *info;
|
|
||||||
|
|
||||||
if (dev->fd < 0) {
|
if (dev->fd < 0) {
|
||||||
log_error("Attempt to close device '%s' "
|
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 */
|
/* Close unless device is known to belong to a locked VG */
|
||||||
if (immediate ||
|
if (immediate ||
|
||||||
(dev->open_count < 1 &&
|
(dev->open_count < 1 && !lvmcache_pvid_is_locked(dev->pvid)))
|
||||||
(!(info = info_from_pvid(dev->pvid, 0)) ||
|
|
||||||
!info->vginfo ||
|
|
||||||
!vgname_is_locked(info->vginfo->vgname))))
|
|
||||||
_close(dev);
|
_close(dev);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -335,9 +335,9 @@ static void __update_lvmcache(const struct format_type *fmt,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
|
lvmcache_set_device_size(info, xlate32(dl->pvd.pv_size) << SECTOR_SHIFT);
|
||||||
dm_list_init(&info->mdas);
|
lvmcache_del_mdas(info);
|
||||||
info->status &= ~CACHE_INVALID;
|
lvmcache_make_valid(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct disk_list *__read_disk(const struct format_type *fmt,
|
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);
|
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.
|
* Build a list of pv_d's structures, allocated from mem.
|
||||||
* We keep track of the first object allocated from the pool
|
* We keep track of the first object allocated from the pool
|
||||||
@ -462,29 +484,31 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
|
|||||||
{
|
{
|
||||||
struct dev_iter *iter;
|
struct dev_iter *iter;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct disk_list *data = NULL;
|
|
||||||
struct lvmcache_vginfo *vginfo;
|
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 */
|
/* Fast path if we already saw this VG and cached the list of PVs */
|
||||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
|
if (vg_name && (vginfo = lvmcache_vginfo_from_vgname(vg_name, NULL))) {
|
||||||
vginfo->infos.n) {
|
|
||||||
dm_list_iterate_items(info, &vginfo->infos) {
|
lvmcache_foreach_pv(vginfo, _read_pv_in_vg, &baton);
|
||||||
dev = info->dev;
|
|
||||||
if (!dev || !(data = read_disk(fmt, dev, mem, vg_name)))
|
if (!baton.empty) {
|
||||||
break;
|
/* Did we find the whole VG? */
|
||||||
_add_pv_to_list(head, data);
|
if (!vg_name || is_orphan_vg(vg_name) ||
|
||||||
|
(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); */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* Failed */
|
|
||||||
dm_list_init(head);
|
|
||||||
/* vgcache_del(vg_name); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(iter = dev_iter_create(filter, 1))) {
|
if (!(iter = dev_iter_create(filter, 1))) {
|
||||||
@ -494,8 +518,8 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
|
|||||||
|
|
||||||
/* Otherwise do a complete scan */
|
/* Otherwise do a complete scan */
|
||||||
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
|
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
|
||||||
if ((data = read_disk(fmt, dev, mem, vg_name))) {
|
if ((baton.data = read_disk(fmt, dev, mem, vg_name))) {
|
||||||
_add_pv_to_list(head, data);
|
_add_pv_to_list(head, baton.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dev_iter_destroy(iter);
|
dev_iter_destroy(iter);
|
||||||
|
@ -413,10 +413,8 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
|
|||||||
pv->vg_name, NULL, 0)))
|
pv->vg_name, NULL, 0)))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
info->device_size = pv->size << SECTOR_SHIFT;
|
lvmcache_update_pv(info, pv, fmt);
|
||||||
info->fmt = fmt;
|
lvmcache_del_mdas(info);
|
||||||
|
|
||||||
dm_list_init(&info->mdas);
|
|
||||||
|
|
||||||
dm_list_init(&pvs);
|
dm_list_init(&pvs);
|
||||||
|
|
||||||
|
@ -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,
|
if (!(info = lvmcache_add(l, (char *)pvd->pv_uuid, dev, vgname, vgid,
|
||||||
exported)))
|
exported)))
|
||||||
return_0;
|
return_0;
|
||||||
*label = info->label;
|
*label = lvmcache_get_label(info);
|
||||||
|
|
||||||
info->device_size = xlate32(pvd->pv_size) << SECTOR_SHIFT;
|
lvmcache_set_device_size(info, xlate32(pvd->pv_size) << SECTOR_SHIFT);
|
||||||
dm_list_init(&info->mdas);
|
lvmcache_del_mdas(info);
|
||||||
|
lvmcache_make_valid(info);
|
||||||
info->status &= ~CACHE_INVALID;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -101,12 +101,11 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
|
|||||||
(char *) &vgid, 0)))
|
(char *) &vgid, 0)))
|
||||||
return_0;
|
return_0;
|
||||||
if (label)
|
if (label)
|
||||||
*label = info->label;
|
*label = lvmcache_get_label(info);
|
||||||
|
|
||||||
info->device_size = xlate32_be(pd->pl_blocks) << SECTOR_SHIFT;
|
lvmcache_set_device_size(info, xlate32_be(pd->pl_blocks) << SECTOR_SHIFT);
|
||||||
dm_list_init(&info->mdas);
|
lvmcache_del_mdas(info);
|
||||||
|
lvmcache_make_valid(info);
|
||||||
info->status &= ~CACHE_INVALID;
|
|
||||||
|
|
||||||
pl->dev = dev;
|
pl->dev = dev;
|
||||||
pl->pv = NULL;
|
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 _read_pool_pv_baton {
|
||||||
struct lvmcache_vginfo *vginfo, struct dm_list *head,
|
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 _read_pool_pv_baton *b = baton;
|
||||||
|
|
||||||
|
b->empty = 0;
|
||||||
|
|
||||||
|
if (lvmcache_device(info) &&
|
||||||
|
!(b->pl = read_pool_disk(b->fmt, lvmcache_device(info), b->mem, b->vgname)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to keep track of the total expected number
|
||||||
|
* of devices per subpool
|
||||||
|
*/
|
||||||
|
if (!b->sp_count) {
|
||||||
|
/* FIXME pl left uninitialised if !info->dev */
|
||||||
|
if (!b->pl) {
|
||||||
|
log_error(INTERNAL_ERROR "device is missing");
|
||||||
|
dm_pool_destroy(b->tmpmem);
|
||||||
|
b->failed = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
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",
|
||||||
|
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 (b->sp_count != b->pl->pd.pl_subpools)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
_add_pl_to_list(b->head, b->pl);
|
||||||
|
|
||||||
|
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 *devcount)
|
||||||
{
|
{
|
||||||
struct lvmcache_info *info;
|
|
||||||
struct pool_list *pl = NULL;
|
|
||||||
struct dm_pool *tmpmem;
|
|
||||||
|
|
||||||
uint32_t sp_count = 0;
|
|
||||||
uint32_t *sp_devs = NULL;
|
|
||||||
uint32_t i;
|
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
|
/* FIXME: maybe should return a different error in memory
|
||||||
* allocation failure */
|
* allocation failure */
|
||||||
if (!(tmpmem = dm_pool_create("pool read_vg", 512)))
|
if (!(b->tmpmem = dm_pool_create("pool read_vg", 512)))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
dm_list_iterate_items(info, &vginfo->infos) {
|
lvmcache_foreach_pv(vginfo, _read_pool_pv, b);
|
||||||
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) {
|
|
||||||
/* FIXME pl left uninitialised if !info->dev */
|
|
||||||
if (!pl) {
|
|
||||||
log_error(INTERNAL_ERROR "device is missing");
|
|
||||||
dm_pool_destroy(tmpmem);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
sp_count = pl->pd.pl_subpools;
|
|
||||||
if (!(sp_devs =
|
|
||||||
dm_pool_zalloc(tmpmem,
|
|
||||||
sizeof(uint32_t) * sp_count))) {
|
|
||||||
log_error("Unable to allocate %d 32-bit uints",
|
|
||||||
sp_count);
|
|
||||||
dm_pool_destroy(tmpmem);
|
|
||||||
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;
|
|
||||||
|
|
||||||
_add_pl_to_list(head, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
*devcount = 0;
|
*devcount = 0;
|
||||||
for (i = 0; i < sp_count; i++)
|
for (i = 0; i < b->sp_count; i++)
|
||||||
*devcount += sp_devs[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 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -311,29 +334,36 @@ int read_pool_pds(const struct format_type *fmt, const char *vg_name,
|
|||||||
uint32_t totaldevs;
|
uint32_t totaldevs;
|
||||||
int full_scan = -1;
|
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 {
|
do {
|
||||||
/*
|
/*
|
||||||
* If the cache scanning doesn't work, this will never work
|
* If the cache scanning doesn't work, this will never work
|
||||||
*/
|
*/
|
||||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
|
if (vg_name && (vginfo = lvmcache_vginfo_from_vgname(vg_name, NULL)) &&
|
||||||
vginfo->infos.n) {
|
_read_vg_pds(&baton, vginfo, &totaldevs) && !baton.empty)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If we found all the devices we were expecting, return
|
||||||
|
* success
|
||||||
|
*/
|
||||||
|
if (dm_list_size(pdhead) == totaldevs)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {
|
/*
|
||||||
/*
|
* accept partial pool if we've done a full rescan of
|
||||||
* If we found all the devices we were
|
* the cache
|
||||||
* expecting, return success
|
*/
|
||||||
*/
|
if (full_scan > 0)
|
||||||
if (dm_list_size(pdhead) == totaldevs)
|
return 1;
|
||||||
return 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* accept partial pool if we've done a full
|
|
||||||
* rescan of the cache
|
|
||||||
*/
|
|
||||||
if (full_scan > 0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Failed */
|
/* Failed */
|
||||||
dm_list_init(pdhead);
|
dm_list_init(pdhead);
|
||||||
|
|
||||||
|
@ -432,7 +432,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
|
|||||||
"not match expected name %s.", vgname);
|
"not match expected name %s.", vgname);
|
||||||
|
|
||||||
bad:
|
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,
|
lvmcache_update_vgname_and_id(info, FMT_TEXT_ORPHAN_VG_NAME,
|
||||||
FMT_TEXT_ORPHAN_VG_NAME, 0, NULL);
|
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));
|
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 */
|
/* Only for orphans */
|
||||||
static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv)
|
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 lvmcache_info *info;
|
||||||
struct mda_context *mdac;
|
struct mda_context *mdac;
|
||||||
struct metadata_area *mda;
|
struct metadata_area *mda;
|
||||||
|
struct _write_single_mda_baton baton;
|
||||||
unsigned mda_index;
|
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. */
|
/* Add a new cache entry with PV info or update existing one. */
|
||||||
if (!(info = lvmcache_add(fmt->labeller, (const char *) &pv->id,
|
if (!(info = lvmcache_add(fmt->labeller, (const char *) &pv->id,
|
||||||
pv->dev, pv->vg_name, NULL, 0)))
|
pv->dev, pv->vg_name, NULL, 0)))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
label = info->label;
|
label = lvmcache_get_label(info);
|
||||||
label->sector = pv->label_sector;
|
label->sector = pv->label_sector;
|
||||||
|
|
||||||
info->device_size = pv->size << SECTOR_SHIFT;
|
lvmcache_update_pv(info, pv, fmt);
|
||||||
info->fmt = fmt;
|
|
||||||
|
|
||||||
/* Flush all cached metadata areas, we will reenter new/modified ones. */
|
/* Flush all cached metadata areas, we will reenter new/modified ones. */
|
||||||
if (info->mdas.n)
|
lvmcache_del_mdas(info);
|
||||||
del_mdas(&info->mdas);
|
|
||||||
else
|
|
||||||
dm_list_init(&info->mdas);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add all new or modified metadata areas for this PV stored in
|
* Add all new or modified metadata areas for this PV stored in
|
||||||
@ -1299,8 +1320,10 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
|
|||||||
dev_name(mdac->area.dev),
|
dev_name(mdac->area.dev),
|
||||||
mdac->area.start >> SECTOR_SHIFT,
|
mdac->area.start >> SECTOR_SHIFT,
|
||||||
mdac->area.size >> SECTOR_SHIFT);
|
mdac->area.size >> SECTOR_SHIFT);
|
||||||
add_mda(fmt, NULL, &info->mdas, mdac->area.dev,
|
|
||||||
mdac->area.start, mdac->area.size, mda_is_ignored(mda));
|
// 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
|
* pvcreate --restorefile. However, we can can have this value in
|
||||||
* metadata which will override the value in the PV header.
|
* 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;
|
return_0;
|
||||||
|
|
||||||
if (!dev_open(pv->dev))
|
if (!dev_open(pv->dev))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
dm_list_iterate_items(mda, &info->mdas) {
|
baton.pv = pv;
|
||||||
mdac = mda->metadata_locn;
|
baton.fmt = fmt;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
dev_close(pv->dev);
|
||||||
return_0;
|
return_0;
|
||||||
}
|
}
|
||||||
@ -1384,68 +1393,6 @@ static int _add_raw(struct dm_list *raw_list, struct device_area *dev_area)
|
|||||||
return 1;
|
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.
|
* 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 label *label;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct lvmcache_info *info;
|
|
||||||
|
|
||||||
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
|
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
if (!(label_read(dev, &label, UINT64_C(0))))
|
if (!(label_read(dev, &label, UINT64_C(0))))
|
||||||
return_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 0;
|
||||||
|
|
||||||
return 1;
|
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.
|
* reread PV mda information from the cache and add it to vg->fid.
|
||||||
*/
|
*/
|
||||||
else {
|
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));
|
log_error("PV %s missing from cache", pv_dev_name(pv));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fmt != info->fmt) {
|
if (!lvmcache_check_format(info, fmt))
|
||||||
log_error("PV %s is a different format (seqno %s)",
|
return_0;
|
||||||
pv_dev_name(pv), info->fmt->name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fid_add_mdas(vg->fid, &info->mdas, pvid, ID_LEN))
|
if (!lvmcache_fid_add_mdas_pv(info, fid))
|
||||||
return_0;
|
return_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1736,8 +1678,8 @@ static int _create_pv_text_instance(struct format_instance *fid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fic->type & FMT_INSTANCE_MDAS &&
|
if (fic->type & FMT_INSTANCE_MDAS &&
|
||||||
(info = info_from_pvid(fic->context.pv_id, 0)))
|
(info = lvmcache_info_from_pvid(fic->context.pv_id, 0)))
|
||||||
fid_add_mdas(fid, &info->mdas, fic->context.pv_id, ID_LEN);
|
lvmcache_fid_add_mdas_pv(info, fid);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1801,7 +1743,6 @@ static int _create_vg_text_instance(struct format_instance *fid,
|
|||||||
struct dm_list *dir_list, *raw_list;
|
struct dm_list *dir_list, *raw_list;
|
||||||
struct text_context tc;
|
struct text_context tc;
|
||||||
struct lvmcache_vginfo *vginfo;
|
struct lvmcache_vginfo *vginfo;
|
||||||
struct lvmcache_info *info;
|
|
||||||
const char *vg_name, *vg_id;
|
const char *vg_name, *vg_id;
|
||||||
|
|
||||||
if (!(fidtc = (struct text_fid_context *)
|
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) {
|
if (type & FMT_INSTANCE_MDAS) {
|
||||||
/* Scan PVs in VG for any further MDAs */
|
/* Scan PVs in VG for any further MDAs */
|
||||||
lvmcache_label_scan(fid->fmt->cmd, 0);
|
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;
|
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 */
|
/* 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;
|
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)));
|
char buffer[64] __attribute__((aligned(8)));
|
||||||
|
|
||||||
if (!id_write_format(&id, buffer, sizeof(buffer)))
|
if (!id_write_format(&id, buffer, sizeof(buffer)))
|
||||||
|
@ -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);
|
struct device *dev, uint64_t start, uint64_t size, unsigned ignored);
|
||||||
void del_mdas(struct dm_list *mdas);
|
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
|
#endif
|
||||||
|
@ -190,7 +190,7 @@ static int _read_pv(struct format_instance *fid,
|
|||||||
/*
|
/*
|
||||||
* Convert the uuid into a device.
|
* 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))) {
|
&pv->label_sector))) {
|
||||||
char buffer[64] __attribute__((aligned(8)));
|
char buffer[64] __attribute__((aligned(8)));
|
||||||
|
|
||||||
|
@ -21,17 +21,7 @@
|
|||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "uuid.h"
|
#include "uuid.h"
|
||||||
|
|
||||||
/* On disk */
|
/* disk_locn and data_area_list are defined in format-text.h */
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Fields with the suffix _xl should be xlate'd wherever they appear */
|
/* Fields with the suffix _xl should be xlate'd wherever they appear */
|
||||||
/* On disk */
|
/* On disk */
|
||||||
|
@ -35,15 +35,41 @@ static int _text_can_handle(struct labeller *l __attribute__((unused)),
|
|||||||
return 0;
|
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)
|
static int _text_write(struct label *label, void *buf)
|
||||||
{
|
{
|
||||||
struct label_header *lh = (struct label_header *) buf;
|
struct label_header *lh = (struct label_header *) buf;
|
||||||
struct pv_header *pvhdr;
|
struct pv_header *pvhdr;
|
||||||
struct lvmcache_info *info;
|
struct lvmcache_info *info;
|
||||||
struct disk_locn *pvh_dlocn_xl;
|
struct _da_setup_baton baton;
|
||||||
struct metadata_area *mda;
|
|
||||||
struct mda_context *mdac;
|
|
||||||
struct data_area_list *da;
|
|
||||||
char buffer[64] __attribute__((aligned(8)));
|
char buffer[64] __attribute__((aligned(8)));
|
||||||
int da1, mda1, mda2;
|
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));
|
pvhdr = (struct pv_header *) ((char *) buf + xlate32(lh->offset_xl));
|
||||||
info = (struct lvmcache_info *) label->info;
|
info = (struct lvmcache_info *) label->info;
|
||||||
pvhdr->device_size_xl = xlate64(info->device_size);
|
pvhdr->device_size_xl = xlate64(lvmcache_device_size(info));
|
||||||
memcpy(pvhdr->pv_uuid, &info->dev->pvid, sizeof(struct id));
|
memcpy(pvhdr->pv_uuid, &lvmcache_device(info)->pvid, sizeof(struct id));
|
||||||
if (!id_write_format((const struct id *)pvhdr->pv_uuid, buffer,
|
if (!id_write_format((const struct id *)pvhdr->pv_uuid, buffer,
|
||||||
sizeof(buffer))) {
|
sizeof(buffer))) {
|
||||||
stack;
|
stack;
|
||||||
buffer[0] = '\0';
|
buffer[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
|
baton.dev = lvmcache_device(info);
|
||||||
|
|
||||||
/* List of data areas (holding PEs) */
|
/* List of data areas (holding PEs) */
|
||||||
dm_list_iterate_items(da, &info->das) {
|
baton.pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
|
||||||
pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset);
|
lvmcache_foreach_da(info, _da_setup, &baton);
|
||||||
pvh_dlocn_xl->size = xlate64(da->disk_locn.size);
|
|
||||||
pvh_dlocn_xl++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NULL-termination */
|
/* NULL-termination */
|
||||||
pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
|
baton.pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
|
||||||
pvh_dlocn_xl->size = xlate64(UINT64_C(0));
|
baton.pvh_dlocn_xl->size = xlate64(UINT64_C(0));
|
||||||
pvh_dlocn_xl++;
|
baton.pvh_dlocn_xl++;
|
||||||
|
|
||||||
/* List of metadata area header locations */
|
/* List of metadata area header locations */
|
||||||
dm_list_iterate_items(mda, &info->mdas) {
|
lvmcache_foreach_mda(info, _mda_setup, &baton);
|
||||||
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++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NULL-termination */
|
/* NULL-termination */
|
||||||
pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
|
baton.pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
|
||||||
pvh_dlocn_xl->size = xlate64(UINT64_C(0));
|
baton.pvh_dlocn_xl->size = xlate64(UINT64_C(0));
|
||||||
|
|
||||||
/* Create debug message with da and mda locations */
|
/* Create debug message with da and mda locations */
|
||||||
if (xlate64(pvhdr->disk_areas_xl[0].offset) ||
|
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"
|
"%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) ? " da1 (" : "",
|
||||||
(da1 > -1) ? 1 : 0,
|
(da1 > -1) ? 1 : 0,
|
||||||
(da1 > -1) ? xlate64(pvhdr->disk_areas_xl[da1].offset) >> SECTOR_SHIFT : 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) {
|
if (da1 < 0) {
|
||||||
log_error(INTERNAL_ERROR "%s label header currently requires "
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,6 +264,62 @@ static int _text_initialise_label(struct labeller *l __attribute__((unused)),
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct _update_mda_baton {
|
||||||
|
struct lvmcache_info *info;
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!dev_open_readonly(mdac->area.dev)) {
|
||||||
|
mda_set_ignored(mda, 1);
|
||||||
|
stack;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
log_debug("Ignoring mda on device %s at offset %"PRIu64,
|
||||||
|
dev_name(mdac->area.dev),
|
||||||
|
mdac->area.start);
|
||||||
|
if (!dev_close(mdac->area.dev))
|
||||||
|
stack;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((vgname = vgname_from_mda(fmt, mdah,
|
||||||
|
&mdac->area,
|
||||||
|
&vgid, &vgstatus, &creation_host,
|
||||||
|
&mdac->free_sectors)) &&
|
||||||
|
!lvmcache_update_vgname_and_id(p->info, vgname,
|
||||||
|
(char *) &vgid, vgstatus,
|
||||||
|
creation_host)) {
|
||||||
|
if (!dev_close(mdac->area.dev))
|
||||||
|
stack;
|
||||||
|
return_0;
|
||||||
|
}
|
||||||
|
close_dev:
|
||||||
|
if (!dev_close(mdac->area.dev))
|
||||||
|
stack;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int _text_read(struct labeller *l, struct device *dev, void *buf,
|
static int _text_read(struct labeller *l, struct device *dev, void *buf,
|
||||||
struct label **label)
|
struct label **label)
|
||||||
{
|
{
|
||||||
@ -258,13 +328,7 @@ static int _text_read(struct labeller *l, struct device *dev, void *buf,
|
|||||||
struct lvmcache_info *info;
|
struct lvmcache_info *info;
|
||||||
struct disk_locn *dlocn_xl;
|
struct disk_locn *dlocn_xl;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
struct metadata_area *mda;
|
struct _update_mda_baton baton;
|
||||||
struct id vgid;
|
|
||||||
struct mda_context *mdac;
|
|
||||||
const char *vgname;
|
|
||||||
uint64_t vgstatus;
|
|
||||||
char *creation_host;
|
|
||||||
struct mda_header *mdah;
|
|
||||||
|
|
||||||
pvhdr = (struct pv_header *) ((char *) buf + xlate32(lh->offset_xl));
|
pvhdr = (struct pv_header *) ((char *) buf + xlate32(lh->offset_xl));
|
||||||
|
|
||||||
@ -272,73 +336,34 @@ static int _text_read(struct labeller *l, struct device *dev, void *buf,
|
|||||||
FMT_TEXT_ORPHAN_VG_NAME,
|
FMT_TEXT_ORPHAN_VG_NAME,
|
||||||
FMT_TEXT_ORPHAN_VG_NAME, 0)))
|
FMT_TEXT_ORPHAN_VG_NAME, 0)))
|
||||||
return_0;
|
return_0;
|
||||||
*label = info->label;
|
|
||||||
|
|
||||||
info->device_size = xlate64(pvhdr->device_size_xl);
|
/* this one is leaked forever */
|
||||||
|
*label = lvmcache_get_label(info);
|
||||||
|
|
||||||
if (info->das.n)
|
lvmcache_set_device_size(info, xlate64(pvhdr->device_size_xl));
|
||||||
del_das(&info->das);
|
|
||||||
dm_list_init(&info->das);
|
|
||||||
|
|
||||||
if (info->mdas.n)
|
lvmcache_del_das(info);
|
||||||
del_mdas(&info->mdas);
|
lvmcache_del_mdas(info);
|
||||||
dm_list_init(&info->mdas);
|
|
||||||
|
|
||||||
/* Data areas holding the PEs */
|
/* Data areas holding the PEs */
|
||||||
dlocn_xl = pvhdr->disk_areas_xl;
|
dlocn_xl = pvhdr->disk_areas_xl;
|
||||||
while ((offset = xlate64(dlocn_xl->offset))) {
|
while ((offset = xlate64(dlocn_xl->offset))) {
|
||||||
add_da(NULL, &info->das, offset,
|
lvmcache_add_da(info, offset, xlate64(dlocn_xl->size));
|
||||||
xlate64(dlocn_xl->size));
|
|
||||||
dlocn_xl++;
|
dlocn_xl++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Metadata area headers */
|
/* Metadata area headers */
|
||||||
dlocn_xl++;
|
dlocn_xl++;
|
||||||
while ((offset = xlate64(dlocn_xl->offset))) {
|
while ((offset = xlate64(dlocn_xl->offset))) {
|
||||||
add_mda(info->fmt, NULL, &info->mdas, dev, offset,
|
lvmcache_add_mda(info, dev, offset, xlate64(dlocn_xl->size), 0);
|
||||||
xlate64(dlocn_xl->size), 0);
|
|
||||||
dlocn_xl++;
|
dlocn_xl++;
|
||||||
}
|
}
|
||||||
|
|
||||||
dm_list_iterate_items(mda, &info->mdas) {
|
baton.info = info;
|
||||||
mdac = (struct mda_context *) mda->metadata_locn;
|
baton.label = *label;
|
||||||
if (!dev_open_readonly(mdac->area.dev)) {
|
|
||||||
mda_set_ignored(mda, 1);
|
|
||||||
stack;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!(mdah = raw_read_mda_header(info->fmt, &mdac->area))) {
|
|
||||||
stack;
|
|
||||||
goto close_dev;
|
|
||||||
}
|
|
||||||
mda_set_ignored(mda, rlocn_is_ignored(mdah->raw_locns));
|
|
||||||
|
|
||||||
if (mda_is_ignored(mda)) {
|
lvmcache_foreach_mda(info, _update_mda, &baton);
|
||||||
log_debug("Ignoring mda on device %s at offset %"PRIu64,
|
lvmcache_make_valid(info);
|
||||||
dev_name(mdac->area.dev),
|
|
||||||
mdac->area.start);
|
|
||||||
if (!dev_close(mdac->area.dev))
|
|
||||||
stack;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((vgname = vgname_from_mda(info->fmt, mdah,
|
|
||||||
&mdac->area,
|
|
||||||
&vgid, &vgstatus, &creation_host,
|
|
||||||
&mdac->free_sectors)) &&
|
|
||||||
!lvmcache_update_vgname_and_id(info, vgname,
|
|
||||||
(char *) &vgid, vgstatus,
|
|
||||||
creation_host)) {
|
|
||||||
if (!dev_close(mdac->area.dev))
|
|
||||||
stack;
|
|
||||||
return_0;
|
|
||||||
}
|
|
||||||
close_dev:
|
|
||||||
if (!dev_close(mdac->area.dev))
|
|
||||||
stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
info->status &= ~CACHE_INVALID;
|
|
||||||
|
|
||||||
return 1;
|
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;
|
struct lvmcache_info *info = (struct lvmcache_info *) label->info;
|
||||||
|
|
||||||
if (info->mdas.n)
|
lvmcache_del_mdas(info);
|
||||||
del_mdas(&info->mdas);
|
lvmcache_del_das(info);
|
||||||
if (info->das.n)
|
|
||||||
del_das(&info->das);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _fmt_text_destroy(struct labeller *l)
|
static void _fmt_text_destroy(struct labeller *l)
|
||||||
|
@ -172,9 +172,9 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
if (!found) {
|
if (!found) {
|
||||||
if ((info = info_from_pvid(dev->pvid, 0)))
|
if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
|
||||||
lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
|
lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
|
||||||
info->fmt->orphan_vg_name,
|
lvmcache_fmt(info)->orphan_vg_name,
|
||||||
0, NULL);
|
0, NULL);
|
||||||
log_very_verbose("%s: No label detected", dev_name(dev));
|
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;
|
struct lvmcache_info *info;
|
||||||
int r = 0;
|
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));
|
log_debug("Using cached label for %s", dev_name(dev));
|
||||||
*result = info->label;
|
*result = lvmcache_get_label(info); /* leaked */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dev_open_readonly(dev)) {
|
if (!dev_open_readonly(dev)) {
|
||||||
stack;
|
stack;
|
||||||
|
|
||||||
if ((info = info_from_pvid(dev->pvid, 0)))
|
if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
|
||||||
lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
|
lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
|
||||||
info->fmt->orphan_vg_name,
|
lvmcache_fmt(info)->orphan_vg_name,
|
||||||
0, NULL);
|
0, NULL);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
@ -348,9 +348,9 @@ int label_verify(struct device *dev)
|
|||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
if (!dev_open_readonly(dev)) {
|
if (!dev_open_readonly(dev)) {
|
||||||
if ((info = info_from_pvid(dev->pvid, 0)))
|
if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
|
||||||
lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
|
lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
|
||||||
info->fmt->orphan_vg_name,
|
lvmcache_fmt(info)->orphan_vg_name,
|
||||||
0, NULL);
|
0, NULL);
|
||||||
|
|
||||||
return_0;
|
return_0;
|
||||||
|
@ -1504,7 +1504,7 @@ struct physical_volume * pvcreate_single(struct cmd_context *cmd,
|
|||||||
pp = &default_pp;
|
pp = &default_pp;
|
||||||
|
|
||||||
if (pp->idp) {
|
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))) {
|
(dev != dev_cache_get(pv_name, cmd->filter))) {
|
||||||
if (!id_write_format((const struct id*)&pp->idp->uuid,
|
if (!id_write_format((const struct id*)&pp->idp->uuid,
|
||||||
buffer, sizeof(buffer)))
|
buffer, sizeof(buffer)))
|
||||||
@ -2671,7 +2671,7 @@ int vg_commit(struct volume_group *vg)
|
|||||||
{
|
{
|
||||||
int cache_updated = 0;
|
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 "
|
log_error(INTERNAL_ERROR "Attempt to write new VG metadata "
|
||||||
"without locking %s", vg->name);
|
"without locking %s", vg->name);
|
||||||
return cache_updated;
|
return cache_updated;
|
||||||
@ -2717,6 +2717,31 @@ void vg_revert(struct volume_group *vg)
|
|||||||
remote_revert_cached_metadata(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 */
|
/* Make orphan PVs look like a VG */
|
||||||
static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
|
static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
|
||||||
int warnings,
|
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_ctx fic;
|
||||||
struct format_instance *fid;
|
struct format_instance *fid;
|
||||||
|
const struct format_type *fmt;
|
||||||
struct lvmcache_vginfo *vginfo;
|
struct lvmcache_vginfo *vginfo;
|
||||||
struct lvmcache_info *info;
|
|
||||||
struct pv_list *pvl;
|
|
||||||
struct volume_group *vg = NULL;
|
struct volume_group *vg = NULL;
|
||||||
struct physical_volume *pv = NULL;
|
struct _vg_read_orphan_baton baton;
|
||||||
|
|
||||||
lvmcache_label_scan(cmd, 0);
|
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;
|
return_NULL;
|
||||||
|
|
||||||
if (!(vg = alloc_vg("vg_read_orphans", cmd, orphan_vgname)))
|
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.type = FMT_INSTANCE_VG | FMT_INSTANCE_AUX_MDAS;
|
||||||
fic.context.vg_ref.vg_name = orphan_vgname;
|
fic.context.vg_ref.vg_name = orphan_vgname;
|
||||||
fic.context.vg_ref.vg_id = NULL;
|
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");
|
log_error("Failed to create format instance");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
vg_set_fid(vg, fid);
|
vg_set_fid(vg, fid);
|
||||||
|
|
||||||
dm_list_iterate_items(info, &vginfo->infos) {
|
baton.warnings = warnings;
|
||||||
if (!(pv = _pv_read(cmd, vg->vgmem, dev_name(info->dev),
|
baton.vg = vg;
|
||||||
vg->fid, warnings, 0))) {
|
lvmcache_foreach_pv(vginfo, _vg_read_orphan_pv, &baton);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return vg;
|
return vg;
|
||||||
bad:
|
bad:
|
||||||
free_pv_fid(pv);
|
|
||||||
release_vg(vg);
|
release_vg(vg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -2848,6 +2865,15 @@ static void check_reappeared_pv(struct volume_group *correct_vg,
|
|||||||
"on it, remove volumes and consider vgreduce --removemissing.");
|
"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
|
/* 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).
|
* inconsistent metadata on disk (i.e. the VG write lock is held).
|
||||||
* This guarantees only consistent metadata is returned.
|
* 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 */
|
/* 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, 1))) {
|
if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 1))) {
|
||||||
lvmcache_label_scan(cmd, 0);
|
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 */
|
/* Independent MDAs aren't supported under low memory */
|
||||||
if (!cmd->independent_metadata_areas && critical_section())
|
if (!cmd->independent_metadata_areas && critical_section())
|
||||||
return_NULL;
|
return_NULL;
|
||||||
lvmcache_label_scan(cmd, 2);
|
lvmcache_label_scan(cmd, 2);
|
||||||
if (!(fmt = fmt_from_vgname(vgname, vgid, 0)))
|
if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 0)))
|
||||||
return_NULL;
|
return_NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now determine the correct vgname if none was supplied */
|
/* 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;
|
return_NULL;
|
||||||
|
|
||||||
if (use_precommitted && !(fmt->features & FMT_PRECOMMIT))
|
if (use_precommitted && !(fmt->features & FMT_PRECOMMIT))
|
||||||
@ -3016,18 +3042,17 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
|||||||
* Check it's an orphan without metadata area
|
* Check it's an orphan without metadata area
|
||||||
* not ignored.
|
* not ignored.
|
||||||
*/
|
*/
|
||||||
if (!(info = info_from_pvid(pvl->pv->dev->pvid, 1)) ||
|
if (!(info = lvmcache_info_from_pvid(pvl->pv->dev->pvid, 1)) ||
|
||||||
!info->vginfo || !is_orphan_vg(info->vginfo->vgname)) {
|
!lvmcache_is_orphan(info)) {
|
||||||
inconsistent_pvs = 1;
|
inconsistent_pvs = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (dm_list_size(&info->mdas)) {
|
if (lvmcache_mda_count(info)) {
|
||||||
if (!fid_add_mdas(fid, &info->mdas,
|
if (!lvmcache_fid_add_mdas_pv(info, fid)) {
|
||||||
info->dev->pvid, ID_LEN)) {
|
|
||||||
release_vg(correct_vg);
|
release_vg(correct_vg);
|
||||||
return_NULL;
|
return_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug("Empty mda found for VG %s.", vgname);
|
log_debug("Empty mda found for VG %s.", vgname);
|
||||||
|
|
||||||
if (inconsistent_mdas)
|
if (inconsistent_mdas)
|
||||||
@ -3037,11 +3062,8 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
|||||||
* If any newly-added mdas are in-use then their
|
* If any newly-added mdas are in-use then their
|
||||||
* metadata needs updating.
|
* metadata needs updating.
|
||||||
*/
|
*/
|
||||||
dm_list_iterate_items(mda, &info->mdas)
|
lvmcache_foreach_mda(info, _check_mda_in_use,
|
||||||
if (!mda_is_ignored(mda)) {
|
&inconsistent_mdas);
|
||||||
inconsistent_mdas = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3110,7 +3132,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
|||||||
if (!cmd->independent_metadata_areas && critical_section())
|
if (!cmd->independent_metadata_areas && critical_section())
|
||||||
return_NULL;
|
return_NULL;
|
||||||
lvmcache_label_scan(cmd, 2);
|
lvmcache_label_scan(cmd, 2);
|
||||||
if (!(fmt = fmt_from_vgname(vgname, vgid, 0)))
|
if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 0)))
|
||||||
return_NULL;
|
return_NULL;
|
||||||
|
|
||||||
if (precommitted && !(fmt->features & FMT_PRECOMMIT))
|
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;
|
const char *vgname;
|
||||||
struct dm_list *vgnames;
|
struct dm_list *vgnames;
|
||||||
struct volume_group *vg;
|
struct volume_group *vg;
|
||||||
struct lvmcache_vginfo *vginfo;
|
|
||||||
struct str_list *strl;
|
struct str_list *strl;
|
||||||
int consistent = 0;
|
int consistent = 0;
|
||||||
|
|
||||||
/* Is corresponding vgname already cached? */
|
/* Is corresponding vgname already cached? */
|
||||||
if ((vginfo = vginfo_from_vgid(vgid)) &&
|
if (lvmcache_vgid_is_cached(vgid)) {
|
||||||
vginfo->vgname && !is_orphan_vg(vginfo->vgname)) {
|
|
||||||
if ((vg = _vg_read(cmd, NULL, vgid, 1,
|
if ((vg = _vg_read(cmd, NULL, vgid, 1,
|
||||||
&consistent, precommitted)) &&
|
&consistent, precommitted)) &&
|
||||||
id_equal(&vg->id, (const struct id *)vgid)) {
|
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);
|
vgname = lvmcache_vgname_from_pvid(cmd, pvid);
|
||||||
|
|
||||||
if (is_orphan_vg(vgname)) {
|
if (is_orphan_vg(vgname)) {
|
||||||
if (!(info = info_from_pvid(pvid, 0))) {
|
if (!(info = lvmcache_info_from_pvid(pvid, 0))) {
|
||||||
return_NULL;
|
return_NULL;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -3490,7 +3510,7 @@ const char *find_vgname_from_pvid(struct cmd_context *cmd,
|
|||||||
* Detecting this means checking every VG by scanning
|
* Detecting this means checking every VG by scanning
|
||||||
* every PV on the system.
|
* every PV on the system.
|
||||||
*/
|
*/
|
||||||
if (mdas_empty_or_ignored(&info->mdas)) {
|
if (lvmcache_uncertain_ownership(info)) {
|
||||||
if (!scan_vgs_for_pvs(cmd, 1)) {
|
if (!scan_vgs_for_pvs(cmd, 1)) {
|
||||||
log_error("Rescan for PVs without "
|
log_error("Rescan for PVs without "
|
||||||
"metadata areas failed.");
|
"metadata areas failed.");
|
||||||
@ -3512,7 +3532,7 @@ const char *find_vgname_from_pvname(struct cmd_context *cmd,
|
|||||||
{
|
{
|
||||||
const char *pvid;
|
const char *pvid;
|
||||||
|
|
||||||
pvid = pvid_from_devname(cmd, pvname);
|
pvid = lvmcache_pvid_from_devname(cmd, pvname);
|
||||||
if (!pvid)
|
if (!pvid)
|
||||||
/* Not a PV */
|
/* Not a PV */
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -3576,7 +3596,7 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
|
|||||||
pv->label_sector = label->sector;
|
pv->label_sector = label->sector;
|
||||||
|
|
||||||
/* FIXME Move more common code up here */
|
/* 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'",
|
log_error("Failed to read existing physical volume '%s'",
|
||||||
pv_name);
|
pv_name);
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -3589,7 +3609,7 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
|
|||||||
goto_bad;
|
goto_bad;
|
||||||
|
|
||||||
if (fid)
|
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 {
|
else {
|
||||||
fic.type = FMT_INSTANCE_PV | FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
|
fic.type = FMT_INSTANCE_PV | FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
|
||||||
fic.context.pv_id = (const char *) &pv->id;
|
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)
|
if (!vgid)
|
||||||
continue; /* FIXME Unnecessary? */
|
continue; /* FIXME Unnecessary? */
|
||||||
consistent = 0;
|
consistent = 0;
|
||||||
if (!(vgname = vgname_from_vgid(NULL, vgid))) {
|
if (!(vgname = lvmcache_vgname_from_vgid(NULL, vgid))) {
|
||||||
stack;
|
stack;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -3777,6 +3797,13 @@ int is_real_vg(const char *vg_name)
|
|||||||
return (vg_name && *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:
|
* Returns:
|
||||||
* 0 - fail
|
* 0 - fail
|
||||||
@ -3787,7 +3814,6 @@ int pv_analyze(struct cmd_context *cmd, const char *pv_name,
|
|||||||
{
|
{
|
||||||
struct label *label;
|
struct label *label;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct metadata_area *mda;
|
|
||||||
struct lvmcache_info *info;
|
struct lvmcache_info *info;
|
||||||
|
|
||||||
dev = dev_cache_get(pv_name, cmd->filter);
|
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
|
* Next, loop through metadata areas
|
||||||
*/
|
*/
|
||||||
info = label->info;
|
info = label->info;
|
||||||
dm_list_iterate_items(mda, &info->mdas)
|
lvmcache_foreach_mda(info, _analyze_mda, (void *)lvmcache_fmt(info));
|
||||||
mda->ops->pv_analyze_mda(info->fmt, mda);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -3932,7 +3957,7 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
|
|||||||
return NULL;
|
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) &&
|
if (!already_locked && !(misc_flags & READ_WITHOUT_LOCK) &&
|
||||||
!lock_vol(cmd, vg_name, lock_flags)) {
|
!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 */
|
/* 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, 1)) {
|
if (!lvmcache_fmt_from_vgname(vgname, NULL, 1)) {
|
||||||
lvmcache_label_scan(cmd, 0);
|
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 */
|
/* Independent MDAs aren't supported under low memory */
|
||||||
if (!cmd->independent_metadata_areas && critical_section()) {
|
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;
|
return FAILED_LOCKING;
|
||||||
}
|
}
|
||||||
lvmcache_label_scan(cmd, 2);
|
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 */
|
/* vgname not found after scanning */
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -143,23 +143,27 @@ uint32_t pv_mda_count(const struct physical_volume *pv)
|
|||||||
{
|
{
|
||||||
struct lvmcache_info *info;
|
struct lvmcache_info *info;
|
||||||
|
|
||||||
info = info_from_pvid((const char *)&pv->id.uuid, 0);
|
info = lvmcache_info_from_pvid((const char *)&pv->id.uuid, 0);
|
||||||
return info ? dm_list_size(&info->mdas) : UINT64_C(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)
|
uint32_t pv_mda_used_count(const struct physical_volume *pv)
|
||||||
{
|
{
|
||||||
struct lvmcache_info *info;
|
struct lvmcache_info *info;
|
||||||
struct metadata_area *mda;
|
|
||||||
uint32_t used_count=0;
|
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)
|
if (!info)
|
||||||
return 0;
|
return 0;
|
||||||
dm_list_iterate_items(mda, &info->mdas) {
|
lvmcache_foreach_mda(info, _count_unignored, &used_count);
|
||||||
if (!mda_is_ignored(mda))
|
|
||||||
used_count++;
|
|
||||||
}
|
|
||||||
return 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);
|
const char *pvid = (const char *)(&pv->id.uuid);
|
||||||
|
|
||||||
/* PVs could have 2 mdas of different sizes (rounding effect) */
|
/* PVs could have 2 mdas of different sizes (rounding effect) */
|
||||||
if ((info = info_from_pvid(pvid, 0)))
|
if ((info = lvmcache_info_from_pvid(pvid, 0)))
|
||||||
min_mda_size = find_min_mda_size(&info->mdas);
|
min_mda_size = lvmcache_smallest_mda_size(info);
|
||||||
return min_mda_size;
|
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)
|
uint64_t pv_mda_free(const struct physical_volume *pv)
|
||||||
{
|
{
|
||||||
struct lvmcache_info *info;
|
struct lvmcache_info *info;
|
||||||
uint64_t freespace = UINT64_MAX, mda_free;
|
uint64_t freespace = UINT64_MAX;
|
||||||
const char *pvid = (const char *)&pv->id.uuid;
|
const char *pvid = (const char *)&pv->id.uuid;
|
||||||
struct metadata_area *mda;
|
|
||||||
|
|
||||||
if ((info = info_from_pvid(pvid, 0)))
|
if ((info = lvmcache_info_from_pvid(pvid, 0)))
|
||||||
dm_list_iterate_items(mda, &info->mdas) {
|
lvmcache_foreach_mda(info, _pv_mda_free, &freespace);
|
||||||
if (!mda->ops->mda_free_sectors)
|
|
||||||
continue;
|
|
||||||
mda_free = mda->ops->mda_free_sectors(mda);
|
|
||||||
if (mda_free < freespace)
|
|
||||||
freespace = mda_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (freespace == UINT64_MAX)
|
if (freespace == UINT64_MAX)
|
||||||
freespace = UINT64_C(0);
|
freespace = UINT64_C(0);
|
||||||
|
|
||||||
return freespace;
|
return freespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,22 +257,51 @@ uint64_t pv_used(const struct physical_volume *pv)
|
|||||||
return used;
|
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)
|
unsigned pv_mda_set_ignored(const struct physical_volume *pv, unsigned mda_ignored)
|
||||||
{
|
{
|
||||||
struct lvmcache_info *info;
|
struct lvmcache_info *info;
|
||||||
struct metadata_area *mda, *vg_mda, *tmda;
|
struct _pv_mda_set_ignored_baton baton;
|
||||||
struct dm_list *mdas_in_use, *mdas_ignored, *mdas_to_change;
|
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;
|
return_0;
|
||||||
|
|
||||||
mdas_in_use = &pv->fid->metadata_areas_in_use;
|
baton.mda_ignored = mda_ignored;
|
||||||
mdas_ignored = &pv->fid->metadata_areas_ignored;
|
baton.mdas_in_use = &pv->fid->metadata_areas_in_use;
|
||||||
mdas_to_change = mda_ignored ? mdas_in_use : mdas_ignored;
|
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)) {
|
if (is_orphan(pv)) {
|
||||||
dm_list_iterate_items(mda, mdas_to_change)
|
dm_list_iterate_items(mda, baton.mdas_to_change)
|
||||||
mda_set_ignored(mda, mda_ignored);
|
mda_set_ignored(mda, baton.mda_ignored);
|
||||||
return 1;
|
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
|
/* FIXME: Try not to update the cache here! Also, try to iterate over
|
||||||
* PV mdas only using the format instance's index somehow
|
* PV mdas only using the format instance's index somehow
|
||||||
* (i.e. try to avoid using mda_locn_match call). */
|
* (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)
|
lvmcache_foreach_mda(info, _pv_mda_set_ignored_one, &baton);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ void release_vg(struct volume_group *vg)
|
|||||||
|
|
||||||
/* Check if there are any vginfo holders */
|
/* Check if there are any vginfo holders */
|
||||||
if (vg->vginfo &&
|
if (vg->vginfo &&
|
||||||
!vginfo_holders_dec_and_test_for_zero(vg->vginfo))
|
!lvmcache_vginfo_holders_dec_and_test_for_zero(vg->vginfo))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_free_vg(vg);
|
_free_vg(vg);
|
||||||
|
@ -587,7 +587,7 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
|
|||||||
}
|
}
|
||||||
dm_list_iterate_items(sl, vgids) {
|
dm_list_iterate_items(sl, vgids) {
|
||||||
vgid = sl->str;
|
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;
|
continue;
|
||||||
ret_max = _process_one_vg(cmd, vg_name, vgid, &tags,
|
ret_max = _process_one_vg(cmd, vg_name, vgid, &tags,
|
||||||
&arg_vgnames,
|
&arg_vgnames,
|
||||||
|
@ -87,7 +87,7 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
|
|||||||
|
|
||||||
dm_list_iterate_items(sl, vgids) {
|
dm_list_iterate_items(sl, vgids) {
|
||||||
vgid = sl->str;
|
vgid = sl->str;
|
||||||
if (!vgid || !(vg_name = vgname_from_vgid(NULL, vgid)))
|
if (!vgid || !(vg_name = lvmcache_vgname_from_vgid(NULL, vgid)))
|
||||||
continue;
|
continue;
|
||||||
if (!strcmp(vg_name, vg_name_old)) {
|
if (!strcmp(vg_name, vg_name_old)) {
|
||||||
if (match) {
|
if (match) {
|
||||||
@ -102,7 +102,7 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
|
|||||||
log_suppress(2);
|
log_suppress(2);
|
||||||
found_id = id_read_format(&id, vg_name_old);
|
found_id = id_read_format(&id, vg_name_old);
|
||||||
log_suppress(0);
|
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;
|
vg_name_old = vg_name;
|
||||||
vgid = (char *)id.uuid;
|
vgid = (char *)id.uuid;
|
||||||
} else
|
} else
|
||||||
|
Loading…
Reference in New Issue
Block a user