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 "lib.h"
17 : : #include "metadata.h"
18 : : #include "disk-rep.h"
19 : : #include "lv_alloc.h"
20 : : #include "display.h"
21 : : #include "segtype.h"
22 : :
23 : : /*
24 : : * After much thought I have decided it is easier,
25 : : * and probably no less efficient, to convert the
26 : : * pe->le map to a full le->pe map, and then
27 : : * process this to get the segments form that
28 : : * we're after. Any code which goes directly from
29 : : * the pe->le map to segments would be gladly
30 : : * accepted, if it is less complicated than this
31 : : * file.
32 : : */
33 : : struct pe_specifier {
34 : : struct physical_volume *pv;
35 : : uint32_t pe;
36 : : };
37 : :
38 : : struct lv_map {
39 : : struct logical_volume *lv;
40 : : uint32_t stripes;
41 : : uint32_t stripe_size;
42 : : struct pe_specifier *map;
43 : : };
44 : :
45 : 0 : static struct dm_hash_table *_create_lv_maps(struct dm_pool *mem,
46 : : struct volume_group *vg)
47 : : {
48 : 0 : struct dm_hash_table *maps = dm_hash_create(32);
49 : : struct lv_list *ll;
50 : : struct lv_map *lvm;
51 : :
52 [ # # ]: 0 : if (!maps) {
53 : 0 : log_error("Unable to create hash table for holding "
54 : : "extent maps.");
55 : 0 : return NULL;
56 : : }
57 : :
58 [ # # ]: 0 : dm_list_iterate_items(ll, &vg->lvs) {
59 [ # # ]: 0 : if (ll->lv->status & SNAPSHOT)
60 : 0 : continue;
61 : :
62 [ # # ]: 0 : if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm))))
63 : 0 : goto_bad;
64 : :
65 : 0 : lvm->lv = ll->lv;
66 [ # # ]: 0 : if (!(lvm->map = dm_pool_zalloc(mem, sizeof(*lvm->map)
67 : 0 : * ll->lv->le_count)))
68 : 0 : goto_bad;
69 : :
70 [ # # ]: 0 : if (!dm_hash_insert(maps, ll->lv->name, lvm))
71 : 0 : goto_bad;
72 : : }
73 : :
74 : 0 : return maps;
75 : :
76 : : bad:
77 : 0 : dm_hash_destroy(maps);
78 : 0 : return NULL;
79 : : }
80 : :
81 : 0 : static int _fill_lv_array(struct lv_map **lvs,
82 : : struct dm_hash_table *maps, struct disk_list *dl)
83 : : {
84 : : struct lvd_list *ll;
85 : : struct lv_map *lvm;
86 : :
87 : 0 : memset(lvs, 0, sizeof(*lvs) * MAX_LV);
88 : :
89 [ # # ]: 0 : dm_list_iterate_items(ll, &dl->lvds) {
90 [ # # ]: 0 : if (!(lvm = dm_hash_lookup(maps, strrchr((char *)ll->lvd.lv_name, '/')
91 : : + 1))) {
92 : 0 : log_error("Physical volume (%s) contains an "
93 : : "unknown logical volume (%s).",
94 : : dev_name(dl->dev), ll->lvd.lv_name);
95 : 0 : return 0;
96 : : }
97 : :
98 : 0 : lvm->stripes = ll->lvd.lv_stripes;
99 : 0 : lvm->stripe_size = ll->lvd.lv_stripesize;
100 : :
101 : 0 : lvs[ll->lvd.lv_number] = lvm;
102 : : }
103 : :
104 : 0 : return 1;
105 : : }
106 : :
107 : 0 : static int _fill_maps(struct dm_hash_table *maps, struct volume_group *vg,
108 : : struct dm_list *pvds)
109 : : {
110 : : struct disk_list *dl;
111 : : struct physical_volume *pv;
112 : : struct lv_map *lvms[MAX_LV], *lvm;
113 : : struct pe_disk *e;
114 : : uint32_t i, lv_num, le;
115 : :
116 [ # # ]: 0 : dm_list_iterate_items(dl, pvds) {
117 : 0 : pv = find_pv(vg, dl->dev);
118 : 0 : e = dl->extents;
119 : :
120 : : /* build an array of lv's for this pv */
121 [ # # ]: 0 : if (!_fill_lv_array(lvms, maps, dl))
122 : 0 : return_0;
123 : :
124 [ # # ]: 0 : for (i = 0; i < dl->pvd.pe_total; i++) {
125 : 0 : lv_num = e[i].lv_num;
126 : :
127 [ # # ]: 0 : if (lv_num == UNMAPPED_EXTENT)
128 : 0 : continue;
129 : :
130 : : else {
131 : 0 : lv_num--;
132 : 0 : lvm = lvms[lv_num];
133 : :
134 [ # # ]: 0 : if (!lvm) {
135 : 0 : log_error("Invalid LV in extent map "
136 : : "(PV %s, PE %" PRIu32
137 : : ", LV %" PRIu32
138 : : ", LE %" PRIu32 ")",
139 : : dev_name(pv->dev), i,
140 : : lv_num, e[i].le_num);
141 : 0 : return 0;
142 : : }
143 : :
144 : 0 : le = e[i].le_num;
145 : :
146 [ # # ]: 0 : if (le >= lvm->lv->le_count) {
147 : 0 : log_error("logical extent number "
148 : : "out of bounds");
149 : 0 : return 0;
150 : : }
151 : :
152 [ # # ]: 0 : if (lvm->map[le].pv) {
153 : 0 : log_error("logical extent (%u) "
154 : : "already mapped.", le);
155 : 0 : return 0;
156 : : }
157 : :
158 : 0 : lvm->map[le].pv = pv;
159 : 0 : lvm->map[le].pe = i;
160 : : }
161 : : }
162 : : }
163 : :
164 : 0 : return 1;
165 : : }
166 : :
167 : 0 : static int _check_single_map(struct lv_map *lvm)
168 : : {
169 : : uint32_t i;
170 : :
171 [ # # ]: 0 : for (i = 0; i < lvm->lv->le_count; i++) {
172 [ # # ]: 0 : if (!lvm->map[i].pv) {
173 : 0 : log_error("Logical volume (%s) contains an incomplete "
174 : : "mapping table.", lvm->lv->name);
175 : 0 : return 0;
176 : : }
177 : : }
178 : :
179 : 0 : return 1;
180 : : }
181 : :
182 : 0 : static int _check_maps_are_complete(struct dm_hash_table *maps)
183 : : {
184 : : struct dm_hash_node *n;
185 : : struct lv_map *lvm;
186 : :
187 [ # # ]: 0 : for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
188 : 0 : lvm = (struct lv_map *) dm_hash_get_data(maps, n);
189 : :
190 [ # # ]: 0 : if (!_check_single_map(lvm))
191 : 0 : return_0;
192 : : }
193 : 0 : return 1;
194 : : }
195 : :
196 : 0 : static uint32_t _area_length(struct lv_map *lvm, uint32_t le)
197 : : {
198 : 0 : uint32_t len = 0;
199 : :
200 : : do
201 : 0 : len++;
202 : 0 : while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
203 : 0 : (lvm->map[le].pv &&
204 [ # # ][ # # ]: 0 : lvm->map[le + len].pe == lvm->map[le].pe + len));
[ # # ]
205 : :
206 : 0 : return len;
207 : : }
208 : :
209 : 0 : static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
210 : : {
211 : 0 : uint32_t le = 0, len;
212 : : struct lv_segment *seg;
213 : : struct segment_type *segtype;
214 : :
215 [ # # ]: 0 : if (!(segtype = get_segtype_from_string(cmd, "striped")))
216 : 0 : return_0;
217 : :
218 [ # # ]: 0 : while (le < lvm->lv->le_count) {
219 : 0 : len = _area_length(lvm, le);
220 : :
221 [ # # ]: 0 : if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le,
222 : : len, 0, 0, NULL, 1, len, 0, 0, 0, NULL))) {
223 : 0 : log_error("Failed to allocate linear segment.");
224 : 0 : return 0;
225 : : }
226 : :
227 [ # # ]: 0 : if (!set_lv_segment_area_pv(seg, 0, lvm->map[le].pv,
228 : 0 : lvm->map[le].pe))
229 : 0 : return_0;
230 : :
231 : 0 : dm_list_add(&lvm->lv->segments, &seg->list);
232 : :
233 : 0 : le += seg->len;
234 : : }
235 : :
236 : 0 : return 1;
237 : : }
238 : :
239 : 0 : static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
240 : : uint32_t area_len, uint32_t base_le,
241 : : uint32_t total_area_len)
242 : : {
243 : : uint32_t st;
244 : :
245 : : /*
246 : : * Is the next physical extent in every stripe adjacent to the last?
247 : : */
248 [ # # ]: 0 : for (st = 0; st < area_count; st++)
249 [ # # ][ # # ]: 0 : if ((lvm->map[base_le + st * total_area_len + area_len].pv !=
[ # # ]
250 : 0 : lvm->map[base_le + st * total_area_len].pv) ||
251 : 0 : (lvm->map[base_le + st * total_area_len].pv &&
252 : 0 : lvm->map[base_le + st * total_area_len + area_len].pe !=
253 : 0 : lvm->map[base_le + st * total_area_len].pe + area_len))
254 : 0 : return 0;
255 : :
256 : 0 : return 1;
257 : : }
258 : :
259 : 0 : static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
260 : : {
261 : 0 : uint32_t st, first_area_le = 0, total_area_len;
262 : : uint32_t area_len;
263 : : struct lv_segment *seg;
264 : : struct segment_type *segtype;
265 : :
266 : : /*
267 : : * Work out overall striped length
268 : : */
269 [ # # ]: 0 : if (lvm->lv->le_count % lvm->stripes) {
270 : 0 : log_error("Number of stripes (%u) incompatible "
271 : : "with logical extent count (%u) for %s",
272 : : lvm->stripes, lvm->lv->le_count, lvm->lv->name);
273 : : }
274 : :
275 : 0 : total_area_len = lvm->lv->le_count / lvm->stripes;
276 : :
277 [ # # ]: 0 : if (!(segtype = get_segtype_from_string(cmd, "striped")))
278 : 0 : return_0;
279 : :
280 [ # # ]: 0 : while (first_area_le < total_area_len) {
281 : 0 : area_len = 1;
282 : :
283 : : /*
284 : : * Find how many extents are contiguous in all stripes
285 : : * and so can form part of this segment
286 : : */
287 [ # # ]: 0 : while (_check_stripe(lvm, lvm->stripes,
288 : : area_len, first_area_le, total_area_len))
289 : 0 : area_len++;
290 : :
291 [ # # ]: 0 : if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv,
292 : : lvm->stripes * first_area_le,
293 : : lvm->stripes * area_len,
294 : : 0, lvm->stripe_size, NULL,
295 : : lvm->stripes,
296 : : area_len, 0, 0, 0, NULL))) {
297 : 0 : log_error("Failed to allocate striped segment.");
298 : 0 : return 0;
299 : : }
300 : :
301 : : /*
302 : : * Set up start positions of each stripe in this segment
303 : : */
304 [ # # ]: 0 : for (st = 0; st < seg->area_count; st++)
305 [ # # ]: 0 : if (!set_lv_segment_area_pv(seg, st,
306 : 0 : lvm->map[first_area_le + st * total_area_len].pv,
307 : 0 : lvm->map[first_area_le + st * total_area_len].pe))
308 : 0 : return_0;
309 : :
310 : 0 : dm_list_add(&lvm->lv->segments, &seg->list);
311 : :
312 : 0 : first_area_le += area_len;
313 : : }
314 : :
315 : 0 : return 1;
316 : : }
317 : :
318 : 0 : static int _build_segments(struct cmd_context *cmd, struct lv_map *lvm)
319 : : {
320 [ # # ]: 0 : return (lvm->stripes > 1 ? _read_stripes(cmd, lvm) :
321 : 0 : _read_linear(cmd, lvm));
322 : : }
323 : :
324 : 0 : static int _build_all_segments(struct cmd_context *cmd, struct dm_hash_table *maps)
325 : : {
326 : : struct dm_hash_node *n;
327 : : struct lv_map *lvm;
328 : :
329 [ # # ]: 0 : for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
330 : 0 : lvm = (struct lv_map *) dm_hash_get_data(maps, n);
331 [ # # ]: 0 : if (!_build_segments(cmd, lvm))
332 : 0 : return_0;
333 : : }
334 : :
335 : 0 : return 1;
336 : : }
337 : :
338 : 0 : int import_extents(struct cmd_context *cmd, struct volume_group *vg,
339 : : struct dm_list *pvds)
340 : : {
341 : 0 : int r = 0;
342 : 0 : struct dm_pool *scratch = dm_pool_create("lvm1 import_extents", 10 * 1024);
343 : : struct dm_hash_table *maps;
344 : :
345 [ # # ]: 0 : if (!scratch)
346 : 0 : return_0;
347 : :
348 [ # # ]: 0 : if (!(maps = _create_lv_maps(scratch, vg))) {
349 : 0 : log_error("Couldn't allocate logical volume maps.");
350 : 0 : goto out;
351 : : }
352 : :
353 [ # # ]: 0 : if (!_fill_maps(maps, vg, pvds)) {
354 : 0 : log_error("Couldn't fill logical volume maps.");
355 : 0 : goto out;
356 : : }
357 : :
358 [ # # ][ # # ]: 0 : if (!_check_maps_are_complete(maps) && !(vg->status & PARTIAL_VG))
359 : 0 : goto_out;
360 : :
361 [ # # ]: 0 : if (!_build_all_segments(cmd, maps)) {
362 : 0 : log_error("Couldn't build extent segments.");
363 : 0 : goto out;
364 : : }
365 : 0 : r = 1;
366 : :
367 : : out:
368 [ # # ]: 0 : if (maps)
369 : 0 : dm_hash_destroy(maps);
370 : 0 : dm_pool_destroy(scratch);
371 : 0 : return r;
372 : : }
|