1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-22 17:35:59 +03:00

Rely upon internally-cached PV labels while corresponding VG lock is held.

This commit is contained in:
Alasdair Kergon 2008-01-29 23:45:48 +00:00
parent d5a9c43cb2
commit 6726c5f958
8 changed files with 83 additions and 19 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.33 -
===================================
Rely upon internally-cached PV labels while corresponding VG lock is held.
Version 2.02.32 - 29th January 2008
===================================

74
lib/cache/lvmcache.c vendored
View File

@ -49,6 +49,41 @@ int lvmcache_init(void)
return 1;
}
static void _update_cache_info_lock_state(struct lvmcache_info *info, int locked)
{
int was_locked = (info->status & CACHE_LOCKED) ? 1 : 0;
/*
* Cache becomes invalid whenever lock state changes
*/
if (was_locked != locked)
info->status |= CACHE_INVALID;
if (locked)
info->status |= CACHE_LOCKED;
else
info->status &= ~CACHE_LOCKED;
}
static void _update_cache_vginfo_lock_state(struct lvmcache_vginfo *vginfo,
int locked)
{
struct lvmcache_info *info;
list_iterate_items(info, &vginfo->infos)
_update_cache_info_lock_state(info, locked);
}
static void _update_cache_lock_state(const char *vgname, int locked)
{
struct lvmcache_vginfo *vginfo;
if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
return;
_update_cache_vginfo_lock_state(vginfo, locked);
}
void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
{
if (!_lock_hash && !lvmcache_init()) {
@ -59,6 +94,8 @@ void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)
if (!dm_hash_insert(_lock_hash, vgname, (void *) 1))
log_error("Cache locking failure for %s", vgname);
_update_cache_lock_state(vgname, 1);
_vgs_locked++;
}
@ -72,7 +109,8 @@ int vgname_is_locked(const char *vgname)
void lvmcache_unlock_vgname(const char *vgname)
{
/* FIXME: Clear all CACHE_LOCKED flags in this vg */
_update_cache_lock_state(vgname, 0);
dm_hash_remove(_lock_hash, vgname);
/* FIXME Do this per-VG */
@ -182,7 +220,22 @@ const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
return vgname;
}
struct lvmcache_info *info_from_pvid(const char *pvid)
static int _info_is_valid(struct lvmcache_info *info)
{
if (info->status & CACHE_INVALID)
return 0;
if (!(info->status & CACHE_LOCKED))
return 0;
return 1;
}
/*
* 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 *info;
char id[ID_LEN + 1] __attribute((aligned(8)));
@ -196,6 +249,9 @@ struct lvmcache_info *info_from_pvid(const char *pvid)
if (!(info = dm_hash_lookup(_pvid_hash, id)))
return NULL;
if (valid_only && !_info_is_valid(info))
return NULL;
return info;
}
@ -344,7 +400,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
struct lvmcache_info *info;
/* Already cached ? */
if ((info = info_from_pvid((char *) pvid))) {
if ((info = info_from_pvid((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))
@ -355,7 +411,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
lvmcache_label_scan(cmd, 0);
/* Try again */
if ((info = info_from_pvid((char *) pvid))) {
if ((info = info_from_pvid((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))
@ -369,7 +425,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
lvmcache_label_scan(cmd, 2);
/* Try again */
if ((info = info_from_pvid((char *) pvid))) {
if ((info = info_from_pvid((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))
@ -645,6 +701,8 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
info->vginfo = vginfo;
list_add(&vginfo->infos, &info->list);
_update_cache_vginfo_lock_state(vginfo, vgname_is_locked(vgname));
/* FIXME Check consistency of list! */
vginfo->fmt = info->fmt;
@ -716,7 +774,7 @@ int lvmcache_update_vg(struct volume_group *vg)
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)) &&
if ((info = info_from_pvid(pvid_s, 0)) &&
!lvmcache_update_vgname_and_id(info, vg->name,
(char *) &vg->id,
vg->status, NULL))
@ -743,8 +801,8 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
strncpy(pvid_s, pvid, sizeof(pvid_s));
pvid_s[sizeof(pvid_s) - 1] = '\0';
if (!(existing = info_from_pvid(pvid_s)) &&
!(existing = info_from_pvid(dev->pvid))) {
if (!(existing = info_from_pvid(pvid_s, 0)) &&
!(existing = info_from_pvid(dev->pvid, 0))) {
if (!(label = label_create(labeller))) {
stack;
return NULL;

View File

@ -86,7 +86,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid);
struct lvmcache_vginfo *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);
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, struct id *pvid);
int vgs_locked(void);

View File

@ -523,7 +523,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)) ||
(!(info = info_from_pvid(dev->pvid, 0)) ||
!info->vginfo ||
!vgname_is_locked(info->vginfo->vgname))))
_close(dev);

View File

@ -305,7 +305,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
/* Add any metadata areas on the PVs */
list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv;
if (!(info = info_from_pvid(pv->dev->pvid))) {
if (!(info = info_from_pvid(pv->dev->pvid, 0))) {
log_error("PV %s missing from cache",
pv_dev_name(pv));
return 0;

View File

@ -391,7 +391,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
}
error:
if ((info = info_from_pvid(dev_area->dev->pvid)))
if ((info = info_from_pvid(dev_area->dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0, NULL);
return NULL;
@ -1610,7 +1610,7 @@ static int _text_pv_setup(const struct format_type *fmt,
/* If new vg, add any further mdas on this PV to the fid's mda list */
if (vg) {
/* Iterate through all mdas on this PV */
if ((info = info_from_pvid(pv->dev->pvid))) {
if ((info = info_from_pvid(pv->dev->pvid, 0))) {
pvmdas = &info->mdas;
list_iterate_items(mda, pvmdas) {
mda_count++;

View File

@ -179,7 +179,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
out:
if (!found) {
if ((info = info_from_pvid(dev->pvid)))
if ((info = info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
0, NULL);
log_very_verbose("%s: No label detected", dev_name(dev));
@ -260,7 +260,6 @@ int label_remove(struct device *dev)
return r;
}
/* FIXME Avoid repeated re-reading if cache lock held */
int label_read(struct device *dev, struct label **result,
uint64_t scan_sector)
{
@ -270,10 +269,16 @@ int label_read(struct device *dev, struct label **result,
struct lvmcache_info *info;
int r = 0;
if ((info = info_from_pvid(dev->pvid, 1))) {
log_debug("Using cached label for %s", dev_name(dev));
*result = info->label;
return 1;
}
if (!dev_open(dev)) {
stack;
if ((info = info_from_pvid(dev->pvid)))
if ((info = info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
0, NULL);
@ -353,7 +358,7 @@ int label_verify(struct device *dev)
int r = 0;
if (!dev_open(dev)) {
if ((info = info_from_pvid(dev->pvid)))
if ((info = info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
0, NULL);

View File

@ -840,7 +840,7 @@ static int _pvmdas_disp(struct dm_report *rh, struct dm_pool *mem,
uint32_t count;
const char *pvid = (const char *)(&((struct id *) data)->uuid);
info = info_from_pvid(pvid);
info = info_from_pvid(pvid, 0);
count = info ? list_size(&info->mdas) : 0;
return _uint32_disp(rh, mem, field, &count, private);
@ -867,7 +867,7 @@ static int _pvmdafree_disp(struct dm_report *rh, struct dm_pool *mem,
const char *pvid = (const char *)(&((struct id *) data)->uuid);
struct metadata_area *mda;
info = info_from_pvid(pvid);
info = info_from_pvid(pvid, 0);
list_iterate_items(mda, &info->mdas) {
if (!mda->ops->mda_free_sectors)