Home | History | Annotate | Line # | Download | only in cache
lvmcache.c revision 1.1.1.1
      1  1.1  haad /*	$NetBSD: lvmcache.c,v 1.1.1.1 2008/12/22 00:17:52 haad Exp $	*/
      2  1.1  haad 
      3  1.1  haad /*
      4  1.1  haad  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
      5  1.1  haad  * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
      6  1.1  haad  *
      7  1.1  haad  * This file is part of LVM2.
      8  1.1  haad  *
      9  1.1  haad  * This copyrighted material is made available to anyone wishing to use,
     10  1.1  haad  * modify, copy, or redistribute it subject to the terms and conditions
     11  1.1  haad  * of the GNU Lesser General Public License v.2.1.
     12  1.1  haad  *
     13  1.1  haad  * You should have received a copy of the GNU Lesser General Public License
     14  1.1  haad  * along with this program; if not, write to the Free Software Foundation,
     15  1.1  haad  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     16  1.1  haad  */
     17  1.1  haad 
     18  1.1  haad #include "lib.h"
     19  1.1  haad #include "lvmcache.h"
     20  1.1  haad #include "toolcontext.h"
     21  1.1  haad #include "dev-cache.h"
     22  1.1  haad #include "locking.h"
     23  1.1  haad #include "metadata.h"
     24  1.1  haad #include "filter.h"
     25  1.1  haad #include "memlock.h"
     26  1.1  haad #include "str_list.h"
     27  1.1  haad #include "format-text.h"
     28  1.1  haad #include "format_pool.h"
     29  1.1  haad #include "format1.h"
     30  1.1  haad 
     31  1.1  haad static struct dm_hash_table *_pvid_hash = NULL;
     32  1.1  haad static struct dm_hash_table *_vgid_hash = NULL;
     33  1.1  haad static struct dm_hash_table *_vgname_hash = NULL;
     34  1.1  haad static struct dm_hash_table *_lock_hash = NULL;
     35  1.1  haad static struct dm_list _vginfos;
     36  1.1  haad static int _scanning_in_progress = 0;
     37  1.1  haad static int _has_scanned = 0;
     38  1.1  haad static int _vgs_locked = 0;
     39  1.1  haad static int _vg_global_lock_held = 0;	/* Global lock held when cache wiped? */
     40  1.1  haad 
     41  1.1  haad int lvmcache_init(void)
     42  1.1  haad {
     43  1.1  haad 	dm_list_init(&_vginfos);
     44  1.1  haad 
     45  1.1  haad 	if (!(_vgname_hash = dm_hash_create(128)))
     46  1.1  haad 		return 0;
     47  1.1  haad 
     48  1.1  haad 	if (!(_vgid_hash = dm_hash_create(128)))
     49  1.1  haad 		return 0;
     50  1.1  haad 
     51  1.1  haad 	if (!(_pvid_hash = dm_hash_create(128)))
     52  1.1  haad 		return 0;
     53  1.1  haad 
     54  1.1  haad 	if (!(_lock_hash = dm_hash_create(128)))
     55  1.1  haad 		return 0;
     56  1.1  haad 
     57  1.1  haad 	if (_vg_global_lock_held)
     58  1.1  haad 		lvmcache_lock_vgname(VG_GLOBAL, 0);
     59  1.1  haad 
     60  1.1  haad 	return 1;
     61  1.1  haad }
     62  1.1  haad 
     63  1.1  haad /* Volume Group metadata cache functions */
     64  1.1  haad static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
     65  1.1  haad {
     66  1.1  haad 	if (!vginfo || !vginfo->vgmetadata)
     67  1.1  haad 		return;
     68  1.1  haad 
     69  1.1  haad 	dm_free(vginfo->vgmetadata);
     70  1.1  haad 
     71  1.1  haad 	vginfo->vgmetadata = NULL;
     72  1.1  haad 
     73  1.1  haad 	log_debug("Metadata cache: VG %s wiped.", vginfo->vgname);
     74  1.1  haad }
     75  1.1  haad 
     76  1.1  haad static void _store_metadata(struct lvmcache_vginfo *vginfo,
     77  1.1  haad 			    struct volume_group *vg, unsigned precommitted)
     78  1.1  haad {
     79  1.1  haad 	int size;
     80  1.1  haad 
     81  1.1  haad 	if (vginfo->vgmetadata)
     82  1.1  haad 		_free_cached_vgmetadata(vginfo);
     83  1.1  haad 
     84  1.1  haad 	if (!(size = export_vg_to_buffer(vg, &vginfo->vgmetadata))) {
     85  1.1  haad 		stack;
     86  1.1  haad 		return;
     87  1.1  haad 	}
     88  1.1  haad 
     89  1.1  haad 	vginfo->precommitted = precommitted;
     90  1.1  haad 
     91  1.1  haad 	log_debug("Metadata cache: VG %s stored (%d bytes%s).", vginfo->vgname,
     92  1.1  haad 		  size, precommitted ? ", precommitted" : "");
     93  1.1  haad }
     94  1.1  haad 
     95  1.1  haad static void _update_cache_info_lock_state(struct lvmcache_info *info,
     96  1.1  haad 					  int locked,
     97  1.1  haad 					  int *cached_vgmetadata_valid)
     98  1.1  haad {
     99  1.1  haad 	int was_locked = (info->status & CACHE_LOCKED) ? 1 : 0;
    100  1.1  haad 
    101  1.1  haad 	/*
    102  1.1  haad 	 * Cache becomes invalid whenever lock state changes unless
    103  1.1  haad 	 * exclusive VG_GLOBAL is held (i.e. while scanning).
    104  1.1  haad 	 */
    105  1.1  haad 	if (!vgname_is_locked(VG_GLOBAL) && (was_locked != locked)) {
    106  1.1  haad 		info->status |= CACHE_INVALID;
    107  1.1  haad 		*cached_vgmetadata_valid = 0;
    108  1.1  haad 	}
    109  1.1  haad 
    110  1.1  haad 	if (locked)
    111  1.1  haad 		info->status |= CACHE_LOCKED;
    112  1.1  haad 	else
    113  1.1  haad 		info->status &= ~CACHE_LOCKED;
    114  1.1  haad }
    115  1.1  haad 
    116  1.1  haad static void _update_cache_vginfo_lock_state(struct lvmcache_vginfo *vginfo,
    117  1.1  haad 					    int locked)
    118  1.1  haad {
    119  1.1  haad 	struct lvmcache_info *info;
    120  1.1  haad 	int cached_vgmetadata_valid = 1;
    121  1.1  haad 
    122  1.1  haad 	dm_list_iterate_items(info, &vginfo->infos)
    123  1.1  haad 		_update_cache_info_lock_state(info, locked,
    124  1.1  haad 					      &cached_vgmetadata_valid);
    125  1.1  haad 
    126  1.1  haad 	if (!cached_vgmetadata_valid)
    127  1.1  haad 		_free_cached_vgmetadata(vginfo);
    128  1.1  haad }
    129  1.1  haad 
    130  1.1  haad static void _update_cache_lock_state(const char *vgname, int locked)
    131  1.1  haad {
    132  1.1  haad 	struct lvmcache_vginfo *vginfo;
    133  1.1  haad 
    134  1.1  haad 	if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
    135  1.1  haad 		return;
    136  1.1  haad 
    137  1.1  haad 	_update_cache_vginfo_lock_state(vginfo, locked);
    138  1.1  haad }
    139  1.1  haad 
    140  1.1  haad static void _drop_metadata(const char *vgname)
    141  1.1  haad {
    142  1.1  haad 	struct lvmcache_vginfo *vginfo;
    143  1.1  haad 	struct lvmcache_info *info;
    144  1.1  haad 
    145  1.1  haad 	if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
    146  1.1  haad 		return;
    147  1.1  haad 
    148  1.1  haad 	/*
    149  1.1  haad 	 * Invalidate cached PV labels.
    150  1.1  haad 	 * If cached precommitted metadata exists that means we
    151  1.1  haad 	 * already invalidated the PV labels (before caching it)
    152  1.1  haad 	 * and we must not do it again.
    153  1.1  haad 	 */
    154  1.1  haad 
    155  1.1  haad 	if (!vginfo->precommitted)
    156  1.1  haad 		dm_list_iterate_items(info, &vginfo->infos)
    157  1.1  haad 			info->status |= CACHE_INVALID;
    158  1.1  haad 
    159  1.1  haad 	_free_cached_vgmetadata(vginfo);
    160  1.1  haad }
    161  1.1  haad 
    162  1.1  haad void lvmcache_drop_metadata(const char *vgname)
    163  1.1  haad {
    164  1.1  haad 	/* For VG_ORPHANS, we need to invalidate all labels on orphan PVs. */
    165  1.1  haad 	if (!strcmp(vgname, VG_ORPHANS)) {
    166  1.1  haad 		_drop_metadata(FMT_TEXT_ORPHAN_VG_NAME);
    167  1.1  haad 		_drop_metadata(FMT_LVM1_ORPHAN_VG_NAME);
    168  1.1  haad 		_drop_metadata(FMT_POOL_ORPHAN_VG_NAME);
    169  1.1  haad 
    170  1.1  haad 		/* Indicate that PVs could now be missing from the cache */
    171  1.1  haad 		init_full_scan_done(0);
    172  1.1  haad 	} else if (!vgname_is_locked(VG_GLOBAL))
    173  1.1  haad 		_drop_metadata(vgname);
    174  1.1  haad }
    175  1.1  haad 
    176  1.1  haad void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
    177  1.1  haad {
    178  1.1  haad 	if (!_lock_hash && !lvmcache_init()) {
    179  1.1  haad 		log_error("Internal cache initialisation failed");
    180  1.1  haad 		return;
    181  1.1  haad 	}
    182  1.1  haad 
    183  1.1  haad 	if (dm_hash_lookup(_lock_hash, vgname))
    184  1.1  haad 		log_error("Internal error: Nested locking attempted on VG %s.",
    185  1.1  haad 			  vgname);
    186  1.1  haad 
    187  1.1  haad 	if (!dm_hash_insert(_lock_hash, vgname, (void *) 1))
    188  1.1  haad 		log_error("Cache locking failure for %s", vgname);
    189  1.1  haad 
    190  1.1  haad 	_update_cache_lock_state(vgname, 1);
    191  1.1  haad 
    192  1.1  haad 	if (strcmp(vgname, VG_GLOBAL))
    193  1.1  haad 		_vgs_locked++;
    194  1.1  haad }
    195  1.1  haad 
    196  1.1  haad int vgname_is_locked(const char *vgname)
    197  1.1  haad {
    198  1.1  haad 	if (!_lock_hash)
    199  1.1  haad 		return 0;
    200  1.1  haad 
    201  1.1  haad 	return dm_hash_lookup(_lock_hash, vgname) ? 1 : 0;
    202  1.1  haad }
    203  1.1  haad 
    204  1.1  haad void lvmcache_unlock_vgname(const char *vgname)
    205  1.1  haad {
    206  1.1  haad 	if (!dm_hash_lookup(_lock_hash, vgname))
    207  1.1  haad 		log_error("Internal error: Attempt to unlock unlocked VG %s.",
    208  1.1  haad 			  vgname);
    209  1.1  haad 
    210  1.1  haad 	_update_cache_lock_state(vgname, 0);
    211  1.1  haad 
    212  1.1  haad 	dm_hash_remove(_lock_hash, vgname);
    213  1.1  haad 
    214  1.1  haad 	/* FIXME Do this per-VG */
    215  1.1  haad 	if (strcmp(vgname, VG_GLOBAL) && !--_vgs_locked)
    216  1.1  haad 		dev_close_all();
    217  1.1  haad }
    218  1.1  haad 
    219  1.1  haad int vgs_locked(void)
    220  1.1  haad {
    221  1.1  haad 	return _vgs_locked;
    222  1.1  haad }
    223  1.1  haad 
    224  1.1  haad static void _vginfo_attach_info(struct lvmcache_vginfo *vginfo,
    225  1.1  haad 				struct lvmcache_info *info)
    226  1.1  haad {
    227  1.1  haad 	if (!vginfo)
    228  1.1  haad 		return;
    229  1.1  haad 
    230  1.1  haad 	info->vginfo = vginfo;
    231  1.1  haad 	dm_list_add(&vginfo->infos, &info->list);
    232  1.1  haad }
    233  1.1  haad 
    234  1.1  haad static void _vginfo_detach_info(struct lvmcache_info *info)
    235  1.1  haad {
    236  1.1  haad 	if (!dm_list_empty(&info->list)) {
    237  1.1  haad 		dm_list_del(&info->list);
    238  1.1  haad 		dm_list_init(&info->list);
    239  1.1  haad 	}
    240  1.1  haad 
    241  1.1  haad 	info->vginfo = NULL;
    242  1.1  haad }
    243  1.1  haad 
    244  1.1  haad /* If vgid supplied, require a match. */
    245  1.1  haad struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
    246  1.1  haad {
    247  1.1  haad 	struct lvmcache_vginfo *vginfo;
    248  1.1  haad 
    249  1.1  haad 	if (!vgname)
    250  1.1  haad 		return vginfo_from_vgid(vgid);
    251  1.1  haad 
    252  1.1  haad 	if (!_vgname_hash)
    253  1.1  haad 		return NULL;
    254  1.1  haad 
    255  1.1  haad 	if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
    256  1.1  haad 		return NULL;
    257  1.1  haad 
    258  1.1  haad 	if (vgid)
    259  1.1  haad 		do
    260  1.1  haad 			if (!strncmp(vgid, vginfo->vgid, ID_LEN))
    261  1.1  haad 				return vginfo;
    262  1.1  haad 		while ((vginfo = vginfo->next));
    263  1.1  haad 
    264  1.1  haad 	return vginfo;
    265  1.1  haad }
    266  1.1  haad 
    267  1.1  haad const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
    268  1.1  haad {
    269  1.1  haad 	struct lvmcache_vginfo *vginfo;
    270  1.1  haad 	struct lvmcache_info *info;
    271  1.1  haad 	struct label *label;
    272  1.1  haad 	struct dm_list *devh, *tmp;
    273  1.1  haad 	struct dm_list devs;
    274  1.1  haad 	struct device_list *devl;
    275  1.1  haad 	char vgid_found[ID_LEN + 1] __attribute((aligned(8)));
    276  1.1  haad 
    277  1.1  haad 	if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
    278  1.1  haad 		return NULL;
    279  1.1  haad 
    280  1.1  haad 	/* This function is normally called before reading metadata so
    281  1.1  haad  	 * we check cached labels here. Unfortunately vginfo is volatile. */
    282  1.1  haad 	dm_list_init(&devs);
    283  1.1  haad 	dm_list_iterate_items(info, &vginfo->infos) {
    284  1.1  haad 		if (!(devl = dm_malloc(sizeof(*devl)))) {
    285  1.1  haad 			log_error("device_list element allocation failed");
    286  1.1  haad 			return NULL;
    287  1.1  haad 		}
    288  1.1  haad 		devl->dev = info->dev;
    289  1.1  haad 		dm_list_add(&devs, &devl->list);
    290  1.1  haad 	}
    291  1.1  haad 
    292  1.1  haad 	memcpy(vgid_found, vginfo->vgid, sizeof(vgid_found));
    293  1.1  haad 
    294  1.1  haad 	dm_list_iterate_safe(devh, tmp, &devs) {
    295  1.1  haad 		devl = dm_list_item(devh, struct device_list);
    296  1.1  haad 		label_read(devl->dev, &label, UINT64_C(0));
    297  1.1  haad 		dm_list_del(&devl->list);
    298  1.1  haad 		dm_free(devl);
    299  1.1  haad 	}
    300  1.1  haad 
    301  1.1  haad 	/* If vginfo changed, caller needs to rescan */
    302  1.1  haad 	if (!(vginfo = vginfo_from_vgname(vgname, vgid_found)) ||
    303  1.1  haad 	    strncmp(vginfo->vgid, vgid_found, ID_LEN))
    304  1.1  haad 		return NULL;
    305  1.1  haad 
    306  1.1  haad 	return vginfo->fmt;
    307  1.1  haad }
    308  1.1  haad 
    309  1.1  haad struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
    310  1.1  haad {
    311  1.1  haad 	struct lvmcache_vginfo *vginfo;
    312  1.1  haad 	char id[ID_LEN + 1] __attribute((aligned(8)));
    313  1.1  haad 
    314  1.1  haad 	if (!_vgid_hash || !vgid)
    315  1.1  haad 		return NULL;
    316  1.1  haad 
    317  1.1  haad 	/* vgid not necessarily NULL-terminated */
    318  1.1  haad 	strncpy(&id[0], vgid, ID_LEN);
    319  1.1  haad 	id[ID_LEN] = '\0';
    320  1.1  haad 
    321  1.1  haad 	if (!(vginfo = dm_hash_lookup(_vgid_hash, id)))
    322  1.1  haad 		return NULL;
    323  1.1  haad 
    324  1.1  haad 	return vginfo;
    325  1.1  haad }
    326  1.1  haad 
    327  1.1  haad const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
    328  1.1  haad {
    329  1.1  haad 	struct lvmcache_vginfo *vginfo;
    330  1.1  haad 	const char *vgname = NULL;
    331  1.1  haad 
    332  1.1  haad 	if ((vginfo = vginfo_from_vgid(vgid)))
    333  1.1  haad 		vgname = vginfo->vgname;
    334  1.1  haad 
    335  1.1  haad 	if (mem && vgname)
    336  1.1  haad 		return dm_pool_strdup(mem, vgname);
    337  1.1  haad 
    338  1.1  haad 	return vgname;
    339  1.1  haad }
    340  1.1  haad 
    341  1.1  haad static int _info_is_valid(struct lvmcache_info *info)
    342  1.1  haad {
    343  1.1  haad 	if (info->status & CACHE_INVALID)
    344  1.1  haad 		return 0;
    345  1.1  haad 
    346  1.1  haad 	/*
    347  1.1  haad 	 * The caller must hold the VG lock to manipulate metadata.
    348  1.1  haad 	 * In a cluster, remote nodes sometimes read metadata in the
    349  1.1  haad 	 * knowledge that the controlling node is holding the lock.
    350  1.1  haad 	 * So if the VG appears to be unlocked here, it should be safe
    351  1.1  haad 	 * to use the cached value.
    352  1.1  haad 	 */
    353  1.1  haad 	if (info->vginfo && !vgname_is_locked(info->vginfo->vgname))
    354  1.1  haad 		return 1;
    355  1.1  haad 
    356  1.1  haad 	if (!(info->status & CACHE_LOCKED))
    357  1.1  haad 		return 0;
    358  1.1  haad 
    359  1.1  haad 	return 1;
    360  1.1  haad }
    361  1.1  haad 
    362  1.1  haad static int _vginfo_is_valid(struct lvmcache_vginfo *vginfo)
    363  1.1  haad {
    364  1.1  haad 	struct lvmcache_info *info;
    365  1.1  haad 
    366  1.1  haad 	/* Invalid if any info is invalid */
    367  1.1  haad 	dm_list_iterate_items(info, &vginfo->infos)
    368  1.1  haad 		if (!_info_is_valid(info))
    369  1.1  haad 			return 0;
    370  1.1  haad 
    371  1.1  haad 	return 1;
    372  1.1  haad }
    373  1.1  haad 
    374  1.1  haad /* vginfo is invalid if it does not contain at least one valid info */
    375  1.1  haad static int _vginfo_is_invalid(struct lvmcache_vginfo *vginfo)
    376  1.1  haad {
    377  1.1  haad 	struct lvmcache_info *info;
    378  1.1  haad 
    379  1.1  haad 	dm_list_iterate_items(info, &vginfo->infos)
    380  1.1  haad 		if (_info_is_valid(info))
    381  1.1  haad 			return 0;
    382  1.1  haad 
    383  1.1  haad 	return 1;
    384  1.1  haad }
    385  1.1  haad 
    386  1.1  haad /*
    387  1.1  haad  * If valid_only is set, data will only be returned if the cached data is
    388  1.1  haad  * known still to be valid.
    389  1.1  haad  */
    390  1.1  haad struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only)
    391  1.1  haad {
    392  1.1  haad 	struct lvmcache_info *info;
    393  1.1  haad 	char id[ID_LEN + 1] __attribute((aligned(8)));
    394  1.1  haad 
    395  1.1  haad 	if (!_pvid_hash || !pvid)
    396  1.1  haad 		return NULL;
    397  1.1  haad 
    398  1.1  haad 	strncpy(&id[0], pvid, ID_LEN);
    399  1.1  haad 	id[ID_LEN] = '\0';
    400  1.1  haad 
    401  1.1  haad 	if (!(info = dm_hash_lookup(_pvid_hash, id)))
    402  1.1  haad 		return NULL;
    403  1.1  haad 
    404  1.1  haad 	if (valid_only && !_info_is_valid(info))
    405  1.1  haad 		return NULL;
    406  1.1  haad 
    407  1.1  haad 	return info;
    408  1.1  haad }
    409  1.1  haad 
    410  1.1  haad static void _rescan_entry(struct lvmcache_info *info)
    411  1.1  haad {
    412  1.1  haad 	struct label *label;
    413  1.1  haad 
    414  1.1  haad 	if (info->status & CACHE_INVALID)
    415  1.1  haad 		label_read(info->dev, &label, UINT64_C(0));
    416  1.1  haad }
    417  1.1  haad 
    418  1.1  haad static int _scan_invalid(void)
    419  1.1  haad {
    420  1.1  haad 	dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _rescan_entry);
    421  1.1  haad 
    422  1.1  haad 	return 1;
    423  1.1  haad }
    424  1.1  haad 
    425  1.1  haad int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
    426  1.1  haad {
    427  1.1  haad 	struct label *label;
    428  1.1  haad 	struct dev_iter *iter;
    429  1.1  haad 	struct device *dev;
    430  1.1  haad 	struct format_type *fmt;
    431  1.1  haad 
    432  1.1  haad 	int r = 0;
    433  1.1  haad 
    434  1.1  haad 	/* Avoid recursion when a PVID can't be found! */
    435  1.1  haad 	if (_scanning_in_progress)
    436  1.1  haad 		return 0;
    437  1.1  haad 
    438  1.1  haad 	_scanning_in_progress = 1;
    439  1.1  haad 
    440  1.1  haad 	if (!_vgname_hash && !lvmcache_init()) {
    441  1.1  haad 		log_error("Internal cache initialisation failed");
    442  1.1  haad 		goto out;
    443  1.1  haad 	}
    444  1.1  haad 
    445  1.1  haad 	if (_has_scanned && !full_scan) {
    446  1.1  haad 		r = _scan_invalid();
    447  1.1  haad 		goto out;
    448  1.1  haad 	}
    449  1.1  haad 
    450  1.1  haad 	if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1 : 0))) {
    451  1.1  haad 		log_error("dev_iter creation failed");
    452  1.1  haad 		goto out;
    453  1.1  haad 	}
    454  1.1  haad 
    455  1.1  haad 	while ((dev = dev_iter_get(iter)))
    456  1.1  haad 		label_read(dev, &label, UINT64_C(0));
    457  1.1  haad 
    458  1.1  haad 	dev_iter_destroy(iter);
    459  1.1  haad 
    460  1.1  haad 	_has_scanned = 1;
    461  1.1  haad 
    462  1.1  haad 	/* Perform any format-specific scanning e.g. text files */
    463  1.1  haad 	dm_list_iterate_items(fmt, &cmd->formats) {
    464  1.1  haad 		if (fmt->ops->scan && !fmt->ops->scan(fmt))
    465  1.1  haad 			goto out;
    466  1.1  haad 	}
    467  1.1  haad 
    468  1.1  haad 	r = 1;
    469  1.1  haad 
    470  1.1  haad       out:
    471  1.1  haad 	_scanning_in_progress = 0;
    472  1.1  haad 
    473  1.1  haad 	return r;
    474  1.1  haad }
    475  1.1  haad 
    476  1.1  haad struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
    477  1.1  haad {
    478  1.1  haad 	struct lvmcache_vginfo *vginfo;
    479  1.1  haad 	struct volume_group *vg;
    480  1.1  haad 	struct format_instance *fid;
    481  1.1  haad 
    482  1.1  haad 	if (!vgid || !(vginfo = vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
    483  1.1  haad 		return NULL;
    484  1.1  haad 
    485  1.1  haad 	if (!_vginfo_is_valid(vginfo))
    486  1.1  haad 		return NULL;
    487  1.1  haad 
    488  1.1  haad 	/*
    489  1.1  haad 	 * Don't return cached data if either:
    490  1.1  haad 	 * (i)  precommitted metadata is requested but we don't have it cached
    491  1.1  haad 	 *      - caller should read it off disk;
    492  1.1  haad 	 * (ii) live metadata is requested but we have precommitted metadata cached
    493  1.1  haad 	 *      and no devices are suspended so caller may read it off disk.
    494  1.1  haad 	 *
    495  1.1  haad 	 * If live metadata is requested but we have precommitted metadata cached
    496  1.1  haad 	 * and devices are suspended, we assume this precommitted metadata has
    497  1.1  haad 	 * already been preloaded and committed so it's OK to return it as live.
    498  1.1  haad 	 * Note that we do not clear the PRECOMMITTED flag.
    499  1.1  haad 	 */
    500  1.1  haad 	if ((precommitted && !vginfo->precommitted) ||
    501  1.1  haad 	    (!precommitted && vginfo->precommitted && !memlock()))
    502  1.1  haad 		return NULL;
    503  1.1  haad 
    504  1.1  haad 	if (!(fid =  vginfo->fmt->ops->create_instance(vginfo->fmt,
    505  1.1  haad 						       vginfo->vgname,
    506  1.1  haad 						       vgid, NULL)))
    507  1.1  haad 		return_NULL;
    508  1.1  haad 
    509  1.1  haad 	if (!(vg = import_vg_from_buffer(vginfo->vgmetadata, fid)) ||
    510  1.1  haad 	    !vg_validate(vg)) {
    511  1.1  haad 		_free_cached_vgmetadata(vginfo);
    512  1.1  haad 		return_NULL;
    513  1.1  haad 	}
    514  1.1  haad 
    515  1.1  haad 	log_debug("Using cached %smetadata for VG %s.",
    516  1.1  haad 		  vginfo->precommitted ? "pre-committed" : "", vginfo->vgname);
    517  1.1  haad 
    518  1.1  haad 	return vg;
    519  1.1  haad }
    520  1.1  haad 
    521  1.1  haad struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
    522  1.1  haad {
    523  1.1  haad 	struct dm_list *vgids;
    524  1.1  haad 	struct lvmcache_vginfo *vginfo;
    525  1.1  haad 
    526  1.1  haad 	lvmcache_label_scan(cmd, full_scan);
    527  1.1  haad 
    528  1.1  haad 	if (!(vgids = str_list_create(cmd->mem))) {
    529  1.1  haad 		log_error("vgids list allocation failed");
    530  1.1  haad 		return NULL;
    531  1.1  haad 	}
    532  1.1  haad 
    533  1.1  haad 	dm_list_iterate_items(vginfo, &_vginfos) {
    534  1.1  haad 		if (!str_list_add(cmd->mem, vgids,
    535  1.1  haad 				  dm_pool_strdup(cmd->mem, vginfo->vgid))) {
    536  1.1  haad 			log_error("strlist allocation failed");
    537  1.1  haad 			return NULL;
    538  1.1  haad 		}
    539  1.1  haad 	}
    540  1.1  haad 
    541  1.1  haad 	return vgids;
    542  1.1  haad }
    543  1.1  haad 
    544  1.1  haad struct dm_list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
    545  1.1  haad {
    546  1.1  haad 	struct dm_list *vgnames;
    547  1.1  haad 	struct lvmcache_vginfo *vginfo;
    548  1.1  haad 
    549  1.1  haad 	lvmcache_label_scan(cmd, full_scan);
    550  1.1  haad 
    551  1.1  haad 	if (!(vgnames = str_list_create(cmd->mem))) {
    552  1.1  haad 		log_error("vgnames list allocation failed");
    553  1.1  haad 		return NULL;
    554  1.1  haad 	}
    555  1.1  haad 
    556  1.1  haad 	dm_list_iterate_items(vginfo, &_vginfos) {
    557  1.1  haad 		if (!str_list_add(cmd->mem, vgnames,
    558  1.1  haad 				  dm_pool_strdup(cmd->mem, vginfo->vgname))) {
    559  1.1  haad 			log_error("strlist allocation failed");
    560  1.1  haad 			return NULL;
    561  1.1  haad 		}
    562  1.1  haad 	}
    563  1.1  haad 
    564  1.1  haad 	return vgnames;
    565  1.1  haad }
    566  1.1  haad 
    567  1.1  haad struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
    568  1.1  haad 				const char *vgid)
    569  1.1  haad {
    570  1.1  haad 	struct dm_list *pvids;
    571  1.1  haad 	struct lvmcache_vginfo *vginfo;
    572  1.1  haad 	struct lvmcache_info *info;
    573  1.1  haad 
    574  1.1  haad 	if (!(pvids = str_list_create(cmd->mem))) {
    575  1.1  haad 		log_error("pvids list allocation failed");
    576  1.1  haad 		return NULL;
    577  1.1  haad 	}
    578  1.1  haad 
    579  1.1  haad 	if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
    580  1.1  haad 		return pvids;
    581  1.1  haad 
    582  1.1  haad 	dm_list_iterate_items(info, &vginfo->infos) {
    583  1.1  haad 		if (!str_list_add(cmd->mem, pvids,
    584  1.1  haad 				  dm_pool_strdup(cmd->mem, info->dev->pvid))) {
    585  1.1  haad 			log_error("strlist allocation failed");
    586  1.1  haad 			return NULL;
    587  1.1  haad 		}
    588  1.1  haad 	}
    589  1.1  haad 
    590  1.1  haad 	return pvids;
    591  1.1  haad }
    592  1.1  haad 
    593  1.1  haad struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
    594  1.1  haad {
    595  1.1  haad 	struct label *label;
    596  1.1  haad 	struct lvmcache_info *info;
    597  1.1  haad 
    598  1.1  haad 	/* Already cached ? */
    599  1.1  haad 	if ((info = info_from_pvid((char *) pvid, 0))) {
    600  1.1  haad 		if (label_read(info->dev, &label, UINT64_C(0))) {
    601  1.1  haad 			info = (struct lvmcache_info *) label->info;
    602  1.1  haad 			if (id_equal(pvid, (struct id *) &info->dev->pvid))
    603  1.1  haad 				return info->dev;
    604  1.1  haad 		}
    605  1.1  haad 	}
    606  1.1  haad 
    607  1.1  haad 	lvmcache_label_scan(cmd, 0);
    608  1.1  haad 
    609  1.1  haad 	/* Try again */
    610  1.1  haad 	if ((info = info_from_pvid((char *) pvid, 0))) {
    611  1.1  haad 		if (label_read(info->dev, &label, UINT64_C(0))) {
    612  1.1  haad 			info = (struct lvmcache_info *) label->info;
    613  1.1  haad 			if (id_equal(pvid, (struct id *) &info->dev->pvid))
    614  1.1  haad 				return info->dev;
    615  1.1  haad 		}
    616  1.1  haad 	}
    617  1.1  haad 
    618  1.1  haad 	if (memlock())
    619  1.1  haad 		return NULL;
    620  1.1  haad 
    621  1.1  haad 	lvmcache_label_scan(cmd, 2);
    622  1.1  haad 
    623  1.1  haad 	/* Try again */
    624  1.1  haad 	if ((info = info_from_pvid((char *) pvid, 0))) {
    625  1.1  haad 		if (label_read(info->dev, &label, UINT64_C(0))) {
    626  1.1  haad 			info = (struct lvmcache_info *) label->info;
    627  1.1  haad 			if (id_equal(pvid, (struct id *) &info->dev->pvid))
    628  1.1  haad 				return info->dev;
    629  1.1  haad 		}
    630  1.1  haad 	}
    631  1.1  haad 
    632  1.1  haad 	return NULL;
    633  1.1  haad }
    634  1.1  haad 
    635  1.1  haad static int _free_vginfo(struct lvmcache_vginfo *vginfo)
    636  1.1  haad {
    637  1.1  haad 	struct lvmcache_vginfo *primary_vginfo, *vginfo2;
    638  1.1  haad 	int r = 1;
    639  1.1  haad 
    640  1.1  haad 	_free_cached_vgmetadata(vginfo);
    641  1.1  haad 
    642  1.1  haad 	vginfo2 = primary_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
    643  1.1  haad 
    644  1.1  haad 	if (vginfo == primary_vginfo) {
    645  1.1  haad 		dm_hash_remove(_vgname_hash, vginfo->vgname);
    646  1.1  haad 		if (vginfo->next && !dm_hash_insert(_vgname_hash, vginfo->vgname,
    647  1.1  haad 						    vginfo->next)) {
    648  1.1  haad 			log_error("_vgname_hash re-insertion for %s failed",
    649  1.1  haad 				  vginfo->vgname);
    650  1.1  haad 			r = 0;
    651  1.1  haad 		}
    652  1.1  haad 	} else do
    653  1.1  haad 		if (vginfo2->next == vginfo) {
    654  1.1  haad 			vginfo2->next = vginfo->next;
    655  1.1  haad 			break;
    656  1.1  haad 		}
    657  1.1  haad  	while ((vginfo2 = primary_vginfo->next));
    658  1.1  haad 
    659  1.1  haad 	if (vginfo->vgname)
    660  1.1  haad 		dm_free(vginfo->vgname);
    661  1.1  haad 
    662  1.1  haad 	if (vginfo->creation_host)
    663  1.1  haad 		dm_free(vginfo->creation_host);
    664  1.1  haad 
    665  1.1  haad 	if (*vginfo->vgid && _vgid_hash &&
    666  1.1  haad 	    vginfo_from_vgid(vginfo->vgid) == vginfo)
    667  1.1  haad 		dm_hash_remove(_vgid_hash, vginfo->vgid);
    668  1.1  haad 
    669  1.1  haad 	dm_list_del(&vginfo->list);
    670  1.1  haad 
    671  1.1  haad 	dm_free(vginfo);
    672  1.1  haad 
    673  1.1  haad 	return r;
    674  1.1  haad }
    675  1.1  haad 
    676  1.1  haad /*
    677  1.1  haad  * vginfo must be info->vginfo unless info is NULL
    678  1.1  haad  */
    679  1.1  haad static int _drop_vginfo(struct lvmcache_info *info, struct lvmcache_vginfo *vginfo)
    680  1.1  haad {
    681  1.1  haad 	if (info)
    682  1.1  haad 		_vginfo_detach_info(info);
    683  1.1  haad 
    684  1.1  haad 	/* vginfo still referenced? */
    685  1.1  haad 	if (!vginfo || is_orphan_vg(vginfo->vgname) ||
    686  1.1  haad 	    !dm_list_empty(&vginfo->infos))
    687  1.1  haad 		return 1;
    688  1.1  haad 
    689  1.1  haad 	if (!_free_vginfo(vginfo))
    690  1.1  haad 		return_0;
    691  1.1  haad 
    692  1.1  haad 	return 1;
    693  1.1  haad }
    694  1.1  haad 
    695  1.1  haad /* Unused
    696  1.1  haad void lvmcache_del(struct lvmcache_info *info)
    697  1.1  haad {
    698  1.1  haad 	if (info->dev->pvid[0] && _pvid_hash)
    699  1.1  haad 		dm_hash_remove(_pvid_hash, info->dev->pvid);
    700  1.1  haad 
    701  1.1  haad 	_drop_vginfo(info, info->vginfo);
    702  1.1  haad 
    703  1.1  haad 	info->label->labeller->ops->destroy_label(info->label->labeller,
    704  1.1  haad 						info->label);
    705  1.1  haad 	dm_free(info);
    706  1.1  haad 
    707  1.1  haad 	return;
    708  1.1  haad } */
    709  1.1  haad 
    710  1.1  haad static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
    711  1.1  haad {
    712  1.1  haad 	if (!strcmp(info->dev->pvid, pvid))
    713  1.1  haad 		return 1;
    714  1.1  haad 	if (*info->dev->pvid) {
    715  1.1  haad 		dm_hash_remove(_pvid_hash, info->dev->pvid);
    716  1.1  haad 	}
    717  1.1  haad 	strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid));
    718  1.1  haad 	if (!dm_hash_insert(_pvid_hash, pvid, info)) {
    719  1.1  haad 		log_error("_lvmcache_update: pvid insertion failed: %s", pvid);
    720  1.1  haad 		return 0;
    721  1.1  haad 	}
    722  1.1  haad 
    723  1.1  haad 	return 1;
    724  1.1  haad }
    725  1.1  haad 
    726  1.1  haad /*
    727  1.1  haad  * vginfo must be info->vginfo unless info is NULL (orphans)
    728  1.1  haad  */
    729  1.1  haad static int _lvmcache_update_vgid(struct lvmcache_info *info,
    730  1.1  haad 				 struct lvmcache_vginfo *vginfo,
    731  1.1  haad 				 const char *vgid)
    732  1.1  haad {
    733  1.1  haad 	if (!vgid || !vginfo ||
    734  1.1  haad 	    !strncmp(vginfo->vgid, vgid, ID_LEN))
    735  1.1  haad 		return 1;
    736  1.1  haad 
    737  1.1  haad 	if (vginfo && *vginfo->vgid)
    738  1.1  haad 		dm_hash_remove(_vgid_hash, vginfo->vgid);
    739  1.1  haad 	if (!vgid) {
    740  1.1  haad 		log_debug("lvmcache: %s: clearing VGID", info ? dev_name(info->dev) : vginfo->vgname);
    741  1.1  haad 		return 1;
    742  1.1  haad 	}
    743  1.1  haad 
    744  1.1  haad 	strncpy(vginfo->vgid, vgid, ID_LEN);
    745  1.1  haad 	vginfo->vgid[ID_LEN] = '\0';
    746  1.1  haad 	if (!dm_hash_insert(_vgid_hash, vginfo->vgid, vginfo)) {
    747  1.1  haad 		log_error("_lvmcache_update: vgid hash insertion failed: %s",
    748  1.1  haad 			  vginfo->vgid);
    749  1.1  haad 		return 0;
    750  1.1  haad 	}
    751  1.1  haad 
    752  1.1  haad 	if (!is_orphan_vg(vginfo->vgname))
    753  1.1  haad 		log_debug("lvmcache: %s: setting %s VGID to %s",
    754  1.1  haad 			  dev_name(info->dev), vginfo->vgname,
    755  1.1  haad 			  vginfo->vgid);
    756  1.1  haad 
    757  1.1  haad 	return 1;
    758  1.1  haad }
    759  1.1  haad 
    760  1.1  haad static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
    761  1.1  haad 			  uint32_t vgstatus, const char *creation_host,
    762  1.1  haad 			  struct lvmcache_vginfo *primary_vginfo)
    763  1.1  haad {
    764  1.1  haad 	struct lvmcache_vginfo *last_vginfo = primary_vginfo;
    765  1.1  haad 	char uuid_primary[64] __attribute((aligned(8)));
    766  1.1  haad 	char uuid_new[64] __attribute((aligned(8)));
    767  1.1  haad 	int use_new = 0;
    768  1.1  haad 
    769  1.1  haad 	/* Pre-existing VG takes precedence. Unexported VG takes precedence. */
    770  1.1  haad 	if (primary_vginfo) {
    771  1.1  haad 		if (!id_write_format((const struct id *)vgid, uuid_new, sizeof(uuid_new)))
    772  1.1  haad 			return_0;
    773  1.1  haad 
    774  1.1  haad 		if (!id_write_format((const struct id *)&primary_vginfo->vgid, uuid_primary,
    775  1.1  haad 				     sizeof(uuid_primary)))
    776  1.1  haad 			return_0;
    777  1.1  haad 
    778  1.1  haad 		/*
    779  1.1  haad 		 * If   Primary not exported, new exported => keep
    780  1.1  haad 		 * Else Primary exported, new not exported => change
    781  1.1  haad 		 * Else Primary has hostname for this machine => keep
    782  1.1  haad 		 * Else Primary has no hostname, new has one => change
    783  1.1  haad 		 * Else New has hostname for this machine => change
    784  1.1  haad 		 * Else Keep primary.
    785  1.1  haad 		 */
    786  1.1  haad 		if (!(primary_vginfo->status & EXPORTED_VG) &&
    787  1.1  haad 		    (vgstatus & EXPORTED_VG))
    788  1.1  haad 			log_error("WARNING: Duplicate VG name %s: "
    789  1.1  haad 				  "Existing %s takes precedence over "
    790  1.1  haad 				  "exported %s", new_vginfo->vgname,
    791  1.1  haad 				  uuid_primary, uuid_new);
    792  1.1  haad 		else if ((primary_vginfo->status & EXPORTED_VG) &&
    793  1.1  haad 			   !(vgstatus & EXPORTED_VG)) {
    794  1.1  haad 			log_error("WARNING: Duplicate VG name %s: "
    795  1.1  haad 				  "%s takes precedence over exported %s",
    796  1.1  haad 				  new_vginfo->vgname, uuid_new,
    797  1.1  haad 				  uuid_primary);
    798  1.1  haad 			use_new = 1;
    799  1.1  haad 		} else if (primary_vginfo->creation_host &&
    800  1.1  haad 			   !strcmp(primary_vginfo->creation_host,
    801  1.1  haad 				   primary_vginfo->fmt->cmd->hostname))
    802  1.1  haad 			log_error("WARNING: Duplicate VG name %s: "
    803  1.1  haad 				  "Existing %s (created here) takes precedence "
    804  1.1  haad 				  "over %s", new_vginfo->vgname, uuid_primary,
    805  1.1  haad 				  uuid_new);
    806  1.1  haad 		else if (!primary_vginfo->creation_host && creation_host) {
    807  1.1  haad 			log_error("WARNING: Duplicate VG name %s: "
    808  1.1  haad 				  "%s (with creation_host) takes precedence over %s",
    809  1.1  haad 				  new_vginfo->vgname, uuid_new,
    810  1.1  haad 				  uuid_primary);
    811  1.1  haad 			use_new = 1;
    812  1.1  haad 		} else if (creation_host &&
    813  1.1  haad 			   !strcmp(creation_host,
    814  1.1  haad 				   primary_vginfo->fmt->cmd->hostname)) {
    815  1.1  haad 			log_error("WARNING: Duplicate VG name %s: "
    816  1.1  haad 				  "%s (created here) takes precedence over %s",
    817  1.1  haad 				  new_vginfo->vgname, uuid_new,
    818  1.1  haad 				  uuid_primary);
    819  1.1  haad 			use_new = 1;
    820  1.1  haad 		}
    821  1.1  haad 
    822  1.1  haad 		if (!use_new) {
    823  1.1  haad 			while (last_vginfo->next)
    824  1.1  haad 				last_vginfo = last_vginfo->next;
    825  1.1  haad 			last_vginfo->next = new_vginfo;
    826  1.1  haad 			return 1;
    827  1.1  haad 		}
    828  1.1  haad 
    829  1.1  haad 		dm_hash_remove(_vgname_hash, primary_vginfo->vgname);
    830  1.1  haad 	}
    831  1.1  haad 
    832  1.1  haad 	if (!dm_hash_insert(_vgname_hash, new_vginfo->vgname, new_vginfo)) {
    833  1.1  haad 		log_error("cache_update: vg hash insertion failed: %s",
    834  1.1  haad 		  	new_vginfo->vgname);
    835  1.1  haad 		return 0;
    836  1.1  haad 	}
    837  1.1  haad 
    838  1.1  haad 	if (primary_vginfo)
    839  1.1  haad 		new_vginfo->next = primary_vginfo;
    840  1.1  haad 
    841  1.1  haad 	return 1;
    842  1.1  haad }
    843  1.1  haad 
    844  1.1  haad static int _lvmcache_update_vgname(struct lvmcache_info *info,
    845  1.1  haad 				   const char *vgname, const char *vgid,
    846  1.1  haad 				   uint32_t vgstatus, const char *creation_host,
    847  1.1  haad 				   const struct format_type *fmt)
    848  1.1  haad {
    849  1.1  haad 	struct lvmcache_vginfo *vginfo, *primary_vginfo, *orphan_vginfo;
    850  1.1  haad 	struct lvmcache_info *info2, *info3;
    851  1.1  haad 	char mdabuf[32];
    852  1.1  haad 	// struct lvmcache_vginfo  *old_vginfo, *next;
    853  1.1  haad 
    854  1.1  haad 	if (!vgname || (info && info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
    855  1.1  haad 		return 1;
    856  1.1  haad 
    857  1.1  haad 	/* Remove existing vginfo entry */
    858  1.1  haad 	if (info)
    859  1.1  haad 		_drop_vginfo(info, info->vginfo);
    860  1.1  haad 
    861  1.1  haad 	/* Get existing vginfo or create new one */
    862  1.1  haad 	if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
    863  1.1  haad /*** FIXME - vginfo ends up duplicated instead of renamed.
    864  1.1  haad 		// Renaming?  This lookup fails.
    865  1.1  haad 		if ((vginfo = vginfo_from_vgid(vgid))) {
    866  1.1  haad 			next = vginfo->next;
    867  1.1  haad 			old_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
    868  1.1  haad 			if (old_vginfo == vginfo) {
    869  1.1  haad 				dm_hash_remove(_vgname_hash, old_vginfo->vgname);
    870  1.1  haad 				if (old_vginfo->next) {
    871  1.1  haad 					if (!dm_hash_insert(_vgname_hash, old_vginfo->vgname, old_vginfo->next)) {
    872  1.1  haad 						log_error("vg hash re-insertion failed: %s",
    873  1.1  haad 							  old_vginfo->vgname);
    874  1.1  haad 						return 0;
    875  1.1  haad 					}
    876  1.1  haad 				}
    877  1.1  haad 			} else do {
    878  1.1  haad 				if (old_vginfo->next == vginfo) {
    879  1.1  haad 					old_vginfo->next = vginfo->next;
    880  1.1  haad 					break;
    881  1.1  haad 				}
    882  1.1  haad 			} while ((old_vginfo = old_vginfo->next));
    883  1.1  haad 			vginfo->next = NULL;
    884  1.1  haad 
    885  1.1  haad 			dm_free(vginfo->vgname);
    886  1.1  haad 			if (!(vginfo->vgname = dm_strdup(vgname))) {
    887  1.1  haad 				log_error("cache vgname alloc failed for %s", vgname);
    888  1.1  haad 				return 0;
    889  1.1  haad 			}
    890  1.1  haad 
    891  1.1  haad 			// Rename so can assume new name does not already exist
    892  1.1  haad 			if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) {
    893  1.1  haad 				log_error("vg hash re-insertion failed: %s",
    894  1.1  haad 					  vginfo->vgname);
    895  1.1  haad 		      		return 0;
    896  1.1  haad 			}
    897  1.1  haad 		} else {
    898  1.1  haad ***/
    899  1.1  haad 		if (!(vginfo = dm_malloc(sizeof(*vginfo)))) {
    900  1.1  haad 			log_error("lvmcache_update_vgname: list alloc failed");
    901  1.1  haad 			return 0;
    902  1.1  haad 		}
    903  1.1  haad 		memset(vginfo, 0, sizeof(*vginfo));
    904  1.1  haad 		if (!(vginfo->vgname = dm_strdup(vgname))) {
    905  1.1  haad 			dm_free(vginfo);
    906  1.1  haad 			log_error("cache vgname alloc failed for %s", vgname);
    907  1.1  haad 			return 0;
    908  1.1  haad 		}
    909  1.1  haad 		dm_list_init(&vginfo->infos);
    910  1.1  haad 
    911  1.1  haad 		/*
    912  1.1  haad 		 * If we're scanning and there's an invalidated entry, remove it.
    913  1.1  haad 		 * Otherwise we risk bogus warnings of duplicate VGs.
    914  1.1  haad 		 */
    915  1.1  haad 		while ((primary_vginfo = vginfo_from_vgname(vgname, NULL)) &&
    916  1.1  haad 		       _scanning_in_progress && _vginfo_is_invalid(primary_vginfo))
    917  1.1  haad 			dm_list_iterate_items_safe(info2, info3, &primary_vginfo->infos) {
    918  1.1  haad 				orphan_vginfo = vginfo_from_vgname(primary_vginfo->fmt->orphan_vg_name, NULL);
    919  1.1  haad 				_drop_vginfo(info2, primary_vginfo);
    920  1.1  haad 				_vginfo_attach_info(orphan_vginfo, info2);
    921  1.1  haad 				if (info2->mdas.n)
    922  1.1  haad 					sprintf(mdabuf, " with %u mdas",
    923  1.1  haad 						dm_list_size(&info2->mdas));
    924  1.1  haad 				else
    925  1.1  haad 					mdabuf[0] = '\0';
    926  1.1  haad 				log_debug("lvmcache: %s: now in VG %s%s%s%s%s",
    927  1.1  haad 					  dev_name(info2->dev),
    928  1.1  haad 					  vgname, orphan_vginfo->vgid[0] ? " (" : "",
    929  1.1  haad 					  orphan_vginfo->vgid[0] ? orphan_vginfo->vgid : "",
    930  1.1  haad 					  orphan_vginfo->vgid[0] ? ")" : "", mdabuf);
    931  1.1  haad 		}
    932  1.1  haad 
    933  1.1  haad 		if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host,
    934  1.1  haad 				    primary_vginfo)) {
    935  1.1  haad 			dm_free(vginfo->vgname);
    936  1.1  haad 			dm_free(vginfo);
    937  1.1  haad 			return 0;
    938  1.1  haad 		}
    939  1.1  haad 		/* Ensure orphans appear last on list_iterate */
    940  1.1  haad 		if (is_orphan_vg(vgname))
    941  1.1  haad 			dm_list_add(&_vginfos, &vginfo->list);
    942  1.1  haad 		else
    943  1.1  haad 			dm_list_add_h(&_vginfos, &vginfo->list);
    944  1.1  haad /***
    945  1.1  haad 		}
    946  1.1  haad ***/
    947  1.1  haad 	}
    948  1.1  haad 
    949  1.1  haad 	if (info)
    950  1.1  haad 		_vginfo_attach_info(vginfo, info);
    951  1.1  haad 	else if (!_lvmcache_update_vgid(NULL, vginfo, vgid)) /* Orphans */
    952  1.1  haad 		return_0;
    953  1.1  haad 
    954  1.1  haad 	_update_cache_vginfo_lock_state(vginfo, vgname_is_locked(vgname));
    955  1.1  haad 
    956  1.1  haad 	/* FIXME Check consistency of list! */
    957  1.1  haad 	vginfo->fmt = fmt;
    958  1.1  haad 
    959  1.1  haad 	if (info) {
    960  1.1  haad 		if (info->mdas.n)
    961  1.1  haad 			sprintf(mdabuf, " with %u mdas", dm_list_size(&info->mdas));
    962  1.1  haad 		else
    963  1.1  haad 			mdabuf[0] = '\0';
    964  1.1  haad 		log_debug("lvmcache: %s: now in VG %s%s%s%s%s",
    965  1.1  haad 			  dev_name(info->dev),
    966  1.1  haad 			  vgname, vginfo->vgid[0] ? " (" : "",
    967  1.1  haad 			  vginfo->vgid[0] ? vginfo->vgid : "",
    968  1.1  haad 			  vginfo->vgid[0] ? ")" : "", mdabuf);
    969  1.1  haad 	} else
    970  1.1  haad 		log_debug("lvmcache: initialised VG %s", vgname);
    971  1.1  haad 
    972  1.1  haad 	return 1;
    973  1.1  haad }
    974  1.1  haad 
    975  1.1  haad static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstatus,
    976  1.1  haad 				     const char *creation_host)
    977  1.1  haad {
    978  1.1  haad 	if (!info || !info->vginfo)
    979  1.1  haad 		return 1;
    980  1.1  haad 
    981  1.1  haad 	if ((info->vginfo->status & EXPORTED_VG) != (vgstatus & EXPORTED_VG))
    982  1.1  haad 		log_debug("lvmcache: %s: VG %s %s exported",
    983  1.1  haad 			  dev_name(info->dev), info->vginfo->vgname,
    984  1.1  haad 			  vgstatus & EXPORTED_VG ? "now" : "no longer");
    985  1.1  haad 
    986  1.1  haad 	info->vginfo->status = vgstatus;
    987  1.1  haad 
    988  1.1  haad 	if (!creation_host)
    989  1.1  haad 		return 1;
    990  1.1  haad 
    991  1.1  haad 	if (info->vginfo->creation_host && !strcmp(creation_host,
    992  1.1  haad 						   info->vginfo->creation_host))
    993  1.1  haad 		return 1;
    994  1.1  haad 
    995  1.1  haad 	if (info->vginfo->creation_host)
    996  1.1  haad 		dm_free(info->vginfo->creation_host);
    997  1.1  haad 
    998  1.1  haad 	if (!(info->vginfo->creation_host = dm_strdup(creation_host))) {
    999  1.1  haad 		log_error("cache creation host alloc failed for %s",
   1000  1.1  haad 			  creation_host);
   1001  1.1  haad 		return 0;
   1002  1.1  haad 	}
   1003  1.1  haad 
   1004  1.1  haad 	log_debug("lvmcache: %s: VG %s: Set creation host to %s.",
   1005  1.1  haad 		  dev_name(info->dev), info->vginfo->vgname, creation_host);
   1006  1.1  haad 
   1007  1.1  haad 	return 1;
   1008  1.1  haad }
   1009  1.1  haad 
   1010  1.1  haad int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt)
   1011  1.1  haad {
   1012  1.1  haad 	if (!_lock_hash && !lvmcache_init()) {
   1013  1.1  haad 		log_error("Internal cache initialisation failed");
   1014  1.1  haad 		return 0;
   1015  1.1  haad 	}
   1016  1.1  haad 
   1017  1.1  haad 	return _lvmcache_update_vgname(NULL, vgname, vgname, 0, "", fmt);
   1018  1.1  haad }
   1019  1.1  haad 
   1020  1.1  haad int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
   1021  1.1  haad 				  const char *vgname, const char *vgid,
   1022  1.1  haad 				  uint32_t vgstatus, const char *creation_host)
   1023  1.1  haad {
   1024  1.1  haad 	if (!vgname && !info->vginfo) {
   1025  1.1  haad 		log_error("Internal error: NULL vgname handed to cache");
   1026  1.1  haad 		/* FIXME Remove this */
   1027  1.1  haad 		vgname = info->fmt->orphan_vg_name;
   1028  1.1  haad 		vgid = vgname;
   1029  1.1  haad 	}
   1030  1.1  haad 
   1031  1.1  haad 	/* If PV without mdas is already in a real VG, don't make it orphan */
   1032  1.1  haad 	if (is_orphan_vg(vgname) && info->vginfo && !dm_list_size(&info->mdas) &&
   1033  1.1  haad 	    !is_orphan_vg(info->vginfo->vgname) && memlock())
   1034  1.1  haad 		return 1;
   1035  1.1  haad 
   1036  1.1  haad 	/* If moving PV from orphan to real VG, always mark it valid */
   1037  1.1  haad 	if (!is_orphan_vg(vgname))
   1038  1.1  haad 		info->status &= ~CACHE_INVALID;
   1039  1.1  haad 
   1040  1.1  haad 	if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus,
   1041  1.1  haad 				     creation_host, info->fmt) ||
   1042  1.1  haad 	    !_lvmcache_update_vgid(info, info->vginfo, vgid) ||
   1043  1.1  haad 	    !_lvmcache_update_vgstatus(info, vgstatus, creation_host))
   1044  1.1  haad 		return_0;
   1045  1.1  haad 
   1046  1.1  haad 	return 1;
   1047  1.1  haad }
   1048  1.1  haad 
   1049  1.1  haad int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
   1050  1.1  haad {
   1051  1.1  haad 	struct pv_list *pvl;
   1052  1.1  haad 	struct lvmcache_info *info;
   1053  1.1  haad 	struct lvmcache_vginfo *vginfo;
   1054  1.1  haad 	char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
   1055  1.1  haad 
   1056  1.1  haad 	pvid_s[sizeof(pvid_s) - 1] = '\0';
   1057  1.1  haad 
   1058  1.1  haad 	dm_list_iterate_items(pvl, &vg->pvs) {
   1059  1.1  haad 		strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
   1060  1.1  haad 		/* FIXME Could pvl->pv->dev->pvid ever be different? */
   1061  1.1  haad 		if ((info = info_from_pvid(pvid_s, 0)) &&
   1062  1.1  haad 		    !lvmcache_update_vgname_and_id(info, vg->name,
   1063  1.1  haad 						   (char *) &vg->id,
   1064  1.1  haad 						   vg->status, NULL))
   1065  1.1  haad 			return_0;
   1066  1.1  haad 	}
   1067  1.1  haad 
   1068  1.1  haad 	/* store text representation of vg to cache */
   1069  1.1  haad 	if (vg->cmd->current_settings.cache_vgmetadata &&
   1070  1.1  haad 	    (vginfo = vginfo_from_vgname(vg->name, NULL)))
   1071  1.1  haad 		_store_metadata(vginfo, vg, precommitted);
   1072  1.1  haad 
   1073  1.1  haad 	return 1;
   1074  1.1  haad }
   1075  1.1  haad 
   1076  1.1  haad struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
   1077  1.1  haad 				   struct device *dev,
   1078  1.1  haad 				   const char *vgname, const char *vgid,
   1079  1.1  haad 				   uint32_t vgstatus)
   1080  1.1  haad {
   1081  1.1  haad 	struct label *label;
   1082  1.1  haad 	struct lvmcache_info *existing, *info;
   1083  1.1  haad 	char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
   1084  1.1  haad 
   1085  1.1  haad 	if (!_vgname_hash && !lvmcache_init()) {
   1086  1.1  haad 		log_error("Internal cache initialisation failed");
   1087  1.1  haad 		return NULL;
   1088  1.1  haad 	}
   1089  1.1  haad 
   1090  1.1  haad 	strncpy(pvid_s, pvid, sizeof(pvid_s));
   1091  1.1  haad 	pvid_s[sizeof(pvid_s) - 1] = '\0';
   1092  1.1  haad 
   1093  1.1  haad 	if (!(existing = info_from_pvid(pvid_s, 0)) &&
   1094  1.1  haad 	    !(existing = info_from_pvid(dev->pvid, 0))) {
   1095  1.1  haad 		if (!(label = label_create(labeller)))
   1096  1.1  haad 			return_NULL;
   1097  1.1  haad 		if (!(info = dm_malloc(sizeof(*info)))) {
   1098  1.1  haad 			log_error("lvmcache_info allocation failed");
   1099  1.1  haad 			label_destroy(label);
   1100  1.1  haad 			return NULL;
   1101  1.1  haad 		}
   1102  1.1  haad 		memset(info, 0, sizeof(*info));
   1103  1.1  haad 
   1104  1.1  haad 		label->info = info;
   1105  1.1  haad 		info->label = label;
   1106  1.1  haad 		dm_list_init(&info->list);
   1107  1.1  haad 		info->dev = dev;
   1108  1.1  haad 	} else {
   1109  1.1  haad 		if (existing->dev != dev) {
   1110  1.1  haad 			/* Is the existing entry a duplicate pvid e.g. md ? */
   1111  1.1  haad 			if (MAJOR(existing->dev->dev) == md_major() &&
   1112  1.1  haad 			    MAJOR(dev->dev) != md_major()) {
   1113  1.1  haad 				log_very_verbose("Ignoring duplicate PV %s on "
   1114  1.1  haad 						 "%s - using md %s",
   1115  1.1  haad 						 pvid, dev_name(dev),
   1116  1.1  haad 						 dev_name(existing->dev));
   1117  1.1  haad 				return NULL;
   1118  1.1  haad 			} else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
   1119  1.1  haad 				   !dm_is_dm_major(MAJOR(dev->dev))) {
   1120  1.1  haad 				log_very_verbose("Ignoring duplicate PV %s on "
   1121  1.1  haad 						 "%s - using dm %s",
   1122  1.1  haad 						 pvid, dev_name(dev),
   1123  1.1  haad 						 dev_name(existing->dev));
   1124  1.1  haad 				return NULL;
   1125  1.1  haad 			} else if (MAJOR(existing->dev->dev) != md_major() &&
   1126  1.1  haad 				   MAJOR(dev->dev) == md_major())
   1127  1.1  haad 				log_very_verbose("Duplicate PV %s on %s - "
   1128  1.1  haad 						 "using md %s", pvid,
   1129  1.1  haad 						 dev_name(existing->dev),
   1130  1.1  haad 						 dev_name(dev));
   1131  1.1  haad 			else if (!dm_is_dm_major(MAJOR(existing->dev->dev)) &&
   1132  1.1  haad 				 dm_is_dm_major(MAJOR(dev->dev)))
   1133  1.1  haad 				log_very_verbose("Duplicate PV %s on %s - "
   1134  1.1  haad 						 "using dm %s", pvid,
   1135  1.1  haad 						 dev_name(existing->dev),
   1136  1.1  haad 						 dev_name(dev));
   1137  1.1  haad 			/* FIXME If both dm, check dependencies */
   1138  1.1  haad 			//else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
   1139  1.1  haad 				 //dm_is_dm_major(MAJOR(dev->dev)))
   1140  1.1  haad 				 //
   1141  1.1  haad 			else
   1142  1.1  haad 				log_error("Found duplicate PV %s: using %s not "
   1143  1.1  haad 					  "%s", pvid, dev_name(dev),
   1144  1.1  haad 					  dev_name(existing->dev));
   1145  1.1  haad 		}
   1146  1.1  haad 		/* Switch over to new preferred device */
   1147  1.1  haad 		existing->dev = dev;
   1148  1.1  haad 		info = existing;
   1149  1.1  haad 		/* Has labeller changed? */
   1150  1.1  haad 		if (info->label->labeller != labeller) {
   1151  1.1  haad 			label_destroy(info->label);
   1152  1.1  haad 			if (!(info->label = label_create(labeller)))
   1153  1.1  haad 				/* FIXME leaves info without label! */
   1154  1.1  haad 				return_NULL;
   1155  1.1  haad 			info->label->info = info;
   1156  1.1  haad 		}
   1157  1.1  haad 		label = info->label;
   1158  1.1  haad 	}
   1159  1.1  haad 
   1160  1.1  haad 	info->fmt = (const struct format_type *) labeller->private;
   1161  1.1  haad 	info->status |= CACHE_INVALID;
   1162  1.1  haad 
   1163  1.1  haad 	if (!_lvmcache_update_pvid(info, pvid_s)) {
   1164  1.1  haad 		if (!existing) {
   1165  1.1  haad 			dm_free(info);
   1166  1.1  haad 			label_destroy(label);
   1167  1.1  haad 		}
   1168  1.1  haad 		return NULL;
   1169  1.1  haad 	}
   1170  1.1  haad 
   1171  1.1  haad 	if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus, NULL)) {
   1172  1.1  haad 		if (!existing) {
   1173  1.1  haad 			dm_hash_remove(_pvid_hash, pvid_s);
   1174  1.1  haad 			strcpy(info->dev->pvid, "");
   1175  1.1  haad 			dm_free(info);
   1176  1.1  haad 			label_destroy(label);
   1177  1.1  haad 		}
   1178  1.1  haad 		return NULL;
   1179  1.1  haad 	}
   1180  1.1  haad 
   1181  1.1  haad 	return info;
   1182  1.1  haad }
   1183  1.1  haad 
   1184  1.1  haad static void _lvmcache_destroy_entry(struct lvmcache_info *info)
   1185  1.1  haad {
   1186  1.1  haad 	_vginfo_detach_info(info);
   1187  1.1  haad 	strcpy(info->dev->pvid, "");
   1188  1.1  haad 	label_destroy(info->label);
   1189  1.1  haad 	dm_free(info);
   1190  1.1  haad }
   1191  1.1  haad 
   1192  1.1  haad static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
   1193  1.1  haad {
   1194  1.1  haad 	struct lvmcache_vginfo *next;
   1195  1.1  haad 
   1196  1.1  haad 	do {
   1197  1.1  haad 		next = vginfo->next;
   1198  1.1  haad 		if (!_free_vginfo(vginfo))
   1199  1.1  haad 			stack;
   1200  1.1  haad 	} while ((vginfo = next));
   1201  1.1  haad }
   1202  1.1  haad 
   1203  1.1  haad static void _lvmcache_destroy_lockname(struct dm_hash_node *n)
   1204  1.1  haad {
   1205  1.1  haad 	char *vgname;
   1206  1.1  haad 
   1207  1.1  haad 	if (!dm_hash_get_data(_lock_hash, n))
   1208  1.1  haad 		return;
   1209  1.1  haad 
   1210  1.1  haad 	vgname = dm_hash_get_key(_lock_hash, n);
   1211  1.1  haad 
   1212  1.1  haad 	if (!strcmp(vgname, VG_GLOBAL))
   1213  1.1  haad 		_vg_global_lock_held = 1;
   1214  1.1  haad 	else
   1215  1.1  haad 		log_error("Internal error: Volume Group %s was not unlocked",
   1216  1.1  haad 			  dm_hash_get_key(_lock_hash, n));
   1217  1.1  haad }
   1218  1.1  haad 
   1219  1.1  haad void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans)
   1220  1.1  haad {
   1221  1.1  haad 	struct dm_hash_node *n;
   1222  1.1  haad 	log_verbose("Wiping internal VG cache");
   1223  1.1  haad 
   1224  1.1  haad 	_has_scanned = 0;
   1225  1.1  haad 
   1226  1.1  haad 	if (_vgid_hash) {
   1227  1.1  haad 		dm_hash_destroy(_vgid_hash);
   1228  1.1  haad 		_vgid_hash = NULL;
   1229  1.1  haad 	}
   1230  1.1  haad 
   1231  1.1  haad 	if (_pvid_hash) {
   1232  1.1  haad 		dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _lvmcache_destroy_entry);
   1233  1.1  haad 		dm_hash_destroy(_pvid_hash);
   1234  1.1  haad 		_pvid_hash = NULL;
   1235  1.1  haad 	}
   1236  1.1  haad 
   1237  1.1  haad 	if (_vgname_hash) {
   1238  1.1  haad 		dm_hash_iter(_vgname_hash,
   1239  1.1  haad 			  (dm_hash_iterate_fn) _lvmcache_destroy_vgnamelist);
   1240  1.1  haad 		dm_hash_destroy(_vgname_hash);
   1241  1.1  haad 		_vgname_hash = NULL;
   1242  1.1  haad 	}
   1243  1.1  haad 
   1244  1.1  haad 	if (_lock_hash) {
   1245  1.1  haad 		dm_hash_iterate(n, _lock_hash)
   1246  1.1  haad 			_lvmcache_destroy_lockname(n);
   1247  1.1  haad 		dm_hash_destroy(_lock_hash);
   1248  1.1  haad 		_lock_hash = NULL;
   1249  1.1  haad 	}
   1250  1.1  haad 
   1251  1.1  haad 	if (!dm_list_empty(&_vginfos))
   1252  1.1  haad 		log_error("Internal error: _vginfos list should be empty");
   1253  1.1  haad 	dm_list_init(&_vginfos);
   1254  1.1  haad 
   1255  1.1  haad 	if (retain_orphans)
   1256  1.1  haad 		init_lvmcache_orphans(cmd);
   1257  1.1  haad }
   1258