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