Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / gpl2 / lvm2 / dist / lib / format1 / import-extents.c
blobd833c2a052cdfc66fcacd3dde140b6621f48930a
1 /* $NetBSD$ */
3 /*
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
18 #include "lib.h"
19 #include "metadata.h"
20 #include "disk-rep.h"
21 #include "lv_alloc.h"
22 #include "display.h"
23 #include "segtype.h"
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
33 * file.
35 struct pe_specifier {
36 struct physical_volume *pv;
37 uint32_t pe;
40 struct lv_map {
41 struct logical_volume *lv;
42 uint32_t stripes;
43 uint32_t stripe_size;
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);
51 struct lv_list *ll;
52 struct lv_map *lvm;
54 if (!maps) {
55 log_error("Unable to create hash table for holding "
56 "extent maps.");
57 return NULL;
60 dm_list_iterate_items(ll, &vg->lvs) {
61 if (ll->lv->status & SNAPSHOT)
62 continue;
64 if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm))))
65 goto_bad;
67 lvm->lv = ll->lv;
68 if (!(lvm->map = dm_pool_zalloc(mem, sizeof(*lvm->map)
69 * ll->lv->le_count)))
70 goto_bad;
72 if (!dm_hash_insert(maps, ll->lv->name, lvm))
73 goto_bad;
76 return maps;
78 bad:
79 dm_hash_destroy(maps);
80 return NULL;
83 static int _fill_lv_array(struct lv_map **lvs,
84 struct dm_hash_table *maps, struct disk_list *dl)
86 struct lvd_list *ll;
87 struct lv_map *lvm;
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, '/')
93 + 1))) {
94 log_error("Physical volume (%s) contains an "
95 "unknown logical volume (%s).",
96 dev_name(dl->dev), ll->lvd.lv_name);
97 return 0;
100 lvm->stripes = ll->lvd.lv_stripes;
101 lvm->stripe_size = ll->lvd.lv_stripesize;
103 lvs[ll->lvd.lv_number] = lvm;
106 return 1;
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;
115 struct pe_disk *e;
116 uint32_t i, lv_num, le;
118 dm_list_iterate_items(dl, pvds) {
119 pv = find_pv(vg, dl->dev);
120 e = dl->extents;
122 /* build an array of lv's for this pv */
123 if (!_fill_lv_array(lvms, maps, dl))
124 return_0;
126 for (i = 0; i < dl->pvd.pe_total; i++) {
127 lv_num = e[i].lv_num;
129 if (lv_num == UNMAPPED_EXTENT)
130 continue;
132 else {
133 lv_num--;
134 lvm = lvms[lv_num];
136 if (!lvm) {
137 log_error("Invalid LV in extent map "
138 "(PV %s, PE %" PRIu32
139 ", LV %" PRIu32
140 ", LE %" PRIu32 ")",
141 dev_name(pv->dev), i,
142 lv_num, e[i].le_num);
143 return 0;
146 le = e[i].le_num;
148 if (le >= lvm->lv->le_count) {
149 log_error("logical extent number "
150 "out of bounds");
151 return 0;
154 if (lvm->map[le].pv) {
155 log_error("logical extent (%u) "
156 "already mapped.", le);
157 return 0;
160 lvm->map[le].pv = pv;
161 lvm->map[le].pe = i;
166 return 1;
169 static int _check_single_map(struct lv_map *lvm)
171 uint32_t i;
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);
177 return 0;
181 return 1;
184 static int _check_maps_are_complete(struct dm_hash_table *maps)
186 struct dm_hash_node *n;
187 struct lv_map *lvm;
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))
193 return_0;
195 return 1;
198 static uint32_t _area_length(struct lv_map *lvm, uint32_t le)
200 uint32_t len = 0;
203 len++;
204 while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
205 (lvm->map[le].pv &&
206 lvm->map[le + len].pe == lvm->map[le].pe + len));
208 return 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")))
218 return_0;
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.");
226 return 0;
229 if (!set_lv_segment_area_pv(seg, 0, lvm->map[le].pv,
230 lvm->map[le].pe))
231 return_0;
233 dm_list_add(&lvm->lv->segments, &seg->list);
235 le += seg->len;
238 return 1;
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)
245 uint32_t st;
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))
256 return 0;
258 return 1;
261 static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
263 uint32_t st, first_area_le = 0, total_area_len;
264 uint32_t 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")))
280 return_0;
282 while (first_area_le < total_area_len) {
283 area_len = 1;
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))
291 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,
297 lvm->stripes,
298 area_len, 0, 0, 0))) {
299 log_error("Failed to allocate striped segment.");
300 return 0;
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))
310 return_0;
312 dm_list_add(&lvm->lv->segments, &seg->list);
314 first_area_le += area_len;
317 return 1;
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;
329 struct lv_map *lvm;
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))
334 return_0;
337 return 1;
340 int import_extents(struct cmd_context *cmd, struct volume_group *vg,
341 struct dm_list *pvds)
343 int r = 0;
344 struct dm_pool *scratch = dm_pool_create("lvm1 import_extents", 10 * 1024);
345 struct dm_hash_table *maps;
347 if (!scratch)
348 return_0;
350 if (!(maps = _create_lv_maps(scratch, vg))) {
351 log_error("Couldn't allocate logical volume maps.");
352 goto out;
355 if (!_fill_maps(maps, vg, pvds)) {
356 log_error("Couldn't fill logical volume maps.");
357 goto out;
360 if (!_check_maps_are_complete(maps) && !(vg->status & PARTIAL_VG))
361 goto_out;
363 if (!_build_all_segments(cmd, maps)) {
364 log_error("Couldn't build extent segments.");
365 goto out;
367 r = 1;
369 out:
370 if (maps)
371 dm_hash_destroy(maps);
372 dm_pool_destroy(scratch);
373 return r;