]>
sourceware.org Git - lvm2.git/blob - tools/vgsplit.c
2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
5 * This file is part of LVM2.
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.
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
18 /* FIXME Why not (lv->vg == vg) ? */
19 static int _lv_is_in_vg(struct volume_group
*vg
, struct logical_volume
*lv
)
23 dm_list_iterate_items(lvl
, &vg
->lvs
)
30 static int _move_one_lv(struct volume_group
*vg_from
,
31 struct volume_group
*vg_to
,
34 struct logical_volume
*lv
= dm_list_item(lvh
, struct lv_list
)->lv
;
36 dm_list_move(&vg_to
->lvs
, lvh
);
39 if (lv_is_active(lv
)) {
40 log_error("Logical volume \"%s\" must be inactive", lv
->name
);
47 static int _move_lvs(struct volume_group
*vg_from
, struct volume_group
*vg_to
)
49 struct dm_list
*lvh
, *lvht
;
50 struct logical_volume
*lv
;
51 struct lv_segment
*seg
;
52 struct physical_volume
*pv
;
53 struct volume_group
*vg_with
;
56 dm_list_iterate_safe(lvh
, lvht
, &vg_from
->lvs
) {
57 lv
= dm_list_item(lvh
, struct lv_list
)->lv
;
59 if ((lv
->status
& SNAPSHOT
))
62 if ((lv
->status
& MIRRORED
))
65 /* Ensure all the PVs used by this LV remain in the same */
66 /* VG as each other */
68 dm_list_iterate_items(seg
, &lv
->segments
) {
69 for (s
= 0; s
< seg
->area_count
; s
++) {
70 /* FIXME Check AREA_LV too */
71 if (seg_type(seg
, s
) != AREA_PV
)
76 if (!pv_is_in_vg(vg_with
, pv
)) {
77 log_error("Can't split Logical "
86 if (pv_is_in_vg(vg_from
, pv
)) {
90 if (pv_is_in_vg(vg_to
, pv
)) {
94 log_error("Physical Volume %s not found",
101 if (vg_with
== vg_from
)
105 if (!_move_one_lv(vg_from
, vg_to
, lvh
))
109 /* FIXME Ensure no LVs contain segs pointing at LVs in the other VG */
115 * Move the hidden / internal "snapshotN" LVs.from 'vg_from' to 'vg_to'.
117 static int _move_snapshots(struct volume_group
*vg_from
,
118 struct volume_group
*vg_to
)
120 struct dm_list
*lvh
, *lvht
;
121 struct logical_volume
*lv
;
122 struct lv_segment
*seg
;
126 dm_list_iterate_safe(lvh
, lvht
, &vg_from
->lvs
) {
127 lv
= dm_list_item(lvh
, struct lv_list
)->lv
;
129 if (!(lv
->status
& SNAPSHOT
))
132 dm_list_iterate_items(seg
, &lv
->segments
) {
133 cow_from
= _lv_is_in_vg(vg_from
, seg
->cow
);
134 origin_from
= _lv_is_in_vg(vg_from
, seg
->origin
);
136 if (cow_from
&& origin_from
)
138 if ((!cow_from
&& origin_from
) ||
139 (cow_from
&& !origin_from
)) {
140 log_error("Can't split snapshot %s between"
141 " two Volume Groups", seg
->cow
->name
);
146 * At this point, the cow and origin should already be
149 if (_lv_is_in_vg(vg_to
, seg
->cow
) &&
150 _lv_is_in_vg(vg_to
, seg
->origin
)) {
151 if (!_move_one_lv(vg_from
, vg_to
, lvh
))
161 static int _move_mirrors(struct volume_group
*vg_from
,
162 struct volume_group
*vg_to
)
164 struct dm_list
*lvh
, *lvht
;
165 struct logical_volume
*lv
;
166 struct lv_segment
*seg
, *log_seg
;
167 unsigned s
, seg_in
, log_in
;
169 dm_list_iterate_safe(lvh
, lvht
, &vg_from
->lvs
) {
170 lv
= dm_list_item(lvh
, struct lv_list
)->lv
;
172 if (!(lv
->status
& MIRRORED
))
178 for (s
= 0; s
< seg
->area_count
; s
++)
179 if (_lv_is_in_vg(vg_to
, seg_lv(seg
, s
)))
182 log_in
= !seg
->log_lv
;
184 log_seg
= first_seg(seg
->log_lv
);
185 if (seg_is_mirrored(log_seg
)) {
188 /* Ensure each log dev is in vg_to */
189 for (s
= 0; s
< log_seg
->area_count
; s
++)
194 log_in
= _lv_is_in_vg(vg_to
, seg
->log_lv
);
197 if ((seg_in
&& seg_in
< seg
->area_count
) ||
198 (seg_in
&& seg
->log_lv
&& !log_in
) ||
199 (!seg_in
&& seg
->log_lv
&& log_in
)) {
200 log_error("Can't split mirror %s between "
201 "two Volume Groups", lv
->name
);
205 if (seg_in
== seg
->area_count
&& log_in
) {
206 if (!_move_one_lv(vg_from
, vg_to
, lvh
))
215 * Create or open the destination of the vgsplit operation.
217 * - non-NULL: VG handle w/VG lock held
218 * - NULL: no VG lock held
220 static struct volume_group
*_vgsplit_to(struct cmd_context
*cmd
,
221 const char *vg_name_to
,
224 struct volume_group
*vg_to
= NULL
;
226 log_verbose("Checking for new volume group \"%s\"", vg_name_to
);
228 * First try to create a new VG. If we cannot create it,
229 * and we get FAILED_EXIST (we will not be holding a lock),
230 * a VG must already exist with this name. We then try to
231 * read the existing VG - the vgsplit will be into an existing VG.
233 * Otherwise, if the lock was successful, it must be the case that
234 * we obtained a WRITE lock and could not find the vgname in the
235 * system. Thus, the split will be into a new VG.
237 vg_to
= vg_create(cmd
, vg_name_to
);
238 if (vg_read_error(vg_to
) == FAILED_LOCKING
) {
239 log_error("Can't get lock for %s", vg_name_to
);
243 if (vg_read_error(vg_to
) == FAILED_EXIST
) {
246 vg_to
= vg_read_for_update(cmd
, vg_name_to
, NULL
, 0);
248 if (vg_read_error(vg_to
)) {
254 } else if (vg_read_error(vg_to
) == SUCCESS
) {
261 * Open the source of the vgsplit operation.
263 * - non-NULL: VG handle w/VG lock held
264 * - NULL: no VG lock held
266 static struct volume_group
*_vgsplit_from(struct cmd_context
*cmd
,
267 const char *vg_name_from
)
269 struct volume_group
*vg_from
;
271 log_verbose("Checking for volume group \"%s\"", vg_name_from
);
273 vg_from
= vg_read_for_update(cmd
, vg_name_from
, NULL
, 0);
274 if (vg_read_error(vg_from
)) {
282 * Has the user given an option related to a new vg as the split destination?
284 static int new_vg_option_specified(struct cmd_context
*cmd
)
286 return(arg_count(cmd
, clustered_ARG
) ||
287 arg_count(cmd
, alloc_ARG
) ||
288 arg_count(cmd
, maxphysicalvolumes_ARG
) ||
289 arg_count(cmd
, maxlogicalvolumes_ARG
) ||
290 arg_count(cmd
, vgmetadatacopies_ARG
));
293 int vgsplit(struct cmd_context
*cmd
, int argc
, char **argv
)
295 struct vgcreate_params vp_new
;
296 struct vgcreate_params vp_def
;
297 const char *vg_name_from
, *vg_name_to
;
298 struct volume_group
*vg_to
= NULL
, *vg_from
= NULL
;
303 int lock_vg_from_first
= 1;
305 if ((arg_count(cmd
, name_ARG
) + argc
) < 3) {
306 log_error("Existing VG, new VG and either physical volumes "
307 "or logical volume required.");
308 return EINVALID_CMD_LINE
;
311 if (arg_count(cmd
, name_ARG
) && (argc
> 2)) {
312 log_error("A logical volume name cannot be given with "
313 "physical volumes.");
317 if (arg_count(cmd
, name_ARG
))
318 lv_name
= arg_value(cmd
, name_ARG
);
322 vg_name_from
= skip_dev_dir(cmd
, argv
[0], NULL
);
323 vg_name_to
= skip_dev_dir(cmd
, argv
[1], NULL
);
327 if (!strcmp(vg_name_to
, vg_name_from
)) {
328 log_error("Duplicate volume group name \"%s\"", vg_name_from
);
332 if (strcmp(vg_name_to
, vg_name_from
) < 0)
333 lock_vg_from_first
= 0;
335 if (lock_vg_from_first
) {
336 vg_from
= _vgsplit_from(cmd
, vg_name_from
);
342 * Set metadata format of original VG.
343 * NOTE: We must set the format before calling vg_create()
344 * since vg_create() calls the per-format constructor.
346 cmd
->fmt
= vg_from
->fid
->fmt
;
348 vg_to
= _vgsplit_to(cmd
, vg_name_to
, &existing_vg
);
350 unlock_and_release_vg(cmd
, vg_from
, vg_name_from
);
355 vg_to
= _vgsplit_to(cmd
, vg_name_to
, &existing_vg
);
360 vg_from
= _vgsplit_from(cmd
, vg_name_from
);
362 unlock_and_release_vg(cmd
, vg_to
, vg_name_to
);
367 if (cmd
->fmt
!= vg_from
->fid
->fmt
) {
368 /* In this case we don't know the vg_from->fid->fmt */
369 log_error("Unable to set new VG metadata type based on "
370 "source VG format - use -M option.");
376 if (new_vg_option_specified(cmd
)) {
377 log_error("Volume group \"%s\" exists, but new VG "
378 "option specified", vg_name_to
);
381 if (!vgs_are_compatible(cmd
, vg_from
,vg_to
))
384 vgcreate_params_set_defaults(&vp_def
, vg_from
);
385 vp_def
.vg_name
= vg_name_to
;
386 if (vgcreate_params_set_from_args(cmd
, &vp_new
, &vp_def
)) {
387 r
= EINVALID_CMD_LINE
;
391 if (vgcreate_params_validate(cmd
, &vp_new
)) {
392 r
= EINVALID_CMD_LINE
;
396 if (!vg_set_extent_size(vg_to
, vp_new
.extent_size
) ||
397 !vg_set_max_lv(vg_to
, vp_new
.max_lv
) ||
398 !vg_set_max_pv(vg_to
, vp_new
.max_pv
) ||
399 !vg_set_alloc_policy(vg_to
, vp_new
.alloc
) ||
400 !vg_set_clustered(vg_to
, vp_new
.clustered
) ||
401 !vg_set_mda_copies(vg_to
, vp_new
.vgmetadatacopies
))
405 /* Archive vg_from before changing it */
406 if (!archive(vg_from
))
409 /* Move PVs across to new structure */
410 for (opt
= 0; opt
< argc
; opt
++) {
411 dm_unescape_colons_and_at_signs(argv
[opt
], NULL
, NULL
);
412 if (!move_pv(vg_from
, vg_to
, argv
[opt
]))
416 /* If an LV given on the cmdline, move used_by PVs */
417 if (lv_name
&& !move_pvs_used_by_lv(vg_from
, vg_to
, lv_name
))
420 /* Move required LVs across, checking consistency */
421 if (!(_move_lvs(vg_from
, vg_to
)))
424 /* FIXME Separate the 'move' from the 'validation' to fix dev stacks */
425 /* Move required mirrors across */
426 if (!(_move_mirrors(vg_from
, vg_to
)))
429 /* Move required snapshots across */
430 if (!(_move_snapshots(vg_from
, vg_to
)))
433 /* Split metadata areas and check if both vgs have at least one area */
434 if (!(vg_split_mdas(cmd
, vg_from
, vg_to
)) && vg_from
->pv_count
) {
435 log_error("Cannot split: Nowhere to store metadata for new Volume Group");
439 /* Set proper name for all PVs in new VG */
440 if (!vg_rename(cmd
, vg_to
, vg_name_to
))
443 /* store it on disks */
444 log_verbose("Writing out updated volume groups");
447 * First, write out the new VG as EXPORTED. We do this first in case
448 * there is a crash - we will still have the new VG information, in an
449 * exported state. Recovery after this point would be removal of the
450 * new VG and redoing the vgsplit.
451 * FIXME: recover automatically or instruct the user?
453 vg_to
->status
|= EXPORTED_VG
;
458 if (!vg_write(vg_to
) || !vg_commit(vg_to
))
464 * Next, write out the updated old VG. If we crash after this point,
465 * recovery is a vgimport on the new VG.
466 * FIXME: recover automatically or instruct the user?
468 if (vg_from
->pv_count
) {
469 if (!vg_write(vg_from
) || !vg_commit(vg_from
))
476 * Finally, remove the EXPORTED flag from the new VG and write it out.
480 vg_to
= vg_read_for_update(cmd
, vg_name_to
, NULL
,
481 READ_ALLOW_EXPORTED
);
482 if (vg_read_error(vg_to
)) {
483 log_error("Volume group \"%s\" became inconsistent: "
484 "please fix manually", vg_name_to
);
489 vg_to
->status
&= ~EXPORTED_VG
;
491 if (!vg_write(vg_to
) || !vg_commit(vg_to
))
496 log_print("%s volume group \"%s\" successfully split from \"%s\"",
497 existing_vg
? "Existing" : "New",
498 vg_to
->name
, vg_from
->name
);
504 * vg_to references elements moved from vg_from
505 * so vg_to has to be freed first.
507 unlock_and_release_vg(cmd
, vg_to
, vg_name_to
);
508 unlock_and_release_vg(cmd
, vg_from
, vg_name_from
);
This page took 0.056497 seconds and 5 git commands to generate.