Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 : : * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
4 : : *
5 : : * This file is part of LVM2.
6 : : *
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.
10 : : *
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
14 : : */
15 : :
16 : : #include "tools.h"
17 : :
18 : : /* FIXME Locking. PVs in VG. */
19 : :
20 : 0 : static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
21 : : void *handle __attribute((unused)))
22 : : {
23 : 0 : struct volume_group *vg = NULL;
24 : 0 : const char *vg_name = NULL;
25 : : struct pv_list *pvl;
26 : : uint64_t sector;
27 : : uint32_t orig_pe_alloc_count;
28 : : /* FIXME Next three only required for format1. */
29 : : uint32_t orig_pe_count, orig_pe_size;
30 : : uint64_t orig_pe_start;
31 : :
32 : 0 : const char *pv_name = pv_dev_name(pv);
33 : 0 : const char *tag = NULL;
34 : : const char *orig_vg_name;
35 : : char uuid[64] __attribute((aligned(8)));
36 : :
37 : 0 : int allocatable = 0;
38 : 0 : int tagarg = 0;
39 : 0 : int r = 0;
40 : :
41 [ # # ]: 0 : if (arg_count(cmd, addtag_ARG))
42 : 0 : tagarg = addtag_ARG;
43 [ # # ]: 0 : else if (arg_count(cmd, deltag_ARG))
44 : 0 : tagarg = deltag_ARG;
45 : :
46 [ # # ]: 0 : if (arg_count(cmd, allocatable_ARG))
47 : 0 : allocatable = !strcmp(arg_str_value(cmd, allocatable_ARG, "n"),
48 : : "y");
49 [ # # ][ # # ]: 0 : else if (tagarg && !(tag = arg_str_value(cmd, tagarg, NULL))) {
50 : 0 : log_error("Failed to get tag");
51 : 0 : return 0;
52 : : }
53 : :
54 : : /* If in a VG, must change using volume group. */
55 [ # # ]: 0 : if (!is_orphan(pv)) {
56 : 0 : vg_name = pv_vg_name(pv);
57 : :
58 : 0 : log_verbose("Finding volume group %s of physical volume %s",
59 : : vg_name, pv_name);
60 : 0 : vg = vg_read_for_update(cmd, vg_name, NULL, 0);
61 [ # # ]: 0 : if (vg_read_error(vg)) {
62 : 0 : vg_release(vg);
63 : 0 : return_0;
64 : : }
65 : :
66 [ # # ]: 0 : if (!(pvl = find_pv_in_vg(vg, pv_name))) {
67 : 0 : log_error("Unable to find \"%s\" in volume group \"%s\"",
68 : : pv_name, vg->name);
69 : 0 : goto out;
70 : : }
71 [ # # ][ # # ]: 0 : if (tagarg && !(vg->fid->fmt->features & FMT_TAGS)) {
72 : 0 : log_error("Volume group containing %s does not "
73 : : "support tags", pv_name);
74 : 0 : goto out;
75 : : }
76 [ # # ][ # # ]: 0 : if (arg_count(cmd, uuid_ARG) && lvs_in_vg_activated(vg)) {
77 : 0 : log_error("Volume group containing %s has active "
78 : : "logical volumes", pv_name);
79 : 0 : goto out;
80 : : }
81 : 0 : pv = pvl->pv;
82 [ # # ]: 0 : if (!archive(vg))
83 : 0 : goto out;
84 : : } else {
85 [ # # ]: 0 : if (tagarg) {
86 : 0 : log_error("Can't change tag on Physical Volume %s not "
87 : : "in volume group", pv_name);
88 : 0 : return 0;
89 : : }
90 : :
91 : 0 : vg_name = VG_ORPHANS;
92 : :
93 [ # # ]: 0 : if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
94 : 0 : log_error("Can't get lock for orphans");
95 : 0 : return 0;
96 : : }
97 : :
98 [ # # ]: 0 : if (!(pv = pv_read(cmd, pv_name, NULL, §or, 1, 0))) {
99 : 0 : unlock_vg(cmd, vg_name);
100 : 0 : log_error("Unable to read PV \"%s\"", pv_name);
101 : 0 : return 0;
102 : : }
103 : : }
104 : :
105 [ # # ]: 0 : if (arg_count(cmd, allocatable_ARG)) {
106 [ # # ][ # # ]: 0 : if (is_orphan(pv) &&
107 : 0 : !(pv->fmt->features & FMT_ORPHAN_ALLOCATABLE)) {
108 : 0 : log_error("Allocatability not supported by orphan "
109 : : "%s format PV %s", pv->fmt->name, pv_name);
110 : 0 : goto out;
111 : : }
112 : :
113 : : /* change allocatability for a PV */
114 [ # # ][ # # ]: 0 : if (allocatable && (pv_status(pv) & ALLOCATABLE_PV)) {
115 : 0 : log_error("Physical volume \"%s\" is already "
116 : : "allocatable", pv_name);
117 : 0 : r = 1;
118 : 0 : goto out;
119 : : }
120 : :
121 [ # # ][ # # ]: 0 : if (!allocatable && !(pv_status(pv) & ALLOCATABLE_PV)) {
122 : 0 : log_error("Physical volume \"%s\" is already "
123 : : "unallocatable", pv_name);
124 : 0 : r = 1;
125 : 0 : goto out;
126 : : }
127 : :
128 [ # # ]: 0 : if (allocatable) {
129 : 0 : log_verbose("Setting physical volume \"%s\" "
130 : : "allocatable", pv_name);
131 : 0 : pv->status |= ALLOCATABLE_PV;
132 : : } else {
133 : 0 : log_verbose("Setting physical volume \"%s\" NOT "
134 : : "allocatable", pv_name);
135 : 0 : pv->status &= ~ALLOCATABLE_PV;
136 : : }
137 [ # # ]: 0 : } else if (tagarg) {
138 : : /* tag or deltag */
139 [ # # ]: 0 : if ((tagarg == addtag_ARG)) {
140 [ # # ]: 0 : if (!str_list_add(cmd->mem, &pv->tags, tag)) {
141 : 0 : log_error("Failed to add tag %s to physical "
142 : : "volume %s", tag, pv_name);
143 : 0 : goto out;
144 : : }
145 : : } else {
146 [ # # ]: 0 : if (!str_list_del(&pv->tags, tag)) {
147 : 0 : log_error("Failed to remove tag %s from "
148 : : "physical volume" "%s", tag, pv_name);
149 : 0 : goto out;
150 : : }
151 : : }
152 : : } else {
153 : : /* --uuid: Change PV ID randomly */
154 [ # # ]: 0 : if (!id_create(&pv->id)) {
155 : 0 : log_error("Failed to generate new random UUID for %s.",
156 : : pv_name);
157 : 0 : goto out;
158 : : }
159 [ # # ]: 0 : if (!id_write_format(&pv->id, uuid, sizeof(uuid)))
160 : 0 : goto_out;
161 : 0 : log_verbose("Changing uuid of %s to %s.", pv_name, uuid);
162 [ # # ]: 0 : if (!is_orphan(pv)) {
163 : 0 : orig_vg_name = pv_vg_name(pv);
164 : 0 : orig_pe_alloc_count = pv_pe_alloc_count(pv);
165 : :
166 : : /* FIXME format1 pv_write doesn't preserve these. */
167 : 0 : orig_pe_size = pv_pe_size(pv);
168 : 0 : orig_pe_start = pv_pe_start(pv);
169 : 0 : orig_pe_count = pv_pe_count(pv);
170 : :
171 : 0 : pv->vg_name = pv->fmt->orphan_vg_name;
172 : 0 : pv->pe_alloc_count = 0;
173 [ # # ]: 0 : if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
174 : 0 : log_error("pv_write with new uuid failed "
175 : : "for %s.", pv_name);
176 : 0 : goto out;
177 : : }
178 : 0 : pv->vg_name = orig_vg_name;
179 : 0 : pv->pe_alloc_count = orig_pe_alloc_count;
180 : :
181 : 0 : pv->pe_size = orig_pe_size;
182 : 0 : pv->pe_start = orig_pe_start;
183 : 0 : pv->pe_count = orig_pe_count;
184 : : }
185 : : }
186 : :
187 : 0 : log_verbose("Updating physical volume \"%s\"", pv_name);
188 [ # # ]: 0 : if (!is_orphan(pv)) {
189 [ # # ][ # # ]: 0 : if (!vg_write(vg) || !vg_commit(vg)) {
190 : 0 : log_error("Failed to store physical volume \"%s\" in "
191 : : "volume group \"%s\"", pv_name, vg->name);
192 : 0 : goto out;
193 : : }
194 : 0 : backup(vg);
195 [ # # ]: 0 : } else if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
196 : 0 : log_error("Failed to store physical volume \"%s\"",
197 : : pv_name);
198 : 0 : goto out;
199 : : }
200 : :
201 : 0 : log_print("Physical volume \"%s\" changed", pv_name);
202 : 0 : r = 1;
203 : : out:
204 : 0 : unlock_and_release_vg(cmd, vg, vg_name);
205 : 0 : return r;
206 : :
207 : : }
208 : :
209 : 0 : int pvchange(struct cmd_context *cmd, int argc, char **argv)
210 : : {
211 : 0 : int opt = 0;
212 : 0 : int done = 0;
213 : 0 : int total = 0;
214 : :
215 : : struct physical_volume *pv;
216 : : char *pv_name;
217 : :
218 : : struct pv_list *pvl;
219 : : struct dm_list *pvslist;
220 : : struct dm_list mdas;
221 : :
222 [ # # ]: 0 : if (arg_count(cmd, allocatable_ARG) + arg_count(cmd, addtag_ARG) +
223 : 0 : arg_count(cmd, deltag_ARG) + arg_count(cmd, uuid_ARG) != 1) {
224 : 0 : log_error("Please give exactly one option of -x, -uuid, "
225 : : "--addtag or --deltag");
226 : 0 : return EINVALID_CMD_LINE;
227 : : }
228 : :
229 [ # # ][ # # ]: 0 : if (!(arg_count(cmd, all_ARG)) && !argc) {
230 : 0 : log_error("Please give a physical volume path");
231 : 0 : return EINVALID_CMD_LINE;
232 : : }
233 : :
234 [ # # ][ # # ]: 0 : if (arg_count(cmd, all_ARG) && argc) {
235 : 0 : log_error("Option a and PhysicalVolumePath are exclusive");
236 : 0 : return EINVALID_CMD_LINE;
237 : : }
238 : :
239 [ # # ]: 0 : if (argc) {
240 : 0 : log_verbose("Using physical volume(s) on command line");
241 [ # # ]: 0 : for (; opt < argc; opt++) {
242 : 0 : pv_name = argv[opt];
243 : 0 : dm_list_init(&mdas);
244 [ # # ]: 0 : if (!(pv = pv_read(cmd, pv_name, &mdas, NULL, 1, 0))) {
245 : 0 : log_error("Failed to read physical volume %s",
246 : : pv_name);
247 : 0 : continue;
248 : : }
249 : : /*
250 : : * If a PV has no MDAs it may appear to be an
251 : : * orphan until the metadata is read off
252 : : * another PV in the same VG. Detecting this
253 : : * means checking every VG by scanning every
254 : : * PV on the system.
255 : : */
256 [ # # ][ # # ]: 0 : if (is_orphan(pv) && !dm_list_size(&mdas)) {
257 [ # # ]: 0 : if (!scan_vgs_for_pvs(cmd)) {
258 : 0 : log_error("Rescan for PVs without "
259 : : "metadata areas failed.");
260 : 0 : continue;
261 : : }
262 [ # # ]: 0 : if (!(pv = pv_read(cmd, pv_name,
263 : : NULL, NULL, 1, 0))) {
264 : 0 : log_error("Failed to read "
265 : : "physical volume %s",
266 : : pv_name);
267 : 0 : continue;
268 : : }
269 : : }
270 : :
271 : 0 : total++;
272 : 0 : done += _pvchange_single(cmd, pv, NULL);
273 : : }
274 : : } else {
275 : 0 : log_verbose("Scanning for physical volume names");
276 [ # # ]: 0 : if (!(pvslist = get_pvs(cmd))) {
277 : 0 : stack;
278 : 0 : return ECMD_FAILED;
279 : : }
280 : :
281 [ # # ]: 0 : dm_list_iterate_items(pvl, pvslist) {
282 : 0 : total++;
283 : 0 : done += _pvchange_single(cmd, pvl->pv, NULL);
284 : : }
285 : : }
286 : :
287 [ # # ][ # # ]: 0 : log_print("%d physical volume%s changed / %d physical volume%s "
288 : : "not changed",
289 : : done, done == 1 ? "" : "s",
290 : : total - done, (total - done) == 1 ? "" : "s");
291 : :
292 [ # # ]: 0 : return (total == done) ? ECMD_PROCESSED : ECMD_FAILED;
293 : : }
|