summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Rockai <prockai@redhat.com>2012-02-10 01:28:27 +0000
committerPetr Rockai <prockai@redhat.com>2012-02-10 01:28:27 +0000
commit8e5f7cf3dc1d75d0a370729326522bcac29b489d (patch)
treea8e7130afabb199942ac06ac6298b13ce4988266
parent5fa417a9c0aa2d7ea80e1087e0d2943536fc5b9d (diff)
downloadlvm2-8e5f7cf3dc1d75d0a370729326522bcac29b489d.tar.gz
lvm2-8e5f7cf3dc1d75d0a370729326522bcac29b489d.tar.xz
lvm2-8e5f7cf3dc1d75d0a370729326522bcac29b489d.zip
Move lvmcache data structures behind an API (making the structures private to
lvmcache.c). No functional change.
-rw-r--r--lib/cache/lvmcache.c368
-rw-r--r--lib/cache/lvmcache.h105
-rw-r--r--lib/device/dev-io.c6
-rw-r--r--lib/format1/disk-rep.c70
-rw-r--r--lib/format1/format1.c6
-rw-r--r--lib/format1/lvm1-label.c9
-rw-r--r--lib/format_pool/disk_rep.c176
-rw-r--r--lib/format_text/format-text.c169
-rw-r--r--lib/format_text/format-text.h12
-rw-r--r--lib/format_text/import_vsn1.c2
-rw-r--r--lib/format_text/layout.h12
-rw-r--r--lib/format_text/text_label.c203
-rw-r--r--lib/label/label.c22
-rw-r--r--lib/metadata/metadata.c129
-rw-r--r--lib/metadata/pv.c114
-rw-r--r--lib/metadata/vg.c2
-rw-r--r--tools/toollib.c2
-rw-r--r--tools/vgrename.c4
18 files changed, 892 insertions, 519 deletions
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index a804d53a..791a1d26 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -28,6 +28,43 @@
#include "format1.h"
#include "config.h"
+#define CACHE_INVALID 0x00000001
+#define CACHE_LOCKED 0x00000002
+
+/* One per device */
+struct lvmcache_info {
+ struct dm_list list; /* Join VG members together */
+ struct dm_list mdas; /* list head for metadata areas */
+ struct dm_list das; /* list head for data areas */
+ struct lvmcache_vginfo *vginfo; /* NULL == unknown */
+ struct label *label;
+ const struct format_type *fmt;
+ struct device *dev;
+ uint64_t device_size; /* Bytes */
+ uint32_t status;
+};
+
+/* One per VG */
+struct lvmcache_vginfo {
+ struct dm_list list; /* Join these vginfos together */
+ struct dm_list infos; /* List head for lvmcache_infos */
+ const struct format_type *fmt;
+ char *vgname; /* "" == orphan */
+ uint32_t status;
+ char vgid[ID_LEN + 1];
+ char _padding[7];
+ struct lvmcache_vginfo *next; /* Another VG with same name? */
+ char *creation_host;
+ size_t vgmetadata_size;
+ char *vgmetadata; /* Copy of VG metadata as format_text string */
+ struct dm_config_tree *cft; /* Config tree created from vgmetadata */
+ /* Lifetime is directly tied to vgmetadata */
+ struct volume_group *cached_vg;
+ unsigned holders;
+ unsigned vg_use_count; /* Counter of vg reusage */
+ unsigned precommitted; /* Is vgmetadata live or precommitted? */
+};
+
static struct dm_hash_table *_pvid_hash = NULL;
static struct dm_hash_table *_vgid_hash = NULL;
static struct dm_hash_table *_vgname_hash = NULL;
@@ -104,7 +141,7 @@ static void _store_metadata(struct volume_group *vg, unsigned precommitted)
char *data;
size_t size;
- if (!(vginfo = vginfo_from_vgid((const char *)&vg->id))) {
+ if (!(vginfo = lvmcache_vginfo_from_vgid((const char *)&vg->id))) {
stack;
return;
}
@@ -147,7 +184,7 @@ static void _update_cache_info_lock_state(struct lvmcache_info *info,
* Cache becomes invalid whenever lock state changes unless
* exclusive VG_GLOBAL is held (i.e. while scanning).
*/
- if (!vgname_is_locked(VG_GLOBAL) && (was_locked != locked)) {
+ if (!lvmcache_vgname_is_locked(VG_GLOBAL) && (was_locked != locked)) {
info->status |= CACHE_INVALID;
*cached_vgmetadata_valid = 0;
}
@@ -176,7 +213,7 @@ static void _update_cache_lock_state(const char *vgname, int locked)
{
struct lvmcache_vginfo *vginfo;
- if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
+ if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
return;
_update_cache_vginfo_lock_state(vginfo, locked);
@@ -187,7 +224,7 @@ static void _drop_metadata(const char *vgname, int drop_precommitted)
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
- if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
+ if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
return;
/*
@@ -220,7 +257,7 @@ void lvmcache_commit_metadata(const char *vgname)
{
struct lvmcache_vginfo *vginfo;
- if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
+ if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
return;
if (vginfo->precommitted) {
@@ -240,7 +277,7 @@ void lvmcache_drop_metadata(const char *vgname, int drop_precommitted)
/* Indicate that PVs could now be missing from the cache */
init_full_scan_done(0);
- } else if (!vgname_is_locked(VG_GLOBAL))
+ } else if (!lvmcache_vgname_is_locked(VG_GLOBAL))
_drop_metadata(vgname, drop_precommitted);
}
@@ -317,7 +354,7 @@ void lvmcache_lock_vgname(const char *vgname, int read_only __attribute__((unuse
_vgs_locked++;
}
-int vgname_is_locked(const char *vgname)
+int lvmcache_vgname_is_locked(const char *vgname)
{
if (!_lock_hash)
return 0;
@@ -340,7 +377,7 @@ void lvmcache_unlock_vgname(const char *vgname)
dev_close_all();
}
-int vgs_locked(void)
+int lvmcache_vgs_locked(void)
{
return _vgs_locked;
}
@@ -366,12 +403,12 @@ static void _vginfo_detach_info(struct lvmcache_info *info)
}
/* If vgid supplied, require a match. */
-struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
+struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname, const char *vgid)
{
struct lvmcache_vginfo *vginfo;
if (!vgname)
- return vginfo_from_vgid(vgid);
+ return lvmcache_vginfo_from_vgid(vgid);
if (!_vgname_hash)
return NULL;
@@ -388,7 +425,7 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
return vginfo;
}
-const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels)
+const struct format_type *lvmcache_fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels)
{
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
@@ -398,7 +435,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid,
struct device_list *devl;
char vgid_found[ID_LEN + 1] __attribute__((aligned(8)));
- if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
+ if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
return NULL;
/*
@@ -431,7 +468,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid,
}
/* If vginfo changed, caller needs to rescan */
- if (!(vginfo = vginfo_from_vgname(vgname, vgid_found)) ||
+ if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid_found)) ||
strncmp(vginfo->vgid, vgid_found, ID_LEN))
return NULL;
@@ -439,7 +476,7 @@ out:
return vginfo->fmt;
}
-struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
+struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid)
{
struct lvmcache_vginfo *vginfo;
char id[ID_LEN + 1] __attribute__((aligned(8)));
@@ -457,12 +494,12 @@ struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
return vginfo;
}
-const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
+const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid)
{
struct lvmcache_vginfo *vginfo;
const char *vgname = NULL;
- if ((vginfo = vginfo_from_vgid(vgid)))
+ if ((vginfo = lvmcache_vginfo_from_vgid(vgid)))
vgname = vginfo->vgname;
if (mem && vgname)
@@ -483,7 +520,7 @@ static int _info_is_valid(struct lvmcache_info *info)
* So if the VG appears to be unlocked here, it should be safe
* to use the cached value.
*/
- if (info->vginfo && !vgname_is_locked(info->vginfo->vgname))
+ if (info->vginfo && !lvmcache_vgname_is_locked(info->vginfo->vgname))
return 1;
if (!(info->status & CACHE_LOCKED))
@@ -520,7 +557,7 @@ static int _vginfo_is_invalid(struct lvmcache_vginfo *vginfo)
* If valid_only is set, data will only be returned if the cached data is
* known still to be valid.
*/
-struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only)
+struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, int valid_only)
{
struct lvmcache_info *info;
char id[ID_LEN + 1] __attribute__((aligned(8)));
@@ -545,12 +582,12 @@ char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid)
struct lvmcache_info *info;
char *vgname;
- if (!device_from_pvid(cmd, (const struct id *)pvid, NULL, NULL)) {
+ if (!lvmcache_device_from_pvid(cmd, (const struct id *)pvid, NULL, NULL)) {
log_error("Couldn't find device with uuid %s.", pvid);
return NULL;
}
- info = info_from_pvid(pvid, 0);
+ info = lvmcache_info_from_pvid(pvid, 0);
if (!info)
return_NULL;
@@ -644,7 +681,7 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
struct format_instance *fid;
struct format_instance_ctx fic;
- if (!vgid || !(vginfo = vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
+ if (!vgid || !(vginfo = lvmcache_vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
return NULL;
if (!_vginfo_is_valid(vginfo))
@@ -708,7 +745,8 @@ bad:
return NULL;
}
-int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo)
+// #if 0
+int lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo)
{
log_debug("VG %s decrementing %d holder(s) at %p.",
vginfo->cached_vg->name, vginfo->holders, vginfo->cached_vg);
@@ -731,6 +769,7 @@ int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo)
return 1;
}
+// #endif
struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd,
int include_internal)
@@ -798,7 +837,7 @@ struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
return NULL;
}
- if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
+ if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
return pvids;
dm_list_iterate_items(info, &vginfo->infos) {
@@ -818,7 +857,7 @@ static struct device *_device_from_pvid(const struct id *pvid,
struct lvmcache_info *info;
struct label *label;
- if ((info = info_from_pvid((const char *) pvid, 0))) {
+ if ((info = lvmcache_info_from_pvid((const char *) pvid, 0))) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid)) {
@@ -831,7 +870,7 @@ static struct device *_device_from_pvid(const struct id *pvid,
return NULL;
}
-struct device *device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
+struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
unsigned *scan_done_once, uint64_t *label_sector)
{
struct device *dev;
@@ -863,7 +902,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
return NULL;
}
-const char *pvid_from_devname(struct cmd_context *cmd,
+const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
const char *devname)
{
struct device *dev;
@@ -889,7 +928,7 @@ static int _free_vginfo(struct lvmcache_vginfo *vginfo)
_free_cached_vgmetadata(vginfo);
- vginfo2 = primary_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
+ vginfo2 = primary_vginfo = lvmcache_vginfo_from_vgname(vginfo->vgname, NULL);
if (vginfo == primary_vginfo) {
dm_hash_remove(_vgname_hash, vginfo->vgname);
@@ -910,7 +949,7 @@ static int _free_vginfo(struct lvmcache_vginfo *vginfo)
dm_free(vginfo->creation_host);
if (*vginfo->vgid && _vgid_hash &&
- vginfo_from_vgid(vginfo->vgid) == vginfo)
+ lvmcache_vginfo_from_vgid(vginfo->vgid) == vginfo)
dm_hash_remove(_vgid_hash, vginfo->vgid);
dm_list_del(&vginfo->list);
@@ -959,6 +998,7 @@ static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
/*
* Nothing to do if already stored with same pvid.
*/
+
if (((dm_hash_lookup(_pvid_hash, pvid)) == info) &&
!strcmp(info->dev->pvid, pvid))
return 1;
@@ -1110,7 +1150,7 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
_drop_vginfo(info, info->vginfo);
/* Get existing vginfo or create new one */
- if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
+ if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
/*** FIXME - vginfo ends up duplicated instead of renamed.
// Renaming? This lookup fails.
if ((vginfo = vginfo_from_vgid(vgid))) {
@@ -1162,9 +1202,9 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
* If we're scanning and there's an invalidated entry, remove it.
* Otherwise we risk bogus warnings of duplicate VGs.
*/
- while ((primary_vginfo = vginfo_from_vgname(vgname, NULL)) &&
+ while ((primary_vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)) &&
_scanning_in_progress && _vginfo_is_invalid(primary_vginfo)) {
- orphan_vginfo = vginfo_from_vgname(primary_vginfo->fmt->orphan_vg_name, NULL);
+ orphan_vginfo = lvmcache_vginfo_from_vgname(primary_vginfo->fmt->orphan_vg_name, NULL);
if (!orphan_vginfo) {
log_error(INTERNAL_ERROR "Orphan vginfo %s lost from cache.",
primary_vginfo->fmt->orphan_vg_name);
@@ -1212,7 +1252,7 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
else if (!_lvmcache_update_vgid(NULL, vginfo, vgid)) /* Orphans */
return_0;
- _update_cache_vginfo_lock_state(vginfo, vgname_is_locked(vgname));
+ _update_cache_vginfo_lock_state(vginfo, lvmcache_vgname_is_locked(vgname));
/* FIXME Check consistency of list! */
vginfo->fmt = fmt;
@@ -1282,6 +1322,8 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
const char *vgname, const char *vgid,
uint32_t vgstatus, const char *creation_host)
{
+ log_error("lvmcache_update_vgname_and_id: %s -> %s", dev_name(info->dev), vgname);
+
if (!vgname && !info->vginfo) {
log_error(INTERNAL_ERROR "NULL vgname handed to cache");
/* FIXME Remove this */
@@ -1319,7 +1361,7 @@ int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
dm_list_iterate_items(pvl, &vg->pvs) {
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
/* FIXME Could pvl->pv->dev->pvid ever be different? */
- if ((info = info_from_pvid(pvid_s, 0)) &&
+ if ((info = lvmcache_info_from_pvid(pvid_s, 0)) &&
!lvmcache_update_vgname_and_id(info, vg->name,
(char *) &vg->id,
vg->status, NULL))
@@ -1350,8 +1392,8 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
strncpy(pvid_s, pvid, sizeof(pvid_s) - 1);
pvid_s[sizeof(pvid_s) - 1] = '\0';
- if (!(existing = info_from_pvid(pvid_s, 0)) &&
- !(existing = info_from_pvid(dev->pvid, 0))) {
+ if (!(existing = lvmcache_info_from_pvid(pvid_s, 0)) &&
+ !(existing = lvmcache_info_from_pvid(dev->pvid, 0))) {
if (!(label = label_create(labeller)))
return_NULL;
if (!(info = dm_zalloc(sizeof(*info)))) {
@@ -1520,3 +1562,259 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans)
if (retain_orphans)
init_lvmcache_orphans(cmd);
}
+
+int lvmcache_pvid_is_locked(const char *pvid) {
+ struct lvmcache_info *info;
+ info = lvmcache_info_from_pvid(pvid, 0);
+ if (!info || !info->vginfo)
+ return 0;
+
+ return lvmcache_vgname_is_locked(info->vginfo->vgname);
+}
+
+int lvmcache_fid_add_mdas(struct lvmcache_info *info, struct format_instance *fid,
+ const char *id, int id_len)
+{
+ return fid_add_mdas(fid, &info->mdas, id, id_len);
+}
+
+int lvmcache_fid_add_mdas_pv(struct lvmcache_info *info, struct format_instance *fid)
+{
+ return lvmcache_fid_add_mdas(info, fid, info->dev->pvid, ID_LEN);
+}
+
+int lvmcache_fid_add_mdas_vg(struct lvmcache_vginfo *vginfo, struct format_instance *fid)
+{
+ struct lvmcache_info *info;
+ dm_list_iterate_items(info, &vginfo->infos) {
+ if (!lvmcache_fid_add_mdas_pv(info, fid))
+ return_0;
+ }
+ return 1;
+}
+
+static int _get_pv_if_in_vg(struct lvmcache_info *info,
+ struct physical_volume *pv)
+{
+ char vgname[NAME_LEN + 1];
+ char vgid[ID_LEN + 1];
+
+ if (info->vginfo && info->vginfo->vgname &&
+ !is_orphan_vg(info->vginfo->vgname)) {
+ /*
+ * get_pv_from_vg_by_id() may call
+ * lvmcache_label_scan() and drop cached
+ * vginfo so make a local copy of string.
+ */
+ strcpy(vgname, info->vginfo->vgname);
+ memcpy(vgid, info->vginfo->vgid, sizeof(vgid));
+
+ if (get_pv_from_vg_by_id(info->fmt, vgname, vgid,
+ info->dev->pvid, pv))
+ return 1;
+ }
+
+ return 0;
+}
+
+int lvmcache_populate_pv_fields(struct lvmcache_info *info,
+ struct physical_volume *pv,
+ int scan_label_only)
+{
+ struct data_area_list *da;
+
+ /* Have we already cached vgname? */
+ if (!scan_label_only && _get_pv_if_in_vg(info, pv))
+ return 1;
+
+ /* Perform full scan (just the first time) and try again */
+ if (!scan_label_only && !critical_section() && !full_scan_done()) {
+ lvmcache_label_scan(info->fmt->cmd, 2);
+
+ if (_get_pv_if_in_vg(info, pv))
+ return 1;
+ }
+
+ /* Orphan */
+ pv->dev = info->dev;
+ pv->fmt = info->fmt;
+ pv->size = info->device_size >> SECTOR_SHIFT;
+ pv->vg_name = FMT_TEXT_ORPHAN_VG_NAME;
+ memcpy(&pv->id, &info->dev->pvid, sizeof(pv->id));
+
+ /* Currently only support exactly one data area */
+ if (dm_list_size(&info->das) != 1) {
+ log_error("Must be exactly one data area (found %d) on PV %s",
+ dm_list_size(&info->das), dev_name(info->dev));
+ return 0;
+ }
+
+ dm_list_iterate_items(da, &info->das)
+ pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
+
+ return 1;
+}
+
+int lvmcache_check_format(struct lvmcache_info *info, const struct format_type *fmt)
+{
+ if (info->fmt != fmt) {
+ log_error("PV %s is a different format (seqno %s)",
+ dev_name(info->dev), info->fmt->name);
+ return 0;
+ }
+ return 1;
+}
+
+void lvmcache_del_mdas(struct lvmcache_info *info)
+{
+ if (info->mdas.n)
+ del_mdas(&info->mdas);
+ dm_list_init(&info->mdas);
+}
+
+void lvmcache_del_das(struct lvmcache_info *info)
+{
+ if (info->das.n)
+ del_das(&info->das);
+ dm_list_init(&info->das);
+}
+
+int lvmcache_add_mda(struct lvmcache_info *info, struct device *dev,
+ uint64_t start, uint64_t size, unsigned ignored)
+{
+ return add_mda(info->fmt, NULL, &info->mdas, dev, start, size, ignored);
+}
+
+int lvmcache_add_da(struct lvmcache_info *info, uint64_t start, uint64_t size)
+{
+ return add_da(NULL, &info->das, start, size);
+}
+
+
+void lvmcache_update_pv(struct lvmcache_info *info, struct physical_volume *pv,
+ const struct format_type *fmt)
+{
+ info->device_size = pv->size << SECTOR_SHIFT;
+ info->fmt = fmt;
+}
+
+int lvmcache_update_das(struct lvmcache_info *info, struct physical_volume *pv)
+{
+ struct data_area_list *da;
+ if (info->das.n) {
+ if (!pv->pe_start)
+ dm_list_iterate_items(da, &info->das)
+ pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
+ del_das(&info->das);
+ } else
+ dm_list_init(&info->das);
+
+ if (!add_da(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
+ return_0;
+
+ return 1;
+}
+
+int lvmcache_foreach_pv(struct lvmcache_vginfo *vginfo,
+ int (*fun)(struct lvmcache_info *, void *),
+ void *baton)
+{
+ struct lvmcache_info *info;
+ dm_list_iterate_items(info, &vginfo->infos) {
+ if (!fun(info, baton))
+ return_0;
+ }
+
+ return 1;
+}
+
+int lvmcache_foreach_mda(struct lvmcache_info *info,
+ int (*fun)(struct metadata_area *, void *),
+ void *baton)
+{
+ struct metadata_area *mda;
+ dm_list_iterate_items(mda, &info->mdas) {
+ if (!fun(mda, baton))
+ return_0;
+ }
+
+ return 1;
+}
+
+int lvmcache_mda_count(struct lvmcache_info *info)
+{
+ return dm_list_size(&info->mdas);
+}
+
+int lvmcache_foreach_da(struct lvmcache_info *info,
+ int (*fun)(struct data_area_list *, void *),
+ void *baton)
+{
+ struct data_area_list *da;
+ dm_list_iterate_items(da, &info->das) {
+ if (!fun(da, baton))
+ return_0;
+ }
+
+ return 1;
+}
+
+/*
+ * The lifetime of the label returned is tied to the lifetime of the
+ * lvmcache_info which is the same as lvmcache itself.
+ */
+struct label *lvmcache_get_label(struct lvmcache_info *info) {
+ return info->label;
+}
+
+void lvmcache_make_valid(struct lvmcache_info *info) {
+ info->status &= ~CACHE_INVALID;
+}
+
+uint64_t lvmcache_device_size(struct lvmcache_info *info) {
+ return info->device_size;
+}
+
+void lvmcache_set_device_size(struct lvmcache_info *info, uint64_t size) {
+ info->device_size = size;
+}
+
+struct device *lvmcache_device(struct lvmcache_info *info) {
+ return info->dev;
+}
+
+int lvmcache_is_orphan(struct lvmcache_info *info) {
+ if (!info->vginfo)
+ return 1; /* FIXME? */
+ return is_orphan_vg(info->vginfo->vgname);
+}
+
+int lvmcache_vgid_is_cached(const char *vgid) {
+ struct lvmcache_vginfo *vginfo;
+ vginfo = lvmcache_vginfo_from_vgid(vgid);
+
+ if (!vginfo || !vginfo->vgname)
+ return 0;
+
+ if (is_orphan_vg(vginfo->vgname))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Return true iff it is impossible to find out from this info alone whether the
+ * PV in question is or is not an orphan.
+ */
+int lvmcache_uncertain_ownership(struct lvmcache_info *info) {
+ return mdas_empty_or_ignored(&info->mdas);
+}
+
+int lvmcache_smallest_mda_size(struct lvmcache_info *info)
+{
+ return find_min_mda_size(&info->mdas);
+}
+
+const struct format_type *lvmcache_fmt(struct lvmcache_info *info) {
+ return info->fmt;
+}
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index 3a8c406b..203040f4 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -24,50 +24,19 @@
#define ORPHAN_PREFIX VG_ORPHANS
#define ORPHAN_VG_NAME(fmt) ORPHAN_PREFIX "_" fmt
-#define CACHE_INVALID 0x00000001
-#define CACHE_LOCKED 0x00000002
-
/* LVM specific per-volume info */
/* Eventual replacement for struct physical_volume perhaps? */
struct cmd_context;
struct format_type;
struct volume_group;
+struct physical_volume;
struct dm_config_tree;
+struct format_instance;
+struct metadata_area;
+struct data_area_list;
-/* One per VG */
-struct lvmcache_vginfo {
- struct dm_list list; /* Join these vginfos together */
- struct dm_list infos; /* List head for lvmcache_infos */
- const struct format_type *fmt;
- char *vgname; /* "" == orphan */
- uint32_t status;
- char vgid[ID_LEN + 1];
- char _padding[7];
- struct lvmcache_vginfo *next; /* Another VG with same name? */
- char *creation_host;
- size_t vgmetadata_size;
- char *vgmetadata; /* Copy of VG metadata as format_text string */
- struct dm_config_tree *cft; /* Config tree created from vgmetadata */
- /* Lifetime is directly tied to vgmetadata */
- struct volume_group *cached_vg;
- unsigned holders;
- unsigned vg_use_count; /* Counter of vg reusage */
- unsigned precommitted; /* Is vgmetadata live or precommitted? */
-};
-
-/* One per device */
-struct lvmcache_info {
- struct dm_list list; /* Join VG members together */
- struct dm_list mdas; /* list head for metadata areas */
- struct dm_list das; /* list head for data areas */
- struct lvmcache_vginfo *vginfo; /* NULL == unknown */
- struct label *label;
- const struct format_type *fmt;
- struct device *dev;
- uint64_t device_size; /* Bytes */
- uint32_t status;
-};
+struct lvmcache_vginfo;
int lvmcache_init(void);
void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans);
@@ -95,21 +64,23 @@ void lvmcache_unlock_vgname(const char *vgname);
int lvmcache_verify_lock_order(const char *vgname);
/* Queries */
-const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels);
+const struct format_type *lvmcache_fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels);
+
/* Decrement and test if there are still vg holders in vginfo. */
-int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo);
-struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
+int lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo);
+
+struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname,
const char *vgid);
-struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
-struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only);
-const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
-struct device *device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
+struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid);
+struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, int valid_only);
+const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid);
+struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
unsigned *scan_done_once, uint64_t *label_sector);
-const char *pvid_from_devname(struct cmd_context *cmd,
+const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
const char *dev_name);
char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid);
-int vgs_locked(void);
-int vgname_is_locked(const char *vgname);
+int lvmcache_vgs_locked(void);
+int lvmcache_vgname_is_locked(const char *vgname);
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
/* If include_internal is not set, return only proper vg names. */
@@ -130,4 +101,46 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted);
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
void lvmcache_commit_metadata(const char *vgname);
+int lvmcache_pvid_is_locked(const char *pvid);
+int lvmcache_fid_add_mdas(struct lvmcache_info *info, struct format_instance *fid,
+ const char *id, int id_len);
+int lvmcache_fid_add_mdas_pv(struct lvmcache_info *info, struct format_instance *fid);
+int lvmcache_fid_add_mdas_vg(struct lvmcache_vginfo *vginfo, struct format_instance *fid);
+int lvmcache_populate_pv_fields(struct lvmcache_info *info,
+ struct physical_volume *pv,
+ int scan_label_only);
+int lvmcache_check_format(struct lvmcache_info *info, const struct format_type *fmt);
+void lvmcache_del_mdas(struct lvmcache_info *info);
+void lvmcache_del_das(struct lvmcache_info *info);
+int lvmcache_add_mda(struct lvmcache_info *info, struct device *dev,
+ uint64_t start, uint64_t size, unsigned ignored);
+int lvmcache_add_da(struct lvmcache_info *info, uint64_t start, uint64_t size);
+
+const struct format_type *lvmcache_fmt(struct lvmcache_info *info);
+struct label *lvmcache_get_label(struct lvmcache_info *info);
+
+void lvmcache_update_pv(struct lvmcache_info *info, struct physical_volume *pv,
+ const struct format_type *fmt);
+int lvmcache_update_das(struct lvmcache_info *info, struct physical_volume *pv);
+int lvmcache_foreach_mda(struct lvmcache_info *info,
+ int (*fun)(struct metadata_area *, void *),
+ void *baton);
+
+int lvmcache_foreach_da(struct lvmcache_info *info,
+ int (*fun)(struct data_area_list *, void *),
+ void *baton);
+
+int lvmcache_foreach_pv(struct lvmcache_vginfo *vg,
+ int (*fun)(struct lvmcache_info *, void *), void * baton);
+
+uint64_t lvmcache_device_size(struct lvmcache_info *info);
+void lvmcache_set_device_size(struct lvmcache_info *info, uint64_t size);
+struct device *lvmcache_device(struct lvmcache_info *info);
+void lvmcache_make_valid(struct lvmcache_info *info);
+int lvmcache_is_orphan(struct lvmcache_info *info);
+int lvmcache_uncertain_ownership(struct lvmcache_info *info);
+int lvmcache_mda_count(struct lvmcache_info *info);
+int lvmcache_vgid_is_cached(const char *vgid);
+int lvmcache_smallest_mda_size(struct lvmcache_info *info);
+
#endif
diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c
index ce767849..d967ba5c 100644
--- a/lib/device/dev-io.c
+++ b/lib/device/dev-io.c
@@ -586,7 +586,6 @@ static void _close(struct device *dev)
static int _dev_close(struct device *dev, int immediate)
{
- struct lvmcache_info *info;
if (dev->fd < 0) {
log_error("Attempt to close device '%s' "
@@ -608,10 +607,7 @@ static int _dev_close(struct device *dev, int immediate)
/* Close unless device is known to belong to a locked VG */
if (immediate ||
- (dev->open_count < 1 &&
- (!(info = info_from_pvid(dev->pvid, 0)) ||
- !info->vginfo ||
- !vgname_is_locked(info->vginfo->vgname))))
+ (dev->open_count < 1 && !lvmcache_pvid_is_locked(dev->pvid)))
_close(dev);
return 1;
diff --git a/lib/format1/disk-rep.c b/lib/format1/disk-rep.c
index c3aeac65..d7c3f7d7 100644
--- a/lib/format1/disk-rep.c
+++ b/lib/format1/disk-rep.c
@@ -335,9 +335,9 @@ static void __update_lvmcache(const struct format_type *fmt,
return;
}
- info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
- dm_list_init(&info->mdas);
- info->status &= ~CACHE_INVALID;
+ lvmcache_set_device_size(info, xlate32(dl->pvd.pv_size) << SECTOR_SHIFT);
+ lvmcache_del_mdas(info);
+ lvmcache_make_valid(info);
}
static struct disk_list *__read_disk(const struct format_type *fmt,
@@ -451,6 +451,28 @@ static void _add_pv_to_list(struct dm_list *head, struct disk_list *data)
dm_list_add(head, &data->list);
}
+struct _read_pvs_in_vg_baton {
+ const char *vg_name;
+ struct dm_list *head;
+ struct disk_list *data;
+ struct dm_pool *mem;
+ int empty;
+};
+
+static int _read_pv_in_vg(struct lvmcache_info *info, void *baton)
+{
+ struct _read_pvs_in_vg_baton *b = baton;
+
+ b->empty = 0;
+
+ if (!lvmcache_device(info) ||
+ !(b->data = read_disk(lvmcache_fmt(info), lvmcache_device(info), b->mem, b->vg_name)))
+ return 0; /* stop here */
+
+ _add_pv_to_list(b->head, b->data);
+ return 1;
+}
+
/*
* Build a list of pv_d's structures, allocated from mem.
* We keep track of the first object allocated from the pool
@@ -462,29 +484,31 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
{
struct dev_iter *iter;
struct device *dev;
- struct disk_list *data = NULL;
struct lvmcache_vginfo *vginfo;
- struct lvmcache_info *info;
+ struct _read_pvs_in_vg_baton baton;
+
+ baton.head = head;
+ baton.empty = 1;
+ baton.data = NULL;
+ baton.mem = mem;
+ baton.vg_name = vg_name;
/* Fast path if we already saw this VG and cached the list of PVs */
- if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
- vginfo->infos.n) {
- dm_list_iterate_items(info, &vginfo->infos) {
- dev = info->dev;
- if (!dev || !(data = read_disk(fmt, dev, mem, vg_name)))
- break;
- _add_pv_to_list(head, data);
- }
+ if (vg_name && (vginfo = lvmcache_vginfo_from_vgname(vg_name, NULL))) {
+
+ lvmcache_foreach_pv(vginfo, _read_pv_in_vg, &baton);
- /* 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;
+ if (!baton.empty) {
+ /* Did we find the whole VG? */
+ 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); */
+ /* Failed */
+ dm_list_init(head);
+ /* vgcache_del(vg_name); */
+ }
}
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 */
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
- if ((data = read_disk(fmt, dev, mem, vg_name))) {
- _add_pv_to_list(head, data);
+ if ((baton.data = read_disk(fmt, dev, mem, vg_name))) {
+ _add_pv_to_list(head, baton.data);
}
}
dev_iter_destroy(iter);
diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index 629bb839..6b5bdb95 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -413,10 +413,8 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
pv->vg_name, NULL, 0)))
return_0;
- info->device_size = pv->size << SECTOR_SHIFT;
- info->fmt = fmt;
-
- dm_list_init(&info->mdas);
+ lvmcache_update_pv(info, pv, fmt);
+ lvmcache_del_mdas(info);
dm_list_init(&pvs);
diff --git a/lib/format1/lvm1-label.c b/lib/format1/lvm1-label.c
index 07596a54..4c157ac5 100644
--- a/lib/format1/lvm1-label.c
+++ b/lib/format1/lvm1-label.c
@@ -77,12 +77,11 @@ static int _lvm1_read(struct labeller *l, struct device *dev, void *buf,
if (!(info = lvmcache_add(l, (char *)pvd->pv_uuid, dev, vgname, vgid,
exported)))
return_0;
- *label = info->label;
+ *label = lvmcache_get_label(info);
- info->device_size = xlate32(pvd->pv_size) << SECTOR_SHIFT;
- dm_list_init(&info->mdas);
-
- info->status &= ~CACHE_INVALID;
+ lvmcache_set_device_size(info, xlate32(pvd->pv_size) << SECTOR_SHIFT);
+ lvmcache_del_mdas(info);
+ lvmcache_make_valid(info);
return 1;
}
diff --git a/lib/format_pool/disk_rep.c b/lib/format_pool/disk_rep.c
index 589ffbf2..2201ab9e 100644
--- a/lib/format_pool/disk_rep.c
+++ b/lib/format_pool/disk_rep.c
@@ -101,12 +101,11 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
(char *) &vgid, 0)))
return_0;
if (label)
- *label = info->label;
+ *label = lvmcache_get_label(info);
- info->device_size = xlate32_be(pd->pl_blocks) << SECTOR_SHIFT;
- dm_list_init(&info->mdas);
-
- info->status &= ~CACHE_INVALID;
+ lvmcache_set_device_size(info, xlate32_be(pd->pl_blocks) << SECTOR_SHIFT);
+ lvmcache_del_mdas(info);
+ lvmcache_make_valid(info);
pl->dev = dev;
pl->pv = NULL;
@@ -236,68 +235,92 @@ void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid)
}
-static int _read_vg_pds(const struct format_type *fmt, struct dm_pool *mem,
- struct lvmcache_vginfo *vginfo, struct dm_list *head,
- uint32_t *devcount)
+struct _read_pool_pv_baton {
+ const struct format_type *fmt;
+ struct dm_pool *mem, *tmpmem;
+ struct pool_list *pl;
+ struct dm_list *head;
+ const char *vgname;
+ uint32_t *sp_devs;
+ int sp_count;
+ int failed;
+ int empty;
+};
+
+static int _read_pool_pv(struct lvmcache_info *info, void *baton)
{
- struct lvmcache_info *info;
- struct pool_list *pl = NULL;
- struct dm_pool *tmpmem;
+ struct _read_pool_pv_baton *b = baton;
+
+ 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;
- uint32_t sp_count = 0;
- uint32_t *sp_devs = NULL;
+ return 1;
+}
+
+static int _read_vg_pds(struct _read_pool_pv_baton *b,
+ struct lvmcache_vginfo *vginfo,
+ uint32_t *devcount)
+{
uint32_t i;
+ b->sp_count = 0;
+ b->sp_devs = NULL;
+ b->failed = 0;
+ b->pl = NULL;
+
/* FIXME: maybe should return a different error in memory
* allocation failure */
- if (!(tmpmem = dm_pool_create("pool read_vg", 512)))
+ if (!(b->tmpmem = dm_pool_create("pool read_vg", 512)))
return_0;
- dm_list_iterate_items(info, &vginfo->infos) {
- if (info->dev &&
- !(pl = read_pool_disk(fmt, info->dev, mem, vginfo->vgname)))
- break;
- /*
- * We need to keep track of the total expected number
- * of devices per subpool
- */
- if (!sp_count) {
- /* 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;
- }
+ lvmcache_foreach_pv(vginfo, _read_pool_pv, b);
*devcount = 0;
- for (i = 0; i < sp_count; i++)
- *devcount += sp_devs[i];
+ for (i = 0; i < b->sp_count; i++)
+ *devcount += b->sp_devs[i];
- dm_pool_destroy(tmpmem);
+ dm_pool_destroy(b->tmpmem);
- if (pl && *pl->pd.pl_pool_name)
+ if (b->pl && *b->pl->pd.pl_pool_name)
return 1;
return 0;
@@ -311,29 +334,36 @@ int read_pool_pds(const struct format_type *fmt, const char *vg_name,
uint32_t totaldevs;
int full_scan = -1;
+ struct _read_pool_pv_baton baton;
+
+ baton.vgname = vg_name;
+ baton.mem = mem;
+ baton.fmt = fmt;
+ baton.head = pdhead;
+ baton.empty = 1;
+
do {
/*
* If the cache scanning doesn't work, this will never work
*/
- if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
- vginfo->infos.n) {
-
- if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {
- /*
- * If we found all the devices we were
- * expecting, return success
- */
- if (dm_list_size(pdhead) == totaldevs)
- return 1;
-
- /*
- * accept partial pool if we've done a full
- * rescan of the cache
- */
- if (full_scan > 0)
- return 1;
- }
+ if (vg_name && (vginfo = lvmcache_vginfo_from_vgname(vg_name, NULL)) &&
+ _read_vg_pds(&baton, vginfo, &totaldevs) && !baton.empty)
+ {
+ /*
+ * If we found all the devices we were expecting, return
+ * success
+ */
+ if (dm_list_size(pdhead) == totaldevs)
+ return 1;
+
+ /*
+ * accept partial pool if we've done a full rescan of
+ * the cache
+ */
+ if (full_scan > 0)
+ return 1;
}
+
/* Failed */
dm_list_init(pdhead);
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 2b73f872..56c6e2e8 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -432,7 +432,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
"not match expected name %s.", vgname);
bad:
- if ((info = info_from_pvid(dev_area->dev->pvid, 0)))
+ if ((info = lvmcache_info_from_pvid(dev_area->dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, FMT_TEXT_ORPHAN_VG_NAME,
FMT_TEXT_ORPHAN_VG_NAME, 0, NULL);
@@ -1251,6 +1251,33 @@ static int _text_scan(const struct format_type *fmt, const char *vgname)
return (_scan_file(fmt, vgname) & _scan_raw(fmt, vgname));
}
+struct _write_single_mda_baton {
+ const struct format_type *fmt;
+ struct physical_volume *pv;
+};
+
+static int _write_single_mda(struct metadata_area *mda, void *baton)
+{
+ struct _write_single_mda_baton *p = baton;
+ struct mda_context *mdac;
+
+ char buf[MDA_HEADER_SIZE] __attribute__((aligned(8)));
+ struct mda_header *mdah = (struct mda_header *) buf;
+
+ mdac = mda->metadata_locn;
+ memset(&buf, 0, sizeof(buf));
+ mdah->size = mdac->area.size;
+ rlocn_set_ignored(mdah->raw_locns, mda_is_ignored(mda));
+
+ if (!_raw_write_mda_header(p->fmt, mdac->area.dev,
+ mdac->area.start, mdah)) {
+ if (!dev_close(p->pv->dev))
+ stack;
+ return_0;
+ }
+ return 1;
+}
+
/* Only for orphans */
static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv)
{
@@ -1260,27 +1287,21 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
struct lvmcache_info *info;
struct mda_context *mdac;
struct metadata_area *mda;
+ struct _write_single_mda_baton baton;
unsigned mda_index;
- char buf[MDA_HEADER_SIZE] __attribute__((aligned(8)));
- struct mda_header *mdah = (struct mda_header *) buf;
- struct data_area_list *da;
/* Add a new cache entry with PV info or update existing one. */
if (!(info = lvmcache_add(fmt->labeller, (const char *) &pv->id,
pv->dev, pv->vg_name, NULL, 0)))
return_0;
- label = info->label;
+ label = lvmcache_get_label(info);
label->sector = pv->label_sector;
- info->device_size = pv->size << SECTOR_SHIFT;
- info->fmt = fmt;
+ lvmcache_update_pv(info, pv, fmt);
/* Flush all cached metadata areas, we will reenter new/modified ones. */
- if (info->mdas.n)
- del_mdas(&info->mdas);
- else
- dm_list_init(&info->mdas);
+ lvmcache_del_mdas(info);
/*
* Add all new or modified metadata areas for this PV stored in
@@ -1299,8 +1320,10 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
dev_name(mdac->area.dev),
mdac->area.start >> SECTOR_SHIFT,
mdac->area.size >> SECTOR_SHIFT);
- add_mda(fmt, NULL, &info->mdas, mdac->area.dev,
- 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
* metadata which will override the value in the PV header.
*/
- if (info->das.n) {
- if (!pv->pe_start)
- dm_list_iterate_items(da, &info->das)
- pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
- del_das(&info->das);
- } else
- dm_list_init(&info->das);
- if (!add_da(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
+ if (!lvmcache_update_das(info, pv))
return_0;
if (!dev_open(pv->dev))
return_0;
- dm_list_iterate_items(mda, &info->mdas) {
- mdac = mda->metadata_locn;
- memset(&buf, 0, sizeof(buf));
- mdah->size = mdac->area.size;
- rlocn_set_ignored(mdah->raw_locns, mda_is_ignored(mda));
- if (!_raw_write_mda_header(fmt, mdac->area.dev,
- mdac->area.start, mdah)) {
- if (!dev_close(pv->dev))
- stack;
- return_0;
- }
- }
+ baton.pv = pv;
+ baton.fmt = fmt;
- if (!label_write(pv->dev, info->label)) {
+ if (!lvmcache_foreach_mda(info, _write_single_mda, &baton))
+ return_0;
+
+ if (!label_write(pv->dev, label)) {
dev_close(pv->dev);
return_0;
}
@@ -1384,68 +1393,6 @@ static int _add_raw(struct dm_list *raw_list, struct device_area *dev_area)
return 1;
}
-static int _get_pv_if_in_vg(struct lvmcache_info *info,
- struct physical_volume *pv)
-{
- char vgname[NAME_LEN + 1];
- char vgid[ID_LEN + 1];
-
- if (info->vginfo && info->vginfo->vgname &&
- !is_orphan_vg(info->vginfo->vgname)) {
- /*
- * get_pv_from_vg_by_id() may call
- * lvmcache_label_scan() and drop cached
- * vginfo so make a local copy of string.
- */
- strcpy(vgname, info->vginfo->vgname);
- memcpy(vgid, info->vginfo->vgid, sizeof(vgid));
-
- if (get_pv_from_vg_by_id(info->fmt, vgname, vgid,
- info->dev->pvid, pv))
- return 1;
- }
-
- return 0;
-}
-
-static int _populate_pv_fields(struct lvmcache_info *info,
- struct physical_volume *pv,
- int scan_label_only)
-{
- struct data_area_list *da;
-
- /* Have we already cached vgname? */
- if (!scan_label_only && _get_pv_if_in_vg(info, pv))
- return 1;
-
- /* Perform full scan (just the first time) and try again */
- if (!scan_label_only && !critical_section() && !full_scan_done()) {
- lvmcache_label_scan(info->fmt->cmd, 2);
-
- if (_get_pv_if_in_vg(info, pv))
- return 1;
- }
-
- /* Orphan */
- pv->dev = info->dev;
- pv->fmt = info->fmt;
- pv->size = info->device_size >> SECTOR_SHIFT;
- pv->vg_name = FMT_TEXT_ORPHAN_VG_NAME;
- memcpy(&pv->id, &info->dev->pvid, sizeof(pv->id));
-
- /* Currently only support exactly one data area */
- if (dm_list_size(&info->das) != 1) {
- log_error("Must be exactly one data area (found %d) on PV %s",
- dm_list_size(&info->das), dev_name(info->dev));
- return 0;
- }
-
- dm_list_iterate_items(da, &info->das)
- pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
-
- return 1;
-}
-
/*
* Copy constructor for a metadata_locn.
*/
@@ -1485,16 +1432,14 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
{
struct label *label;
struct device *dev;
- struct lvmcache_info *info;
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
return_0;
if (!(label_read(dev, &label, UINT64_C(0))))
return_0;
- info = (struct lvmcache_info *) label->info;
- if (!_populate_pv_fields(info, pv, scan_label_only))
+ if (!lvmcache_populate_pv_fields(label->info, pv, scan_label_only))
return 0;
return 1;
@@ -1670,18 +1615,15 @@ static int _text_pv_setup(const struct format_type *fmt,
* reread PV mda information from the cache and add it to vg->fid.
*/
else {
- if (!(info = info_from_pvid(pv->dev->pvid, 0))) {
+ if (!(info = lvmcache_info_from_pvid(pv->dev->pvid, 0))) {
log_error("PV %s missing from cache", pv_dev_name(pv));
return 0;
}
- if (fmt != info->fmt) {
- log_error("PV %s is a different format (seqno %s)",
- pv_dev_name(pv), info->fmt->name);
- return 0;
- }
+ if (!lvmcache_check_format(info, fmt))
+ return_0;
- if (!fid_add_mdas(vg->fid, &info->mdas, pvid, ID_LEN))
+ if (!lvmcache_fid_add_mdas_pv(info, fid))
return_0;
}
@@ -1736,8 +1678,8 @@ static int _create_pv_text_instance(struct format_instance *fid,
}
if (fic->type & FMT_INSTANCE_MDAS &&
- (info = info_from_pvid(fic->context.pv_id, 0)))
- fid_add_mdas(fid, &info->mdas, fic->context.pv_id, ID_LEN);
+ (info = lvmcache_info_from_pvid(fic->context.pv_id, 0)))
+ lvmcache_fid_add_mdas_pv(info, fid);
return 1;
}
@@ -1801,7 +1743,6 @@ static int _create_vg_text_instance(struct format_instance *fid,
struct dm_list *dir_list, *raw_list;
struct text_context tc;
struct lvmcache_vginfo *vginfo;
- struct lvmcache_info *info;
const char *vg_name, *vg_id;
if (!(fidtc = (struct text_fid_context *)
@@ -1873,12 +1814,10 @@ static int _create_vg_text_instance(struct format_instance *fid,
if (type & FMT_INSTANCE_MDAS) {
/* Scan PVs in VG for any further MDAs */
lvmcache_label_scan(fid->fmt->cmd, 0);
- if (!(vginfo = vginfo_from_vgname(vg_name, vg_id)))
+ if (!(vginfo = lvmcache_vginfo_from_vgname(vg_name, vg_id)))
+ goto_out;
+ if (!lvmcache_fid_add_mdas_vg(vginfo, fid))
goto_out;
- dm_list_iterate_items(info, &vginfo->infos) {
- if (!fid_add_mdas(fid, &info->mdas, info->dev->pvid, ID_LEN))
- return_0;
- }
}
/* FIXME Check raw metadata area count - rescan if required */
@@ -2314,7 +2253,7 @@ static int _get_config_disk_area(struct cmd_context *cmd,
return 0;
}
- if (!(dev_area.dev = device_from_pvid(cmd, &id, NULL, NULL))) {
+ if (!(dev_area.dev = lvmcache_device_from_pvid(cmd, &id, NULL, NULL))) {
char buffer[64] __attribute__((aligned(8)));
if (!id_write_format(&id, buffer, sizeof(buffer)))
diff --git a/lib/format_text/format-text.h b/lib/format_text/format-text.h
index 0281879d..d8ec2555 100644
--- a/lib/format_text/format-text.h
+++ b/lib/format_text/format-text.h
@@ -62,4 +62,16 @@ int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct dm_list *
struct device *dev, uint64_t start, uint64_t size, unsigned ignored);
void del_mdas(struct dm_list *mdas);
+/* On disk */
+struct disk_locn {
+ uint64_t offset; /* Offset in bytes to start sector */
+ uint64_t size; /* Bytes */
+} __attribute__ ((packed));
+
+/* Data areas (holding PEs) */
+struct data_area_list {
+ struct dm_list list;
+ struct disk_locn disk_locn;
+};
+
#endif
diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
index 2ad0380f..bfd8c973 100644
--- a/lib/format_text/import_vsn1.c
+++ b/lib/format_text/import_vsn1.c
@@ -190,7 +190,7 @@ static int _read_pv(struct format_instance *fid,
/*
* Convert the uuid into a device.
*/
- if (!(pv->dev = device_from_pvid(fid->fmt->cmd, &pv->id, scan_done_once,
+ if (!(pv->dev = lvmcache_device_from_pvid(fid->fmt->cmd, &pv->id, scan_done_once,
&pv->label_sector))) {
char buffer[64] __attribute__((aligned(8)));
diff --git a/lib/format_text/layout.h b/lib/format_text/layout.h
index a3141e07..1a9856d3 100644
--- a/lib/format_text/layout.h
+++ b/lib/format_text/layout.h
@@ -21,17 +21,7 @@
#include "metadata.h"
#include "uuid.h"
-/* On disk */
-struct disk_locn {
- uint64_t offset; /* Offset in bytes to start sector */
- uint64_t size; /* Bytes */
-} __attribute__ ((packed));
-
-/* Data areas (holding PEs) */
-struct data_area_list {
- struct dm_list list;
- struct disk_locn disk_locn;
-};
+/* disk_locn and data_area_list are defined in format-text.h */
/* Fields with the suffix _xl should be xlate'd wherever they appear */
/* On disk */
diff --git a/lib/format_text/text_label.c b/lib/format_text/text_label.c
index 11f93e20..b4257a7d 100644
--- a/lib/format_text/text_label.c
+++ b/lib/format_text/text_label.c
@@ -35,15 +35,41 @@ static int _text_can_handle(struct labeller *l __attribute__((unused)),
return 0;
}
+struct _da_setup_baton {
+ struct disk_locn *pvh_dlocn_xl;
+ struct device *dev;
+};
+
+static int _da_setup(struct data_area_list *da, void *baton)
+{
+ struct _da_setup_baton *p = baton;
+ p->pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset);
+ p->pvh_dlocn_xl->size = xlate64(da->disk_locn.size);
+ p->pvh_dlocn_xl++;
+ return 1;
+}
+
+static int _mda_setup(struct metadata_area *mda, void *baton)
+{
+ struct _da_setup_baton *p = baton;
+ struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
+
+ if (mdac->area.dev != p->dev)
+ return 1;
+
+ p->pvh_dlocn_xl->offset = xlate64(mdac->area.start);
+ p->pvh_dlocn_xl->size = xlate64(mdac->area.size);
+ p->pvh_dlocn_xl++;
+
+ return 1;
+}
+
static int _text_write(struct label *label, void *buf)
{
struct label_header *lh = (struct label_header *) buf;
struct pv_header *pvhdr;
struct lvmcache_info *info;
- struct disk_locn *pvh_dlocn_xl;
- struct metadata_area *mda;
- struct mda_context *mdac;
- struct data_area_list *da;
+ struct _da_setup_baton baton;
char buffer[64] __attribute__((aligned(8)));
int da1, mda1, mda2;
@@ -54,43 +80,31 @@ static int _text_write(struct label *label, void *buf)
pvhdr = (struct pv_header *) ((char *) buf + xlate32(lh->offset_xl));
info = (struct lvmcache_info *) label->info;
- pvhdr->device_size_xl = xlate64(info->device_size);
- memcpy(pvhdr->pv_uuid, &info->dev->pvid, sizeof(struct id));
+ pvhdr->device_size_xl = xlate64(lvmcache_device_size(info));
+ memcpy(pvhdr->pv_uuid, &lvmcache_device(info)->pvid, sizeof(struct id));
if (!id_write_format((const struct id *)pvhdr->pv_uuid, buffer,
sizeof(buffer))) {
stack;
buffer[0] = '\0';
}
- pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
+ baton.dev = lvmcache_device(info);
/* List of data areas (holding PEs) */
- dm_list_iterate_items(da, &info->das) {
- pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset);
- pvh_dlocn_xl->size = xlate64(da->disk_locn.size);
- pvh_dlocn_xl++;
- }
+ baton.pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
+ lvmcache_foreach_da(info, _da_setup, &baton);
/* NULL-termination */
- pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
- pvh_dlocn_xl->size = xlate64(UINT64_C(0));
- pvh_dlocn_xl++;
+ baton.pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
+ baton.pvh_dlocn_xl->size = xlate64(UINT64_C(0));
+ baton.pvh_dlocn_xl++;
/* List of metadata area header locations */
- dm_list_iterate_items(mda, &info->mdas) {
- mdac = (struct mda_context *) mda->metadata_locn;
-
- if (mdac->area.dev != info->dev)
- continue;
-
- pvh_dlocn_xl->offset = xlate64(mdac->area.start);
- pvh_dlocn_xl->size = xlate64(mdac->area.size);
- pvh_dlocn_xl++;
- }
+ lvmcache_foreach_mda(info, _mda_setup, &baton);
/* NULL-termination */
- pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
- pvh_dlocn_xl->size = xlate64(UINT64_C(0));
+ baton.pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
+ baton.pvh_dlocn_xl->size = xlate64(UINT64_C(0));
/* Create debug message with da and mda locations */
if (xlate64(pvhdr->disk_areas_xl[0].offset) ||
@@ -113,7 +127,7 @@ static int _text_write(struct label *label, void *buf)
"%s%.*" PRIu64 "%s%.*" PRIu64 "%s"
"%s%.*" PRIu64 "%s%.*" PRIu64 "%s"
"%s%.*" PRIu64 "%s%.*" PRIu64 "%s",
- dev_name(info->dev), buffer, info->device_size,
+ dev_name(lvmcache_device(info)), buffer, lvmcache_device_size(info),
(da1 > -1) ? " da1 (" : "",
(da1 > -1) ? 1 : 0,
(da1 > -1) ? xlate64(pvhdr->disk_areas_xl[da1].offset) >> SECTOR_SHIFT : 0,
@@ -138,7 +152,7 @@ static int _text_write(struct label *label, void *buf)
if (da1 < 0) {
log_error(INTERNAL_ERROR "%s label header currently requires "
- "a data area.", dev_name(info->dev));
+ "a data area.", dev_name(lvmcache_device(info)));
return 0;
}
@@ -250,6 +264,62 @@ static int _text_initialise_label(struct labeller *l __attribute__((unused)),
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,
struct label **label)
{
@@ -258,13 +328,7 @@ static int _text_read(struct labeller *l, struct device *dev, void *buf,
struct lvmcache_info *info;
struct disk_locn *dlocn_xl;
uint64_t offset;
- struct metadata_area *mda;
- struct id vgid;
- struct mda_context *mdac;
- const char *vgname;
- uint64_t vgstatus;
- char *creation_host;
- struct mda_header *mdah;
+ struct _update_mda_baton baton;
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, 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)
- del_das(&info->das);
- dm_list_init(&info->das);
+ lvmcache_set_device_size(info, xlate64(pvhdr->device_size_xl));
- if (info->mdas.n)
- del_mdas(&info->mdas);
- dm_list_init(&info->mdas);
+ lvmcache_del_das(info);
+ lvmcache_del_mdas(info);
/* Data areas holding the PEs */
dlocn_xl = pvhdr->disk_areas_xl;
while ((offset = xlate64(dlocn_xl->offset))) {
- add_da(NULL, &info->das, offset,
- xlate64(dlocn_xl->size));
+ lvmcache_add_da(info, offset, xlate64(dlocn_xl->size));
dlocn_xl++;
}
/* Metadata area headers */
dlocn_xl++;
while ((offset = xlate64(dlocn_xl->offset))) {
- add_mda(info->fmt, NULL, &info->mdas, dev, offset,
- xlate64(dlocn_xl->size), 0);
+ lvmcache_add_mda(info, dev, offset, xlate64(dlocn_xl->size), 0);
dlocn_xl++;
}
- dm_list_iterate_items(mda, &info->mdas) {
- mdac = (struct mda_context *) mda->metadata_locn;
- if (!dev_open_readonly(mdac->area.dev)) {
- mda_set_ignored(mda, 1);
- stack;
- continue;
- }
- 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)) {
- 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;
- 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;
- }
+ baton.info = info;
+ baton.label = *label;
- info->status &= ~CACHE_INVALID;
+ lvmcache_foreach_mda(info, _update_mda, &baton);
+ lvmcache_make_valid(info);
return 1;
}
@@ -348,10 +373,8 @@ static void _text_destroy_label(struct labeller *l __attribute__((unused)),
{
struct lvmcache_info *info = (struct lvmcache_info *) label->info;
- if (info->mdas.n)
- del_mdas(&info->mdas);
- if (info->das.n)
- del_das(&info->das);
+ lvmcache_del_mdas(info);
+ lvmcache_del_das(info);
}
static void _fmt_text_destroy(struct labeller *l)
diff --git a/lib/label/label.c b/lib/label/label.c
index f377367e..c38ea16e 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -172,9 +172,9 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
out:
if (!found) {
- if ((info = info_from_pvid(dev->pvid, 0)))
- lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
- info->fmt->orphan_vg_name,
+ if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
+ lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
+ lvmcache_fmt(info)->orphan_vg_name,
0, NULL);
log_very_verbose("%s: No label detected", dev_name(dev));
}
@@ -261,18 +261,18 @@ int label_read(struct device *dev, struct label **result,
struct lvmcache_info *info;
int r = 0;
- if ((info = info_from_pvid(dev->pvid, 1))) {
+ if ((info = lvmcache_info_from_pvid(dev->pvid, 1))) {
log_debug("Using cached label for %s", dev_name(dev));
- *result = info->label;
+ *result = lvmcache_get_label(info); /* leaked */
return 1;
}
if (!dev_open_readonly(dev)) {
stack;
- if ((info = info_from_pvid(dev->pvid, 0)))
- lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
- info->fmt->orphan_vg_name,
+ if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
+ lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
+ lvmcache_fmt(info)->orphan_vg_name,
0, NULL);
return r;
@@ -348,9 +348,9 @@ int label_verify(struct device *dev)
int r = 0;
if (!dev_open_readonly(dev)) {
- if ((info = info_from_pvid(dev->pvid, 0)))
- lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
- info->fmt->orphan_vg_name,
+ if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
+ lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
+ lvmcache_fmt(info)->orphan_vg_name,
0, NULL);
return_0;
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 523284dc..b487d6ad 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1504,7 +1504,7 @@ struct physical_volume * pvcreate_single(struct cmd_context *cmd,
pp = &default_pp;
if (pp->idp) {
- if ((dev = device_from_pvid(cmd, pp->idp, NULL, NULL)) &&
+ if ((dev = lvmcache_device_from_pvid(cmd, pp->idp, NULL, NULL)) &&
(dev != dev_cache_get(pv_name, cmd->filter))) {
if (!id_write_format((const struct id*)&pp->idp->uuid,
buffer, sizeof(buffer)))
@@ -2671,7 +2671,7 @@ int vg_commit(struct volume_group *vg)
{
int cache_updated = 0;
- if (!vgname_is_locked(vg->name)) {
+ if (!lvmcache_vgname_is_locked(vg->name)) {
log_error(INTERNAL_ERROR "Attempt to write new VG metadata "
"without locking %s", vg->name);
return cache_updated;
@@ -2717,6 +2717,31 @@ void vg_revert(struct volume_group *vg)
remote_revert_cached_metadata(vg);
}
+struct _vg_read_orphan_baton {
+ struct volume_group *vg;
+ int warnings;
+};
+
+static int _vg_read_orphan_pv(struct lvmcache_info *info, void *baton)
+{
+ struct _vg_read_orphan_baton *b = baton;
+ struct physical_volume *pv = NULL;
+ struct pv_list *pvl;
+
+ if (!(pv = _pv_read(b->vg->cmd, b->vg->vgmem, dev_name(lvmcache_device(info)),
+ b->vg->fid, b->warnings, 0))) {
+ return 1;
+ }
+ if (!(pvl = dm_pool_zalloc(b->vg->vgmem, sizeof(*pvl)))) {
+ log_error("pv_list allocation failed");
+ free_pv_fid(pv);
+ return 0;
+ }
+ pvl->pv = pv;
+ add_pvl_to_vgs(b->vg, pvl);
+ return 1;
+}
+
/* Make orphan PVs look like a VG */
static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
int warnings,
@@ -2724,15 +2749,17 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
{
struct format_instance_ctx fic;
struct format_instance *fid;
+ const struct format_type *fmt;
struct lvmcache_vginfo *vginfo;
- struct lvmcache_info *info;
- struct pv_list *pvl;
struct volume_group *vg = NULL;
- struct physical_volume *pv = NULL;
+ struct _vg_read_orphan_baton baton;
lvmcache_label_scan(cmd, 0);
- if (!(vginfo = vginfo_from_vgname(orphan_vgname, NULL)))
+ if (!(vginfo = lvmcache_vginfo_from_vgname(orphan_vgname, NULL)))
+ return_NULL;
+
+ if (!(fmt = lvmcache_fmt_from_vgname(orphan_vgname, NULL, 0)))
return_NULL;
if (!(vg = alloc_vg("vg_read_orphans", cmd, orphan_vgname)))
@@ -2742,28 +2769,18 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
fic.type = FMT_INSTANCE_VG | FMT_INSTANCE_AUX_MDAS;
fic.context.vg_ref.vg_name = orphan_vgname;
fic.context.vg_ref.vg_id = NULL;
- if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt, &fic))) {
+ if (!(fid = fmt->ops->create_instance(fmt, &fic))) {
log_error("Failed to create format instance");
goto bad;
}
vg_set_fid(vg, fid);
- dm_list_iterate_items(info, &vginfo->infos) {
- if (!(pv = _pv_read(cmd, vg->vgmem, dev_name(info->dev),
- vg->fid, warnings, 0))) {
- continue;
- }
- if (!(pvl = dm_pool_zalloc(vg->vgmem, sizeof(*pvl)))) {
- log_error("pv_list allocation failed");
- goto bad;
- }
- pvl->pv = pv;
- add_pvl_to_vgs(vg, pvl);
- }
+ baton.warnings = warnings;
+ baton.vg = vg;
+ lvmcache_foreach_pv(vginfo, _vg_read_orphan_pv, &baton);
return vg;
bad:
- free_pv_fid(pv);
release_vg(vg);
return NULL;
}
@@ -2848,6 +2865,15 @@ static void check_reappeared_pv(struct volume_group *correct_vg,
"on it, remove volumes and consider vgreduce --removemissing.");
}
}
+
+static int _check_mda_in_use(struct metadata_area *mda, void *_in_use)
+{
+ int *in_use = _in_use;
+ if (!mda_is_ignored(mda))
+ *in_use = 1;
+ return 1;
+}
+
/* Caller sets consistent to 1 if it's safe for vg_read_internal to correct
* inconsistent metadata on disk (i.e. the VG write lock is held).
* This guarantees only consistent metadata is returned.
@@ -2913,20 +2939,20 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
/* Find the vgname in the cache */
/* If it's not there we must do full scan to be completely sure */
- if (!(fmt = fmt_from_vgname(vgname, vgid, 1))) {
+ if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 1))) {
lvmcache_label_scan(cmd, 0);
- if (!(fmt = fmt_from_vgname(vgname, vgid, 1))) {
+ if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 1))) {
/* Independent MDAs aren't supported under low memory */
if (!cmd->independent_metadata_areas && critical_section())
return_NULL;
lvmcache_label_scan(cmd, 2);
- if (!(fmt = fmt_from_vgname(vgname, vgid, 0)))
+ if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 0)))
return_NULL;
}
}
/* Now determine the correct vgname if none was supplied */
- if (!vgname && !(vgname = vgname_from_vgid(cmd->mem, vgid)))
+ if (!vgname && !(vgname = lvmcache_vgname_from_vgid(cmd->mem, vgid)))
return_NULL;
if (use_precommitted && !(fmt->features & FMT_PRECOMMIT))
@@ -3016,18 +3042,17 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
* Check it's an orphan without metadata area
* not ignored.
*/
- if (!(info = info_from_pvid(pvl->pv->dev->pvid, 1)) ||
- !info->vginfo || !is_orphan_vg(info->vginfo->vgname)) {
+ if (!(info = lvmcache_info_from_pvid(pvl->pv->dev->pvid, 1)) ||
+ !lvmcache_is_orphan(info)) {
inconsistent_pvs = 1;
break;
}
- if (dm_list_size(&info->mdas)) {
- if (!fid_add_mdas(fid, &info->mdas,
- info->dev->pvid, ID_LEN)) {
+ if (lvmcache_mda_count(info)) {
+ if (!lvmcache_fid_add_mdas_pv(info, fid)) {
release_vg(correct_vg);
return_NULL;
}
-
+
log_debug("Empty mda found for VG %s.", vgname);
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
* metadata needs updating.
*/
- dm_list_iterate_items(mda, &info->mdas)
- if (!mda_is_ignored(mda)) {
- inconsistent_mdas = 1;
- break;
- }
+ lvmcache_foreach_mda(info, _check_mda_in_use,
+ &inconsistent_mdas);
}
}
@@ -3110,7 +3132,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
if (!cmd->independent_metadata_areas && critical_section())
return_NULL;
lvmcache_label_scan(cmd, 2);
- if (!(fmt = fmt_from_vgname(vgname, vgid, 0)))
+ if (!(fmt = lvmcache_fmt_from_vgname(vgname, vgid, 0)))
return_NULL;
if (precommitted && !(fmt->features & FMT_PRECOMMIT))
@@ -3383,13 +3405,11 @@ static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
const char *vgname;
struct dm_list *vgnames;
struct volume_group *vg;
- struct lvmcache_vginfo *vginfo;
struct str_list *strl;
int consistent = 0;
/* Is corresponding vgname already cached? */
- if ((vginfo = vginfo_from_vgid(vgid)) &&
- vginfo->vgname && !is_orphan_vg(vginfo->vgname)) {
+ if (lvmcache_vgid_is_cached(vgid)) {
if ((vg = _vg_read(cmd, NULL, vgid, 1,
&consistent, precommitted)) &&
id_equal(&vg->id, (const struct id *)vgid)) {
@@ -3480,7 +3500,7 @@ const char *find_vgname_from_pvid(struct cmd_context *cmd,
vgname = lvmcache_vgname_from_pvid(cmd, pvid);
if (is_orphan_vg(vgname)) {
- if (!(info = info_from_pvid(pvid, 0))) {
+ if (!(info = lvmcache_info_from_pvid(pvid, 0))) {
return_NULL;
}
/*
@@ -3490,7 +3510,7 @@ const char *find_vgname_from_pvid(struct cmd_context *cmd,
* Detecting this means checking every VG by scanning
* every PV on the system.
*/
- if (mdas_empty_or_ignored(&info->mdas)) {
+ if (lvmcache_uncertain_ownership(info)) {
if (!scan_vgs_for_pvs(cmd, 1)) {
log_error("Rescan for PVs without "
"metadata areas failed.");
@@ -3512,7 +3532,7 @@ const char *find_vgname_from_pvname(struct cmd_context *cmd,
{
const char *pvid;
- pvid = pvid_from_devname(cmd, pvname);
+ pvid = lvmcache_pvid_from_devname(cmd, pvname);
if (!pvid)
/* Not a PV */
return NULL;
@@ -3576,7 +3596,7 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
pv->label_sector = label->sector;
/* FIXME Move more common code up here */
- if (!(info->fmt->ops->pv_read(info->fmt, pv_name, pv, scan_label_only))) {
+ if (!(lvmcache_fmt(info)->ops->pv_read(lvmcache_fmt(info), pv_name, pv, scan_label_only))) {
log_error("Failed to read existing physical volume '%s'",
pv_name);
goto bad;
@@ -3589,7 +3609,7 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
goto_bad;
if (fid)
- fid_add_mdas(fid, &info->mdas, (const char *) &pv->id, ID_LEN);
+ lvmcache_fid_add_mdas(info, fid, (const char *) &pv->id, ID_LEN);
else {
fic.type = FMT_INSTANCE_PV | FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
fic.context.pv_id = (const char *) &pv->id;
@@ -3656,7 +3676,7 @@ static int _get_pvs(struct cmd_context *cmd, int warnings, struct dm_list **pvsl
if (!vgid)
continue; /* FIXME Unnecessary? */
consistent = 0;
- if (!(vgname = vgname_from_vgid(NULL, vgid))) {
+ if (!(vgname = lvmcache_vgname_from_vgid(NULL, vgid))) {
stack;
continue;
}
@@ -3777,6 +3797,13 @@ int is_real_vg(const char *vg_name)
return (vg_name && *vg_name != '#');
}
+static int _analyze_mda(struct metadata_area *mda, void *baton)
+{
+ const struct format_type *fmt = baton;
+ mda->ops->pv_analyze_mda(fmt, mda);
+ return 1;
+}
+
/*
* Returns:
* 0 - fail
@@ -3787,7 +3814,6 @@ int pv_analyze(struct cmd_context *cmd, const char *pv_name,
{
struct label *label;
struct device *dev;
- struct metadata_area *mda;
struct lvmcache_info *info;
dev = dev_cache_get(pv_name, cmd->filter);
@@ -3813,8 +3839,7 @@ int pv_analyze(struct cmd_context *cmd, const char *pv_name,
* Next, loop through metadata areas
*/
info = label->info;
- dm_list_iterate_items(mda, &info->mdas)
- mda->ops->pv_analyze_mda(info->fmt, mda);
+ lvmcache_foreach_mda(info, _analyze_mda, (void *)lvmcache_fmt(info));
return 1;
}
@@ -3932,7 +3957,7 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
return NULL;
}
- already_locked = vgname_is_locked(vg_name);
+ already_locked = lvmcache_vgname_is_locked(vg_name);
if (!already_locked && !(misc_flags & READ_WITHOUT_LOCK) &&
!lock_vol(cmd, vg_name, lock_flags)) {
@@ -4096,9 +4121,9 @@ uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname)
/* Find the vgname in the cache */
/* If it's not there we must do full scan to be completely sure */
- if (!fmt_from_vgname(vgname, NULL, 1)) {
+ if (!lvmcache_fmt_from_vgname(vgname, NULL, 1)) {
lvmcache_label_scan(cmd, 0);
- if (!fmt_from_vgname(vgname, NULL, 1)) {
+ if (!lvmcache_fmt_from_vgname(vgname, NULL, 1)) {
/* Independent MDAs aren't supported under low memory */
if (!cmd->independent_metadata_areas && critical_section()) {
/*
@@ -4109,7 +4134,7 @@ uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname)
return FAILED_LOCKING;
}
lvmcache_label_scan(cmd, 2);
- if (!fmt_from_vgname(vgname, NULL, 0)) {
+ if (!lvmcache_fmt_from_vgname(vgname, NULL, 0)) {
/* vgname not found after scanning */
return SUCCESS;
}
diff --git a/lib/metadata/pv.c b/lib/metadata/pv.c
index f6c32b90..09b869b7 100644
--- a/lib/metadata/pv.c
+++ b/lib/metadata/pv.c
@@ -143,23 +143,27 @@ uint32_t pv_mda_count(const struct physical_volume *pv)
{
struct lvmcache_info *info;
- info = info_from_pvid((const char *)&pv->id.uuid, 0);
- return info ? dm_list_size(&info->mdas) : UINT64_C(0);
+ info = lvmcache_info_from_pvid((const char *)&pv->id.uuid, 0);
+ return info ? lvmcache_mda_count(info) : UINT64_C(0);
+}
+
+static int _count_unignored(struct metadata_area *mda, void *baton)
+{
+ uint32_t *count = baton;
+ if (!mda_is_ignored(mda))
+ (*count) ++;
+ return 1;
}
uint32_t pv_mda_used_count(const struct physical_volume *pv)
{
struct lvmcache_info *info;
- struct metadata_area *mda;
uint32_t used_count=0;
- info = info_from_pvid((const char *)&pv->id.uuid, 0);
+ info = lvmcache_info_from_pvid((const char *)&pv->id.uuid, 0);
if (!info)
return 0;
- dm_list_iterate_items(mda, &info->mdas) {
- if (!mda_is_ignored(mda))
- used_count++;
- }
+ lvmcache_foreach_mda(info, _count_unignored, &used_count);
return used_count;
}
@@ -209,29 +213,36 @@ uint64_t pv_mda_size(const struct physical_volume *pv)
const char *pvid = (const char *)(&pv->id.uuid);
/* PVs could have 2 mdas of different sizes (rounding effect) */
- if ((info = info_from_pvid(pvid, 0)))
- min_mda_size = find_min_mda_size(&info->mdas);
+ if ((info = lvmcache_info_from_pvid(pvid, 0)))
+ min_mda_size = lvmcache_smallest_mda_size(info);
return min_mda_size;
}
+static int _pv_mda_free(struct metadata_area *mda, void *baton) {
+ uint64_t mda_free;
+ uint64_t *freespace = baton;
+
+ if (!mda->ops->mda_free_sectors)
+ return 1;
+
+ mda_free = mda->ops->mda_free_sectors(mda);
+ if (mda_free < *freespace)
+ *freespace = mda_free;
+ return 1;
+}
+
uint64_t pv_mda_free(const struct physical_volume *pv)
{
struct lvmcache_info *info;
- uint64_t freespace = UINT64_MAX, mda_free;
+ uint64_t freespace = UINT64_MAX;
const char *pvid = (const char *)&pv->id.uuid;
- struct metadata_area *mda;
- if ((info = info_from_pvid(pvid, 0)))
- dm_list_iterate_items(mda, &info->mdas) {
- if (!mda->ops->mda_free_sectors)
- continue;
- mda_free = mda->ops->mda_free_sectors(mda);
- if (mda_free < freespace)
- freespace = mda_free;
- }
+ if ((info = lvmcache_info_from_pvid(pvid, 0)))
+ lvmcache_foreach_mda(info, _pv_mda_free, &freespace);
if (freespace == UINT64_MAX)
freespace = UINT64_C(0);
+
return freespace;
}
@@ -246,22 +257,51 @@ uint64_t pv_used(const struct physical_volume *pv)
return used;
}
+struct _pv_mda_set_ignored_baton {
+ unsigned mda_ignored;
+ struct dm_list *mdas_in_use, *mdas_ignored, *mdas_to_change;
+};
+
+static int _pv_mda_set_ignored_one(struct metadata_area *mda, void *baton)
+{
+ struct _pv_mda_set_ignored_baton *b = baton;
+ struct metadata_area *vg_mda, *tmda;
+
+ if (mda_is_ignored(mda) && !b->mda_ignored) {
+ /* Changing an ignored mda to one in_use requires moving it */
+ dm_list_iterate_items_safe(vg_mda, tmda, b->mdas_ignored)
+ if (mda_locns_match(mda, vg_mda)) {
+ mda_set_ignored(vg_mda, b->mda_ignored);
+ dm_list_move(b->mdas_in_use, &vg_mda->list);
+ }
+ }
+
+ dm_list_iterate_items_safe(vg_mda, tmda, b->mdas_in_use)
+ if (mda_locns_match(mda, vg_mda))
+ /* Don't move mda: needs writing to disk. */
+ mda_set_ignored(vg_mda, b->mda_ignored);
+
+ mda_set_ignored(mda, b->mda_ignored);
+ return 1;
+}
+
unsigned pv_mda_set_ignored(const struct physical_volume *pv, unsigned mda_ignored)
{
struct lvmcache_info *info;
- struct metadata_area *mda, *vg_mda, *tmda;
- struct dm_list *mdas_in_use, *mdas_ignored, *mdas_to_change;
+ struct _pv_mda_set_ignored_baton baton;
+ struct metadata_area *mda;
- if (!(info = info_from_pvid((const char *)&pv->id.uuid, 0)))
+ if (!(info = lvmcache_info_from_pvid((const char *)&pv->id.uuid, 0)))
return_0;
- mdas_in_use = &pv->fid->metadata_areas_in_use;
- mdas_ignored = &pv->fid->metadata_areas_ignored;
- mdas_to_change = mda_ignored ? mdas_in_use : mdas_ignored;
+ baton.mda_ignored = mda_ignored;
+ baton.mdas_in_use = &pv->fid->metadata_areas_in_use;
+ baton.mdas_ignored = &pv->fid->metadata_areas_ignored;
+ baton.mdas_to_change = baton.mda_ignored ? baton.mdas_in_use : baton.mdas_ignored;
if (is_orphan(pv)) {
- dm_list_iterate_items(mda, mdas_to_change)
- mda_set_ignored(mda, mda_ignored);
+ dm_list_iterate_items(mda, baton.mdas_to_change)
+ mda_set_ignored(mda, baton.mda_ignored);
return 1;
}
@@ -288,22 +328,8 @@ unsigned pv_mda_set_ignored(const struct physical_volume *pv, unsigned mda_ignor
/* FIXME: Try not to update the cache here! Also, try to iterate over
* PV mdas only using the format instance's index somehow
* (i.e. try to avoid using mda_locn_match call). */
- dm_list_iterate_items(mda, &info->mdas) {
- if (mda_is_ignored(mda) && !mda_ignored)
- /* Changing an ignored mda to one in_use requires moving it */
- dm_list_iterate_items_safe(vg_mda, tmda, mdas_ignored)
- if (mda_locns_match(mda, vg_mda)) {
- mda_set_ignored(vg_mda, mda_ignored);
- dm_list_move(mdas_in_use, &vg_mda->list);
- }
-
- dm_list_iterate_items_safe(vg_mda, tmda, mdas_in_use)
- if (mda_locns_match(mda, vg_mda))
- /* Don't move mda: needs writing to disk. */
- mda_set_ignored(vg_mda, mda_ignored);
-
- mda_set_ignored(mda, mda_ignored);
- }
+
+ lvmcache_foreach_mda(info, _pv_mda_set_ignored_one, &baton);
return 1;
}
diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c
index b0ce3bf7..3159e3e9 100644
--- a/lib/metadata/vg.c
+++ b/lib/metadata/vg.c
@@ -84,7 +84,7 @@ void release_vg(struct volume_group *vg)
/* Check if there are any vginfo holders */
if (vg->vginfo &&
- !vginfo_holders_dec_and_test_for_zero(vg->vginfo))
+ !lvmcache_vginfo_holders_dec_and_test_for_zero(vg->vginfo))
return;
_free_vg(vg);
diff --git a/tools/toollib.c b/tools/toollib.c
index 652330c1..bd24dad8 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -587,7 +587,7 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
}
dm_list_iterate_items(sl, vgids) {
vgid = sl->str;
- if (!(vgid) || !(vg_name = vgname_from_vgid(cmd->mem, vgid)))
+ if (!(vgid) || !(vg_name = lvmcache_vgname_from_vgid(cmd->mem, vgid)))
continue;
ret_max = _process_one_vg(cmd, vg_name, vgid, &tags,
&arg_vgnames,
diff --git a/tools/vgrename.c b/tools/vgrename.c
index 1f1f9434..58e559b0 100644
--- a/tools/vgrename.c
+++ b/tools/vgrename.c
@@ -87,7 +87,7 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
dm_list_iterate_items(sl, vgids) {
vgid = sl->str;
- if (!vgid || !(vg_name = vgname_from_vgid(NULL, vgid)))
+ if (!vgid || !(vg_name = lvmcache_vgname_from_vgid(NULL, vgid)))
continue;
if (!strcmp(vg_name, vg_name_old)) {
if (match) {
@@ -102,7 +102,7 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
log_suppress(2);
found_id = id_read_format(&id, vg_name_old);
log_suppress(0);
- if (found_id && (vg_name = vgname_from_vgid(cmd->mem, (char *)id.uuid))) {
+ if (found_id && (vg_name = lvmcache_vgname_from_vgid(cmd->mem, (char *)id.uuid))) {
vg_name_old = vg_name;
vgid = (char *)id.uuid;
} else