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