LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/tools - toollib.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 18 816 2.2 %
Date: 2010-04-13 Functions: 1 30 3.3 %
Branches: 10 656 1.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
       3                 :            :  * Copyright (C) 2004-2009 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 "tools.h"
      17                 :            : #include "lv_alloc.h"
      18                 :            : #include "xlate.h"
      19                 :            : 
      20                 :            : #include <sys/stat.h>
      21                 :            : #include <sys/wait.h>
      22                 :            : 
      23                 :          0 : const char *command_name(struct cmd_context *cmd)
      24                 :            : {
      25                 :          0 :         return cmd->command->name;
      26                 :            : }
      27                 :            : 
      28                 :            : /*
      29                 :            :  * Strip dev_dir if present
      30                 :            :  */
      31                 :          0 : char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name,
      32                 :            :                    unsigned *dev_dir_found)
      33                 :            : {
      34                 :          0 :         const char *dmdir = dm_dir();
      35                 :          0 :         size_t dmdir_len = strlen(dmdir), vglv_sz;
      36                 :            :         char *vgname, *lvname, *layer, *vglv;
      37                 :            : 
      38                 :            :         /* FIXME Do this properly */
      39         [ #  # ]:          0 :         if (*vg_name == '/') {
      40         [ #  # ]:          0 :                 while (*vg_name == '/')
      41                 :          0 :                         vg_name++;
      42                 :          0 :                 vg_name--;
      43                 :            :         }
      44                 :            : 
      45                 :            :         /* Reformat string if /dev/mapper found */
      46 [ #  # ][ #  # ]:          0 :         if (!strncmp(vg_name, dmdir, dmdir_len) && vg_name[dmdir_len] == '/') {
      47         [ #  # ]:          0 :                 if (dev_dir_found)
      48                 :          0 :                         *dev_dir_found = 1;
      49                 :          0 :                 vg_name += dmdir_len;
      50         [ #  # ]:          0 :                 while (*vg_name == '/')
      51                 :          0 :                         vg_name++;
      52                 :            : 
      53 [ #  # ][ #  # ]:          0 :                 if (!dm_split_lvm_name(cmd->mem, vg_name, &vgname, &lvname, &layer) ||
      54                 :          0 :                     *layer) {
      55                 :          0 :                         log_error("skip_dev_dir: Couldn't split up device name %s",
      56                 :            :                                   vg_name);
      57                 :          0 :                         return (char *) vg_name;
      58                 :            :                 }
      59                 :          0 :                 vglv_sz = strlen(vgname) + strlen(lvname) + 2;
      60   [ #  #  #  # ]:          0 :                 if (!(vglv = dm_pool_alloc(cmd->mem, vglv_sz)) ||
      61                 :            :                     dm_snprintf(vglv, vglv_sz, "%s%s%s", vgname,
      62                 :          0 :                                  *lvname ? "/" : "",
      63         [ #  # ]:          0 :                                  lvname) < 0) {
      64                 :          0 :                         log_error("vg/lv string alloc failed");
      65                 :          0 :                         return (char *) vg_name;
      66                 :            :                 }
      67                 :          0 :                 return vglv;
      68                 :            :         }
      69                 :            : 
      70         [ #  # ]:          0 :         if (!strncmp(vg_name, cmd->dev_dir, strlen(cmd->dev_dir))) {
      71         [ #  # ]:          0 :                 if (dev_dir_found)
      72                 :          0 :                         *dev_dir_found = 1;
      73                 :          0 :                 vg_name += strlen(cmd->dev_dir);
      74         [ #  # ]:          0 :                 while (*vg_name == '/')
      75                 :          0 :                         vg_name++;
      76         [ #  # ]:          0 :         } else if (dev_dir_found)
      77                 :          0 :                 *dev_dir_found = 0;
      78                 :            : 
      79                 :          0 :         return (char *) vg_name;
      80                 :            : }
      81                 :            : 
      82                 :            : /*
      83                 :            :  * Metadata iteration functions
      84                 :            :  */
      85                 :          0 : int process_each_lv_in_vg(struct cmd_context *cmd,
      86                 :            :                           struct volume_group *vg,
      87                 :            :                           const struct dm_list *arg_lvnames,
      88                 :            :                           const struct dm_list *tags,
      89                 :            :                           struct dm_list *failed_lvs,
      90                 :            :                           void *handle,
      91                 :            :                           process_single_lv_fn_t process_single)
      92                 :            : {
      93                 :          0 :         int ret_max = ECMD_PROCESSED;
      94                 :          0 :         int ret = 0;
      95                 :          0 :         unsigned process_all = 0;
      96                 :          0 :         unsigned process_lv = 0;
      97                 :          0 :         unsigned tags_supplied = 0;
      98                 :          0 :         unsigned lvargs_supplied = 0;
      99                 :          0 :         unsigned lvargs_matched = 0;
     100                 :            : 
     101                 :            :         struct lv_list *lvl;
     102                 :            : 
     103         [ #  # ]:          0 :         if (failed_lvs)
     104                 :          0 :                 dm_list_init(failed_lvs);
     105                 :            : 
     106         [ #  # ]:          0 :         if (!vg_check_status(vg, EXPORTED_VG))
     107                 :          0 :                 return ECMD_FAILED;
     108                 :            : 
     109 [ #  # ][ #  # ]:          0 :         if (tags && !dm_list_empty(tags))
     110                 :          0 :                 tags_supplied = 1;
     111                 :            : 
     112 [ #  # ][ #  # ]:          0 :         if (arg_lvnames && !dm_list_empty(arg_lvnames))
     113                 :          0 :                 lvargs_supplied = 1;
     114                 :            : 
     115                 :            :         /* Process all LVs in this VG if no restrictions given */
     116 [ #  # ][ #  # ]:          0 :         if (!tags_supplied && !lvargs_supplied)
     117                 :          0 :                 process_all = 1;
     118                 :            : 
     119                 :            :         /* Or if VG tags match */
     120         [ #  # ]:          0 :         if (!process_lv && tags_supplied &&
           [ #  #  #  # ]
     121                 :          0 :             str_list_match_list(tags, &vg->tags)) {
     122                 :          0 :                 process_all = 1;
     123                 :            :         }
     124                 :            : 
     125         [ #  # ]:          0 :         dm_list_iterate_items(lvl, &vg->lvs) {
     126         [ #  # ]:          0 :                 if (lvl->lv->status & SNAPSHOT)
     127                 :          0 :                         continue;
     128                 :            : 
     129 [ #  # ][ #  # ]:          0 :                 if (lv_is_virtual_origin(lvl->lv) && !arg_count(cmd, all_ARG))
     130                 :          0 :                         continue;
     131                 :            : 
     132                 :            :                 /* Should we process this LV? */
     133         [ #  # ]:          0 :                 if (process_all)
     134                 :          0 :                         process_lv = 1;
     135                 :            :                 else
     136                 :          0 :                         process_lv = 0;
     137                 :            : 
     138                 :            :                 /* LV tag match? */
     139         [ #  # ]:          0 :                 if (!process_lv && tags_supplied &&
           [ #  #  #  # ]
     140                 :          0 :                     str_list_match_list(tags, &lvl->lv->tags)) {
     141                 :          0 :                         process_lv = 1;
     142                 :            :                 }
     143                 :            : 
     144                 :            :                 /* LV name match? */
     145   [ #  #  #  # ]:          0 :                 if (lvargs_supplied &&
     146                 :          0 :                     str_list_match_item(arg_lvnames, lvl->lv->name)) {
     147                 :          0 :                         process_lv = 1;
     148                 :          0 :                         lvargs_matched++;
     149                 :            :                 }
     150                 :            : 
     151         [ #  # ]:          0 :                 if (!process_lv)
     152                 :          0 :                         continue;
     153                 :            : 
     154                 :          0 :                 lvl->lv->vg->missing_vgs = 0;
     155                 :          0 :                 ret = process_single(cmd, lvl->lv, handle);
     156   [ #  #  #  # ]:          0 :                 if (ret != ECMD_PROCESSED && failed_lvs) {
     157         [ #  # ]:          0 :                         if (!str_list_add(cmd->mem, failed_lvs,
     158                 :          0 :                                           dm_pool_strdup(cmd->mem,
     159                 :          0 :                                                          lvl->lv->name))) {
     160                 :          0 :                                 log_error("Allocation failed for str_list.");
     161                 :          0 :                                 return ECMD_FAILED;
     162                 :            :                         }
     163         [ #  # ]:          0 :                         if (lvl->lv->vg->missing_vgs)
     164                 :          0 :                                 ret = ECMD_PROCESSED;
     165                 :            :                 }
     166         [ #  # ]:          0 :                 if (ret > ret_max)
     167                 :          0 :                         ret_max = ret;
     168         [ #  # ]:          0 :                 if (sigint_caught())
     169                 :          0 :                         return ret_max;
     170                 :            :         }
     171                 :            : 
     172 [ #  # ][ #  # ]:          0 :         if (lvargs_supplied && lvargs_matched != dm_list_size(arg_lvnames)) {
     173                 :          0 :                 log_error("One or more specified logical volume(s) not found.");
     174         [ #  # ]:          0 :                 if (ret_max < ECMD_FAILED)
     175                 :          0 :                         ret_max = ECMD_FAILED;
     176                 :            :         }
     177                 :            : 
     178                 :          0 :         return ret_max;
     179                 :            : }
     180                 :            : 
     181                 :          0 : int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
     182                 :            :                     uint32_t flags, void *handle,
     183                 :            :                     int (*process_single) (struct cmd_context * cmd,
     184                 :            :                                            struct logical_volume * lv,
     185                 :            :                                            void *handle))
     186                 :            : {
     187                 :          0 :         int opt = 0;
     188                 :          0 :         int ret_max = ECMD_PROCESSED;
     189                 :          0 :         int ret = 0;
     190                 :            : 
     191                 :            :         struct dm_list *tags_arg;
     192                 :            :         struct dm_list *vgnames;        /* VGs to process */
     193                 :            :         struct str_list *sll, *strl;
     194                 :            :         struct vgs_list *vgs_vg;
     195                 :            :         struct dm_list vgs_list;
     196                 :            :         struct dm_list failed_lvs;
     197                 :            :         struct dm_list tags, lvnames;
     198                 :            :         struct dm_list arg_lvnames;     /* Cmdline vgname or vgname/lvname */
     199                 :            :         char *vglv;
     200                 :            :         size_t vglv_sz;
     201                 :            : 
     202                 :            :         const char *vgname;
     203                 :            : 
     204                 :          0 :         dm_list_init(&tags);
     205                 :          0 :         dm_list_init(&arg_lvnames);
     206                 :          0 :         dm_list_init(&failed_lvs);
     207                 :            : 
     208         [ #  # ]:          0 :         if (argc) {
     209                 :            :                 struct dm_list arg_vgnames;
     210                 :            : 
     211                 :          0 :                 log_verbose("Using logical volume(s) on command line");
     212                 :          0 :                 dm_list_init(&arg_vgnames);
     213                 :            : 
     214         [ #  # ]:          0 :                 for (; opt < argc; opt++) {
     215                 :          0 :                         const char *lv_name = argv[opt];
     216                 :            :                         char *vgname_def;
     217                 :          0 :                         unsigned dev_dir_found = 0;
     218                 :            : 
     219                 :            :                         /* Do we have a tag or vgname or lvname? */
     220                 :          0 :                         vgname = lv_name;
     221                 :            : 
     222         [ #  # ]:          0 :                         if (*vgname == '@') {
     223         [ #  # ]:          0 :                                 if (!validate_name(vgname + 1)) {
     224                 :          0 :                                         log_error("Skipping invalid tag %s",
     225                 :            :                                                   vgname);
     226                 :          0 :                                         continue;
     227                 :            :                                 }
     228         [ #  # ]:          0 :                                 if (!str_list_add(cmd->mem, &tags,
     229                 :          0 :                                                   dm_pool_strdup(cmd->mem,
     230                 :            :                                                               vgname + 1))) {
     231                 :          0 :                                         log_error("strlist allocation failed");
     232                 :          0 :                                         return ECMD_FAILED;
     233                 :            :                                 }
     234                 :          0 :                                 continue;
     235                 :            :                         }
     236                 :            : 
     237                 :            :                         /* FIXME Jumbled parsing */
     238                 :          0 :                         vgname = skip_dev_dir(cmd, vgname, &dev_dir_found);
     239                 :            : 
     240         [ #  # ]:          0 :                         if (*vgname == '/') {
     241                 :          0 :                                 log_error("\"%s\": Invalid path for Logical "
     242                 :            :                                           "Volume", argv[opt]);
     243         [ #  # ]:          0 :                                 if (ret_max < ECMD_FAILED)
     244                 :          0 :                                         ret_max = ECMD_FAILED;
     245                 :          0 :                                 continue;
     246                 :            :                         }
     247                 :          0 :                         lv_name = vgname;
     248         [ #  # ]:          0 :                         if (strchr(vgname, '/')) {
     249                 :            :                                 /* Must be an LV */
     250                 :          0 :                                 lv_name = strchr(vgname, '/');
     251         [ #  # ]:          0 :                                 while (*lv_name == '/')
     252                 :          0 :                                         lv_name++;
     253         [ #  # ]:          0 :                                 if (!(vgname = extract_vgname(cmd, vgname))) {
     254         [ #  # ]:          0 :                                         if (ret_max < ECMD_FAILED)
     255                 :          0 :                                                 ret_max = ECMD_FAILED;
     256                 :          0 :                                         continue;
     257                 :            :                                 }
     258   [ #  #  #  # ]:          0 :                         } else if (!dev_dir_found &&
     259                 :          0 :                                    (vgname_def = default_vgname(cmd))) {
     260                 :          0 :                                 vgname = vgname_def;
     261                 :            :                         } else
     262                 :          0 :                                 lv_name = NULL;
     263                 :            : 
     264         [ #  # ]:          0 :                         if (!str_list_add(cmd->mem, &arg_vgnames,
     265                 :          0 :                                           dm_pool_strdup(cmd->mem, vgname))) {
     266                 :          0 :                                 log_error("strlist allocation failed");
     267                 :          0 :                                 return ECMD_FAILED;
     268                 :            :                         }
     269                 :            : 
     270         [ #  # ]:          0 :                         if (!lv_name) {
     271         [ #  # ]:          0 :                                 if (!str_list_add(cmd->mem, &arg_lvnames,
     272                 :          0 :                                                   dm_pool_strdup(cmd->mem,
     273                 :            :                                                               vgname))) {
     274                 :          0 :                                         log_error("strlist allocation failed");
     275                 :          0 :                                         return ECMD_FAILED;
     276                 :            :                                 }
     277                 :            :                         } else {
     278                 :          0 :                                 vglv_sz = strlen(vgname) + strlen(lv_name) + 2;
     279   [ #  #  #  # ]:          0 :                                 if (!(vglv = dm_pool_alloc(cmd->mem, vglv_sz)) ||
     280                 :            :                                     dm_snprintf(vglv, vglv_sz, "%s/%s", vgname,
     281                 :          0 :                                                  lv_name) < 0) {
     282                 :          0 :                                         log_error("vg/lv string alloc failed");
     283                 :          0 :                                         return ECMD_FAILED;
     284                 :            :                                 }
     285         [ #  # ]:          0 :                                 if (!str_list_add(cmd->mem, &arg_lvnames, vglv)) {
     286                 :          0 :                                         log_error("strlist allocation failed");
     287                 :          0 :                                         return ECMD_FAILED;
     288                 :            :                                 }
     289                 :            :                         }
     290                 :            :                 }
     291                 :          0 :                 vgnames = &arg_vgnames;
     292                 :            :         }
     293                 :            : 
     294 [ #  # ][ #  # ]:          0 :         if (!argc || !dm_list_empty(&tags)) {
     295                 :          0 :                 log_verbose("Finding all logical volumes");
     296   [ #  #  #  # ]:          0 :                 if (!(vgnames = get_vgnames(cmd, 0)) || dm_list_empty(vgnames)) {
     297                 :          0 :                         log_error("No volume groups found");
     298                 :          0 :                         return ret_max;
     299                 :            :                 }
     300                 :            :         }
     301                 :            : 
     302         [ #  # ]:          0 :         dm_list_iterate_items(strl, vgnames) {
     303                 :          0 :                 vgname = strl->str;
     304                 :          0 :                 dm_list_init(&vgs_list);
     305         [ #  # ]:          0 :                 if (!(vgs_vg = vgs_list_add(cmd->mem, &vgs_list,
     306                 :            :                                             vgname, NULL, flags))) {
     307                 :          0 :                         stack;
     308                 :          0 :                         return ECMD_FAILED;
     309                 :            :                 }
     310                 :            : 
     311         [ #  # ]:          0 :                 if (!vgs_list_read(cmd, &vgs_list, vgs_vg)) {
     312                 :          0 :                         vgs_list_release(&vgs_list, vgs_vg);
     313         [ #  # ]:          0 :                         if (ret_max < ECMD_FAILED) {
     314                 :          0 :                                 log_error("Skipping volume group %s", vgname);
     315                 :          0 :                                 ret_max = ECMD_FAILED;
     316                 :            :                         } else
     317                 :          0 :                                 stack;
     318                 :          0 :                         continue;
     319                 :            :                 }
     320                 :            : 
     321                 :          0 :                 tags_arg = &tags;
     322                 :          0 :                 dm_list_init(&lvnames);     /* LVs to be processed in this VG */
     323         [ #  # ]:          0 :                 dm_list_iterate_items(sll, &arg_lvnames) {
     324                 :          0 :                         const char *vg_name = sll->str;
     325                 :          0 :                         const char *lv_name = strchr(vg_name, '/');
     326                 :            : 
     327 [ #  # ][ #  # ]:          0 :                         if ((!lv_name && !strcmp(vg_name, vgname))) {
     328                 :            :                                 /* Process all LVs in this VG */
     329                 :          0 :                                 tags_arg = NULL;
     330                 :          0 :                                 dm_list_init(&lvnames);
     331                 :          0 :                                 break;
     332 [ #  # ][ #  # ]:          0 :                         } else if (!strncmp(vg_name, vgname, strlen(vgname)) &&
     333                 :          0 :                                    strlen(vgname) == (size_t) (lv_name - vg_name)) {
     334         [ #  # ]:          0 :                                 if (!str_list_add(cmd->mem, &lvnames,
     335                 :          0 :                                                   dm_pool_strdup(cmd->mem,
     336                 :            :                                                               lv_name + 1))) {
     337                 :          0 :                                         log_error("strlist allocation failed");
     338                 :          0 :                                         vgs_list_release(&vgs_list,vgs_vg);
     339                 :          0 :                                         return ECMD_FAILED;
     340                 :            :                                 }
     341                 :            :                         }
     342                 :            :                 }
     343                 :            : 
     344         [ #  # ]:          0 :                 while (!sigint_caught()) {
     345                 :          0 :                         ret = process_each_lv_in_vg(cmd, vgs_vg->vg, &lvnames,
     346                 :            :                                                     tags_arg, &failed_lvs,
     347                 :            :                                                     handle, process_single);
     348   [ #  #  #  # ]:          0 :                         if (ret != ECMD_PROCESSED ||
     349                 :          0 :                             dm_list_empty(&failed_lvs))
     350                 :            :                                 break;
     351                 :            : 
     352                 :            :                         /* Try again with failed LVs in this VG */
     353                 :          0 :                         dm_list_init(&lvnames);
     354                 :          0 :                         dm_list_splice(&failed_lvs, &lvnames);
     355                 :            : 
     356                 :          0 :                         vgs_list_release(&vgs_list, vgs_vg);
     357         [ #  # ]:          0 :                         if (!vgs_list_read(cmd, &vgs_list, vgs_vg)) {
     358                 :          0 :                                 ret = ECMD_FAILED; /* break */
     359                 :          0 :                                 break;
     360                 :            :                         }
     361                 :            :                 }
     362         [ #  # ]:          0 :                 if (ret > ret_max)
     363                 :          0 :                         ret_max = ret;
     364                 :            : 
     365                 :          0 :                 vgs_list_release(&vgs_list, vgs_vg);
     366         [ #  # ]:          0 :                 if (sigint_caught())
     367                 :          0 :                         return ECMD_FAILED;
     368                 :            :         }
     369                 :            : 
     370                 :          0 :         return ret_max;
     371                 :            : }
     372                 :            : 
     373                 :          0 : int process_each_segment_in_pv(struct cmd_context *cmd,
     374                 :            :                                struct volume_group *vg,
     375                 :            :                                struct physical_volume *pv,
     376                 :            :                                void *handle,
     377                 :            :                                int (*process_single) (struct cmd_context * cmd,
     378                 :            :                                                       struct volume_group * vg,
     379                 :            :                                                       struct pv_segment * pvseg,
     380                 :            :                                                       void *handle))
     381                 :            : {
     382                 :            :         struct pv_segment *pvseg;
     383                 :            :         struct pv_list *pvl;
     384                 :          0 :         const char *vg_name = NULL;
     385                 :          0 :         int ret_max = ECMD_PROCESSED;
     386                 :            :         int ret;
     387                 :          0 :         struct volume_group *old_vg = vg;
     388                 :          0 :         struct pv_segment _free_pv_segment = { .pv = pv };
     389                 :            : 
     390 [ #  # ][ #  # ]:          0 :         if (is_pv(pv) && !vg && !is_orphan(pv)) {
                 [ #  # ]
     391                 :          0 :                 vg_name = pv_vg_name(pv);
     392                 :            : 
     393                 :          0 :                 vg = vg_read(cmd, vg_name, NULL, 0);
     394         [ #  # ]:          0 :                 if (vg_read_error(vg)) {
     395                 :          0 :                         vg_release(vg);
     396                 :          0 :                         log_error("Skipping volume group %s", vg_name);
     397                 :          0 :                         return ECMD_FAILED;
     398                 :            :                 }
     399                 :            : 
     400                 :            :                 /*
     401                 :            :                  * Replace possibly incomplete PV structure with new one
     402                 :            :                  * allocated in vg_read_internal() path.
     403                 :            :                  */
     404         [ #  # ]:          0 :                 if (!(pvl = find_pv_in_vg(vg, pv_dev_name(pv)))) {
     405                 :          0 :                          log_error("Unable to find %s in volume group %s",
     406                 :            :                                    pv_dev_name(pv), vg_name);
     407                 :          0 :                          unlock_and_release_vg(cmd, vg, vg_name);
     408                 :          0 :                          return ECMD_FAILED;
     409                 :            :                 }
     410                 :            : 
     411                 :          0 :                 pv = pvl->pv;
     412                 :            :         }
     413                 :            : 
     414         [ #  # ]:          0 :         if (dm_list_empty(&pv->segments)) {
     415                 :          0 :                 ret = process_single(cmd, NULL, &_free_pv_segment, handle);
     416         [ #  # ]:          0 :                 if (ret > ret_max)
     417                 :          0 :                         ret_max = ret;
     418                 :            :         } else
     419         [ #  # ]:          0 :                 dm_list_iterate_items(pvseg, &pv->segments) {
     420                 :          0 :                         ret = process_single(cmd, vg, pvseg, handle);
     421         [ #  # ]:          0 :                         if (ret > ret_max)
     422                 :          0 :                                 ret_max = ret;
     423         [ #  # ]:          0 :                         if (sigint_caught())
     424                 :          0 :                                 break;
     425                 :            :                 }
     426                 :            : 
     427         [ #  # ]:          0 :         if (vg_name)
     428                 :          0 :                 unlock_vg(cmd, vg_name);
     429         [ #  # ]:          0 :         if (!old_vg)
     430                 :          0 :                 vg_release(vg);
     431                 :            : 
     432                 :          0 :         return ret_max;
     433                 :            : }
     434                 :            : 
     435                 :          0 : int process_each_segment_in_lv(struct cmd_context *cmd,
     436                 :            :                                struct logical_volume *lv,
     437                 :            :                                void *handle,
     438                 :            :                                int (*process_single) (struct cmd_context * cmd,
     439                 :            :                                                       struct lv_segment * seg,
     440                 :            :                                                       void *handle))
     441                 :            : {
     442                 :            :         struct lv_segment *seg;
     443                 :          0 :         int ret_max = ECMD_PROCESSED;
     444                 :            :         int ret;
     445                 :            : 
     446         [ #  # ]:          0 :         dm_list_iterate_items(seg, &lv->segments) {
     447                 :          0 :                 ret = process_single(cmd, seg, handle);
     448         [ #  # ]:          0 :                 if (ret > ret_max)
     449                 :          0 :                         ret_max = ret;
     450         [ #  # ]:          0 :                 if (sigint_caught())
     451                 :          0 :                         break;
     452                 :            :         }
     453                 :            : 
     454                 :          0 :         return ret_max;
     455                 :            : }
     456                 :            : 
     457                 :          0 : static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
     458                 :            :                            const char *vgid,
     459                 :            :                            struct dm_list *tags, struct dm_list *arg_vgnames,
     460                 :            :                            uint32_t flags, void *handle, int ret_max,
     461                 :            :                            int (*process_single) (struct cmd_context * cmd,
     462                 :            :                                                   const char *vg_name,
     463                 :            :                                                   struct volume_group * vg,
     464                 :            :                                                   void *handle))
     465                 :            : {
     466                 :            :         struct dm_list vgs_list;
     467                 :            :         struct vgs_list *vgs_vg;
     468                 :          0 :         int ret = 0;
     469                 :            : 
     470                 :          0 :         log_verbose("Finding volume group \"%s\"", vg_name);
     471                 :            : 
     472                 :          0 :         dm_list_init(&vgs_list);
     473                 :          0 :         vgs_vg = vgs_list_add(cmd->mem, &vgs_list, vg_name, vgid, flags);
     474         [ #  # ]:          0 :         if (!vgs_vg)
     475                 :          0 :                 return_0;
     476                 :            : 
     477         [ #  # ]:          0 :         while (!sigint_caught()) {
     478         [ #  # ]:          0 :                 if (!vgs_list_read(cmd, &vgs_list, vgs_vg))
     479                 :            :                         /* Allow FAILED_INCONSISTENT through only for vgcfgrestore */
     480 [ #  # ][ #  # ]:          0 :                         if (vg_read_error(vgs_vg->vg) &&
                 [ #  # ]
     481                 :          0 :                             (!((flags & READ_ALLOW_INCONSISTENT) &&
     482                 :            :                                (vg_read_error(vgs_vg->vg) == FAILED_INCONSISTENT)))) {
     483                 :          0 :                                 ret = ECMD_FAILED;
     484                 :          0 :                                 break;
     485                 :            :                         }
     486                 :            : 
     487 [ #  #  #  #  # :          0 :                 if (!dm_list_empty(tags) &&
                      # ]
     488                 :            :                     /* Only process if a tag matches or it's on arg_vgnames */
     489                 :          0 :                     !str_list_match_item(arg_vgnames, vg_name) &&
     490                 :          0 :                     !str_list_match_list(tags, &vgs_vg->vg->tags))
     491                 :          0 :                         break;
     492                 :            : 
     493                 :          0 :                 ret = process_single(cmd, vg_name, vgs_vg->vg, handle);
     494                 :            : 
     495         [ #  # ]:          0 :                 if (vg_read_error(vgs_vg->vg)) /* FAILED_INCONSISTENT */
     496                 :          0 :                         break;
     497                 :            : 
     498         [ #  # ]:          0 :                 if (!vgs_vg->vg->missing_vgs)
     499                 :          0 :                         break;
     500                 :            : 
     501                 :          0 :                 vgs_list_release(&vgs_list, vgs_vg);
     502                 :            :         }
     503                 :            : 
     504                 :          0 :         vgs_list_release(&vgs_list, vgs_vg);
     505                 :            : 
     506                 :          0 :         return (ret > ret_max) ? ret : ret_max;
     507                 :            : }
     508                 :            : 
     509                 :          0 : int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
     510                 :            :                     uint32_t flags, void *handle,
     511                 :            :                     int (*process_single) (struct cmd_context * cmd,
     512                 :            :                                            const char *vg_name,
     513                 :            :                                            struct volume_group * vg,
     514                 :            :                                            void *handle))
     515                 :            : {
     516                 :          0 :         int opt = 0;
     517                 :          0 :         int ret_max = ECMD_PROCESSED;
     518                 :            : 
     519                 :            :         struct str_list *sl;
     520                 :            :         struct dm_list *vgnames, *vgids;
     521                 :            :         struct dm_list arg_vgnames, tags;
     522                 :            : 
     523                 :            :         const char *vg_name, *vgid;
     524                 :            : 
     525                 :          0 :         dm_list_init(&tags);
     526                 :          0 :         dm_list_init(&arg_vgnames);
     527                 :            : 
     528         [ #  # ]:          0 :         if (argc) {
     529                 :          0 :                 log_verbose("Using volume group(s) on command line");
     530                 :            : 
     531         [ #  # ]:          0 :                 for (; opt < argc; opt++) {
     532                 :          0 :                         vg_name = argv[opt];
     533         [ #  # ]:          0 :                         if (*vg_name == '@') {
     534         [ #  # ]:          0 :                                 if (!validate_name(vg_name + 1)) {
     535                 :          0 :                                         log_error("Skipping invalid tag %s",
     536                 :            :                                                   vg_name);
     537         [ #  # ]:          0 :                                         if (ret_max < EINVALID_CMD_LINE)
     538                 :          0 :                                                 ret_max = EINVALID_CMD_LINE;
     539                 :          0 :                                         continue;
     540                 :            :                                 }
     541         [ #  # ]:          0 :                                 if (!str_list_add(cmd->mem, &tags,
     542                 :          0 :                                                   dm_pool_strdup(cmd->mem,
     543                 :            :                                                               vg_name + 1))) {
     544                 :          0 :                                         log_error("strlist allocation failed");
     545                 :          0 :                                         return ECMD_FAILED;
     546                 :            :                                 }
     547                 :          0 :                                 continue;
     548                 :            :                         }
     549                 :            : 
     550                 :          0 :                         vg_name = skip_dev_dir(cmd, vg_name, NULL);
     551         [ #  # ]:          0 :                         if (strchr(vg_name, '/')) {
     552                 :          0 :                                 log_error("Invalid volume group name: %s",
     553                 :            :                                           vg_name);
     554         [ #  # ]:          0 :                                 if (ret_max < EINVALID_CMD_LINE)
     555                 :          0 :                                         ret_max = EINVALID_CMD_LINE;
     556                 :          0 :                                 continue;
     557                 :            :                         }
     558         [ #  # ]:          0 :                         if (!str_list_add(cmd->mem, &arg_vgnames,
     559                 :          0 :                                           dm_pool_strdup(cmd->mem, vg_name))) {
     560                 :          0 :                                 log_error("strlist allocation failed");
     561                 :          0 :                                 return ECMD_FAILED;
     562                 :            :                         }
     563                 :            :                 }
     564                 :            : 
     565                 :          0 :                 vgnames = &arg_vgnames;
     566                 :            :         }
     567                 :            : 
     568 [ #  # ][ #  # ]:          0 :         if (!argc || !dm_list_empty(&tags)) {
     569                 :          0 :                 log_verbose("Finding all volume groups");
     570   [ #  #  #  # ]:          0 :                 if (!(vgids = get_vgids(cmd, 0)) || dm_list_empty(vgids)) {
     571                 :          0 :                         log_error("No volume groups found");
     572                 :          0 :                         return ret_max;
     573                 :            :                 }
     574         [ #  # ]:          0 :                 dm_list_iterate_items(sl, vgids) {
     575                 :          0 :                         vgid = sl->str;
     576 [ #  # ][ #  # ]:          0 :                         if (!(vgid) || !(vg_name = vgname_from_vgid(cmd->mem, vgid)))
     577                 :          0 :                                 continue;
     578                 :          0 :                         ret_max = _process_one_vg(cmd, vg_name, vgid, &tags,
     579                 :            :                                                   &arg_vgnames,
     580                 :            :                                                   flags, handle,
     581                 :            :                                                   ret_max, process_single);
     582         [ #  # ]:          0 :                         if (sigint_caught())
     583                 :          0 :                                 return ret_max;
     584                 :            :                 }
     585                 :            :         } else {
     586         [ #  # ]:          0 :                 dm_list_iterate_items(sl, vgnames) {
     587                 :          0 :                         vg_name = sl->str;
     588         [ #  # ]:          0 :                         if (is_orphan_vg(vg_name))
     589                 :          0 :                                 continue;       /* FIXME Unnecessary? */
     590                 :          0 :                         ret_max = _process_one_vg(cmd, vg_name, NULL, &tags,
     591                 :            :                                                   &arg_vgnames,
     592                 :            :                                                   flags, handle,
     593                 :            :                                                   ret_max, process_single);
     594         [ #  # ]:          0 :                         if (sigint_caught())
     595                 :          0 :                                 return ret_max;
     596                 :            :                 }
     597                 :            :         }
     598                 :            : 
     599                 :          0 :         return ret_max;
     600                 :            : }
     601                 :            : 
     602                 :          0 : int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
     603                 :            :                           const struct dm_list *tags, void *handle,
     604                 :            :                           process_single_pv_fn_t process_single)
     605                 :            : {
     606                 :          0 :         int ret_max = ECMD_PROCESSED;
     607                 :          0 :         int ret = 0;
     608                 :            :         struct pv_list *pvl;
     609                 :            : 
     610         [ #  # ]:          0 :         dm_list_iterate_items(pvl, &vg->pvs) {
     611         [ #  # ]:          0 :                 if (tags && !dm_list_empty(tags) &&
           [ #  #  #  # ]
     612                 :          0 :                     !str_list_match_list(tags, &pvl->pv->tags)) {
     613                 :          0 :                         continue;
     614                 :            :                 }
     615         [ #  # ]:          0 :                 if ((ret = process_single(cmd, vg, pvl->pv, handle)) > ret_max)
     616                 :          0 :                         ret_max = ret;
     617         [ #  # ]:          0 :                 if (sigint_caught())
     618                 :          0 :                         return ret_max;
     619                 :            :         }
     620                 :            : 
     621                 :          0 :         return ret_max;
     622                 :            : }
     623                 :            : 
     624                 :          0 : static int _process_all_devs(struct cmd_context *cmd, void *handle,
     625                 :            :                     int (*process_single) (struct cmd_context * cmd,
     626                 :            :                                            struct volume_group * vg,
     627                 :            :                                            struct physical_volume * pv,
     628                 :            :                                            void *handle))
     629                 :            : {
     630                 :            :         struct physical_volume *pv;
     631                 :            :         struct physical_volume pv_dummy;
     632                 :            :         struct dev_iter *iter;
     633                 :            :         struct device *dev;
     634                 :            : 
     635                 :          0 :         int ret_max = ECMD_PROCESSED;
     636                 :          0 :         int ret = 0;
     637                 :            : 
     638         [ #  # ]:          0 :         if (!scan_vgs_for_pvs(cmd)) {
     639                 :          0 :                 stack;
     640                 :          0 :                 return ECMD_FAILED;
     641                 :            :         }
     642                 :            : 
     643         [ #  # ]:          0 :         if (!(iter = dev_iter_create(cmd->filter, 1))) {
     644                 :          0 :                 log_error("dev_iter creation failed");
     645                 :          0 :                 return ECMD_FAILED;
     646                 :            :         }
     647                 :            : 
     648         [ #  # ]:          0 :         while ((dev = dev_iter_get(iter))) {
     649         [ #  # ]:          0 :                 if (!(pv = pv_read(cmd, dev_name(dev), NULL, NULL, 0, 0))) {
     650                 :          0 :                         memset(&pv_dummy, 0, sizeof(pv_dummy));
     651                 :          0 :                         dm_list_init(&pv_dummy.tags);
     652                 :          0 :                         dm_list_init(&pv_dummy.segments);
     653                 :          0 :                         pv_dummy.dev = dev;
     654                 :          0 :                         pv_dummy.fmt = NULL;
     655                 :          0 :                         pv = &pv_dummy;
     656                 :            :                 }
     657                 :          0 :                 ret = process_single(cmd, NULL, pv, handle);
     658         [ #  # ]:          0 :                 if (ret > ret_max)
     659                 :          0 :                         ret_max = ret;
     660         [ #  # ]:          0 :                 if (sigint_caught())
     661                 :          0 :                         break;
     662                 :            :         }
     663                 :            : 
     664                 :          0 :         dev_iter_destroy(iter);
     665                 :            : 
     666                 :          0 :         return ret_max;
     667                 :            : }
     668                 :            : 
     669                 :            : /*
     670                 :            :  * If the lock_type is LCK_VG_READ (used only in reporting commands),
     671                 :            :  * we lock VG_GLOBAL to enable use of metadata cache.
     672                 :            :  * This can pause alongide pvscan or vgscan process for a while.
     673                 :            :  */
     674                 :          1 : int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
     675                 :            :                     struct volume_group *vg, uint32_t flags,
     676                 :            :                     int scan_label_only, void *handle,
     677                 :            :                     int (*process_single) (struct cmd_context * cmd,
     678                 :            :                                            struct volume_group * vg,
     679                 :            :                                            struct physical_volume * pv,
     680                 :            :                                            void *handle))
     681                 :            : {
     682                 :          1 :         int opt = 0;
     683                 :          1 :         int ret_max = ECMD_PROCESSED;
     684                 :          1 :         int ret = 0;
     685 [ +  - ][ +  - ]:          1 :         int lock_global = !(flags & READ_WITHOUT_LOCK) && !(flags & READ_FOR_UPDATE);
     686                 :            : 
     687                 :            :         struct pv_list *pvl;
     688                 :            :         struct physical_volume *pv;
     689                 :            :         struct dm_list *pvslist, *vgnames;
     690                 :            :         struct dm_list tags;
     691                 :            :         struct str_list *sll;
     692                 :            :         char *tagname;
     693                 :          1 :         int scanned = 0;
     694                 :            :         struct dm_list mdas;
     695                 :            : 
     696                 :          1 :         dm_list_init(&tags);
     697                 :            : 
     698   [ +  -  -  + ]:          1 :         if (lock_global && !lock_vol(cmd, VG_GLOBAL, LCK_VG_READ)) {
     699                 :          0 :                 log_error("Unable to obtain global lock.");
     700                 :          0 :                 return ECMD_FAILED;
     701                 :            :         }
     702                 :            : 
     703         [ -  + ]:          1 :         if (argc) {
     704                 :          0 :                 log_verbose("Using physical volume(s) on command line");
     705         [ #  # ]:          0 :                 for (; opt < argc; opt++) {
     706         [ #  # ]:          0 :                         if (*argv[opt] == '@') {
     707                 :          0 :                                 tagname = argv[opt] + 1;
     708                 :            : 
     709         [ #  # ]:          0 :                                 if (!validate_name(tagname)) {
     710                 :          0 :                                         log_error("Skipping invalid tag %s",
     711                 :            :                                                   tagname);
     712         [ #  # ]:          0 :                                         if (ret_max < EINVALID_CMD_LINE)
     713                 :          0 :                                                 ret_max = EINVALID_CMD_LINE;
     714                 :          0 :                                         continue;
     715                 :            :                                 }
     716         [ #  # ]:          0 :                                 if (!str_list_add(cmd->mem, &tags,
     717                 :          0 :                                                   dm_pool_strdup(cmd->mem,
     718                 :            :                                                               tagname))) {
     719                 :          0 :                                         log_error("strlist allocation failed");
     720                 :          0 :                                         goto bad;
     721                 :            :                                 }
     722                 :          0 :                                 continue;
     723                 :            :                         }
     724         [ #  # ]:          0 :                         if (vg) {
     725         [ #  # ]:          0 :                                 if (!(pvl = find_pv_in_vg(vg, argv[opt]))) {
     726                 :          0 :                                         log_error("Physical Volume \"%s\" not "
     727                 :            :                                                   "found in Volume Group "
     728                 :            :                                                   "\"%s\"", argv[opt],
     729                 :            :                                                   vg->name);
     730                 :          0 :                                         ret_max = ECMD_FAILED;
     731                 :          0 :                                         continue;
     732                 :            :                                 }
     733                 :          0 :                                 pv = pvl->pv;
     734                 :            :                         } else {
     735                 :            : 
     736                 :          0 :                                 dm_list_init(&mdas);
     737         [ #  # ]:          0 :                                 if (!(pv = pv_read(cmd, argv[opt], &mdas,
     738                 :            :                                                    NULL, 1, scan_label_only))) {
     739                 :          0 :                                         log_error("Failed to read physical "
     740                 :            :                                                   "volume \"%s\"", argv[opt]);
     741                 :          0 :                                         ret_max = ECMD_FAILED;
     742                 :          0 :                                         continue;
     743                 :            :                                 }
     744                 :            : 
     745                 :            :                                 /*
     746                 :            :                                  * If a PV has no MDAs it may appear to be an
     747                 :            :                                  * orphan until the metadata is read off
     748                 :            :                                  * another PV in the same VG.  Detecting this
     749                 :            :                                  * means checking every VG by scanning every
     750                 :            :                                  * PV on the system.
     751                 :            :                                  */
     752         [ #  # ]:          0 :                                 if (!scanned && is_orphan(pv) &&
           [ #  #  #  # ]
     753                 :          0 :                                     !dm_list_size(&mdas)) {
     754   [ #  #  #  # ]:          0 :                                         if (!scan_label_only &&
     755                 :          0 :                                             !scan_vgs_for_pvs(cmd)) {
     756                 :          0 :                                                 stack;
     757                 :          0 :                                                 ret_max = ECMD_FAILED;
     758                 :          0 :                                                 continue;
     759                 :            :                                         }
     760                 :          0 :                                         scanned = 1;
     761         [ #  # ]:          0 :                                         if (!(pv = pv_read(cmd, argv[opt],
     762                 :            :                                                            NULL, NULL, 1,
     763                 :            :                                                            scan_label_only))) {
     764                 :          0 :                                                 log_error("Failed to read "
     765                 :            :                                                           "physical volume "
     766                 :            :                                                           "\"%s\"", argv[opt]);
     767                 :          0 :                                                 ret_max = ECMD_FAILED;
     768                 :          0 :                                                 continue;
     769                 :            :                                         }
     770                 :            :                                 }
     771                 :            :                         }
     772                 :            : 
     773                 :          0 :                         ret = process_single(cmd, vg, pv, handle);
     774         [ #  # ]:          0 :                         if (ret > ret_max)
     775                 :          0 :                                 ret_max = ret;
     776         [ #  # ]:          0 :                         if (sigint_caught())
     777                 :          0 :                                 goto out;
     778                 :            :                 }
     779         [ #  # ]:          0 :                 if (!dm_list_empty(&tags) && (vgnames = get_vgnames(cmd, 1)) &&
           [ #  #  #  # ]
     780                 :          0 :                            !dm_list_empty(vgnames)) {
     781         [ #  # ]:          0 :                         dm_list_iterate_items(sll, vgnames) {
     782                 :          0 :                                 vg = vg_read(cmd, sll->str, NULL, flags);
     783         [ #  # ]:          0 :                                 if (vg_read_error(vg)) {
     784                 :          0 :                                         ret_max = ECMD_FAILED;
     785                 :          0 :                                         vg_release(vg);
     786                 :          0 :                                         stack;
     787                 :          0 :                                         continue;
     788                 :            :                                 }
     789                 :            : 
     790                 :          0 :                                 ret = process_each_pv_in_vg(cmd, vg, &tags,
     791                 :            :                                                             handle,
     792                 :            :                                                             process_single);
     793                 :            : 
     794                 :          0 :                                 unlock_and_release_vg(cmd, vg, sll->str);
     795                 :            : 
     796         [ #  # ]:          0 :                                 if (ret > ret_max)
     797                 :          0 :                                         ret_max = ret;
     798         [ #  # ]:          0 :                                 if (sigint_caught())
     799                 :          0 :                                         goto out;
     800                 :            :                         }
     801                 :            :                 }
     802                 :            :         } else {
     803         [ -  + ]:          1 :                 if (vg) {
     804                 :          0 :                         log_verbose("Using all physical volume(s) in "
     805                 :            :                                     "volume group");
     806                 :          0 :                         ret = process_each_pv_in_vg(cmd, vg, NULL, handle,
     807                 :            :                                                     process_single);
     808         [ #  # ]:          0 :                         if (ret > ret_max)
     809                 :          0 :                                 ret_max = ret;
     810         [ #  # ]:          0 :                         if (sigint_caught())
     811                 :          0 :                                 goto out;
     812         [ -  + ]:          1 :                 } else if (arg_count(cmd, all_ARG)) {
     813                 :          0 :                         ret = _process_all_devs(cmd, handle, process_single);
     814         [ #  # ]:          0 :                         if (ret > ret_max)
     815                 :          0 :                                 ret_max = ret;
     816         [ #  # ]:          0 :                         if (sigint_caught())
     817                 :          0 :                                 goto out;
     818                 :            :                 } else {
     819                 :          1 :                         log_verbose("Scanning for physical volume names");
     820                 :            : 
     821         [ -  + ]:          1 :                         if (!(pvslist = get_pvs(cmd)))
     822                 :          0 :                                 goto bad;
     823                 :            : 
     824         [ -  + ]:          1 :                         dm_list_iterate_items(pvl, pvslist) {
     825                 :          0 :                                 ret = process_single(cmd, NULL, pvl->pv,
     826                 :            :                                                      handle);
     827         [ #  # ]:          0 :                                 if (ret > ret_max)
     828                 :          0 :                                         ret_max = ret;
     829         [ #  # ]:          0 :                                 if (sigint_caught())
     830                 :          0 :                                         goto out;
     831                 :            :                         }
     832                 :            :                 }
     833                 :            :         }
     834                 :            : out:
     835         [ +  - ]:          1 :         if (lock_global)
     836                 :          1 :                 unlock_vg(cmd, VG_GLOBAL);
     837                 :          1 :         return ret_max;
     838                 :            : bad:
     839         [ #  # ]:          0 :         if (lock_global)
     840                 :          0 :                 unlock_vg(cmd, VG_GLOBAL);
     841                 :            : 
     842                 :          1 :         return ECMD_FAILED;
     843                 :            : }
     844                 :            : 
     845                 :            : /*
     846                 :            :  * Determine volume group name from a logical volume name
     847                 :            :  */
     848                 :          0 : const char *extract_vgname(struct cmd_context *cmd, const char *lv_name)
     849                 :            : {
     850                 :          0 :         const char *vg_name = lv_name;
     851                 :            :         char *st;
     852                 :          0 :         char *dev_dir = cmd->dev_dir;
     853                 :          0 :         int dev_dir_provided = 0;
     854                 :            : 
     855                 :            :         /* Path supplied? */
     856 [ #  # ][ #  # ]:          0 :         if (vg_name && strchr(vg_name, '/')) {
     857                 :            :                 /* Strip dev_dir (optional) */
     858         [ #  # ]:          0 :                 if (*vg_name == '/') {
     859         [ #  # ]:          0 :                         while (*vg_name == '/')
     860                 :          0 :                                 vg_name++;
     861                 :          0 :                         vg_name--;
     862                 :            :                 }
     863         [ #  # ]:          0 :                 if (!strncmp(vg_name, dev_dir, strlen(dev_dir))) {
     864                 :          0 :                         vg_name += strlen(dev_dir);
     865                 :          0 :                         dev_dir_provided = 1;
     866         [ #  # ]:          0 :                         while (*vg_name == '/')
     867                 :          0 :                                 vg_name++;
     868                 :            :                 }
     869         [ #  # ]:          0 :                 if (*vg_name == '/') {
     870                 :          0 :                         log_error("\"%s\": Invalid path for Logical "
     871                 :            :                                   "Volume", lv_name);
     872                 :          0 :                         return 0;
     873                 :            :                 }
     874                 :            : 
     875                 :            :                 /* Require exactly one set of consecutive slashes */
     876         [ #  # ]:          0 :                 if ((st = strchr(vg_name, '/')))
     877         [ #  # ]:          0 :                         while (*st == '/')
     878                 :          0 :                                 st++;
     879                 :            : 
     880 [ #  # ][ #  # ]:          0 :                 if (!strchr(vg_name, '/') || strchr(st, '/')) {
     881                 :          0 :                         log_error("\"%s\": Invalid path for Logical Volume",
     882                 :            :                                   lv_name);
     883                 :          0 :                         return 0;
     884                 :            :                 }
     885                 :            : 
     886                 :          0 :                 vg_name = dm_pool_strdup(cmd->mem, vg_name);
     887         [ #  # ]:          0 :                 if (!vg_name) {
     888                 :          0 :                         log_error("Allocation of vg_name failed");
     889                 :          0 :                         return 0;
     890                 :            :                 }
     891                 :            : 
     892                 :          0 :                 *strchr(vg_name, '/') = '\0';
     893                 :          0 :                 return vg_name;
     894                 :            :         }
     895                 :            : 
     896         [ #  # ]:          0 :         if (!(vg_name = default_vgname(cmd))) {
     897         [ #  # ]:          0 :                 if (lv_name)
     898                 :          0 :                         log_error("Path required for Logical Volume \"%s\"",
     899                 :            :                                   lv_name);
     900                 :          0 :                 return 0;
     901                 :            :         }
     902                 :            : 
     903                 :          0 :         return vg_name;
     904                 :            : }
     905                 :            : 
     906                 :            : /*
     907                 :            :  * Extract default volume group name from environment
     908                 :            :  */
     909                 :          0 : char *default_vgname(struct cmd_context *cmd)
     910                 :            : {
     911                 :            :         char *vg_path;
     912                 :            : 
     913                 :            :         /* Take default VG from environment? */
     914                 :          0 :         vg_path = getenv("LVM_VG_NAME");
     915         [ #  # ]:          0 :         if (!vg_path)
     916                 :          0 :                 return 0;
     917                 :            : 
     918                 :          0 :         vg_path = skip_dev_dir(cmd, vg_path, NULL);
     919                 :            : 
     920         [ #  # ]:          0 :         if (strchr(vg_path, '/')) {
     921                 :          0 :                 log_error("Environment Volume Group in LVM_VG_NAME invalid: "
     922                 :            :                           "\"%s\"", vg_path);
     923                 :          0 :                 return 0;
     924                 :            :         }
     925                 :            : 
     926                 :          0 :         return dm_pool_strdup(cmd->mem, vg_path);
     927                 :            : }
     928                 :            : 
     929                 :            : /*
     930                 :            :  * Process physical extent range specifiers
     931                 :            :  */
     932                 :          0 : static int _add_pe_range(struct dm_pool *mem, const char *pvname,
     933                 :            :                          struct dm_list *pe_ranges, uint32_t start, uint32_t count)
     934                 :            : {
     935                 :            :         struct pe_range *per;
     936                 :            : 
     937                 :          0 :         log_debug("Adding PE range: start PE %" PRIu32 " length %" PRIu32
     938                 :            :                   " on %s", start, count, pvname);
     939                 :            : 
     940                 :            :         /* Ensure no overlap with existing areas */
     941         [ #  # ]:          0 :         dm_list_iterate_items(per, pe_ranges) {
     942 [ #  # ][ #  # ]:          0 :                 if (((start < per->start) && (start + count - 1 >= per->start))
         [ #  # ][ #  # ]
     943                 :          0 :                     || ((start >= per->start) &&
     944                 :          0 :                         (per->start + per->count - 1) >= start)) {
     945                 :          0 :                         log_error("Overlapping PE ranges specified (%" PRIu32
     946                 :            :                                   "-%" PRIu32 ", %" PRIu32 "-%" PRIu32 ")"
     947                 :            :                                   " on %s",
     948                 :            :                                   start, start + count - 1, per->start,
     949                 :            :                                   per->start + per->count - 1, pvname);
     950                 :          0 :                         return 0;
     951                 :            :                 }
     952                 :            :         }
     953                 :            : 
     954         [ #  # ]:          0 :         if (!(per = dm_pool_alloc(mem, sizeof(*per)))) {
     955                 :          0 :                 log_error("Allocation of list failed");
     956                 :          0 :                 return 0;
     957                 :            :         }
     958                 :            : 
     959                 :          0 :         per->start = start;
     960                 :          0 :         per->count = count;
     961                 :          0 :         dm_list_add(pe_ranges, &per->list);
     962                 :            : 
     963                 :          0 :         return 1;
     964                 :            : }
     965                 :            : 
     966                 :          0 : static int xstrtouint32(const char *s, char **p, int base, uint32_t *result)
     967                 :            : {
     968                 :            :         unsigned long ul;
     969                 :            : 
     970                 :          0 :         errno = 0;
     971                 :          0 :         ul = strtoul(s, p, base);
     972   [ #  #  #  # ]:          0 :         if (errno || *p == s || (uint32_t) ul != ul)
     973                 :          0 :                 return -1;
     974                 :          0 :         *result = ul;
     975                 :          0 :         return 0;
     976                 :            : }
     977                 :            : 
     978                 :          0 : static int _parse_pes(struct dm_pool *mem, char *c, struct dm_list *pe_ranges,
     979                 :            :                       const char *pvname, uint32_t size)
     980                 :            : {
     981                 :            :         char *endptr;
     982                 :            :         uint32_t start, end;
     983                 :            : 
     984                 :            :         /* Default to whole PV */
     985         [ #  # ]:          0 :         if (!c) {
     986         [ #  # ]:          0 :                 if (!_add_pe_range(mem, pvname, pe_ranges, UINT32_C(0), size))
     987                 :          0 :                         return_0;
     988                 :          0 :                 return 1;
     989                 :            :         }
     990                 :            : 
     991         [ #  # ]:          0 :         while (*c) {
     992         [ #  # ]:          0 :                 if (*c != ':')
     993                 :          0 :                         goto error;
     994                 :            : 
     995                 :          0 :                 c++;
     996                 :            : 
     997                 :            :                 /* Disallow :: and :\0 */
     998 [ #  # ][ #  # ]:          0 :                 if (*c == ':' || !*c)
     999                 :            :                         goto error;
    1000                 :            : 
    1001                 :            :                 /* Default to whole range */
    1002                 :          0 :                 start = UINT32_C(0);
    1003                 :          0 :                 end = size - 1;
    1004                 :            : 
    1005                 :            :                 /* Start extent given? */
    1006         [ #  # ]:          0 :                 if (isdigit(*c)) {
    1007         [ #  # ]:          0 :                         if (xstrtouint32(c, &endptr, 10, &start))
    1008                 :          0 :                                 goto error;
    1009                 :          0 :                         c = endptr;
    1010                 :            :                         /* Just one number given? */
    1011 [ #  # ][ #  # ]:          0 :                         if (!*c || *c == ':')
    1012                 :          0 :                                 end = start;
    1013                 :            :                 }
    1014                 :            :                 /* Range? */
    1015         [ #  # ]:          0 :                 if (*c == '-') {
    1016                 :          0 :                         c++;
    1017         [ #  # ]:          0 :                         if (isdigit(*c)) {
    1018         [ #  # ]:          0 :                                 if (xstrtouint32(c, &endptr, 10, &end))
    1019                 :          0 :                                         goto error;
    1020                 :          0 :                                 c = endptr;
    1021                 :            :                         }
    1022                 :            :                 }
    1023 [ #  # ][ #  # ]:          0 :                 if (*c && *c != ':')
    1024                 :          0 :                         goto error;
    1025                 :            : 
    1026 [ #  # ][ #  # ]:          0 :                 if ((start > end) || (end > size - 1)) {
    1027                 :          0 :                         log_error("PE range error: start extent %" PRIu32 " to "
    1028                 :            :                                   "end extent %" PRIu32, start, end);
    1029                 :          0 :                         return 0;
    1030                 :            :                 }
    1031                 :            : 
    1032         [ #  # ]:          0 :                 if (!_add_pe_range(mem, pvname, pe_ranges, start, end - start + 1))
    1033                 :          0 :                         return_0;
    1034                 :            : 
    1035                 :            :         }
    1036                 :            : 
    1037                 :          0 :         return 1;
    1038                 :            : 
    1039                 :            :       error:
    1040                 :          0 :         log_error("Physical extent parsing error at %s", c);
    1041                 :          0 :         return 0;
    1042                 :            : }
    1043                 :            : 
    1044                 :          0 : static int _create_pv_entry(struct dm_pool *mem, struct pv_list *pvl,
    1045                 :            :                              char *colon, int allocatable_only, struct dm_list *r)
    1046                 :            : {
    1047                 :            :         const char *pvname;
    1048                 :          0 :         struct pv_list *new_pvl = NULL, *pvl2;
    1049                 :            :         struct dm_list *pe_ranges;
    1050                 :            : 
    1051                 :          0 :         pvname = pv_dev_name(pvl->pv);
    1052   [ #  #  #  # ]:          0 :         if (allocatable_only && !(pvl->pv->status & ALLOCATABLE_PV)) {
    1053                 :          0 :                 log_error("Physical volume %s not allocatable", pvname);
    1054                 :          0 :                 return 1;
    1055                 :            :         }
    1056                 :            : 
    1057 [ #  # ][ #  # ]:          0 :         if (allocatable_only && is_missing_pv(pvl->pv)) {
    1058                 :          0 :                 log_error("Physical volume %s is missing", pvname);
    1059                 :          0 :                 return 1;
    1060                 :            :         }
    1061                 :            : 
    1062 [ #  # ][ #  # ]:          0 :         if (allocatable_only &&
    1063                 :          0 :             (pvl->pv->pe_count == pvl->pv->pe_alloc_count)) {
    1064                 :          0 :                 log_error("No free extents on physical volume \"%s\"", pvname);
    1065                 :          0 :                 return 1;
    1066                 :            :         }
    1067                 :            : 
    1068         [ #  # ]:          0 :         dm_list_iterate_items(pvl2, r)
    1069         [ #  # ]:          0 :                 if (pvl->pv->dev == pvl2->pv->dev) {
    1070                 :          0 :                         new_pvl = pvl2;
    1071                 :          0 :                         break;
    1072                 :            :                 }
    1073                 :            : 
    1074         [ #  # ]:          0 :         if (!new_pvl) {
    1075         [ #  # ]:          0 :                 if (!(new_pvl = dm_pool_alloc(mem, sizeof(*new_pvl)))) {
    1076                 :          0 :                         log_error("Unable to allocate physical volume list.");
    1077                 :          0 :                         return 0;
    1078                 :            :                 }
    1079                 :            : 
    1080                 :          0 :                 memcpy(new_pvl, pvl, sizeof(*new_pvl));
    1081                 :            : 
    1082         [ #  # ]:          0 :                 if (!(pe_ranges = dm_pool_alloc(mem, sizeof(*pe_ranges)))) {
    1083                 :          0 :                         log_error("Allocation of pe_ranges list failed");
    1084                 :          0 :                         return 0;
    1085                 :            :                 }
    1086                 :          0 :                 dm_list_init(pe_ranges);
    1087                 :          0 :                 new_pvl->pe_ranges = pe_ranges;
    1088                 :          0 :                 dm_list_add(r, &new_pvl->list);
    1089                 :            :         }
    1090                 :            : 
    1091                 :            :         /* Determine selected physical extents */
    1092         [ #  # ]:          0 :         if (!_parse_pes(mem, colon, new_pvl->pe_ranges, pv_dev_name(pvl->pv),
    1093                 :          0 :                         pvl->pv->pe_count))
    1094                 :          0 :                 return_0;
    1095                 :            : 
    1096                 :          0 :         return 1;
    1097                 :            : }
    1098                 :            : 
    1099                 :          0 : struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int argc,
    1100                 :            :                             char **argv, int allocatable_only)
    1101                 :            : {
    1102                 :            :         struct dm_list *r;
    1103                 :            :         struct pv_list *pvl;
    1104                 :            :         struct dm_list tags, arg_pvnames;
    1105                 :          0 :         const char *pvname = NULL;
    1106                 :            :         char *colon, *tagname;
    1107                 :            :         int i;
    1108                 :            : 
    1109                 :            :         /* Build up list of PVs */
    1110         [ #  # ]:          0 :         if (!(r = dm_pool_alloc(mem, sizeof(*r)))) {
    1111                 :          0 :                 log_error("Allocation of list failed");
    1112                 :          0 :                 return NULL;
    1113                 :            :         }
    1114                 :          0 :         dm_list_init(r);
    1115                 :            : 
    1116                 :          0 :         dm_list_init(&tags);
    1117                 :          0 :         dm_list_init(&arg_pvnames);
    1118                 :            : 
    1119         [ #  # ]:          0 :         for (i = 0; i < argc; i++) {
    1120         [ #  # ]:          0 :                 if (*argv[i] == '@') {
    1121                 :          0 :                         tagname = argv[i] + 1;
    1122         [ #  # ]:          0 :                         if (!validate_name(tagname)) {
    1123                 :          0 :                                 log_error("Skipping invalid tag %s", tagname);
    1124                 :          0 :                                 continue;
    1125                 :            :                         }
    1126         [ #  # ]:          0 :                         dm_list_iterate_items(pvl, &vg->pvs) {
    1127         [ #  # ]:          0 :                                 if (str_list_match_item(&pvl->pv->tags,
    1128                 :            :                                                         tagname)) {
    1129         [ #  # ]:          0 :                                         if (!_create_pv_entry(mem, pvl, NULL,
    1130                 :            :                                                               allocatable_only,
    1131                 :            :                                                               r))
    1132                 :          0 :                                                 return_NULL;
    1133                 :            :                                 }
    1134                 :            :                         }
    1135                 :          0 :                         continue;
    1136                 :            :                 }
    1137                 :            : 
    1138                 :          0 :                 pvname = argv[i];
    1139                 :            : 
    1140         [ #  # ]:          0 :                 if ((colon = strchr(pvname, ':'))) {
    1141         [ #  # ]:          0 :                         if (!(pvname = dm_pool_strndup(mem, pvname,
    1142                 :          0 :                                                     (unsigned) (colon -
    1143                 :            :                                                                 pvname)))) {
    1144                 :          0 :                                 log_error("Failed to clone PV name");
    1145                 :          0 :                                 return NULL;
    1146                 :            :                         }
    1147                 :            :                 }
    1148                 :            : 
    1149         [ #  # ]:          0 :                 if (!(pvl = find_pv_in_vg(vg, pvname))) {
    1150                 :          0 :                         log_error("Physical Volume \"%s\" not found in "
    1151                 :            :                                   "Volume Group \"%s\"", pvname, vg->name);
    1152                 :          0 :                         return NULL;
    1153                 :            :                 }
    1154         [ #  # ]:          0 :                 if (!_create_pv_entry(mem, pvl, colon, allocatable_only, r))
    1155                 :          0 :                         return_NULL;
    1156                 :            :         }
    1157                 :            : 
    1158         [ #  # ]:          0 :         if (dm_list_empty(r))
    1159                 :          0 :                 log_error("No specified PVs have space available");
    1160                 :            : 
    1161         [ #  # ]:          0 :         return dm_list_empty(r) ? NULL : r;
    1162                 :            : }
    1163                 :            : 
    1164                 :          0 : struct dm_list *clone_pv_list(struct dm_pool *mem, struct dm_list *pvsl)
    1165                 :            : {
    1166                 :            :         struct dm_list *r;
    1167                 :            :         struct pv_list *pvl, *new_pvl;
    1168                 :            : 
    1169                 :            :         /* Build up list of PVs */
    1170         [ #  # ]:          0 :         if (!(r = dm_pool_alloc(mem, sizeof(*r)))) {
    1171                 :          0 :                 log_error("Allocation of list failed");
    1172                 :          0 :                 return NULL;
    1173                 :            :         }
    1174                 :          0 :         dm_list_init(r);
    1175                 :            : 
    1176         [ #  # ]:          0 :         dm_list_iterate_items(pvl, pvsl) {
    1177         [ #  # ]:          0 :                 if (!(new_pvl = dm_pool_zalloc(mem, sizeof(*new_pvl)))) {
    1178                 :          0 :                         log_error("Unable to allocate physical volume list.");
    1179                 :          0 :                         return NULL;
    1180                 :            :                 }
    1181                 :            : 
    1182                 :          0 :                 memcpy(new_pvl, pvl, sizeof(*new_pvl));
    1183                 :          0 :                 dm_list_add(r, &new_pvl->list);
    1184                 :            :         }
    1185                 :            : 
    1186                 :          0 :         return r;
    1187                 :            : }
    1188                 :            : 
    1189                 :          0 : int apply_lvname_restrictions(const char *name)
    1190                 :            : {
    1191         [ #  # ]:          0 :         if (!strncmp(name, "snapshot", 8)) {
    1192                 :          0 :                 log_error("Names starting \"snapshot\" are reserved. "
    1193                 :            :                           "Please choose a different LV name.");
    1194                 :          0 :                 return 0;
    1195                 :            :         }
    1196                 :            : 
    1197         [ #  # ]:          0 :         if (!strncmp(name, "pvmove", 6)) {
    1198                 :          0 :                 log_error("Names starting \"pvmove\" are reserved. "
    1199                 :            :                           "Please choose a different LV name.");
    1200                 :          0 :                 return 0;
    1201                 :            :         }
    1202                 :            : 
    1203         [ #  # ]:          0 :         if (strstr(name, "_mlog")) {
    1204                 :          0 :                 log_error("Names including \"_mlog\" are reserved. "
    1205                 :            :                           "Please choose a different LV name.");
    1206                 :          0 :                 return 0;
    1207                 :            :         }
    1208                 :            : 
    1209         [ #  # ]:          0 :         if (strstr(name, "_mimage")) {
    1210                 :          0 :                 log_error("Names including \"_mimage\" are reserved. "
    1211                 :            :                           "Please choose a different LV name.");
    1212                 :          0 :                 return 0;
    1213                 :            :         }
    1214                 :            : 
    1215         [ #  # ]:          0 :         if (strstr(name, "_vorigin")) {
    1216                 :          0 :                 log_error("Names including \"_vorigin\" are reserved. "
    1217                 :            :                           "Please choose a different LV name.");
    1218                 :          0 :                 return 0;
    1219                 :            :         }
    1220                 :            : 
    1221                 :          0 :         return 1;
    1222                 :            : }
    1223                 :            : 
    1224                 :          0 : int is_reserved_lvname(const char *name)
    1225                 :            : {
    1226                 :            :         int rc, old_suppress;
    1227                 :            : 
    1228                 :          0 :         old_suppress = log_suppress(2);
    1229                 :          0 :         rc = !apply_lvname_restrictions(name);
    1230                 :          0 :         log_suppress(old_suppress);
    1231                 :            : 
    1232                 :          0 :         return rc;
    1233                 :            : }
    1234                 :            : 
    1235                 :          0 : void vgcreate_params_set_defaults(struct vgcreate_params *vp_def,
    1236                 :            :                                   struct volume_group *vg)
    1237                 :            : {
    1238         [ #  # ]:          0 :         if (vg) {
    1239                 :          0 :                 vp_def->vg_name = NULL;
    1240                 :          0 :                 vp_def->extent_size = vg->extent_size;
    1241                 :          0 :                 vp_def->max_pv = vg->max_pv;
    1242                 :          0 :                 vp_def->max_lv = vg->max_lv;
    1243                 :          0 :                 vp_def->alloc = vg->alloc;
    1244                 :          0 :                 vp_def->clustered = vg_is_clustered(vg);
    1245                 :            :         } else {
    1246                 :          0 :                 vp_def->vg_name = NULL;
    1247                 :          0 :                 vp_def->extent_size = DEFAULT_EXTENT_SIZE * 2;
    1248                 :          0 :                 vp_def->max_pv = DEFAULT_MAX_PV;
    1249                 :          0 :                 vp_def->max_lv = DEFAULT_MAX_LV;
    1250                 :          0 :                 vp_def->alloc = DEFAULT_ALLOC_POLICY;
    1251                 :          0 :                 vp_def->clustered = DEFAULT_CLUSTERED;
    1252                 :            :         }
    1253                 :          0 : }
    1254                 :            : 
    1255                 :            : /*
    1256                 :            :  * Set members of struct vgcreate_params from cmdline arguments.
    1257                 :            :  * Do preliminary validation with arg_*() interface.
    1258                 :            :  * Further, more generic validation is done in validate_vgcreate_params().
    1259                 :            :  * This function is to remain in tools directory.
    1260                 :            :  */
    1261                 :          0 : int vgcreate_params_set_from_args(struct cmd_context *cmd,
    1262                 :            :                                   struct vgcreate_params *vp_new,
    1263                 :            :                                   struct vgcreate_params *vp_def)
    1264                 :            : {
    1265                 :          0 :         vp_new->vg_name = skip_dev_dir(cmd, vp_def->vg_name, NULL);
    1266                 :          0 :         vp_new->max_lv = arg_uint_value(cmd, maxlogicalvolumes_ARG,
    1267                 :            :                                         vp_def->max_lv);
    1268                 :          0 :         vp_new->max_pv = arg_uint_value(cmd, maxphysicalvolumes_ARG,
    1269                 :            :                                         vp_def->max_pv);
    1270                 :          0 :         vp_new->alloc = arg_uint_value(cmd, alloc_ARG, vp_def->alloc);
    1271                 :            : 
    1272                 :            :         /* Units of 512-byte sectors */
    1273                 :          0 :         vp_new->extent_size =
    1274                 :          0 :             arg_uint_value(cmd, physicalextentsize_ARG, vp_def->extent_size);
    1275                 :            : 
    1276         [ #  # ]:          0 :         if (arg_count(cmd, clustered_ARG))
    1277                 :          0 :                 vp_new->clustered =
    1278         [ #  # ]:          0 :                         !strcmp(arg_str_value(cmd, clustered_ARG,
    1279                 :          0 :                                               vp_def->clustered ? "y":"n"), "y");
    1280                 :            :         else
    1281                 :            :                 /* Default depends on current locking type */
    1282                 :          0 :                 vp_new->clustered = locking_is_clustered();
    1283                 :            : 
    1284         [ #  # ]:          0 :         if (arg_sign_value(cmd, physicalextentsize_ARG, 0) == SIGN_MINUS) {
    1285                 :          0 :                 log_error("Physical extent size may not be negative");
    1286                 :          0 :                 return 1;
    1287                 :            :         }
    1288                 :            : 
    1289         [ #  # ]:          0 :         if (arg_sign_value(cmd, maxlogicalvolumes_ARG, 0) == SIGN_MINUS) {
    1290                 :          0 :                 log_error("Max Logical Volumes may not be negative");
    1291                 :          0 :                 return 1;
    1292                 :            :         }
    1293                 :            : 
    1294         [ #  # ]:          0 :         if (arg_sign_value(cmd, maxphysicalvolumes_ARG, 0) == SIGN_MINUS) {
    1295                 :          0 :                 log_error("Max Physical Volumes may not be negative");
    1296                 :          0 :                 return 1;
    1297                 :            :         }
    1298                 :            : 
    1299                 :          0 :         return 0;
    1300                 :            : }
    1301                 :            : 
    1302                 :          0 : int lv_refresh(struct cmd_context *cmd, struct logical_volume *lv)
    1303                 :            : {
    1304                 :          0 :         int r = 0;
    1305                 :            : 
    1306 [ #  # ][ #  # ]:          0 :         r = suspend_lv(cmd, lv);
    1307         [ #  # ]:          0 :         if (!r)
    1308                 :          0 :                 goto_out;
    1309                 :            : 
    1310 [ #  # ][ #  # ]:          0 :         r = resume_lv(cmd, lv);
    1311         [ #  # ]:          0 :         if (!r)
    1312                 :          0 :                 goto_out;
    1313                 :            : 
    1314                 :            :         /*
    1315                 :            :          * check if snapshot merge should be polled
    1316                 :            :          * - unfortunately: even though the dev_manager will clear
    1317                 :            :          *   the lv's merge attributes if a merge is not possible;
    1318                 :            :          *   it is clearing a different instance of the lv (as
    1319                 :            :          *   retrieved with lv_from_lvid)
    1320                 :            :          * - fortunately: polldaemon will immediately shutdown if the
    1321                 :            :          *   origin doesn't have a status with a snapshot percentage
    1322                 :            :          */
    1323 [ #  # ][ #  # ]:          0 :         if (background_polling() && lv_is_origin(lv) && lv_is_merging_origin(lv))
                 [ #  # ]
    1324                 :          0 :                 lv_spawn_background_polling(cmd, lv);
    1325                 :            : 
    1326                 :            : out:
    1327                 :          0 :         return r;
    1328                 :            : }
    1329                 :            : 
    1330                 :          0 : int vg_refresh_visible(struct cmd_context *cmd, struct volume_group *vg)
    1331                 :            : {
    1332                 :            :         struct lv_list *lvl;
    1333                 :          0 :         int r = 1;
    1334                 :            : 
    1335         [ #  # ]:          0 :         dm_list_iterate_items(lvl, &vg->lvs)
    1336         [ #  # ]:          0 :                 if (lv_is_visible(lvl->lv))
    1337         [ #  # ]:          0 :                         if (!lv_refresh(cmd, lvl->lv))
    1338                 :          0 :                                 r = 0;
    1339                 :            : 
    1340                 :          0 :         return r;
    1341                 :            : }
    1342                 :            : 
    1343                 :          0 : void lv_spawn_background_polling(struct cmd_context *cmd,
    1344                 :            :                                  struct logical_volume *lv)
    1345                 :            : {
    1346                 :            :         const char *pvname;
    1347                 :            : 
    1348   [ #  #  #  # ]:          0 :         if ((lv->status & PVMOVE) &&
    1349                 :          0 :             (pvname = get_pvmove_pvname_from_lv_mirr(lv))) {
    1350                 :          0 :                 log_verbose("Spawning background pvmove process for %s",
    1351                 :            :                             pvname);
    1352                 :          0 :                 pvmove_poll(cmd, pvname, 1);
    1353   [ #  #  #  # ]:          0 :         } else if ((lv->status & LOCKED) &&
    1354                 :          0 :             (pvname = get_pvmove_pvname_from_lv(lv))) {
    1355                 :          0 :                 log_verbose("Spawning background pvmove process for %s",
    1356                 :            :                             pvname);
    1357                 :          0 :                 pvmove_poll(cmd, pvname, 1);
    1358                 :            :         }
    1359                 :            : 
    1360         [ #  # ]:          0 :         if (lv->status & (CONVERTING|MERGING)) {
    1361                 :          0 :                 log_verbose("Spawning background lvconvert process for %s",
    1362                 :            :                         lv->name);
    1363                 :          0 :                 lvconvert_poll(cmd, lv, 1);
    1364                 :            :         }
    1365                 :          0 : }
    1366                 :            : 
    1367                 :            : /*
    1368                 :            :  * Intial sanity checking of non-recovery related command-line arguments.
    1369                 :            :  *
    1370                 :            :  * Output arguments:
    1371                 :            :  * pp: structure allocated by caller, fields written / validated here
    1372                 :            :  */
    1373                 :          0 : int pvcreate_params_validate(struct cmd_context *cmd,
    1374                 :            :                              int argc, char **argv,
    1375                 :            :                              struct pvcreate_params *pp)
    1376                 :            : {
    1377         [ #  # ]:          0 :         if (!argc) {
    1378                 :          0 :                 log_error("Please enter a physical volume path");
    1379                 :          0 :                 return 0;
    1380                 :            :         }
    1381                 :            : 
    1382 [ #  # ][ #  # ]:          0 :         if (arg_count(cmd, yes_ARG) && !arg_count(cmd, force_ARG)) {
    1383                 :          0 :                 log_error("Option y can only be given with option f");
    1384                 :          0 :                 return 0;
    1385                 :            :         }
    1386                 :            : 
    1387                 :          0 :         pp->yes = arg_count(cmd, yes_ARG);
    1388                 :          0 :         pp->force = arg_count(cmd, force_ARG);
    1389                 :            : 
    1390         [ #  # ]:          0 :         if (arg_int_value(cmd, labelsector_ARG, 0) >= LABEL_SCAN_SECTORS) {
    1391                 :          0 :                 log_error("labelsector must be less than %lu",
    1392                 :            :                           LABEL_SCAN_SECTORS);
    1393                 :          0 :                 return 0;
    1394                 :            :         } else {
    1395                 :          0 :                 pp->labelsector = arg_int64_value(cmd, labelsector_ARG,
    1396                 :            :                                                   DEFAULT_LABELSECTOR);
    1397                 :            :         }
    1398                 :            : 
    1399 [ #  #  #  #  # :          0 :         if (!(cmd->fmt->features & FMT_MDAS) &&
          #  #  #  #  # ]
    1400                 :          0 :             (arg_count(cmd, pvmetadatacopies_ARG) ||
    1401                 :          0 :              arg_count(cmd, metadatasize_ARG)   ||
    1402                 :          0 :              arg_count(cmd, dataalignment_ARG)  ||
    1403                 :          0 :              arg_count(cmd, dataalignmentoffset_ARG))) {
    1404                 :          0 :                 log_error("Metadata and data alignment parameters only "
    1405                 :            :                           "apply to text format.");
    1406                 :          0 :                 return 0;
    1407                 :            :         }
    1408                 :            : 
    1409   [ #  #  #  # ]:          0 :         if (arg_count(cmd, pvmetadatacopies_ARG) &&
    1410                 :          0 :             arg_int_value(cmd, pvmetadatacopies_ARG, -1) > 2) {
    1411                 :          0 :                 log_error("Metadatacopies may only be 0, 1 or 2");
    1412                 :          0 :                 return 0;
    1413                 :            :         }
    1414                 :            : 
    1415         [ #  # ]:          0 :         if (arg_count(cmd, zero_ARG))
    1416                 :          0 :                 pp->zero = strcmp(arg_str_value(cmd, zero_ARG, "y"), "n");
    1417                 :            : 
    1418         [ #  # ]:          0 :         if (arg_sign_value(cmd, dataalignment_ARG, 0) == SIGN_MINUS) {
    1419                 :          0 :                 log_error("Physical volume data alignment may not be negative");
    1420                 :          0 :                 return 0;
    1421                 :            :         }
    1422                 :          0 :         pp->data_alignment = arg_uint64_value(cmd, dataalignment_ARG, UINT64_C(0));
    1423                 :            : 
    1424         [ #  # ]:          0 :         if (pp->data_alignment > ULONG_MAX) {
    1425                 :          0 :                 log_error("Physical volume data alignment is too big.");
    1426                 :          0 :                 return 0;
    1427                 :            :         }
    1428                 :            : 
    1429 [ #  # ][ #  # ]:          0 :         if (pp->data_alignment && pp->pe_start) {
    1430         [ #  # ]:          0 :                 if (pp->pe_start % pp->data_alignment)
    1431                 :          0 :                         log_warn("WARNING: Ignoring data alignment %" PRIu64
    1432                 :            :                                  " incompatible with --restorefile value (%"
    1433                 :            :                                  PRIu64").", pp->data_alignment, pp->pe_start);
    1434                 :          0 :                 pp->data_alignment = 0;
    1435                 :            :         }
    1436                 :            : 
    1437         [ #  # ]:          0 :         if (arg_sign_value(cmd, dataalignmentoffset_ARG, 0) == SIGN_MINUS) {
    1438                 :          0 :                 log_error("Physical volume data alignment offset may not be negative");
    1439                 :          0 :                 return 0;
    1440                 :            :         }
    1441                 :          0 :         pp->data_alignment_offset = arg_uint64_value(cmd, dataalignmentoffset_ARG, UINT64_C(0));
    1442                 :            : 
    1443         [ #  # ]:          0 :         if (pp->data_alignment_offset > ULONG_MAX) {
    1444                 :          0 :                 log_error("Physical volume data alignment offset is too big.");
    1445                 :          0 :                 return 0;
    1446                 :            :         }
    1447                 :            : 
    1448 [ #  # ][ #  # ]:          0 :         if (pp->data_alignment_offset && pp->pe_start) {
    1449                 :          0 :                 log_warn("WARNING: Ignoring data alignment offset %" PRIu64
    1450                 :            :                          " incompatible with --restorefile value (%"
    1451                 :            :                          PRIu64").", pp->data_alignment_offset, pp->pe_start);
    1452                 :          0 :                 pp->data_alignment_offset = 0;
    1453                 :            :         }
    1454                 :            : 
    1455         [ #  # ]:          0 :         if (arg_sign_value(cmd, metadatasize_ARG, 0) == SIGN_MINUS) {
    1456                 :          0 :                 log_error("Metadata size may not be negative");
    1457                 :          0 :                 return 0;
    1458                 :            :         }
    1459                 :            : 
    1460                 :          0 :         pp->pvmetadatasize = arg_uint64_value(cmd, metadatasize_ARG, UINT64_C(0));
    1461         [ #  # ]:          0 :         if (!pp->pvmetadatasize)
    1462                 :          0 :                 pp->pvmetadatasize = find_config_tree_int(cmd,
    1463                 :            :                                                  "metadata/pvmetadatasize",
    1464                 :            :                                                  DEFAULT_PVMETADATASIZE);
    1465                 :            : 
    1466                 :          0 :         pp->pvmetadatacopies = arg_int_value(cmd, pvmetadatacopies_ARG, -1);
    1467         [ #  # ]:          0 :         if (pp->pvmetadatacopies < 0)
    1468                 :          0 :                 pp->pvmetadatacopies = find_config_tree_int(cmd,
    1469                 :            :                                                    "metadata/pvmetadatacopies",
    1470                 :            :                                                    DEFAULT_PVMETADATACOPIES);
    1471                 :            : 
    1472                 :          0 :         return 1;
    1473                 :            : }
    1474                 :            : 
    1475                 :          0 : int get_activation_monitoring_mode(struct cmd_context *cmd,
    1476                 :            :                                    struct volume_group *vg,
    1477                 :            :                                    int *monitoring_mode)
    1478                 :            : {
    1479                 :          0 :         *monitoring_mode = DEFAULT_DMEVENTD_MONITOR;
    1480                 :            : 
    1481   [ #  #  #  # ]:          0 :         if (arg_count(cmd, monitor_ARG) &&
    1482                 :          0 :             arg_count(cmd, ignoremonitoring_ARG)) {
    1483                 :          0 :                 log_error("Conflicting monitor and ignoremonitoring options");
    1484                 :          0 :                 return 0;
    1485                 :            :         }
    1486                 :            : 
    1487         [ #  # ]:          0 :         if (arg_count(cmd, monitor_ARG))
    1488                 :          0 :                 *monitoring_mode = arg_int_value(cmd, monitor_ARG,
    1489                 :            :                                                  DEFAULT_DMEVENTD_MONITOR);
    1490         [ #  # ]:          0 :         else if (is_static() || arg_count(cmd, ignoremonitoring_ARG) ||
           [ #  #  #  # ]
    1491                 :          0 :                  !find_config_tree_bool(cmd, "activation/monitoring",
    1492                 :            :                                         DEFAULT_DMEVENTD_MONITOR))
    1493                 :          0 :                 *monitoring_mode = DMEVENTD_MONITOR_IGNORE;
    1494                 :            : 
    1495 [ #  # ][ #  # ]:          0 :         if (vg && vg_is_clustered(vg) &&
                 [ #  # ]
    1496                 :          0 :             *monitoring_mode == DMEVENTD_MONITOR_IGNORE) {
    1497         [ #  # ]:          0 :                 log_error("%s is incompatible with clustered Volume Group "
    1498                 :            :                           "\"%s\": Skipping.",
    1499                 :            :                           (arg_count(cmd, ignoremonitoring_ARG) ?
    1500                 :            :                            "--ignoremonitoring" : "activation/monitoring=0"),
    1501                 :            :                           vg->name);
    1502                 :          0 :                 return 0;
    1503                 :            :         }
    1504                 :            :         
    1505                 :          0 :         return 1;
    1506                 :            : }
    1507                 :            : 
    1508                 :            : /*
    1509                 :            :  * Generic stripe parameter checks.
    1510                 :            :  */
    1511                 :          0 : static int _validate_stripe_params(struct cmd_context *cmd, uint32_t *stripes,
    1512                 :            :                                    uint32_t *stripe_size)
    1513                 :            : {
    1514 [ #  # ][ #  # ]:          0 :         if (*stripes == 1 && *stripe_size) {
    1515                 :          0 :                 log_print("Ignoring stripesize argument with single stripe");
    1516                 :          0 :                 *stripe_size = 0;
    1517                 :            :         }
    1518                 :            : 
    1519 [ #  # ][ #  # ]:          0 :         if (*stripes > 1 && !*stripe_size) {
    1520                 :          0 :                 *stripe_size = find_config_tree_int(cmd, "metadata/stripesize", DEFAULT_STRIPESIZE) * 2;
    1521                 :          0 :                 log_print("Using default stripesize %s",
    1522                 :            :                           display_size(cmd, (uint64_t) *stripe_size));
    1523                 :            :         }
    1524                 :            : 
    1525 [ #  # ][ #  # ]:          0 :         if (*stripes < 1 || *stripes > MAX_STRIPES) {
    1526                 :          0 :                 log_error("Number of stripes (%d) must be between %d and %d",
    1527                 :            :                           *stripes, 1, MAX_STRIPES);
    1528                 :          0 :                 return 0;
    1529                 :            :         }
    1530                 :            : 
    1531 [ #  # ][ #  # ]:          0 :         if (*stripes > 1 && (*stripe_size < STRIPE_SIZE_MIN ||
                 [ #  # ]
    1532                 :          0 :                              *stripe_size & (*stripe_size - 1))) {
    1533                 :          0 :                 log_error("Invalid stripe size %s",
    1534                 :            :                           display_size(cmd, (uint64_t) *stripe_size));
    1535                 :          0 :                 return 0;
    1536                 :            :         }
    1537                 :            : 
    1538                 :          0 :         return 1;
    1539                 :            : }
    1540                 :            : 
    1541                 :            : /*
    1542                 :            :  * The stripe size is limited by the size of a uint32_t, but since the
    1543                 :            :  * value given by the user is doubled, and the final result must be a
    1544                 :            :  * power of 2, we must divide UINT_MAX by four and add 1 (to round it
    1545                 :            :  * up to the power of 2)
    1546                 :            :  */
    1547                 :          0 : int get_stripe_params(struct cmd_context *cmd, uint32_t *stripes, uint32_t *stripe_size)
    1548                 :            : {
    1549                 :            :         /* stripes_long_ARG takes precedence (for lvconvert) */
    1550         [ #  # ]:          0 :         *stripes = arg_uint_value(cmd, arg_count(cmd, stripes_long_ARG) ? stripes_long_ARG : stripes_ARG, 1);
    1551                 :            : 
    1552                 :          0 :         *stripe_size = arg_uint_value(cmd, stripesize_ARG, 0);
    1553         [ #  # ]:          0 :         if (*stripe_size) {
    1554         [ #  # ]:          0 :                 if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) {
    1555                 :          0 :                         log_error("Negative stripesize is invalid");
    1556                 :          0 :                         return 0;
    1557                 :            :                 }
    1558                 :            : 
    1559         [ #  # ]:          0 :                 if(*stripe_size > STRIPE_SIZE_LIMIT * 2) {
    1560                 :          0 :                         log_error("Stripe size cannot be larger than %s",
    1561                 :            :                                   display_size(cmd, (uint64_t) STRIPE_SIZE_LIMIT));
    1562                 :          0 :                         return 0;
    1563                 :            :                 }
    1564                 :            :         }
    1565                 :            : 
    1566                 :          0 :         return _validate_stripe_params(cmd, stripes, stripe_size);
    1567                 :            : }
    1568                 :            : 

Generated by: LCOV version 1.8