Initial import of binutils 2.22 on the new vendor branch
[dragonfly.git] / contrib / lvm2 / dist / tools / vgsplit.c
1 /*      $NetBSD: vgsplit.c,v 1.1.1.2 2009/12/02 00:25:46 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
20 /* FIXME Why not (lv->vg == vg) ? */
21 static int _lv_is_in_vg(struct volume_group *vg, struct logical_volume *lv)
22 {
23         struct lv_list *lvl;
24
25         dm_list_iterate_items(lvl, &vg->lvs)
26                 if (lv == lvl->lv)
27                          return 1;
28
29         return 0;
30 }
31
32 static int _move_one_lv(struct volume_group *vg_from,
33                          struct volume_group *vg_to,
34                          struct dm_list *lvh)
35 {
36         struct logical_volume *lv = dm_list_item(lvh, struct lv_list)->lv;
37
38         dm_list_move(&vg_to->lvs, lvh);
39
40         if (lv_is_active(lv)) {
41                 log_error("Logical volume \"%s\" must be inactive", lv->name);
42                 return 0;
43         }
44
45         return 1;
46 }
47
48 static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
49 {
50         struct dm_list *lvh, *lvht;
51         struct logical_volume *lv;
52         struct lv_segment *seg;
53         struct physical_volume *pv;
54         struct volume_group *vg_with;
55         unsigned s;
56
57         dm_list_iterate_safe(lvh, lvht, &vg_from->lvs) {
58                 lv = dm_list_item(lvh, struct lv_list)->lv;
59
60                 if ((lv->status & SNAPSHOT))
61                         continue;
62
63                 if ((lv->status & MIRRORED))
64                         continue;
65
66                 /* Ensure all the PVs used by this LV remain in the same */
67                 /* VG as each other */
68                 vg_with = NULL;
69                 dm_list_iterate_items(seg, &lv->segments) {
70                         for (s = 0; s < seg->area_count; s++) {
71                                 /* FIXME Check AREA_LV too */
72                                 if (seg_type(seg, s) != AREA_PV)
73                                         continue;
74
75                                 pv = seg_pv(seg, s);
76                                 if (vg_with) {
77                                         if (!pv_is_in_vg(vg_with, pv)) {
78                                                 log_error("Can't split Logical "
79                                                           "Volume %s between "
80                                                           "two Volume Groups",
81                                                           lv->name);
82                                                 return 0;
83                                         }
84                                         continue;
85                                 }
86
87                                 if (pv_is_in_vg(vg_from, pv)) {
88                                         vg_with = vg_from;
89                                         continue;
90                                 }
91                                 if (pv_is_in_vg(vg_to, pv)) {
92                                         vg_with = vg_to;
93                                         continue;
94                                 }
95                                 log_error("Physical Volume %s not found",
96                                           pv_dev_name(pv));
97                                 return 0;
98                         }
99
100                 }
101
102                 if (vg_with == vg_from)
103                         continue;
104
105                 /* Move this LV */
106                 if (!_move_one_lv(vg_from, vg_to, lvh))
107                         return_0;
108         }
109
110         /* FIXME Ensure no LVs contain segs pointing at LVs in the other VG */
111
112         return 1;
113 }
114
115 /*
116  * Move the hidden / internal "snapshotN" LVs.from 'vg_from' to 'vg_to'.
117  */
118 static int _move_snapshots(struct volume_group *vg_from,
119                            struct volume_group *vg_to)
120 {
121         struct dm_list *lvh, *lvht;
122         struct logical_volume *lv;
123         struct lv_segment *seg;
124         int cow_from = 0;
125         int origin_from = 0;
126
127         dm_list_iterate_safe(lvh, lvht, &vg_from->lvs) {
128                 lv = dm_list_item(lvh, struct lv_list)->lv;
129
130                 if (!(lv->status & SNAPSHOT))
131                         continue;
132
133                 dm_list_iterate_items(seg, &lv->segments) {
134                         cow_from = _lv_is_in_vg(vg_from, seg->cow);
135                         origin_from = _lv_is_in_vg(vg_from, seg->origin);
136
137                         if (cow_from && origin_from)
138                                 continue;
139                         if ((!cow_from && origin_from) ||
140                              (cow_from && !origin_from)) {
141                                 log_error("Can't split snapshot %s between"
142                                           " two Volume Groups", seg->cow->name);
143                                 return 0;
144                         }
145
146                         /*
147                          * At this point, the cow and origin should already be
148                          * in vg_to.
149                          */
150                         if (_lv_is_in_vg(vg_to, seg->cow) &&
151                             _lv_is_in_vg(vg_to, seg->origin)) {
152                                 if (!_move_one_lv(vg_from, vg_to, lvh))
153                                         return_0;
154                         }
155                 }
156
157         }
158
159         return 1;
160 }
161
162 static int _move_mirrors(struct volume_group *vg_from,
163                          struct volume_group *vg_to)
164 {
165         struct dm_list *lvh, *lvht;
166         struct logical_volume *lv;
167         struct lv_segment *seg;
168         unsigned s, seg_in, log_in;
169
170         dm_list_iterate_safe(lvh, lvht, &vg_from->lvs) {
171                 lv = dm_list_item(lvh, struct lv_list)->lv;
172
173                 if (!(lv->status & MIRRORED))
174                         continue;
175
176                 seg = first_seg(lv);
177
178                 seg_in = 0;
179                 for (s = 0; s < seg->area_count; s++)
180                         if (_lv_is_in_vg(vg_to, seg_lv(seg, s)))
181                             seg_in++;
182
183                 log_in = (!seg->log_lv || _lv_is_in_vg(vg_to, seg->log_lv));
184
185                 if ((seg_in && seg_in < seg->area_count) ||
186                     (seg_in && seg->log_lv && !log_in) ||
187                     (!seg_in && seg->log_lv && log_in)) {
188                         log_error("Can't split mirror %s between "
189                                   "two Volume Groups", lv->name);
190                         return 0;
191                 }
192
193                 if (seg_in == seg->area_count && log_in) {
194                         if (!_move_one_lv(vg_from, vg_to, lvh))
195                                 return_0;
196                 }
197         }
198
199         return 1;
200 }
201
202 /*
203  * Create or open the destination of the vgsplit operation.
204  * Returns
205  * - non-NULL: VG handle w/VG lock held
206  * - NULL: no VG lock held
207  */
208 static struct volume_group *_vgsplit_to(struct cmd_context *cmd,
209                                         const char *vg_name_to,
210                                         int *existing_vg)
211 {
212         struct volume_group *vg_to = NULL;
213
214         log_verbose("Checking for new volume group \"%s\"", vg_name_to);
215         /*
216          * First try to create a new VG.  If we cannot create it,
217          * and we get FAILED_EXIST (we will not be holding a lock),
218          * a VG must already exist with this name.  We then try to
219          * read the existing VG - the vgsplit will be into an existing VG.
220          *
221          * Otherwise, if the lock was successful, it must be the case that
222          * we obtained a WRITE lock and could not find the vgname in the
223          * system.  Thus, the split will be into a new VG.
224          */
225         vg_to = vg_create(cmd, vg_name_to);
226         if (vg_read_error(vg_to) == FAILED_LOCKING) {
227                 log_error("Can't get lock for %s", vg_name_to);
228                 vg_release(vg_to);
229                 return NULL;
230         }
231         if (vg_read_error(vg_to) == FAILED_EXIST) {
232                 *existing_vg = 1;
233                 vg_release(vg_to);
234                 vg_to = vg_read_for_update(cmd, vg_name_to, NULL, 0);
235
236                 if (vg_read_error(vg_to)) {
237                         vg_release(vg_to);
238                         stack;
239                         return NULL;
240                 }
241
242         } else if (vg_read_error(vg_to) == SUCCESS) {
243                 *existing_vg = 0;
244         }
245         return vg_to;
246 }
247
248 /*
249  * Open the source of the vgsplit operation.
250  * Returns
251  * - non-NULL: VG handle w/VG lock held
252  * - NULL: no VG lock held
253  */
254 static struct volume_group *_vgsplit_from(struct cmd_context *cmd,
255                                           const char *vg_name_from)
256 {
257         struct volume_group *vg_from;
258
259         log_verbose("Checking for volume group \"%s\"", vg_name_from);
260
261         vg_from = vg_read_for_update(cmd, vg_name_from, NULL, 0);
262         if (vg_read_error(vg_from)) {
263                 vg_release(vg_from);
264                 return NULL;
265         }
266         return vg_from;
267 }
268
269 /*
270  * Has the user given an option related to a new vg as the split destination?
271  */
272 static int new_vg_option_specified(struct cmd_context *cmd)
273 {
274         return(arg_count(cmd, clustered_ARG) ||
275                arg_count(cmd, alloc_ARG) ||
276                arg_count(cmd, maxphysicalvolumes_ARG) ||
277                arg_count(cmd, maxlogicalvolumes_ARG));
278 }
279
280 int vgsplit(struct cmd_context *cmd, int argc, char **argv)
281 {
282         struct vgcreate_params vp_new;
283         struct vgcreate_params vp_def;
284         char *vg_name_from, *vg_name_to;
285         struct volume_group *vg_to = NULL, *vg_from = NULL;
286         int opt;
287         int existing_vg = 0;
288         int r = ECMD_FAILED;
289         const char *lv_name;
290         int lock_vg_from_first = 1;
291
292         if ((arg_count(cmd, name_ARG) + argc) < 3) {
293                 log_error("Existing VG, new VG and either physical volumes "
294                           "or logical volume required.");
295                 return EINVALID_CMD_LINE;
296         }
297
298         if (arg_count(cmd, name_ARG) && (argc > 2)) {
299                 log_error("A logical volume name cannot be given with "
300                           "physical volumes.");
301                 return ECMD_FAILED;
302         }
303
304         if (arg_count(cmd, name_ARG))
305                 lv_name = arg_value(cmd, name_ARG);
306         else
307                 lv_name = NULL;
308
309         vg_name_from = skip_dev_dir(cmd, argv[0], NULL);
310         vg_name_to = skip_dev_dir(cmd, argv[1], NULL);
311         argc -= 2;
312         argv += 2;
313
314         if (!strcmp(vg_name_to, vg_name_from)) {
315                 log_error("Duplicate volume group name \"%s\"", vg_name_from);
316                 return ECMD_FAILED;
317         }
318
319         if (strcmp(vg_name_to, vg_name_from) < 0)
320                 lock_vg_from_first = 0;
321
322         if (lock_vg_from_first) {
323                 vg_from = _vgsplit_from(cmd, vg_name_from);
324                 if (!vg_from) {
325                         stack;
326                         return ECMD_FAILED;
327                 }
328                 /*
329                  * Set metadata format of original VG.
330                  * NOTE: We must set the format before calling vg_create()
331                  * since vg_create() calls the per-format constructor.
332                  */
333                 cmd->fmt = vg_from->fid->fmt;
334
335                 vg_to = _vgsplit_to(cmd, vg_name_to, &existing_vg);
336                 if (!vg_to) {
337                         unlock_and_release_vg(cmd, vg_from, vg_name_from);
338                         stack;
339                         return ECMD_FAILED;
340                 }
341         } else {
342                 vg_to = _vgsplit_to(cmd, vg_name_to, &existing_vg);
343                 if (!vg_to) {
344                         stack;
345                         return ECMD_FAILED;
346                 }
347                 vg_from = _vgsplit_from(cmd, vg_name_from);
348                 if (!vg_from) {
349                         unlock_and_release_vg(cmd, vg_to, vg_name_to);
350                         stack;
351                         return ECMD_FAILED;
352                 }
353
354                 if (cmd->fmt != vg_from->fid->fmt) {
355                         /* In this case we don't know the vg_from->fid->fmt */
356                         log_error("Unable to set new VG metadata type based on "
357                                   "source VG format - use -M option.");
358                         goto bad;
359                 }
360         }
361
362         if (existing_vg) {
363                 if (new_vg_option_specified(cmd)) {
364                         log_error("Volume group \"%s\" exists, but new VG "
365                                     "option specified", vg_name_to);
366                         goto bad;
367                 }
368                 if (!vgs_are_compatible(cmd, vg_from,vg_to))
369                         goto_bad;
370         } else {
371                 vgcreate_params_set_defaults(&vp_def, vg_from);
372                 vp_def.vg_name = vg_name_to;
373                 if (vgcreate_params_set_from_args(cmd, &vp_new, &vp_def)) {
374                         r = EINVALID_CMD_LINE;
375                         goto_bad;
376                 }
377
378                 if (vgcreate_params_validate(cmd, &vp_new)) {
379                         r = EINVALID_CMD_LINE;
380                         goto_bad;
381                 }
382
383                 if (!vg_set_extent_size(vg_to, vp_new.extent_size) ||
384                     !vg_set_max_lv(vg_to, vp_new.max_lv) ||
385                     !vg_set_max_pv(vg_to, vp_new.max_pv) ||
386                     !vg_set_alloc_policy(vg_to, vp_new.alloc) ||
387                     !vg_set_clustered(vg_to, vp_new.clustered))
388                         goto_bad;
389         }
390
391         /* Archive vg_from before changing it */
392         if (!archive(vg_from))
393                 goto_bad;
394
395         /* Move PVs across to new structure */
396         for (opt = 0; opt < argc; opt++) {
397                 if (!move_pv(vg_from, vg_to, argv[opt]))
398                         goto_bad;
399         }
400
401         /* If an LV given on the cmdline, move used_by PVs */
402         if (lv_name && !move_pvs_used_by_lv(vg_from, vg_to, lv_name))
403                 goto_bad;
404
405         /* Move required LVs across, checking consistency */
406         if (!(_move_lvs(vg_from, vg_to)))
407                 goto_bad;
408
409         /* FIXME Separate the 'move' from the 'validation' to fix dev stacks */
410         /* Move required mirrors across */
411         if (!(_move_mirrors(vg_from, vg_to)))
412                 goto_bad;
413
414         /* Move required snapshots across */
415         if (!(_move_snapshots(vg_from, vg_to)))
416                 goto_bad;
417
418         /* Split metadata areas and check if both vgs have at least one area */
419         if (!(vg_split_mdas(cmd, vg_from, vg_to)) && vg_from->pv_count) {
420                 log_error("Cannot split: Nowhere to store metadata for new Volume Group");
421                 goto bad;
422         }
423
424         /* Set proper name for all PVs in new VG */
425         if (!vg_rename(cmd, vg_to, vg_name_to))
426                 goto_bad;
427
428         /* store it on disks */
429         log_verbose("Writing out updated volume groups");
430
431         /*
432          * First, write out the new VG as EXPORTED.  We do this first in case
433          * there is a crash - we will still have the new VG information, in an
434          * exported state.  Recovery after this point would be removal of the
435          * new VG and redoing the vgsplit.
436          * FIXME: recover automatically or instruct the user?
437          */
438         vg_to->status |= EXPORTED_VG;
439
440         if (!archive(vg_to))
441                 goto_bad;
442
443         if (!vg_write(vg_to) || !vg_commit(vg_to))
444                 goto_bad;
445
446         backup(vg_to);
447
448         /*
449          * Next, write out the updated old VG.  If we crash after this point,
450          * recovery is a vgimport on the new VG.
451          * FIXME: recover automatically or instruct the user?
452          */
453         if (vg_from->pv_count) {
454                 if (!vg_write(vg_from) || !vg_commit(vg_from))
455                         goto_bad;
456
457                 backup(vg_from);
458         }
459
460         /*
461          * Finally, remove the EXPORTED flag from the new VG and write it out.
462          */
463         if (!test_mode()) {
464                 vg_release(vg_to);
465                 vg_to = vg_read_for_update(cmd, vg_name_to, NULL,
466                                            READ_ALLOW_EXPORTED);
467                 if (vg_read_error(vg_to)) {
468                         log_error("Volume group \"%s\" became inconsistent: "
469                                   "please fix manually", vg_name_to);
470                         goto bad;
471                 }
472         }
473
474         vg_to->status &= ~EXPORTED_VG;
475
476         if (!vg_write(vg_to) || !vg_commit(vg_to))
477                 goto_bad;
478
479         backup(vg_to);
480
481         log_print("%s volume group \"%s\" successfully split from \"%s\"",
482                   existing_vg ? "Existing" : "New",
483                   vg_to->name, vg_from->name);
484
485         r = ECMD_PROCESSED;
486
487 bad:
488         if (lock_vg_from_first) {
489                 unlock_and_release_vg(cmd, vg_to, vg_name_to);
490                 unlock_and_release_vg(cmd, vg_from, vg_name_from);
491         } else {
492                 unlock_and_release_vg(cmd, vg_from, vg_name_from);
493                 unlock_and_release_vg(cmd, vg_to, vg_name_to);
494         }
495         return r;
496 }