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