]>
Commit | Line | Data |
---|---|---|
5a52dca9 | 1 | /* |
6606c3ae | 2 | * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. |
be684599 | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
5a52dca9 | 4 | * |
6606c3ae | 5 | * This file is part of LVM2. |
5a52dca9 | 6 | * |
6606c3ae AK |
7 | * This copyrighted material is made available to anyone wishing to use, |
8 | * modify, copy, or redistribute it subject to the terms and conditions | |
be684599 | 9 | * of the GNU Lesser General Public License v.2.1. |
5a52dca9 | 10 | * |
be684599 | 11 | * You should have received a copy of the GNU Lesser General Public License |
6606c3ae AK |
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 | |
5a52dca9 AK |
14 | */ |
15 | ||
16 | #include "tools.h" | |
5a52dca9 AK |
17 | |
18 | static int vgconvert_single(struct cmd_context *cmd, const char *vg_name, | |
13e8c7e4 | 19 | struct volume_group *vg, |
08f1ddea | 20 | void *handle __attribute__((unused))) |
5a52dca9 | 21 | { |
f74bd57e | 22 | struct physical_volume *pv, *existing_pv; |
fee16e10 AK |
23 | struct logical_volume *lv; |
24 | struct lv_list *lvl; | |
5a52dca9 AK |
25 | int pvmetadatacopies = 0; |
26 | uint64_t pvmetadatasize = 0; | |
f74bd57e PR |
27 | uint64_t pe_start = 0; |
28 | struct pv_list *pvl; | |
29 | int change_made = 0; | |
fee16e10 AK |
30 | struct lvinfo info; |
31 | int active = 0; | |
5a52dca9 | 32 | |
651ff9b3 AK |
33 | if (!vg_check_status(vg, LVM_WRITE | EXPORTED_VG)) { |
34 | stack; | |
5a52dca9 | 35 | return ECMD_FAILED; |
651ff9b3 | 36 | } |
5a52dca9 | 37 | |
f74bd57e | 38 | if (vg->fid->fmt == cmd->fmt) { |
5a52dca9 AK |
39 | log_error("Volume group \"%s\" already uses format %s", |
40 | vg_name, cmd->fmt->name); | |
41 | return ECMD_FAILED; | |
42 | } | |
43 | ||
f74bd57e | 44 | if (cmd->fmt->features & FMT_MDAS) { |
fbf6b89a | 45 | if (arg_sign_value(cmd, metadatasize_ARG, SIGN_NONE) == SIGN_MINUS) { |
fdd4f3c0 AK |
46 | log_error("Metadata size may not be negative"); |
47 | return EINVALID_CMD_LINE; | |
48 | } | |
49 | ||
8ef2b021 | 50 | pvmetadatasize = arg_uint64_value(cmd, metadatasize_ARG, |
204a12e5 | 51 | UINT64_C(0)); |
5a52dca9 AK |
52 | if (!pvmetadatasize) |
53 | pvmetadatasize = | |
2293567c | 54 | find_config_tree_int(cmd, |
5a52dca9 | 55 | "metadata/pvmetadatasize", |
814643d8 | 56 | DEFAULT_PVMETADATASIZE); |
5a52dca9 | 57 | |
0ddb66ef | 58 | pvmetadatacopies = arg_int_value(cmd, pvmetadatacopies_ARG, -1); |
5a52dca9 AK |
59 | if (pvmetadatacopies < 0) |
60 | pvmetadatacopies = | |
2293567c | 61 | find_config_tree_int(cmd, |
5a52dca9 | 62 | "metadata/pvmetadatacopies", |
814643d8 | 63 | DEFAULT_PVMETADATACOPIES); |
5a52dca9 AK |
64 | } |
65 | ||
66 | if (!archive(vg)) { | |
67 | log_error("Archive of \"%s\" metadata failed.", vg_name); | |
68 | return ECMD_FAILED; | |
69 | } | |
70 | ||
3a2fb073 MB |
71 | /* Set PV/LV limit if converting from unlimited metadata format */ |
72 | if (vg->fid->fmt->features & FMT_UNLIMITED_VOLS && | |
f74bd57e | 73 | !(cmd->fmt->features & FMT_UNLIMITED_VOLS)) { |
3a2fb073 MB |
74 | if (!vg->max_lv) |
75 | vg->max_lv = 255; | |
76 | if (!vg->max_pv) | |
77 | vg->max_pv = 255; | |
78 | } | |
79 | ||
9c520b11 MB |
80 | /* If converting to restricted lvid, check if lvid is compatible */ |
81 | if (!(vg->fid->fmt->features & FMT_RESTRICTED_LVIDS) && | |
f74bd57e | 82 | cmd->fmt->features & FMT_RESTRICTED_LVIDS) |
2c44337b | 83 | dm_list_iterate_items(lvl, &vg->lvs) |
9c520b11 MB |
84 | if (!lvid_in_restricted_range(&lvl->lv->lvid)) { |
85 | log_error("Logical volume %s lvid format is" | |
86 | " incompatible with requested" | |
87 | " metadata format.", lvl->lv->name); | |
88 | return ECMD_FAILED; | |
89 | } | |
90 | ||
fee16e10 | 91 | /* Attempt to change any LVIDs that are too big */ |
f74bd57e | 92 | if (cmd->fmt->features & FMT_RESTRICTED_LVIDS) { |
2c44337b | 93 | dm_list_iterate_items(lvl, &vg->lvs) { |
fee16e10 | 94 | lv = lvl->lv; |
072893aa AK |
95 | if (lv->status & SNAPSHOT) |
96 | continue; | |
fee16e10 AK |
97 | if (lvnum_from_lvid(&lv->lvid) < MAX_RESTRICTED_LVS) |
98 | continue; | |
2d6fcbf6 | 99 | if (lv_info(cmd, lv, 0, &info, 0, 0) && info.exists) { |
fee16e10 AK |
100 | log_error("Logical volume %s must be " |
101 | "deactivated before conversion.", | |
102 | lv->name); | |
103 | active++; | |
104 | continue; | |
105 | } | |
106 | lvid_from_lvnum(&lv->lvid, &lv->vg->id, find_free_lvnum(lv)); | |
107 | ||
108 | } | |
109 | } | |
110 | ||
651ff9b3 AK |
111 | if (active) { |
112 | stack; | |
fee16e10 | 113 | return ECMD_FAILED; |
651ff9b3 | 114 | } |
fee16e10 | 115 | |
f74bd57e PR |
116 | dm_list_iterate_items(pvl, &vg->pvs) { |
117 | existing_pv = pvl->pv; | |
118 | ||
119 | pe_start = pv_pe_start(existing_pv); | |
120 | /* pe_end = pv_pe_count(existing_pv) * pv_pe_size(existing_pv) + pe_start - 1; */ | |
121 | ||
122 | if (!(pv = pv_create(cmd, pv_dev(existing_pv), | |
123 | &existing_pv->id, 0, 0, 0, | |
124 | pe_start, pv_pe_count(existing_pv), | |
125 | pv_pe_size(existing_pv), | |
126 | arg_int64_value(cmd, labelsector_ARG, | |
127 | DEFAULT_LABELSECTOR), | |
128 | pvmetadatacopies, pvmetadatasize, 0))) { | |
129 | log_error("Failed to setup physical volume \"%s\"", | |
130 | pv_dev_name(existing_pv)); | |
131 | if (change_made) | |
132 | log_error("Use pvcreate and vgcfgrestore to " | |
133 | "repair from archived metadata."); | |
134 | return ECMD_FAILED; | |
135 | } | |
136 | ||
137 | /* Need to revert manually if it fails after this point */ | |
138 | change_made = 1; | |
139 | ||
140 | log_verbose("Set up physical volume for \"%s\" with %" PRIu64 | |
141 | " available sectors", pv_dev_name(pv), pv_size(pv)); | |
142 | ||
143 | /* Wipe existing label first */ | |
144 | if (!label_remove(pv_dev(pv))) { | |
145 | log_error("Failed to wipe existing label on %s", | |
146 | pv_dev_name(pv)); | |
147 | log_error("Use pvcreate and vgcfgrestore to repair " | |
148 | "from archived metadata."); | |
149 | return ECMD_FAILED; | |
150 | } | |
151 | ||
152 | log_very_verbose("Writing physical volume data to disk \"%s\"", | |
153 | pv_dev_name(pv)); | |
3b97e8d6 | 154 | if (!(pv_write(cmd, pv, 0))) { |
f74bd57e PR |
155 | log_error("Failed to write physical volume \"%s\"", |
156 | pv_dev_name(pv)); | |
157 | log_error("Use pvcreate and vgcfgrestore to repair " | |
158 | "from archived metadata."); | |
159 | return ECMD_FAILED; | |
160 | } | |
161 | log_verbose("Physical volume \"%s\" successfully created", | |
162 | pv_dev_name(pv)); | |
f74bd57e PR |
163 | } |
164 | ||
5a52dca9 | 165 | log_verbose("Deleting existing metadata for VG %s", vg_name); |
940077d0 | 166 | if (!vg_remove_mdas(vg)) { |
5a52dca9 AK |
167 | log_error("Removal of existing metadata for %s failed.", |
168 | vg_name); | |
f74bd57e PR |
169 | log_error("Use pvcreate and vgcfgrestore to repair " |
170 | "from archived metadata."); | |
171 | return ECMD_FAILED; | |
5a52dca9 AK |
172 | } |
173 | ||
098102af AK |
174 | /* FIXME Cache the label format change so we don't have to skip this */ |
175 | if (test_mode()) { | |
176 | log_verbose("Test mode: Skipping metadata writing for VG %s in" | |
177 | " format %s", vg_name, cmd->fmt->name); | |
cfb7bfc7 | 178 | return ECMD_PROCESSED; |
098102af AK |
179 | } |
180 | ||
5a52dca9 | 181 | log_verbose("Writing metadata for VG %s using format %s", vg_name, |
f74bd57e PR |
182 | cmd->fmt->name); |
183 | if (!backup_restore_vg(cmd, vg)) { | |
5a52dca9 | 184 | log_error("Conversion failed for volume group %s.", vg_name); |
f74bd57e PR |
185 | log_error("Use pvcreate and vgcfgrestore to repair from " |
186 | "archived metadata."); | |
187 | return ECMD_FAILED; | |
5a52dca9 AK |
188 | } |
189 | log_print("Volume group %s successfully converted", vg_name); | |
190 | ||
191 | backup(vg); | |
192 | ||
cfb7bfc7 | 193 | return ECMD_PROCESSED; |
5a52dca9 AK |
194 | } |
195 | ||
196 | int vgconvert(struct cmd_context *cmd, int argc, char **argv) | |
197 | { | |
198 | if (!argc) { | |
199 | log_error("Please enter volume group(s)"); | |
200 | return EINVALID_CMD_LINE; | |
201 | } | |
202 | ||
203 | if (arg_int_value(cmd, labelsector_ARG, 0) >= LABEL_SCAN_SECTORS) { | |
204 | log_error("labelsector must be less than %lu", | |
205 | LABEL_SCAN_SECTORS); | |
206 | return EINVALID_CMD_LINE; | |
207 | } | |
208 | ||
0ddb66ef DW |
209 | if (arg_count(cmd, metadatacopies_ARG)) { |
210 | log_error("Invalid option --metadatacopies, " | |
211 | "use --pvmetadatacopies instead."); | |
212 | return EINVALID_CMD_LINE; | |
213 | } | |
5a52dca9 | 214 | if (!(cmd->fmt->features & FMT_MDAS) && |
0ddb66ef | 215 | (arg_count(cmd, pvmetadatacopies_ARG) || |
5a52dca9 AK |
216 | arg_count(cmd, metadatasize_ARG))) { |
217 | log_error("Metadata parameters only apply to text format"); | |
218 | return EINVALID_CMD_LINE; | |
219 | } | |
220 | ||
0ddb66ef DW |
221 | if (arg_count(cmd, pvmetadatacopies_ARG) && |
222 | arg_int_value(cmd, pvmetadatacopies_ARG, -1) > 2) { | |
5a52dca9 AK |
223 | log_error("Metadatacopies may only be 0, 1 or 2"); |
224 | return EINVALID_CMD_LINE; | |
225 | } | |
226 | ||
13e8c7e4 | 227 | return process_each_vg(cmd, argc, argv, READ_FOR_UPDATE, NULL, |
5a52dca9 AK |
228 | &vgconvert_single); |
229 | } |