4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
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.
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
20 static int vgconvert_single(struct cmd_context
*cmd
, const char *vg_name
,
21 struct volume_group
*vg
,
22 void *handle
__attribute((unused
)))
24 struct physical_volume
*pv
, *existing_pv
;
25 struct logical_volume
*lv
;
29 int pvmetadatacopies
= 0;
30 uint64_t pvmetadatasize
= 0;
31 uint64_t pe_end
= 0, pe_start
= 0;
37 if (!vg_check_status(vg
, LVM_WRITE
| EXPORTED_VG
)) {
42 if (vg
->fid
->fmt
== cmd
->fmt
) {
43 log_error("Volume group \"%s\" already uses format %s",
44 vg_name
, cmd
->fmt
->name
);
48 if (cmd
->fmt
->features
& FMT_MDAS
) {
49 if (arg_sign_value(cmd
, metadatasize_ARG
, 0) == SIGN_MINUS
) {
50 log_error("Metadata size may not be negative");
51 return EINVALID_CMD_LINE
;
54 pvmetadatasize
= arg_uint64_value(cmd
, metadatasize_ARG
,
58 find_config_tree_int(cmd
,
59 "metadata/pvmetadatasize",
60 DEFAULT_PVMETADATASIZE
);
62 pvmetadatacopies
= arg_int_value(cmd
, pvmetadatacopies_ARG
, -1);
63 if (pvmetadatacopies
< 0)
65 find_config_tree_int(cmd
,
66 "metadata/pvmetadatacopies",
67 DEFAULT_PVMETADATACOPIES
);
71 log_error("Archive of \"%s\" metadata failed.", vg_name
);
75 /* Set PV/LV limit if converting from unlimited metadata format */
76 if (vg
->fid
->fmt
->features
& FMT_UNLIMITED_VOLS
&&
77 !(cmd
->fmt
->features
& FMT_UNLIMITED_VOLS
)) {
84 /* If converting to restricted lvid, check if lvid is compatible */
85 if (!(vg
->fid
->fmt
->features
& FMT_RESTRICTED_LVIDS
) &&
86 cmd
->fmt
->features
& FMT_RESTRICTED_LVIDS
)
87 dm_list_iterate_items(lvl
, &vg
->lvs
)
88 if (!lvid_in_restricted_range(&lvl
->lv
->lvid
)) {
89 log_error("Logical volume %s lvid format is"
90 " incompatible with requested"
91 " metadata format.", lvl
->lv
->name
);
95 /* Attempt to change any LVIDs that are too big */
96 if (cmd
->fmt
->features
& FMT_RESTRICTED_LVIDS
) {
97 dm_list_iterate_items(lvl
, &vg
->lvs
) {
99 if (lv
->status
& SNAPSHOT
)
101 if (lvnum_from_lvid(&lv
->lvid
) < MAX_RESTRICTED_LVS
)
103 if (lv_info(cmd
, lv
, &info
, 0, 0) && info
.exists
) {
104 log_error("Logical volume %s must be "
105 "deactivated before conversion.",
110 lvid_from_lvnum(&lv
->lvid
, &lv
->vg
->id
, find_free_lvnum(lv
));
120 dm_list_iterate_items(pvl
, &vg
->pvs
) {
121 existing_pv
= pvl
->pv
;
123 pe_start
= pv_pe_start(existing_pv
);
124 pe_end
= pv_pe_count(existing_pv
) * pv_pe_size(existing_pv
)
128 if (!(pv
= pv_create(cmd
, pv_dev(existing_pv
),
129 &existing_pv
->id
, size
, 0, 0,
130 pe_start
, pv_pe_count(existing_pv
),
131 pv_pe_size(existing_pv
), pvmetadatacopies
,
132 pvmetadatasize
, &mdas
))) {
133 log_error("Failed to setup physical volume \"%s\"",
134 pv_dev_name(existing_pv
));
136 log_error("Use pvcreate and vgcfgrestore to "
137 "repair from archived metadata.");
141 /* Need to revert manually if it fails after this point */
144 log_verbose("Set up physical volume for \"%s\" with %" PRIu64
145 " available sectors", pv_dev_name(pv
), pv_size(pv
));
147 /* Wipe existing label first */
148 if (!label_remove(pv_dev(pv
))) {
149 log_error("Failed to wipe existing label on %s",
151 log_error("Use pvcreate and vgcfgrestore to repair "
152 "from archived metadata.");
156 log_very_verbose("Writing physical volume data to disk \"%s\"",
158 if (!(pv_write(cmd
, pv
, &mdas
,
159 arg_int64_value(cmd
, labelsector_ARG
,
160 DEFAULT_LABELSECTOR
)))) {
161 log_error("Failed to write physical volume \"%s\"",
163 log_error("Use pvcreate and vgcfgrestore to repair "
164 "from archived metadata.");
167 log_verbose("Physical volume \"%s\" successfully created",
172 log_verbose("Deleting existing metadata for VG %s", vg_name
);
173 if (!vg_remove_mdas(vg
)) {
174 log_error("Removal of existing metadata for %s failed.",
176 log_error("Use pvcreate and vgcfgrestore to repair "
177 "from archived metadata.");
181 /* FIXME Cache the label format change so we don't have to skip this */
183 log_verbose("Test mode: Skipping metadata writing for VG %s in"
184 " format %s", vg_name
, cmd
->fmt
->name
);
185 return ECMD_PROCESSED
;
188 log_verbose("Writing metadata for VG %s using format %s", vg_name
,
190 if (!backup_restore_vg(cmd
, vg
)) {
191 log_error("Conversion failed for volume group %s.", vg_name
);
192 log_error("Use pvcreate and vgcfgrestore to repair from "
193 "archived metadata.");
196 log_print("Volume group %s successfully converted", vg_name
);
200 return ECMD_PROCESSED
;
203 int vgconvert(struct cmd_context
*cmd
, int argc
, char **argv
)
206 log_error("Please enter volume group(s)");
207 return EINVALID_CMD_LINE
;
210 if (arg_int_value(cmd
, labelsector_ARG
, 0) >= LABEL_SCAN_SECTORS
) {
211 log_error("labelsector must be less than %lu",
213 return EINVALID_CMD_LINE
;
216 if (arg_count(cmd
, metadatacopies_ARG
)) {
217 log_error("Invalid option --metadatacopies, "
218 "use --pvmetadatacopies instead.");
219 return EINVALID_CMD_LINE
;
221 if (!(cmd
->fmt
->features
& FMT_MDAS
) &&
222 (arg_count(cmd
, pvmetadatacopies_ARG
) ||
223 arg_count(cmd
, metadatasize_ARG
))) {
224 log_error("Metadata parameters only apply to text format");
225 return EINVALID_CMD_LINE
;
228 if (arg_count(cmd
, pvmetadatacopies_ARG
) &&
229 arg_int_value(cmd
, pvmetadatacopies_ARG
, -1) > 2) {
230 log_error("Metadatacopies may only be 0, 1 or 2");
231 return EINVALID_CMD_LINE
;
234 return process_each_vg(cmd
, argc
, argv
, READ_FOR_UPDATE
, NULL
,