4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 * After much thought I have decided it is easier,
27 * and probably no less efficient, to convert the
28 * pe->le map to a full le->pe map, and then
29 * process this to get the segments form that
30 * we're after. Any code which goes directly from
31 * the pe->le map to segments would be gladly
32 * accepted, if it is less complicated than this
36 struct physical_volume
*pv
;
41 struct logical_volume
*lv
;
44 struct pe_specifier
*map
;
47 static struct dm_hash_table
*_create_lv_maps(struct dm_pool
*mem
,
48 struct volume_group
*vg
)
50 struct dm_hash_table
*maps
= dm_hash_create(32);
55 log_error("Unable to create hash table for holding "
60 dm_list_iterate_items(ll
, &vg
->lvs
) {
61 if (ll
->lv
->status
& SNAPSHOT
)
64 if (!(lvm
= dm_pool_alloc(mem
, sizeof(*lvm
))))
68 if (!(lvm
->map
= dm_pool_zalloc(mem
, sizeof(*lvm
->map
)
72 if (!dm_hash_insert(maps
, ll
->lv
->name
, lvm
))
79 dm_hash_destroy(maps
);
83 static int _fill_lv_array(struct lv_map
**lvs
,
84 struct dm_hash_table
*maps
, struct disk_list
*dl
)
89 memset(lvs
, 0, sizeof(*lvs
) * MAX_LV
);
91 dm_list_iterate_items(ll
, &dl
->lvds
) {
92 if (!(lvm
= dm_hash_lookup(maps
, strrchr((char *)ll
->lvd
.lv_name
, '/')
94 log_error("Physical volume (%s) contains an "
95 "unknown logical volume (%s).",
96 dev_name(dl
->dev
), ll
->lvd
.lv_name
);
100 lvm
->stripes
= ll
->lvd
.lv_stripes
;
101 lvm
->stripe_size
= ll
->lvd
.lv_stripesize
;
103 lvs
[ll
->lvd
.lv_number
] = lvm
;
109 static int _fill_maps(struct dm_hash_table
*maps
, struct volume_group
*vg
,
110 struct dm_list
*pvds
)
112 struct disk_list
*dl
;
113 struct physical_volume
*pv
;
114 struct lv_map
*lvms
[MAX_LV
], *lvm
;
116 uint32_t i
, lv_num
, le
;
118 dm_list_iterate_items(dl
, pvds
) {
119 pv
= find_pv(vg
, dl
->dev
);
122 /* build an array of lv's for this pv */
123 if (!_fill_lv_array(lvms
, maps
, dl
))
126 for (i
= 0; i
< dl
->pvd
.pe_total
; i
++) {
127 lv_num
= e
[i
].lv_num
;
129 if (lv_num
== UNMAPPED_EXTENT
)
137 log_error("Invalid LV in extent map "
138 "(PV %s, PE %" PRIu32
141 dev_name(pv
->dev
), i
,
142 lv_num
, e
[i
].le_num
);
148 if (le
>= lvm
->lv
->le_count
) {
149 log_error("logical extent number "
154 if (lvm
->map
[le
].pv
) {
155 log_error("logical extent (%u) "
156 "already mapped.", le
);
160 lvm
->map
[le
].pv
= pv
;
169 static int _check_single_map(struct lv_map
*lvm
)
173 for (i
= 0; i
< lvm
->lv
->le_count
; i
++) {
174 if (!lvm
->map
[i
].pv
) {
175 log_error("Logical volume (%s) contains an incomplete "
176 "mapping table.", lvm
->lv
->name
);
184 static int _check_maps_are_complete(struct dm_hash_table
*maps
)
186 struct dm_hash_node
*n
;
189 for (n
= dm_hash_get_first(maps
); n
; n
= dm_hash_get_next(maps
, n
)) {
190 lvm
= (struct lv_map
*) dm_hash_get_data(maps
, n
);
192 if (!_check_single_map(lvm
))
198 static uint32_t _area_length(struct lv_map
*lvm
, uint32_t le
)
204 while ((lvm
->map
[le
+ len
].pv
== lvm
->map
[le
].pv
) &&
206 lvm
->map
[le
+ len
].pe
== lvm
->map
[le
].pe
+ len
));
211 static int _read_linear(struct cmd_context
*cmd
, struct lv_map
*lvm
)
213 uint32_t le
= 0, len
;
214 struct lv_segment
*seg
;
215 struct segment_type
*segtype
;
217 if (!(segtype
= get_segtype_from_string(cmd
, "striped")))
220 while (le
< lvm
->lv
->le_count
) {
221 len
= _area_length(lvm
, le
);
223 if (!(seg
= alloc_lv_segment(cmd
->mem
, segtype
, lvm
->lv
, le
,
224 len
, 0, 0, NULL
, 1, len
, 0, 0, 0))) {
225 log_error("Failed to allocate linear segment.");
229 if (!set_lv_segment_area_pv(seg
, 0, lvm
->map
[le
].pv
,
233 dm_list_add(&lvm
->lv
->segments
, &seg
->list
);
241 static int _check_stripe(struct lv_map
*lvm
, uint32_t area_count
,
242 uint32_t area_len
, uint32_t base_le
,
243 uint32_t total_area_len
)
248 * Is the next physical extent in every stripe adjacent to the last?
250 for (st
= 0; st
< area_count
; st
++)
251 if ((lvm
->map
[base_le
+ st
* total_area_len
+ area_len
].pv
!=
252 lvm
->map
[base_le
+ st
* total_area_len
].pv
) ||
253 (lvm
->map
[base_le
+ st
* total_area_len
].pv
&&
254 lvm
->map
[base_le
+ st
* total_area_len
+ area_len
].pe
!=
255 lvm
->map
[base_le
+ st
* total_area_len
].pe
+ area_len
))
261 static int _read_stripes(struct cmd_context
*cmd
, struct lv_map
*lvm
)
263 uint32_t st
, first_area_le
= 0, total_area_len
;
265 struct lv_segment
*seg
;
266 struct segment_type
*segtype
;
269 * Work out overall striped length
271 if (lvm
->lv
->le_count
% lvm
->stripes
) {
272 log_error("Number of stripes (%u) incompatible "
273 "with logical extent count (%u) for %s",
274 lvm
->stripes
, lvm
->lv
->le_count
, lvm
->lv
->name
);
277 total_area_len
= lvm
->lv
->le_count
/ lvm
->stripes
;
279 if (!(segtype
= get_segtype_from_string(cmd
, "striped")))
282 while (first_area_le
< total_area_len
) {
286 * Find how many extents are contiguous in all stripes
287 * and so can form part of this segment
289 while (_check_stripe(lvm
, lvm
->stripes
,
290 area_len
, first_area_le
, total_area_len
))
293 if (!(seg
= alloc_lv_segment(cmd
->mem
, segtype
, lvm
->lv
,
294 lvm
->stripes
* first_area_le
,
295 lvm
->stripes
* area_len
,
296 0, lvm
->stripe_size
, NULL
,
298 area_len
, 0, 0, 0))) {
299 log_error("Failed to allocate striped segment.");
304 * Set up start positions of each stripe in this segment
306 for (st
= 0; st
< seg
->area_count
; st
++)
307 if (!set_lv_segment_area_pv(seg
, st
,
308 lvm
->map
[first_area_le
+ st
* total_area_len
].pv
,
309 lvm
->map
[first_area_le
+ st
* total_area_len
].pe
))
312 dm_list_add(&lvm
->lv
->segments
, &seg
->list
);
314 first_area_le
+= area_len
;
320 static int _build_segments(struct cmd_context
*cmd
, struct lv_map
*lvm
)
322 return (lvm
->stripes
> 1 ? _read_stripes(cmd
, lvm
) :
323 _read_linear(cmd
, lvm
));
326 static int _build_all_segments(struct cmd_context
*cmd
, struct dm_hash_table
*maps
)
328 struct dm_hash_node
*n
;
331 for (n
= dm_hash_get_first(maps
); n
; n
= dm_hash_get_next(maps
, n
)) {
332 lvm
= (struct lv_map
*) dm_hash_get_data(maps
, n
);
333 if (!_build_segments(cmd
, lvm
))
340 int import_extents(struct cmd_context
*cmd
, struct volume_group
*vg
,
341 struct dm_list
*pvds
)
344 struct dm_pool
*scratch
= dm_pool_create("lvm1 import_extents", 10 * 1024);
345 struct dm_hash_table
*maps
;
350 if (!(maps
= _create_lv_maps(scratch
, vg
))) {
351 log_error("Couldn't allocate logical volume maps.");
355 if (!_fill_maps(maps
, vg
, pvds
)) {
356 log_error("Couldn't fill logical volume maps.");
360 if (!_check_maps_are_complete(maps
) && !(vg
->status
& PARTIAL_VG
))
363 if (!_build_all_segments(cmd
, maps
)) {
364 log_error("Couldn't build extent segments.");
371 dm_hash_destroy(maps
);
372 dm_pool_destroy(scratch
);