2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
5 * This file is part of LVM2.
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.
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
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
34 struct physical_volume *pv;
39 struct logical_volume *lv;
42 struct pe_specifier *map;
45 static struct dm_hash_table *_create_lv_maps(struct dm_pool *mem,
46 struct volume_group *vg)
48 struct dm_hash_table *maps = dm_hash_create(32);
53 log_error("Unable to create hash table for holding "
58 dm_list_iterate_items(ll, &vg->lvs) {
59 if (ll->lv->status & SNAPSHOT)
62 if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm))))
66 if (!(lvm->map = dm_pool_zalloc(mem, sizeof(*lvm->map)
70 if (!dm_hash_insert(maps, ll->lv->name, lvm))
77 dm_hash_destroy(maps);
81 static int _fill_lv_array(struct lv_map **lvs,
82 struct dm_hash_table *maps, struct disk_list *dl)
87 memset(lvs, 0, sizeof(*lvs) * MAX_LV);
89 dm_list_iterate_items(ll, &dl->lvds) {
90 if (!(lvm = dm_hash_lookup(maps, strrchr((char *)ll->lvd.lv_name, '/')
92 log_error("Physical volume (%s) contains an "
93 "unknown logical volume (%s).",
94 dev_name(dl->dev), ll->lvd.lv_name);
98 lvm->stripes = ll->lvd.lv_stripes;
99 lvm->stripe_size = ll->lvd.lv_stripesize;
101 lvs[ll->lvd.lv_number] = lvm;
107 static int _fill_maps(struct dm_hash_table *maps, struct volume_group *vg,
108 struct dm_list *pvds)
110 struct disk_list *dl;
111 struct physical_volume *pv;
112 struct lv_map *lvms[MAX_LV], *lvm;
114 uint32_t i, lv_num, le;
116 dm_list_iterate_items(dl, pvds) {
117 pv = find_pv(vg, dl->dev);
120 /* build an array of lv's for this pv */
121 if (!_fill_lv_array(lvms, maps, dl))
124 for (i = 0; i < dl->pvd.pe_total; i++) {
125 lv_num = e[i].lv_num;
127 if (lv_num == UNMAPPED_EXTENT)
135 log_error("Invalid LV in extent map "
136 "(PV %s, PE %" PRIu32
139 dev_name(pv->dev), i,
140 lv_num, e[i].le_num);
146 if (le >= lvm->lv->le_count) {
147 log_error("logical extent number "
152 if (lvm->map[le].pv) {
153 log_error("logical extent (%u) "
154 "already mapped.", le);
158 lvm->map[le].pv = pv;
167 static int _check_single_map(struct lv_map *lvm)
171 for (i = 0; i < lvm->lv->le_count; i++) {
172 if (!lvm->map[i].pv) {
173 log_error("Logical volume (%s) contains an incomplete "
174 "mapping table.", lvm->lv->name);
182 static int _check_maps_are_complete(struct dm_hash_table *maps)
184 struct dm_hash_node *n;
187 for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
188 lvm = (struct lv_map *) dm_hash_get_data(maps, n);
190 if (!_check_single_map(lvm))
196 static uint32_t _area_length(struct lv_map *lvm, uint32_t le)
202 while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
204 lvm->map[le + len].pe == lvm->map[le].pe + len));
209 static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
211 uint32_t le = 0, len;
212 struct lv_segment *seg;
213 struct segment_type *segtype;
215 if (!(segtype = get_segtype_from_string(cmd, "striped")))
218 while (le < lvm->lv->le_count) {
219 len = _area_length(lvm, le);
221 if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le,
222 len, 0, 0, NULL, 1, len, 0, 0, 0, NULL))) {
223 log_error("Failed to allocate linear segment.");
227 if (!set_lv_segment_area_pv(seg, 0, lvm->map[le].pv,
231 dm_list_add(&lvm->lv->segments, &seg->list);
239 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)
246 * Is the next physical extent in every stripe adjacent to the last?
248 for (st = 0; st < area_count; st++)
249 if ((lvm->map[base_le + st * total_area_len + area_len].pv !=
250 lvm->map[base_le + st * total_area_len].pv) ||
251 (lvm->map[base_le + st * total_area_len].pv &&
252 lvm->map[base_le + st * total_area_len + area_len].pe !=
253 lvm->map[base_le + st * total_area_len].pe + area_len))
259 static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
261 uint32_t st, first_area_le = 0, total_area_len;
263 struct lv_segment *seg;
264 struct segment_type *segtype;
267 * Work out overall striped length
269 if (lvm->lv->le_count % lvm->stripes) {
270 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);
275 total_area_len = lvm->lv->le_count / lvm->stripes;
277 if (!(segtype = get_segtype_from_string(cmd, "striped")))
280 while (first_area_le < total_area_len) {
284 * Find how many extents are contiguous in all stripes
285 * and so can form part of this segment
287 while (_check_stripe(lvm, lvm->stripes,
288 area_len, first_area_le, total_area_len))
291 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,
296 area_len, 0, 0, 0, NULL))) {
297 log_error("Failed to allocate striped segment.");
302 * Set up start positions of each stripe in this segment
304 for (st = 0; st < seg->area_count; st++)
305 if (!set_lv_segment_area_pv(seg, st,
306 lvm->map[first_area_le + st * total_area_len].pv,
307 lvm->map[first_area_le + st * total_area_len].pe))
310 dm_list_add(&lvm->lv->segments, &seg->list);
312 first_area_le += area_len;
318 static int _build_segments(struct cmd_context *cmd, struct lv_map *lvm)
320 return (lvm->stripes > 1 ? _read_stripes(cmd, lvm) :
321 _read_linear(cmd, lvm));
324 static int _build_all_segments(struct cmd_context *cmd, struct dm_hash_table *maps)
326 struct dm_hash_node *n;
329 for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
330 lvm = (struct lv_map *) dm_hash_get_data(maps, n);
331 if (!_build_segments(cmd, lvm))
338 int import_extents(struct cmd_context *cmd, struct volume_group *vg,
339 struct dm_list *pvds)
342 struct dm_pool *scratch = dm_pool_create("lvm1 import_extents", 10 * 1024);
343 struct dm_hash_table *maps;
348 if (!(maps = _create_lv_maps(scratch, vg))) {
349 log_error("Couldn't allocate logical volume maps.");
353 if (!_fill_maps(maps, vg, pvds)) {
354 log_error("Couldn't fill logical volume maps.");
358 if (!_check_maps_are_complete(maps) && !(vg->status & PARTIAL_VG))
361 if (!_build_all_segments(cmd, maps)) {
362 log_error("Couldn't build extent segments.");
369 dm_hash_destroy(maps);
370 dm_pool_destroy(scratch);