]>
sourceware.org Git - lvm2.git/blob - lib/format1/import-extents.c
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
))))
67 * Alloc 1 extra element, so the loop in _area_length() and
68 * _check_stripe() finds the last map member as noncontinuous.
70 if (!(lvm
->map
= dm_pool_zalloc(mem
, sizeof(*lvm
->map
)
71 * (ll
->lv
->le_count
+ 1))))
74 if (!dm_hash_insert(maps
, ll
->lv
->name
, lvm
))
81 dm_hash_destroy(maps
);
85 static int _fill_lv_array(struct lv_map
**lvs
,
86 struct dm_hash_table
*maps
, struct disk_list
*dl
)
91 memset(lvs
, 0, sizeof(*lvs
) * MAX_LV
);
93 dm_list_iterate_items(ll
, &dl
->lvds
) {
94 if (!(lvm
= dm_hash_lookup(maps
, strrchr((char *)ll
->lvd
.lv_name
, '/')
96 log_error("Physical volume (%s) contains an "
97 "unknown logical volume (%s).",
98 dev_name(dl
->dev
), ll
->lvd
.lv_name
);
102 lvm
->stripes
= ll
->lvd
.lv_stripes
;
103 lvm
->stripe_size
= ll
->lvd
.lv_stripesize
;
105 lvs
[ll
->lvd
.lv_number
] = lvm
;
111 static int _fill_maps(struct dm_hash_table
*maps
, struct volume_group
*vg
,
112 struct dm_list
*pvds
)
114 struct disk_list
*dl
;
115 struct physical_volume
*pv
;
116 struct lv_map
*lvms
[MAX_LV
], *lvm
;
118 uint32_t i
, lv_num
, le
;
120 dm_list_iterate_items(dl
, pvds
) {
121 pv
= find_pv(vg
, dl
->dev
);
124 /* build an array of lv's for this pv */
125 if (!_fill_lv_array(lvms
, maps
, dl
))
128 for (i
= 0; i
< dl
->pvd
.pe_total
; i
++) {
129 lv_num
= e
[i
].lv_num
;
131 if (lv_num
== UNMAPPED_EXTENT
)
139 log_error("Invalid LV in extent map "
140 "(PV %s, PE %" PRIu32
143 dev_name(pv
->dev
), i
,
144 lv_num
, e
[i
].le_num
);
150 if (le
>= lvm
->lv
->le_count
) {
151 log_error("logical extent number "
156 if (lvm
->map
[le
].pv
) {
157 log_error("logical extent (%u) "
158 "already mapped.", le
);
162 lvm
->map
[le
].pv
= pv
;
171 static int _check_single_map(struct lv_map
*lvm
)
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
);
186 static int _check_maps_are_complete(struct dm_hash_table
*maps
)
188 struct dm_hash_node
*n
;
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
);
194 if (!_check_single_map(lvm
))
200 static uint32_t _area_length(struct lv_map
*lvm
, uint32_t le
)
206 while ((lvm
->map
[le
+ len
].pv
== lvm
->map
[le
].pv
) &&
208 lvm
->map
[le
+ len
].pe
== lvm
->map
[le
].pe
+ len
));
213 static int _read_linear(struct cmd_context
*cmd
, struct lv_map
*lvm
)
215 uint32_t le
= 0, len
;
216 struct lv_segment
*seg
;
217 struct segment_type
*segtype
;
219 if (!(segtype
= get_segtype_from_string(cmd
, "striped")))
222 while (le
< lvm
->lv
->le_count
) {
223 len
= _area_length(lvm
, le
);
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.");
231 if (!set_lv_segment_area_pv(seg
, 0, lvm
->map
[le
].pv
,
235 dm_list_add(&lvm
->lv
->segments
, &seg
->list
);
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
)
250 * Is the next physical extent in every stripe adjacent to the last?
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
))
263 static int _read_stripes(struct cmd_context
*cmd
, struct lv_map
*lvm
)
265 uint32_t st
, first_area_le
= 0, total_area_len
;
267 struct lv_segment
*seg
;
268 struct segment_type
*segtype
;
271 * Work out overall striped length
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
);
279 total_area_len
= lvm
->lv
->le_count
/ lvm
->stripes
;
281 if (!(segtype
= get_segtype_from_string(cmd
, "striped")))
284 while (first_area_le
< total_area_len
) {
288 * Find how many extents are contiguous in all stripes
289 * and so can form part of this segment
291 while (_check_stripe(lvm
, lvm
->stripes
,
292 area_len
, first_area_le
, total_area_len
))
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
,
300 area_len
, 0, 0, 0, NULL
))) {
301 log_error("Failed to allocate striped segment.");
306 * Set up start positions of each stripe in this segment
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
))
314 dm_list_add(&lvm
->lv
->segments
, &seg
->list
);
316 first_area_le
+= area_len
;
322 static int _build_segments(struct cmd_context
*cmd
, struct lv_map
*lvm
)
324 return (lvm
->stripes
> 1 ? _read_stripes(cmd
, lvm
) :
325 _read_linear(cmd
, lvm
));
328 static int _build_all_segments(struct cmd_context
*cmd
, struct dm_hash_table
*maps
)
330 struct dm_hash_node
*n
;
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
))
342 int import_extents(struct cmd_context
*cmd
, struct volume_group
*vg
,
343 struct dm_list
*pvds
)
346 struct dm_pool
*scratch
= dm_pool_create("lvm1 import_extents", 10 * 1024);
347 struct dm_hash_table
*maps
;
352 if (!(maps
= _create_lv_maps(scratch
, vg
))) {
353 log_error("Couldn't allocate logical volume maps.");
357 if (!_fill_maps(maps
, vg
, pvds
)) {
358 log_error("Couldn't fill logical volume maps.");
362 if (!_check_maps_are_complete(maps
) && !(vg
->status
& PARTIAL_VG
))
365 if (!_build_all_segments(cmd
, maps
)) {
366 log_error("Couldn't build extent segments.");
373 dm_hash_destroy(maps
);
374 dm_pool_destroy(scratch
);
This page took 0.051688 seconds and 5 git commands to generate.