xref: /netbsd/external/gpl2/lvm2/dist/tools/toollib.c (revision 7c604eea)
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