]>
Commit | Line | Data |
---|---|---|
317919c7 | 1 | /* |
67cdbd7e | 2 | * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. |
be684599 | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
317919c7 | 4 | * |
6606c3ae | 5 | * This file is part of LVM2. |
317919c7 | 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. |
317919c7 | 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 | |
317919c7 AK |
14 | */ |
15 | ||
16 | #include "tools.h" | |
17 | ||
1a832398 DW |
18 | static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg, |
19 | struct physical_volume *pv, | |
08f1ddea | 20 | void *handle __attribute__((unused))) |
317919c7 | 21 | { |
bd236f65 | 22 | uint32_t orig_pe_alloc_count; |
239c4fe6 AK |
23 | /* FIXME Next three only required for format1. */ |
24 | uint32_t orig_pe_count, orig_pe_size; | |
25 | uint64_t orig_pe_start; | |
317919c7 | 26 | |
1b8de4cb | 27 | const char *pv_name = pv_dev_name(pv); |
bd236f65 | 28 | const char *orig_vg_name; |
08f1ddea | 29 | char uuid[64] __attribute__((aligned(8))); |
317919c7 | 30 | |
15e6db35 | 31 | int allocatable = 0; |
b51cd542 | 32 | int tagargs = 0; |
88fc1b14 | 33 | int mda_ignore = 0; |
cf6dd251 | 34 | |
b51cd542 | 35 | tagargs = arg_count(cmd, addtag_ARG) + arg_count(cmd, deltag_ARG); |
15e6db35 AK |
36 | |
37 | if (arg_count(cmd, allocatable_ARG)) | |
38 | allocatable = !strcmp(arg_str_value(cmd, allocatable_ARG, "n"), | |
39 | "y"); | |
88fc1b14 DW |
40 | if (arg_count(cmd, metadataignore_ARG)) |
41 | mda_ignore = !strcmp(arg_str_value(cmd, metadataignore_ARG, "n"), | |
42 | "y"); | |
317919c7 | 43 | |
f53c6aa6 | 44 | /* If in a VG, must change using volume group. */ |
9c1dbeb3 | 45 | if (!is_orphan(pv)) { |
b51cd542 | 46 | if (tagargs && !(vg->fid->fmt->features & FMT_TAGS)) { |
cf6dd251 AK |
47 | log_error("Volume group containing %s does not " |
48 | "support tags", pv_name); | |
b51cd542 | 49 | return 0; |
cf6dd251 | 50 | } |
15e6db35 | 51 | if (arg_count(cmd, uuid_ARG) && lvs_in_vg_activated(vg)) { |
15e6db35 AK |
52 | log_error("Volume group containing %s has active " |
53 | "logical volumes", pv_name); | |
b51cd542 | 54 | return 0; |
15e6db35 | 55 | } |
614a4508 | 56 | if (!archive(vg)) |
b51cd542 | 57 | return 0; |
5a52dca9 | 58 | } else { |
b51cd542 | 59 | if (tagargs) { |
cf6dd251 AK |
60 | log_error("Can't change tag on Physical Volume %s not " |
61 | "in volume group", pv_name); | |
62 | return 0; | |
63 | } | |
8f8a968d | 64 | } |
317919c7 | 65 | |
15e6db35 | 66 | if (arg_count(cmd, allocatable_ARG)) { |
9c1dbeb3 | 67 | if (is_orphan(pv) && |
15e6db35 AK |
68 | !(pv->fmt->features & FMT_ORPHAN_ALLOCATABLE)) { |
69 | log_error("Allocatability not supported by orphan " | |
70 | "%s format PV %s", pv->fmt->name, pv_name); | |
b51cd542 | 71 | return 0; |
15e6db35 | 72 | } |
317919c7 | 73 | |
15e6db35 | 74 | /* change allocatability for a PV */ |
ff77bb1a | 75 | if (allocatable && (pv_status(pv) & ALLOCATABLE_PV)) { |
15e6db35 AK |
76 | log_error("Physical volume \"%s\" is already " |
77 | "allocatable", pv_name); | |
b51cd542 | 78 | return 1; |
15e6db35 | 79 | } |
317919c7 | 80 | |
ff77bb1a | 81 | if (!allocatable && !(pv_status(pv) & ALLOCATABLE_PV)) { |
15e6db35 AK |
82 | log_error("Physical volume \"%s\" is already " |
83 | "unallocatable", pv_name); | |
b51cd542 | 84 | return 1; |
15e6db35 AK |
85 | } |
86 | ||
87 | if (allocatable) { | |
88 | log_verbose("Setting physical volume \"%s\" " | |
89 | "allocatable", pv_name); | |
90 | pv->status |= ALLOCATABLE_PV; | |
91 | } else { | |
92 | log_verbose("Setting physical volume \"%s\" NOT " | |
93 | "allocatable", pv_name); | |
94 | pv->status &= ~ALLOCATABLE_PV; | |
95 | } | |
b51cd542 | 96 | } |
f8452d8c | 97 | |
b51cd542 AK |
98 | if (tagargs) { |
99 | /* tag or deltag */ | |
100 | if (arg_count(cmd, addtag_ARG) && !change_tag(cmd, NULL, NULL, pv, addtag_ARG)) | |
101 | return_0; | |
f8452d8c | 102 | |
b51cd542 AK |
103 | if (arg_count(cmd, deltag_ARG) && !change_tag(cmd, NULL, NULL, pv, deltag_ARG)) |
104 | return_0; | |
105 | ||
106 | } | |
f8452d8c | 107 | |
b51cd542 | 108 | if (arg_count(cmd, metadataignore_ARG)) { |
90b96af6 | 109 | if ((vg_mda_copies(vg) != VGMETADATACOPIES_UNMANAGED) && |
96c3c464 | 110 | (arg_count(cmd, force_ARG) == PROMPT) && |
69e80c9e DW |
111 | yes_no_prompt("Override preferred number of copies " |
112 | "of VG %s metadata? [y/n]: ", | |
113 | pv_vg_name(pv)) == 'n') { | |
90b96af6 | 114 | log_error("Physical volume %s not changed", pv_name); |
b51cd542 | 115 | return 0; |
90b96af6 | 116 | } |
a375ced3 | 117 | if (!pv_change_metadataignore(pv, mda_ignore)) |
b51cd542 AK |
118 | return_0; |
119 | } | |
120 | ||
121 | if (arg_count(cmd, uuid_ARG)) { | |
15e6db35 | 122 | /* --uuid: Change PV ID randomly */ |
51aed199 | 123 | memcpy(&pv->old_id, &pv->id, sizeof(pv->id)); |
52f9afec AK |
124 | if (!id_create(&pv->id)) { |
125 | log_error("Failed to generate new random UUID for %s.", | |
126 | pv_name); | |
b51cd542 | 127 | return 0; |
bd236f65 | 128 | } |
043b1362 | 129 | if (!id_write_format(&pv->id, uuid, sizeof(uuid))) |
b51cd542 | 130 | return 0; |
bd236f65 | 131 | log_verbose("Changing uuid of %s to %s.", pv_name, uuid); |
9c1dbeb3 | 132 | if (!is_orphan(pv)) { |
ff77bb1a DW |
133 | orig_vg_name = pv_vg_name(pv); |
134 | orig_pe_alloc_count = pv_pe_alloc_count(pv); | |
239c4fe6 AK |
135 | |
136 | /* FIXME format1 pv_write doesn't preserve these. */ | |
137 | orig_pe_size = pv_pe_size(pv); | |
138 | orig_pe_start = pv_pe_start(pv); | |
139 | orig_pe_count = pv_pe_count(pv); | |
140 | ||
bb097a97 | 141 | pv->vg_name = pv->fmt->orphan_vg_name; |
bd236f65 | 142 | pv->pe_alloc_count = 0; |
3b97e8d6 | 143 | if (!(pv_write(cmd, pv, 0))) { |
bd236f65 AK |
144 | log_error("pv_write with new uuid failed " |
145 | "for %s.", pv_name); | |
b51cd542 | 146 | return 0; |
bd236f65 AK |
147 | } |
148 | pv->vg_name = orig_vg_name; | |
149 | pv->pe_alloc_count = orig_pe_alloc_count; | |
239c4fe6 AK |
150 | |
151 | pv->pe_size = orig_pe_size; | |
152 | pv->pe_start = orig_pe_start; | |
153 | pv->pe_count = orig_pe_count; | |
bd236f65 | 154 | } |
317919c7 AK |
155 | } |
156 | ||
08907484 | 157 | log_verbose("Updating physical volume \"%s\"", pv_name); |
9c1dbeb3 | 158 | if (!is_orphan(pv)) { |
914c9723 | 159 | if (!vg_write(vg) || !vg_commit(vg)) { |
08907484 HM |
160 | log_error("Failed to store physical volume \"%s\" in " |
161 | "volume group \"%s\"", pv_name, vg->name); | |
b51cd542 | 162 | return 0; |
317919c7 | 163 | } |
197c3f2a | 164 | backup(vg); |
3b97e8d6 | 165 | } else if (!(pv_write(cmd, pv, 0))) { |
d38bf361 AK |
166 | log_error("Failed to store physical volume \"%s\"", |
167 | pv_name); | |
b51cd542 | 168 | return 0; |
317919c7 | 169 | } |
8f8a968d | 170 | |
08907484 | 171 | log_print("Physical volume \"%s\" changed", pv_name); |
8f8a968d | 172 | |
b51cd542 | 173 | return 1; |
317919c7 | 174 | } |
5a52dca9 AK |
175 | |
176 | int pvchange(struct cmd_context *cmd, int argc, char **argv) | |
177 | { | |
178 | int opt = 0; | |
179 | int done = 0; | |
180 | int total = 0; | |
181 | ||
1a832398 | 182 | struct volume_group *vg; |
bad35c65 PR |
183 | const char *vg_name; |
184 | char *pv_name; | |
5a52dca9 | 185 | |
f2b7349e | 186 | struct pv_list *pvl; |
1a832398 DW |
187 | struct dm_list *vgnames; |
188 | struct str_list *sll; | |
5a52dca9 | 189 | |
b51cd542 | 190 | if (!(arg_count(cmd, allocatable_ARG) + arg_is_set(cmd, addtag_ARG) + |
f8452d8c | 191 | arg_is_set(cmd, deltag_ARG) + arg_count(cmd, uuid_ARG) + |
b51cd542 AK |
192 | arg_count(cmd, metadataignore_ARG))) { |
193 | log_error("Please give one or more of -x, -uuid, " | |
194 | "--addtag, --deltag or --metadataignore"); | |
5a52dca9 AK |
195 | return EINVALID_CMD_LINE; |
196 | } | |
197 | ||
198 | if (!(arg_count(cmd, all_ARG)) && !argc) { | |
199 | log_error("Please give a physical volume path"); | |
200 | return EINVALID_CMD_LINE; | |
201 | } | |
202 | ||
203 | if (arg_count(cmd, all_ARG) && argc) { | |
204 | log_error("Option a and PhysicalVolumePath are exclusive"); | |
205 | return EINVALID_CMD_LINE; | |
206 | } | |
207 | ||
208 | if (argc) { | |
209 | log_verbose("Using physical volume(s) on command line"); | |
210 | for (; opt < argc; opt++) { | |
211 | pv_name = argv[opt]; | |
e59e2f7c | 212 | dm_unescape_colons_and_at_signs(pv_name, NULL, NULL); |
1a832398 DW |
213 | vg_name = find_vgname_from_pvname(cmd, pv_name); |
214 | if (!vg_name) { | |
c29d2465 AK |
215 | log_error("Failed to read physical volume %s", |
216 | pv_name); | |
5a52dca9 AK |
217 | continue; |
218 | } | |
1a832398 DW |
219 | vg = vg_read_for_update(cmd, vg_name, NULL, 0); |
220 | if (vg_read_error(vg)) { | |
077a6755 | 221 | release_vg(vg); |
1a832398 DW |
222 | stack; |
223 | continue; | |
224 | } | |
225 | pvl = find_pv_in_vg(vg, pv_name); | |
226 | if (!pvl || !pvl->pv) { | |
227 | log_error("Unable to find %s in %s", | |
228 | pv_name, vg_name); | |
229 | continue; | |
1b8b6246 AK |
230 | } |
231 | ||
5a52dca9 | 232 | total++; |
1a832398 DW |
233 | done += _pvchange_single(cmd, vg, |
234 | pvl->pv, NULL); | |
077a6755 | 235 | unlock_and_release_vg(cmd, vg, vg_name); |
5a52dca9 AK |
236 | } |
237 | } else { | |
238 | log_verbose("Scanning for physical volume names"); | |
1a832398 DW |
239 | /* FIXME: share code with toollib */ |
240 | /* | |
241 | * Take the global lock here so the lvmcache remains | |
242 | * consistent across orphan/non-orphan vg locks. If we don't | |
243 | * take the lock here, pvs with 0 mdas in a non-orphan VG will | |
244 | * be processed twice. | |
245 | */ | |
246 | if (!lock_vol(cmd, VG_GLOBAL, LCK_VG_WRITE)) { | |
247 | log_error("Unable to obtain global lock."); | |
5a52dca9 AK |
248 | return ECMD_FAILED; |
249 | } | |
250 | ||
1a832398 DW |
251 | if ((vgnames = get_vgnames(cmd, 1)) && |
252 | !dm_list_empty(vgnames)) { | |
253 | dm_list_iterate_items(sll, vgnames) { | |
254 | vg = vg_read_for_update(cmd, sll->str, NULL, 0); | |
255 | if (vg_read_error(vg)) { | |
077a6755 | 256 | release_vg(vg); |
1a832398 DW |
257 | stack; |
258 | continue; | |
259 | } | |
260 | dm_list_iterate_items(pvl, &vg->pvs) { | |
261 | total++; | |
262 | done += _pvchange_single(cmd, vg, | |
263 | pvl->pv, | |
264 | NULL); | |
265 | } | |
077a6755 | 266 | unlock_and_release_vg(cmd, vg, sll->str); |
1a832398 | 267 | } |
5a52dca9 | 268 | } |
fadd9341 | 269 | unlock_vg(cmd, VG_GLOBAL); |
5a52dca9 AK |
270 | } |
271 | ||
272 | log_print("%d physical volume%s changed / %d physical volume%s " | |
273 | "not changed", | |
15e6db35 AK |
274 | done, done == 1 ? "" : "s", |
275 | total - done, (total - done) == 1 ? "" : "s"); | |
5a52dca9 | 276 | |
cfb7bfc7 | 277 | return (total == done) ? ECMD_PROCESSED : ECMD_FAILED; |
5a52dca9 | 278 | } |