lvchange.c revision 1.1.1.2 1 /* $NetBSD: lvchange.c,v 1.1.1.2 2009/02/18 11:17:43 haad Exp $ */
2
3 /*
4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 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
20 static int lvchange_permission(struct cmd_context *cmd,
21 struct logical_volume *lv)
22 {
23 uint32_t lv_access;
24 struct lvinfo info;
25
26 lv_access = arg_uint_value(cmd, permission_ARG, 0);
27
28 if ((lv_access & LVM_WRITE) && (lv->status & LVM_WRITE)) {
29 log_error("Logical volume \"%s\" is already writable",
30 lv->name);
31 return 0;
32 }
33
34 if (!(lv_access & LVM_WRITE) && !(lv->status & LVM_WRITE)) {
35 log_error("Logical volume \"%s\" is already read only",
36 lv->name);
37 return 0;
38 }
39
40 if ((lv->status & MIRRORED) && (vg_is_clustered(lv->vg)) &&
41 lv_info(cmd, lv, &info, 0, 0) && info.exists) {
42 log_error("Cannot change permissions of mirror \"%s\" "
43 "while active.", lv->name);
44 return 0;
45 }
46
47 if (lv_access & LVM_WRITE) {
48 lv->status |= LVM_WRITE;
49 log_verbose("Setting logical volume \"%s\" read/write",
50 lv->name);
51 } else {
52 lv->status &= ~LVM_WRITE;
53 log_verbose("Setting logical volume \"%s\" read-only",
54 lv->name);
55 }
56
57 log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
58 if (!vg_write(lv->vg))
59 return_0;
60
61 backup(lv->vg);
62
63 if (!suspend_lv(cmd, lv)) {
64 log_error("Failed to lock %s", lv->name);
65 vg_revert(lv->vg);
66 return 0;
67 }
68
69 if (!vg_commit(lv->vg)) {
70 resume_lv(cmd, lv);
71 return 0;
72 }
73
74 log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name);
75 if (!resume_lv(cmd, lv)) {
76 log_error("Problem reactivating %s", lv->name);
77 return 0;
78 }
79
80 return 1;
81 }
82
83 static int lvchange_monitoring(struct cmd_context *cmd,
84 struct logical_volume *lv)
85 {
86 struct lvinfo info;
87
88 if (!lv_info(cmd, lv, &info, 0, 0) || !info.exists) {
89 log_error("Logical volume, %s, is not active", lv->name);
90 return 0;
91 }
92
93 /* do not monitor pvmove lv's */
94 if (lv->status & PVMOVE)
95 return 1;
96
97 if ((dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) &&
98 !monitor_dev_for_events(cmd, lv, dmeventd_monitor_mode()))
99 stack;
100
101 return 1;
102 }
103
104 static int lvchange_availability(struct cmd_context *cmd,
105 struct logical_volume *lv)
106 {
107 int activate;
108 const char *pvname;
109 char *lv_full_name;
110 uint32_t len;
111
112 activate = arg_uint_value(cmd, available_ARG, 0);
113
114 if (activate == CHANGE_ALN) {
115 log_verbose("Deactivating logical volume \"%s\" locally",
116 lv->name);
117 if (!deactivate_lv_local(cmd, lv))
118 return_0;
119 } else if (activate == CHANGE_AN) {
120 log_verbose("Deactivating logical volume \"%s\"", lv->name);
121 if (!deactivate_lv(cmd, lv))
122 return_0;
123 } else {
124 if (lockingfailed() && (vg_is_clustered(lv->vg))) {
125 log_verbose("Locking failed: ignoring clustered "
126 "logical volume %s", lv->name);
127 return 0;
128 }
129
130 if (lv_is_origin(lv) || (activate == CHANGE_AE)) {
131 log_verbose("Activating logical volume \"%s\" "
132 "exclusively", lv->name);
133 if (!activate_lv_excl(cmd, lv))
134 return_0;
135 } else if (activate == CHANGE_ALY) {
136 log_verbose("Activating logical volume \"%s\" locally",
137 lv->name);
138 if (!activate_lv_local(cmd, lv))
139 return_0;
140 } else {
141 log_verbose("Activating logical volume \"%s\"",
142 lv->name);
143 if (!activate_lv(cmd, lv))
144 return_0;
145 }
146
147 if ((lv->status & LOCKED) &&
148 (pvname = get_pvmove_pvname_from_lv(lv))) {
149 log_verbose("Spawning background pvmove process for %s",
150 pvname);
151 pvmove_poll(cmd, pvname, 1);
152 }
153
154 if (lv->status & CONVERTING) {
155 len = strlen(lv->vg->name) + strlen(lv->name) + 2;
156 if (!(lv_full_name = alloca(len)))
157 return_0;
158 if (!dm_snprintf(lv_full_name, len, "%s/%s",
159 lv->vg->name, lv->name))
160 return_0;
161 log_verbose("Spawning background lvconvert process for %s",
162 lv->name);
163 lvconvert_poll(cmd, lv_full_name, 1);
164 }
165 }
166
167 return 1;
168 }
169
170 static int lvchange_refresh(struct cmd_context *cmd, struct logical_volume *lv)
171 {
172 log_verbose("Refreshing logical volume \"%s\" (if active)", lv->name);
173 return lv_refresh(cmd, lv);
174 }
175
176 static int lvchange_resync(struct cmd_context *cmd,
177 struct logical_volume *lv)
178 {
179 int active = 0;
180 int monitored;
181 struct lvinfo info;
182 struct logical_volume *log_lv;
183
184 if (!(lv->status & MIRRORED)) {
185 log_error("Unable to resync %s because it is not mirrored.",
186 lv->name);
187 return 1;
188 }
189
190 if (lv->status & PVMOVE) {
191 log_error("Unable to resync pvmove volume %s", lv->name);
192 return 0;
193 }
194
195 if (lv->status & LOCKED) {
196 log_error("Unable to resync locked volume %s", lv->name);
197 return 0;
198 }
199
200 if (lv_info(cmd, lv, &info, 1, 0)) {
201 if (info.open_count) {
202 log_error("Can't resync open logical volume \"%s\"",
203 lv->name);
204 return ECMD_FAILED;
205 }
206
207 if (info.exists) {
208 if (!arg_count(cmd, yes_ARG) &&
209 yes_no_prompt("Do you really want to deactivate "
210 "logical volume %s to resync it? [y/n]: ",
211 lv->name) == 'n') {
212 log_print("Logical volume \"%s\" not resynced",
213 lv->name);
214 return ECMD_FAILED;
215 }
216
217 if (sigint_caught())
218 return ECMD_FAILED;
219
220 active = 1;
221 }
222 }
223
224 /* Activate exclusively to ensure no nodes still have LV active */
225 monitored = dmeventd_monitor_mode();
226 init_dmeventd_monitor(0);
227
228 if (vg_is_clustered(lv->vg) && !activate_lv_excl(cmd, lv)) {
229 log_error("Can't get exclusive access to clustered volume %s",
230 lv->name);
231 return ECMD_FAILED;
232 }
233
234 if (!deactivate_lv(cmd, lv)) {
235 log_error("Unable to deactivate %s for resync", lv->name);
236 return 0;
237 }
238
239 init_dmeventd_monitor(monitored);
240
241 log_lv = first_seg(lv)->log_lv;
242
243 log_very_verbose("Starting resync of %s%s%s mirror \"%s\"",
244 (active) ? "active " : "",
245 vg_is_clustered(lv->vg) ? "clustered " : "",
246 (log_lv) ? "disk-logged" : "core-logged",
247 lv->name);
248
249 /*
250 * If this mirror has a core log (i.e. !log_lv),
251 * then simply deactivating/activating will cause
252 * it to reset the sync status. We only need to
253 * worry about persistent logs.
254 */
255 if (!log_lv && !(lv->status & MIRROR_NOTSYNCED)) {
256 if (active && !activate_lv(cmd, lv)) {
257 log_error("Failed to reactivate %s to resynchronize "
258 "mirror", lv->name);
259 return 0;
260 }
261 return 1;
262 }
263
264 lv->status &= ~MIRROR_NOTSYNCED;
265
266 if (log_lv) {
267 /* Separate mirror log so we can clear it */
268 detach_mirror_log(first_seg(lv));
269
270 if (!vg_write(lv->vg)) {
271 log_error("Failed to write intermediate VG metadata.");
272 if (!attach_mirror_log(first_seg(lv), log_lv))
273 stack;
274 if (active && !activate_lv(cmd, lv))
275 stack;
276 return 0;
277 }
278
279 backup(lv->vg);
280
281 if (!vg_commit(lv->vg)) {
282 log_error("Failed to commit intermediate VG metadata.");
283 if (!attach_mirror_log(first_seg(lv), log_lv))
284 stack;
285 if (active && !activate_lv(cmd, lv))
286 stack;
287 return 0;
288 }
289
290 if (!activate_lv(cmd, log_lv)) {
291 log_error("Unable to activate %s for mirror log resync",
292 log_lv->name);
293 return 0;
294 }
295
296 log_very_verbose("Clearing log device %s", log_lv->name);
297 if (!set_lv(cmd, log_lv, log_lv->size, 0)) {
298 log_error("Unable to reset sync status for %s", lv->name);
299 if (!deactivate_lv(cmd, log_lv))
300 log_error("Failed to deactivate log LV after "
301 "wiping failed");
302 return 0;
303 }
304
305 if (!deactivate_lv(cmd, log_lv)) {
306 log_error("Unable to deactivate log LV %s after wiping "
307 "for resync", log_lv->name);
308 return 0;
309 }
310
311 /* Put mirror log back in place */
312 if (!attach_mirror_log(first_seg(lv), log_lv))
313 stack;
314 }
315
316 log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
317 if (!vg_write(lv->vg) || !vg_commit(lv->vg)) {
318 log_error("Failed to update metadata on disk.");
319 return 0;
320 }
321
322 if (active && !activate_lv(cmd, lv)) {
323 log_error("Failed to reactivate %s after resync", lv->name);
324 return 0;
325 }
326
327 return 1;
328 }
329
330 static int lvchange_alloc(struct cmd_context *cmd, struct logical_volume *lv)
331 {
332 int want_contiguous = 0;
333 alloc_policy_t alloc;
334
335 want_contiguous = strcmp(arg_str_value(cmd, contiguous_ARG, "n"), "n");
336 alloc = want_contiguous ? ALLOC_CONTIGUOUS : ALLOC_INHERIT;
337 alloc = arg_uint_value(cmd, alloc_ARG, alloc);
338
339 if (alloc == lv->alloc) {
340 log_error("Allocation policy of logical volume \"%s\" is "
341 "already %s", lv->name, get_alloc_string(alloc));
342 return 0;
343 }
344
345 lv->alloc = alloc;
346
347 /* FIXME If contiguous, check existing extents already are */
348
349 log_verbose("Setting contiguous allocation policy for \"%s\" to %s",
350 lv->name, get_alloc_string(alloc));
351
352 log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
353
354 if (!vg_write(lv->vg))
355 return_0;
356
357 backup(lv->vg);
358
359 /* No need to suspend LV for this change */
360 if (!vg_commit(lv->vg))
361 return_0;
362
363 return 1;
364 }
365
366 static int lvchange_readahead(struct cmd_context *cmd,
367 struct logical_volume *lv)
368 {
369 unsigned read_ahead = 0;
370 unsigned pagesize = (unsigned) lvm_getpagesize() >> SECTOR_SHIFT;
371
372 read_ahead = arg_uint_value(cmd, readahead_ARG, 0);
373
374 if (read_ahead != DM_READ_AHEAD_AUTO &&
375 (lv->vg->fid->fmt->features & FMT_RESTRICTED_READAHEAD) &&
376 (read_ahead < 2 || read_ahead > 120)) {
377 log_error("Metadata only supports readahead values between 2 and 120.");
378 return 0;
379 }
380
381 if (read_ahead != DM_READ_AHEAD_AUTO &&
382 read_ahead != DM_READ_AHEAD_NONE && read_ahead % pagesize) {
383 read_ahead = (read_ahead / pagesize) * pagesize;
384 log_verbose("Rounding down readahead to %u sectors, a multiple "
385 "of page size %u.", read_ahead, pagesize);
386 }
387
388 if (lv->read_ahead == read_ahead) {
389 if (read_ahead == DM_READ_AHEAD_AUTO)
390 log_error("Read ahead is already auto for \"%s\"", lv->name);
391 else
392 log_error("Read ahead is already %u for \"%s\"",
393 read_ahead, lv->name);
394 return 0;
395 }
396
397 lv->read_ahead = read_ahead;
398
399 log_verbose("Setting read ahead to %u for \"%s\"", read_ahead,
400 lv->name);
401
402 log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
403 if (!vg_write(lv->vg))
404 return_0;
405
406 backup(lv->vg);
407
408 if (!suspend_lv(cmd, lv)) {
409 log_error("Failed to lock %s", lv->name);
410 vg_revert(lv->vg);
411 return 0;
412 }
413
414 if (!vg_commit(lv->vg)) {
415 resume_lv(cmd, lv);
416 return 0;
417 }
418
419 log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name);
420 if (!resume_lv(cmd, lv)) {
421 log_error("Problem reactivating %s", lv->name);
422 return 0;
423 }
424
425 return 1;
426 }
427
428 static int lvchange_persistent(struct cmd_context *cmd,
429 struct logical_volume *lv)
430 {
431 struct lvinfo info;
432 int active = 0;
433
434 if (!strcmp(arg_str_value(cmd, persistent_ARG, "n"), "n")) {
435 if (!(lv->status & FIXED_MINOR)) {
436 log_error("Minor number is already not persistent "
437 "for \"%s\"", lv->name);
438 return 0;
439 }
440 lv->status &= ~FIXED_MINOR;
441 lv->minor = -1;
442 lv->major = -1;
443 log_verbose("Disabling persistent device number for \"%s\"",
444 lv->name);
445 } else {
446 if (!arg_count(cmd, minor_ARG) && lv->minor < 0) {
447 log_error("Minor number must be specified with -My");
448 return 0;
449 }
450 if (!arg_count(cmd, major_ARG) && lv->major < 0) {
451 log_error("Major number must be specified with -My");
452 return 0;
453 }
454 if (lv_info(cmd, lv, &info, 0, 0) && info.exists)
455 active = 1;
456 if (active && !arg_count(cmd, force_ARG) &&
457 yes_no_prompt("Logical volume %s will be "
458 "deactivated temporarily. "
459 "Continue? [y/n]: ", lv->name) == 'n') {
460 log_print("%s device number not changed.",
461 lv->name);
462 return 0;
463 }
464
465 if (sigint_caught())
466 return 0;
467
468 log_verbose("Ensuring %s is inactive.", lv->name);
469 if (!deactivate_lv(cmd, lv)) {
470 log_error("%s: deactivation failed", lv->name);
471 return 0;
472 }
473 lv->status |= FIXED_MINOR;
474 lv->minor = arg_int_value(cmd, minor_ARG, lv->minor);
475 lv->major = arg_int_value(cmd, major_ARG, lv->major);
476 log_verbose("Setting persistent device number to (%d, %d) "
477 "for \"%s\"", lv->major, lv->minor, lv->name);
478
479 }
480
481 log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
482 if (!vg_write(lv->vg))
483 return_0;
484
485 backup(lv->vg);
486
487 if (!vg_commit(lv->vg))
488 return_0;
489
490 if (active) {
491 log_verbose("Re-activating logical volume \"%s\"", lv->name);
492 if (!activate_lv(cmd, lv)) {
493 log_error("%s: reactivation failed", lv->name);
494 return 0;
495 }
496 }
497
498 return 1;
499 }
500
501 static int lvchange_tag(struct cmd_context *cmd, struct logical_volume *lv,
502 int arg)
503 {
504 const char *tag;
505
506 if (!(tag = arg_str_value(cmd, arg, NULL))) {
507 log_error("Failed to get tag");
508 return 0;
509 }
510
511 if (!(lv->vg->fid->fmt->features & FMT_TAGS)) {
512 log_error("Logical volume %s/%s does not support tags",
513 lv->vg->name, lv->name);
514 return 0;
515 }
516
517 if ((arg == addtag_ARG)) {
518 if (!str_list_add(cmd->mem, &lv->tags, tag)) {
519 log_error("Failed to add tag %s to %s/%s",
520 tag, lv->vg->name, lv->name);
521 return 0;
522 }
523 } else {
524 if (!str_list_del(&lv->tags, tag)) {
525 log_error("Failed to remove tag %s from %s/%s",
526 tag, lv->vg->name, lv->name);
527 return 0;
528 }
529 }
530
531 log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
532 if (!vg_write(lv->vg))
533 return_0;
534
535 backup(lv->vg);
536
537 /* No need to suspend LV for this change */
538 if (!vg_commit(lv->vg))
539 return_0;
540
541 return 1;
542 }
543
544 static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
545 void *handle __attribute((unused)))
546 {
547 int doit = 0, docmds = 0;
548 int archived = 0;
549
550 if (!(lv->vg->status & LVM_WRITE) &&
551 (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
552 arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG) ||
553 arg_count(cmd, alloc_ARG))) {
554 log_error("Only -a permitted with read-only volume "
555 "group \"%s\"", lv->vg->name);
556 return EINVALID_CMD_LINE;
557 }
558
559 if (lv_is_origin(lv) &&
560 (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
561 arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG) ||
562 arg_count(cmd, alloc_ARG))) {
563 log_error("Can't change logical volume \"%s\" under snapshot",
564 lv->name);
565 return ECMD_FAILED;
566 }
567
568 if (lv_is_cow(lv)) {
569 log_error("Can't change snapshot logical volume \"%s\"",
570 lv->name);
571 return ECMD_FAILED;
572 }
573
574 if (lv->status & PVMOVE) {
575 log_error("Unable to change pvmove LV %s", lv->name);
576 if (arg_count(cmd, available_ARG))
577 log_error("Use 'pvmove --abort' to abandon a pvmove");
578 return ECMD_FAILED;
579 }
580
581 if (lv->status & MIRROR_LOG) {
582 log_error("Unable to change mirror log LV %s directly", lv->name);
583 return ECMD_FAILED;
584 }
585
586 if (lv->status & MIRROR_IMAGE) {
587 log_error("Unable to change mirror image LV %s directly",
588 lv->name);
589 return ECMD_FAILED;
590 }
591
592 if (!(lv_is_displayable(lv))) {
593 log_error("Unable to change internal LV %s directly",
594 lv->name);
595 return ECMD_FAILED;
596 }
597
598 init_dmeventd_monitor(arg_int_value(cmd, monitor_ARG,
599 (is_static() || arg_count(cmd, ignoremonitoring_ARG)) ?
600 DMEVENTD_MONITOR_IGNORE : DEFAULT_DMEVENTD_MONITOR));
601
602 /* access permission change */
603 if (arg_count(cmd, permission_ARG)) {
604 if (!archive(lv->vg))
605 return ECMD_FAILED;
606 archived = 1;
607 doit += lvchange_permission(cmd, lv);
608 docmds++;
609 }
610
611 /* allocation policy change */
612 if (arg_count(cmd, contiguous_ARG) || arg_count(cmd, alloc_ARG)) {
613 if (!archived && !archive(lv->vg))
614 return ECMD_FAILED;
615 archived = 1;
616 doit += lvchange_alloc(cmd, lv);
617 docmds++;
618 }
619
620 /* read ahead sector change */
621 if (arg_count(cmd, readahead_ARG)) {
622 if (!archived && !archive(lv->vg))
623 return ECMD_FAILED;
624 archived = 1;
625 doit += lvchange_readahead(cmd, lv);
626 docmds++;
627 }
628
629 /* read ahead sector change */
630 if (arg_count(cmd, persistent_ARG)) {
631 if (!archived && !archive(lv->vg))
632 return ECMD_FAILED;
633 archived = 1;
634 doit += lvchange_persistent(cmd, lv);
635 docmds++;
636 if (sigint_caught())
637 return ECMD_FAILED;
638 }
639
640 /* add tag */
641 if (arg_count(cmd, addtag_ARG)) {
642 if (!archived && !archive(lv->vg))
643 return ECMD_FAILED;
644 archived = 1;
645 doit += lvchange_tag(cmd, lv, addtag_ARG);
646 docmds++;
647 }
648
649 /* del tag */
650 if (arg_count(cmd, deltag_ARG)) {
651 if (!archived && !archive(lv->vg))
652 return ECMD_FAILED;
653 archived = 1;
654 doit += lvchange_tag(cmd, lv, deltag_ARG);
655 docmds++;
656 }
657
658 if (doit)
659 log_print("Logical volume \"%s\" changed", lv->name);
660
661 if (arg_count(cmd, resync_ARG))
662 if (!lvchange_resync(cmd, lv))
663 return ECMD_FAILED;
664
665 /* availability change */
666 if (arg_count(cmd, available_ARG)) {
667 if (!lvchange_availability(cmd, lv))
668 return ECMD_FAILED;
669 }
670
671 if (arg_count(cmd, refresh_ARG))
672 if (!lvchange_refresh(cmd, lv))
673 return ECMD_FAILED;
674
675 if (!arg_count(cmd, available_ARG) &&
676 !arg_count(cmd, refresh_ARG) &&
677 arg_count(cmd, monitor_ARG)) {
678 if (!lvchange_monitoring(cmd, lv))
679 return ECMD_FAILED;
680 }
681
682 if (doit != docmds)
683 return ECMD_FAILED;
684
685 return ECMD_PROCESSED;
686 }
687
688 int lvchange(struct cmd_context *cmd, int argc, char **argv)
689 {
690 if (!arg_count(cmd, available_ARG) && !arg_count(cmd, contiguous_ARG)
691 && !arg_count(cmd, permission_ARG) && !arg_count(cmd, readahead_ARG)
692 && !arg_count(cmd, minor_ARG) && !arg_count(cmd, major_ARG)
693 && !arg_count(cmd, persistent_ARG) && !arg_count(cmd, addtag_ARG)
694 && !arg_count(cmd, deltag_ARG) && !arg_count(cmd, refresh_ARG)
695 && !arg_count(cmd, alloc_ARG) && !arg_count(cmd, monitor_ARG)
696 && !arg_count(cmd, resync_ARG)) {
697 log_error("Need 1 or more of -a, -C, -j, -m, -M, -p, -r, "
698 "--resync, --refresh, --alloc, --addtag, --deltag "
699 "or --monitor");
700 return EINVALID_CMD_LINE;
701 }
702
703 if (arg_count(cmd, ignorelockingfailure_ARG) &&
704 (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
705 arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG) ||
706 arg_count(cmd, addtag_ARG) || arg_count(cmd, deltag_ARG) ||
707 arg_count(cmd, refresh_ARG) || arg_count(cmd, alloc_ARG))) {
708 log_error("Only -a permitted with --ignorelockingfailure");
709 return EINVALID_CMD_LINE;
710 }
711
712 if (!argc) {
713 log_error("Please give logical volume path(s)");
714 return EINVALID_CMD_LINE;
715 }
716
717 if ((arg_count(cmd, minor_ARG) || arg_count(cmd, major_ARG)) &&
718 !arg_count(cmd, persistent_ARG)) {
719 log_error("--major and --minor require -My");
720 return EINVALID_CMD_LINE;
721 }
722
723 if (arg_count(cmd, minor_ARG) && argc != 1) {
724 log_error("Only give one logical volume when specifying minor");
725 return EINVALID_CMD_LINE;
726 }
727
728 if (arg_count(cmd, contiguous_ARG) && arg_count(cmd, alloc_ARG)) {
729 log_error("Only one of --alloc and --contiguous permitted");
730 return EINVALID_CMD_LINE;
731 }
732
733 return process_each_lv(cmd, argc, argv, LCK_VG_WRITE, NULL,
734 &lvchange_single);
735 }
736