Initial import of binutils 2.22 on the new vendor branch
[dragonfly.git] / contrib / lvm2 / dist / tools / vgchange.c
1 /*      $NetBSD: vgchange.c,v 1.1.1.3 2009/12/02 00:25:51 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 _monitor_lvs_in_vg(struct cmd_context *cmd,
21                                struct volume_group *vg, int reg)
22 {
23         struct lv_list *lvl;
24         struct logical_volume *lv;
25         struct lvinfo info;
26         int lv_active;
27         int count = 0;
28
29         dm_list_iterate_items(lvl, &vg->lvs) {
30                 lv = lvl->lv;
31
32                 if (!lv_info(cmd, lv, &info, 0, 0))
33                         lv_active = 0;
34                 else
35                         lv_active = info.exists;
36
37                 /*
38                  * FIXME: Need to consider all cases... PVMOVE, etc
39                  */
40                 if ((lv->status & PVMOVE) || !lv_active)
41                         continue;
42
43                 if (!monitor_dev_for_events(cmd, lv, reg)) {
44                         continue;
45                 } else
46                         count++;
47         }
48
49         /*
50          * returns the number of _new_ monitored devices
51          */
52
53         return count;
54 }
55
56 static int _activate_lvs_in_vg(struct cmd_context *cmd,
57                                struct volume_group *vg, int activate)
58 {
59         struct lv_list *lvl;
60         struct logical_volume *lv;
61         int count = 0, expected_count = 0;
62
63         dm_list_iterate_items(lvl, &vg->lvs) {
64                 lv = lvl->lv;
65
66                 if (!lv_is_visible(lv))
67                         continue;
68
69                 /* Only request activation of snapshot origin devices */
70                 if ((lv->status & SNAPSHOT) || lv_is_cow(lv))
71                         continue;
72
73                 /* Only request activation of mirror LV */
74                 if ((lv->status & MIRROR_IMAGE) || (lv->status & MIRROR_LOG))
75                         continue;
76
77                 /* Can't deactivate a pvmove LV */
78                 /* FIXME There needs to be a controlled way of doing this */
79                 if (((activate == CHANGE_AN) || (activate == CHANGE_ALN)) &&
80                     ((lv->status & PVMOVE) ))
81                         continue;
82
83                 expected_count++;
84
85                 if (activate == CHANGE_AN) {
86                         if (!deactivate_lv(cmd, lv))
87                                 continue;
88                 } else if (activate == CHANGE_ALN) {
89                         if (!deactivate_lv_local(cmd, lv))
90                                 continue;
91                 } else if (lv_is_origin(lv) || (activate == CHANGE_AE)) {
92                         if (!activate_lv_excl(cmd, lv))
93                                 continue;
94                 } else if (activate == CHANGE_ALY) {
95                         if (!activate_lv_local(cmd, lv))
96                                 continue;
97                 } else if (!activate_lv(cmd, lv))
98                         continue;
99
100                 if (activate != CHANGE_AN && activate != CHANGE_ALN &&
101                     (lv->status & (PVMOVE|CONVERTING)))
102                         lv_spawn_background_polling(cmd, lv);
103
104                 count++;
105         }
106
107         if (expected_count)
108                 log_verbose("%s %d logical volumes in volume group %s",
109                             activate ? "Activated" : "Deactivated",
110                             count, vg->name);
111
112         return (expected_count != count) ? ECMD_FAILED : ECMD_PROCESSED;
113 }
114
115 static int _vgchange_monitoring(struct cmd_context *cmd, struct volume_group *vg)
116 {
117         int active, monitored;
118
119         if ((active = lvs_in_vg_activated(vg)) &&
120             dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) {
121                 monitored = _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode());
122                 log_print("%d logical volume(s) in volume group "
123                             "\"%s\" %smonitored",
124                             monitored, vg->name, (dmeventd_monitor_mode()) ? "" : "un");
125         }
126
127         return ECMD_PROCESSED;
128 }
129
130 static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
131 {
132         int lv_open, active, monitored;
133         int available, ret;
134         int activate = 1;
135
136         /*
137          * Safe, since we never write out new metadata here. Required for
138          * partial activation to work.
139          */
140         cmd->handles_missing_pvs = 1;
141
142         available = arg_uint_value(cmd, available_ARG, 0);
143
144         if ((available == CHANGE_AN) || (available == CHANGE_ALN))
145                 activate = 0;
146
147         /* FIXME: Force argument to deactivate them? */
148         if (!activate && (lv_open = lvs_in_vg_opened(vg))) {
149                 log_error("Can't deactivate volume group \"%s\" with %d open "
150                           "logical volume(s)", vg->name, lv_open);
151                 return ECMD_FAILED;
152         }
153
154         /* FIXME Move into library where clvmd can use it */
155         if (activate)
156                 check_current_backup(vg);
157
158         if (activate && (active = lvs_in_vg_activated(vg))) {
159                 log_verbose("%d logical volume(s) in volume group \"%s\" "
160                             "already active", active, vg->name);
161                 if (dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) {
162                         monitored = _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode());
163                         log_verbose("%d existing logical volume(s) in volume "
164                                     "group \"%s\" %smonitored",
165                                     monitored, vg->name,
166                                     dmeventd_monitor_mode() ? "" : "un");
167                 }
168         }
169
170         ret = _activate_lvs_in_vg(cmd, vg, available);
171
172         log_print("%d logical volume(s) in volume group \"%s\" now active",
173                   lvs_in_vg_activated(vg), vg->name);
174         return ret;
175 }
176
177 static int _vgchange_alloc(struct cmd_context *cmd, struct volume_group *vg)
178 {
179         alloc_policy_t alloc;
180
181         alloc = arg_uint_value(cmd, alloc_ARG, ALLOC_NORMAL);
182
183         if (!archive(vg)) {
184                 stack;
185                 return ECMD_FAILED;
186         }
187
188         /* FIXME: make consistent with vg_set_alloc_policy() */
189         if (alloc == vg->alloc) {
190                 log_error("Volume group allocation policy is already %s",
191                           get_alloc_string(vg->alloc));
192                 return ECMD_FAILED;
193         }
194         if (!vg_set_alloc_policy(vg, alloc)) {
195                 stack;
196                 return ECMD_FAILED;
197         }
198
199         if (!vg_write(vg) || !vg_commit(vg)) {
200                 stack;
201                 return ECMD_FAILED;
202         }
203
204         backup(vg);
205
206         log_print("Volume group \"%s\" successfully changed", vg->name);
207
208         return ECMD_PROCESSED;
209 }
210
211 static int _vgchange_resizeable(struct cmd_context *cmd,
212                                 struct volume_group *vg)
213 {
214         int resizeable = !strcmp(arg_str_value(cmd, resizeable_ARG, "n"), "y");
215
216         if (resizeable && vg_is_resizeable(vg)) {
217                 log_error("Volume group \"%s\" is already resizeable",
218                           vg->name);
219                 return ECMD_FAILED;
220         }
221
222         if (!resizeable && !vg_is_resizeable(vg)) {
223                 log_error("Volume group \"%s\" is already not resizeable",
224                           vg->name);
225                 return ECMD_FAILED;
226         }
227
228         if (!archive(vg)) {
229                 stack;
230                 return ECMD_FAILED;
231         }
232
233         if (resizeable)
234                 vg->status |= RESIZEABLE_VG;
235         else
236                 vg->status &= ~RESIZEABLE_VG;
237
238         if (!vg_write(vg) || !vg_commit(vg)) {
239                 stack;
240                 return ECMD_FAILED;
241         }
242
243         backup(vg);
244
245         log_print("Volume group \"%s\" successfully changed", vg->name);
246
247         return ECMD_PROCESSED;
248 }
249
250 static int _vgchange_clustered(struct cmd_context *cmd,
251                                struct volume_group *vg)
252 {
253         int clustered = !strcmp(arg_str_value(cmd, clustered_ARG, "n"), "y");
254
255         if (clustered && (vg_is_clustered(vg))) {
256                 log_error("Volume group \"%s\" is already clustered",
257                           vg->name);
258                 return ECMD_FAILED;
259         }
260
261         if (!clustered && !(vg_is_clustered(vg))) {
262                 log_error("Volume group \"%s\" is already not clustered",
263                           vg->name);
264                 return ECMD_FAILED;
265         }
266
267         if (!archive(vg)) {
268                 stack;
269                 return ECMD_FAILED;
270         }
271
272         if (!vg_set_clustered(vg, clustered))
273                 return ECMD_FAILED;
274
275         if (!vg_write(vg) || !vg_commit(vg)) {
276                 stack;
277                 return ECMD_FAILED;
278         }
279
280         backup(vg);
281
282         log_print("Volume group \"%s\" successfully changed", vg->name);
283
284         return ECMD_PROCESSED;
285 }
286
287 static int _vgchange_logicalvolume(struct cmd_context *cmd,
288                                    struct volume_group *vg)
289 {
290         uint32_t max_lv = arg_uint_value(cmd, logicalvolume_ARG, 0);
291
292         if (!archive(vg)) {
293                 stack;
294                 return ECMD_FAILED;
295         }
296
297         if (!vg_set_max_lv(vg, max_lv)) {
298                 stack;
299                 return ECMD_FAILED;
300         }
301
302         if (!vg_write(vg) || !vg_commit(vg)) {
303                 stack;
304                 return ECMD_FAILED;
305         }
306
307         backup(vg);
308
309         log_print("Volume group \"%s\" successfully changed", vg->name);
310
311         return ECMD_PROCESSED;
312 }
313
314 static int _vgchange_physicalvolumes(struct cmd_context *cmd,
315                                      struct volume_group *vg)
316 {
317         uint32_t max_pv = arg_uint_value(cmd, maxphysicalvolumes_ARG, 0);
318
319         if (arg_sign_value(cmd, maxphysicalvolumes_ARG, 0) == SIGN_MINUS) {
320                 log_error("MaxPhysicalVolumes may not be negative");
321                 return EINVALID_CMD_LINE;
322         }
323
324         if (!archive(vg)) {
325                 stack;
326                 return ECMD_FAILED;
327         }
328
329         if (!vg_set_max_pv(vg, max_pv)) {
330                 stack;
331                 return ECMD_FAILED;
332         }
333
334         if (!vg_write(vg) || !vg_commit(vg)) {
335                 stack;
336                 return ECMD_FAILED;
337         }
338
339         backup(vg);
340
341         log_print("Volume group \"%s\" successfully changed", vg->name);
342
343         return ECMD_PROCESSED;
344 }
345
346 static int _vgchange_pesize(struct cmd_context *cmd, struct volume_group *vg)
347 {
348         uint32_t extent_size;
349
350         if (arg_sign_value(cmd, physicalextentsize_ARG, 0) == SIGN_MINUS) {
351                 log_error("Physical extent size may not be negative");
352                 return EINVALID_CMD_LINE;
353         }
354
355         extent_size = arg_uint_value(cmd, physicalextentsize_ARG, 0);
356         /* FIXME: remove check - redundant with vg_change_pesize */
357         if (extent_size == vg->extent_size) {
358                 log_error("Physical extent size of VG %s is already %s",
359                           vg->name, display_size(cmd, (uint64_t) extent_size));
360                 return ECMD_PROCESSED;
361         }
362
363         if (!archive(vg)) {
364                 stack;
365                 return ECMD_FAILED;
366         }
367
368         if (!vg_set_extent_size(vg, extent_size)) {
369                 stack;
370                 return EINVALID_CMD_LINE;
371         }
372
373         if (!vg_write(vg) || !vg_commit(vg)) {
374                 stack;
375                 return ECMD_FAILED;
376         }
377
378         backup(vg);
379
380         log_print("Volume group \"%s\" successfully changed", vg->name);
381
382         return ECMD_PROCESSED;
383 }
384
385 static int _vgchange_tag(struct cmd_context *cmd, struct volume_group *vg,
386                          int arg)
387 {
388         const char *tag;
389
390         if (!(tag = arg_str_value(cmd, arg, NULL))) {
391                 log_error("Failed to get tag");
392                 return ECMD_FAILED;
393         }
394
395         if (!(vg->fid->fmt->features & FMT_TAGS)) {
396                 log_error("Volume group %s does not support tags", vg->name);
397                 return ECMD_FAILED;
398         }
399
400         if (!archive(vg)) {
401                 stack;
402                 return ECMD_FAILED;
403         }
404
405         if ((arg == addtag_ARG)) {
406                 if (!str_list_add(cmd->mem, &vg->tags, tag)) {
407                         log_error("Failed to add tag %s to volume group %s",
408                                   tag, vg->name);
409                         return ECMD_FAILED;
410                 }
411         } else {
412                 if (!str_list_del(&vg->tags, tag)) {
413                         log_error("Failed to remove tag %s from volume group "
414                                   "%s", tag, vg->name);
415                         return ECMD_FAILED;
416                 }
417         }
418
419         if (!vg_write(vg) || !vg_commit(vg)) {
420                 stack;
421                 return ECMD_FAILED;
422         }
423
424         backup(vg);
425
426         log_print("Volume group \"%s\" successfully changed", vg->name);
427
428         return ECMD_PROCESSED;
429 }
430
431 static int _vgchange_uuid(struct cmd_context *cmd __attribute((unused)),
432                           struct volume_group *vg)
433 {
434         struct lv_list *lvl;
435
436         if (lvs_in_vg_activated(vg)) {
437                 log_error("Volume group has active logical volumes");
438                 return ECMD_FAILED;
439         }
440
441         if (!archive(vg)) {
442                 stack;
443                 return ECMD_FAILED;
444         }
445
446         if (!id_create(&vg->id)) {
447                 log_error("Failed to generate new random UUID for VG %s.",
448                           vg->name);
449                 return ECMD_FAILED;
450         }
451
452         dm_list_iterate_items(lvl, &vg->lvs) {
453                 memcpy(&lvl->lv->lvid, &vg->id, sizeof(vg->id));
454         }
455
456         if (!vg_write(vg) || !vg_commit(vg)) {
457                 stack;
458                 return ECMD_FAILED;
459         }
460
461         backup(vg);
462
463         log_print("Volume group \"%s\" successfully changed", vg->name);
464
465         return ECMD_PROCESSED;
466 }
467
468 static int _vgchange_refresh(struct cmd_context *cmd, struct volume_group *vg)
469 {
470         log_verbose("Refreshing volume group \"%s\"", vg->name);
471
472         if (!vg_refresh_visible(cmd, vg)) {
473                 stack;
474                 return ECMD_FAILED;
475         }
476
477         return ECMD_PROCESSED;
478 }
479
480 static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
481                            struct volume_group *vg,
482                            void *handle __attribute((unused)))
483 {
484         int r = ECMD_FAILED;
485
486         if (vg_is_exported(vg)) {
487                 log_error("Volume group \"%s\" is exported", vg_name);
488                 return ECMD_FAILED;
489         }
490
491         init_dmeventd_monitor(arg_int_value(cmd, monitor_ARG,
492                                             (is_static() || arg_count(cmd, ignoremonitoring_ARG)) ?
493                                             DMEVENTD_MONITOR_IGNORE : DEFAULT_DMEVENTD_MONITOR));
494
495         if (arg_count(cmd, available_ARG))
496                 r = _vgchange_available(cmd, vg);
497
498         else if (arg_count(cmd, monitor_ARG))
499                 r = _vgchange_monitoring(cmd, vg);
500
501         else if (arg_count(cmd, resizeable_ARG))
502                 r = _vgchange_resizeable(cmd, vg);
503
504         else if (arg_count(cmd, logicalvolume_ARG))
505                 r = _vgchange_logicalvolume(cmd, vg);
506
507         else if (arg_count(cmd, maxphysicalvolumes_ARG))
508                 r = _vgchange_physicalvolumes(cmd, vg);
509
510         else if (arg_count(cmd, addtag_ARG))
511                 r = _vgchange_tag(cmd, vg, addtag_ARG);
512
513         else if (arg_count(cmd, deltag_ARG))
514                 r = _vgchange_tag(cmd, vg, deltag_ARG);
515
516         else if (arg_count(cmd, physicalextentsize_ARG))
517                 r = _vgchange_pesize(cmd, vg);
518
519         else if (arg_count(cmd, uuid_ARG))
520                 r = _vgchange_uuid(cmd, vg);
521
522         else if (arg_count(cmd, alloc_ARG))
523                 r = _vgchange_alloc(cmd, vg);
524
525         else if (arg_count(cmd, clustered_ARG))
526                 r = _vgchange_clustered(cmd, vg);
527
528         else if (arg_count(cmd, refresh_ARG))
529                 r = _vgchange_refresh(cmd, vg);
530
531         return r;
532 }
533
534 int vgchange(struct cmd_context *cmd, int argc, char **argv)
535 {
536         if (!
537             (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
538              arg_count(cmd, maxphysicalvolumes_ARG) +
539              arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
540              arg_count(cmd, addtag_ARG) + arg_count(cmd, uuid_ARG) +
541              arg_count(cmd, physicalextentsize_ARG) +
542              arg_count(cmd, clustered_ARG) + arg_count(cmd, alloc_ARG) +
543              arg_count(cmd, monitor_ARG) + arg_count(cmd, refresh_ARG))) {
544                 log_error("One of -a, -c, -l, -p, -s, -x, --refresh, "
545                                 "--uuid, --alloc, --addtag or --deltag required");
546                 return EINVALID_CMD_LINE;
547         }
548
549         /* FIXME Cope with several changes at once! */
550         if (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
551             arg_count(cmd, maxphysicalvolumes_ARG) +
552             arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
553             arg_count(cmd, addtag_ARG) + arg_count(cmd, alloc_ARG) +
554             arg_count(cmd, uuid_ARG) + arg_count(cmd, clustered_ARG) +
555             arg_count(cmd, physicalextentsize_ARG) > 1) {
556                 log_error("Only one of -a, -c, -l, -p, -s, -x, --uuid, "
557                           "--alloc, --addtag or --deltag allowed");
558                 return EINVALID_CMD_LINE;
559         }
560
561         if (arg_count(cmd, ignorelockingfailure_ARG) &&
562             !arg_count(cmd, available_ARG)) {
563                 log_error("--ignorelockingfailure only available with -a");
564                 return EINVALID_CMD_LINE;
565         }
566
567         if (arg_count(cmd, available_ARG) == 1
568             && arg_count(cmd, autobackup_ARG)) {
569                 log_error("-A option not necessary with -a option");
570                 return EINVALID_CMD_LINE;
571         }
572
573         return process_each_vg(cmd, argc, argv,
574                                (arg_count(cmd, available_ARG)) ?
575                                0 : READ_FOR_UPDATE,
576                                NULL,
577                                &vgchange_single);
578 }