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