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