LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/lib/cache - lvmcache.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 172 621 27.7 %
Date: 2010-04-13 Functions: 21 48 43.8 %
Branches: 88 526 16.7 %

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

Generated by: LCOV version 1.8