Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 : : * Copyright (C) 2004-2006 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 : : /*
17 : : * Translates between disk and in-core formats.
18 : : */
19 : :
20 : : #include "lib.h"
21 : : #include "disk-rep.h"
22 : : #include "lvm-string.h"
23 : : #include "filter.h"
24 : : #include "toolcontext.h"
25 : : #include "segtype.h"
26 : : #include "pv_alloc.h"
27 : : #include "display.h"
28 : : #include "lvmcache.h"
29 : : #include "metadata.h"
30 : :
31 : : #include <time.h>
32 : :
33 : 0 : static int _check_vg_name(const char *name)
34 : : {
35 : 0 : return strlen(name) < NAME_LEN;
36 : : }
37 : :
38 : : /*
39 : : * Extracts the last part of a path.
40 : : */
41 : 0 : static char *_create_lv_name(struct dm_pool *mem, const char *full_name)
42 : : {
43 : 0 : const char *ptr = strrchr(full_name, '/');
44 : :
45 [ # # ]: 0 : if (!ptr)
46 : 0 : ptr = full_name;
47 : : else
48 : 0 : ptr++;
49 : :
50 : 0 : return dm_pool_strdup(mem, ptr);
51 : : }
52 : :
53 : 0 : int import_pv(const struct format_type *fmt, struct dm_pool *mem,
54 : : struct device *dev, struct volume_group *vg,
55 : : struct physical_volume *pv, struct pv_disk *pvd,
56 : : struct vg_disk *vgd)
57 : : {
58 : : uint64_t size;
59 : :
60 : 0 : memset(pv, 0, sizeof(*pv));
61 : 0 : memcpy(&pv->id, pvd->pv_uuid, ID_LEN);
62 : :
63 : 0 : pv->dev = dev;
64 [ # # ]: 0 : if (!*pvd->vg_name)
65 : 0 : pv->vg_name = fmt->orphan_vg_name;
66 [ # # ]: 0 : else if (!(pv->vg_name = dm_pool_strdup(mem, (char *)pvd->vg_name))) {
67 : 0 : log_error("Volume Group name allocation failed.");
68 : 0 : return 0;
69 : : }
70 : :
71 : 0 : memcpy(&pv->vgid, vgd->vg_uuid, sizeof(vg->id));
72 : :
73 : : /* Store system_id from first PV if PV belongs to a VG */
74 [ # # ][ # # ]: 0 : if (vg && !*vg->system_id)
75 : 0 : strncpy(vg->system_id, (char *)pvd->system_id, NAME_LEN);
76 : :
77 [ # # ][ # # ]: 0 : if (vg &&
78 : 0 : strncmp(vg->system_id, (char *)pvd->system_id, sizeof(pvd->system_id)))
79 : 0 : log_very_verbose("System ID %s on %s differs from %s for "
80 : : "volume group", pvd->system_id,
81 : : pv_dev_name(pv), vg->system_id);
82 : :
83 : : /*
84 : : * If exported, we still need to flag in pv->status too because
85 : : * we don't always have a struct volume_group when we need this.
86 : : */
87 [ # # ]: 0 : if (pvd->pv_status & VG_EXPORTED)
88 : 0 : pv->status |= EXPORTED_VG;
89 : :
90 [ # # ]: 0 : if (pvd->pv_allocatable)
91 : 0 : pv->status |= ALLOCATABLE_PV;
92 : :
93 : 0 : pv->size = pvd->pv_size;
94 : 0 : pv->pe_size = pvd->pe_size;
95 : 0 : pv->pe_start = pvd->pe_start;
96 : 0 : pv->pe_count = pvd->pe_total;
97 : 0 : pv->pe_alloc_count = 0;
98 : 0 : pv->pe_align = 0;
99 : :
100 : : /* Fix up pv size if missing or impossibly large */
101 [ # # ][ # # ]: 0 : if (!pv->size || pv->size > (1ULL << 62)) {
102 [ # # ]: 0 : if (!dev_get_size(dev, &pv->size)) {
103 : 0 : log_error("%s: Couldn't get size.", pv_dev_name(pv));
104 : 0 : return 0;
105 : : }
106 : 0 : log_verbose("Fixing up missing format1 size (%s) "
107 : : "for PV %s", display_size(fmt->cmd, pv->size),
108 : : pv_dev_name(pv));
109 [ # # ]: 0 : if (vg) {
110 : 0 : size = pv->pe_count * (uint64_t) vg->extent_size +
111 : : pv->pe_start;
112 [ # # ]: 0 : if (size > pv->size)
113 : 0 : log_warn("WARNING: Physical Volume %s is too "
114 : : "large for underlying device",
115 : : pv_dev_name(pv));
116 : : }
117 : : }
118 : :
119 : 0 : dm_list_init(&pv->tags);
120 : 0 : dm_list_init(&pv->segments);
121 : :
122 [ # # ]: 0 : if (!alloc_pv_segment_whole_pv(mem, pv))
123 : 0 : return_0;
124 : :
125 : 0 : return 1;
126 : : }
127 : :
128 : 0 : static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
129 : : {
130 : :
131 [ # # ]: 0 : if (dm_snprintf(s, NAME_LEN, "%s%s%lu",
132 : : prefix, cmd->hostname, time(NULL)) < 0) {
133 : 0 : log_error("Generated system_id too long");
134 : 0 : return 0;
135 : : }
136 : :
137 : 0 : return 1;
138 : : }
139 : :
140 : 0 : int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute((unused)),
141 : : struct volume_group *vg,
142 : : struct pv_disk *pvd, struct physical_volume *pv)
143 : : {
144 : 0 : memset(pvd, 0, sizeof(*pvd));
145 : :
146 : 0 : pvd->id[0] = 'H';
147 : 0 : pvd->id[1] = 'M';
148 : 0 : pvd->version = 1;
149 : :
150 : 0 : memcpy(pvd->pv_uuid, pv->id.uuid, ID_LEN);
151 : :
152 [ # # ][ # # ]: 0 : if (pv->vg_name && !is_orphan(pv)) {
153 [ # # ]: 0 : if (!_check_vg_name(pv->vg_name))
154 : 0 : return_0;
155 : 0 : strncpy((char *)pvd->vg_name, pv->vg_name, sizeof(pvd->vg_name));
156 : : }
157 : :
158 : : /* Preserve existing system_id if it exists */
159 [ # # ][ # # ]: 0 : if (vg && *vg->system_id)
160 : 0 : strncpy((char *)pvd->system_id, vg->system_id, sizeof(pvd->system_id));
161 : :
162 : : /* Is VG already exported or being exported? */
163 [ # # ][ # # ]: 0 : if (vg && vg_is_exported(vg)) {
164 : : /* Does system_id need setting? */
165 [ # # ][ # # ]: 0 : if (!*vg->system_id ||
166 : 0 : strncmp(vg->system_id, EXPORTED_TAG,
167 : 0 : sizeof(EXPORTED_TAG) - 1)) {
168 [ # # ]: 0 : if (!_system_id(cmd, (char *)pvd->system_id, EXPORTED_TAG))
169 : 0 : return_0;
170 : : }
171 [ # # ]: 0 : if (strlen((char *)pvd->vg_name) + sizeof(EXPORTED_TAG) >
172 : : sizeof(pvd->vg_name)) {
173 : 0 : log_error("Volume group name %s too long to export",
174 : : pvd->vg_name);
175 : 0 : return 0;
176 : : }
177 : 0 : strcat((char *)pvd->vg_name, EXPORTED_TAG);
178 : : }
179 : :
180 : : /* Is VG being imported? */
181 [ # # ][ # # ]: 0 : if (vg && !vg_is_exported(vg) && *vg->system_id &&
[ # # ][ # # ]
182 : 0 : !strncmp(vg->system_id, EXPORTED_TAG, sizeof(EXPORTED_TAG) - 1)) {
183 [ # # ]: 0 : if (!_system_id(cmd, (char *)pvd->system_id, IMPORTED_TAG))
184 : 0 : return_0;
185 : : }
186 : :
187 : : /* Generate system_id if PV is in VG */
188 [ # # ]: 0 : if (!pvd->system_id || !*pvd->system_id)
189 [ # # ]: 0 : if (!_system_id(cmd, (char *)pvd->system_id, ""))
190 : 0 : return_0;
191 : :
192 : : /* Update internal system_id if we changed it */
193 [ # # ][ # # ]: 0 : if (vg &&
[ # # ]
194 : 0 : (!*vg->system_id ||
195 : 0 : strncmp(vg->system_id, (char *)pvd->system_id, sizeof(pvd->system_id))))
196 : 0 : strncpy(vg->system_id, (char *)pvd->system_id, NAME_LEN);
197 : :
198 : : //pvd->pv_major = MAJOR(pv->dev);
199 : :
200 [ # # ]: 0 : if (pv->status & ALLOCATABLE_PV)
201 : 0 : pvd->pv_allocatable = PV_ALLOCATABLE;
202 : :
203 : 0 : pvd->pv_size = pv->size;
204 : 0 : pvd->lv_cur = 0; /* this is set when exporting the lv list */
205 [ # # ]: 0 : if (vg)
206 : 0 : pvd->pe_size = vg->extent_size;
207 : : else
208 : 0 : pvd->pe_size = pv->pe_size;
209 : 0 : pvd->pe_total = pv->pe_count;
210 : 0 : pvd->pe_allocated = pv->pe_alloc_count;
211 : 0 : pvd->pe_start = pv->pe_start;
212 : :
213 : 0 : return 1;
214 : : }
215 : :
216 : 0 : int import_vg(struct dm_pool *mem,
217 : : struct volume_group *vg, struct disk_list *dl)
218 : : {
219 : 0 : struct vg_disk *vgd = &dl->vgd;
220 : 0 : memcpy(vg->id.uuid, vgd->vg_uuid, ID_LEN);
221 : :
222 [ # # ]: 0 : if (!_check_vg_name((char *)dl->pvd.vg_name))
223 : 0 : return_0;
224 : :
225 [ # # ]: 0 : if (!(vg->name = dm_pool_strdup(mem, (char *)dl->pvd.vg_name)))
226 : 0 : return_0;
227 : :
228 [ # # ]: 0 : if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN)))
229 : 0 : return_0;
230 : :
231 : 0 : *vg->system_id = '\0';
232 : :
233 [ # # ]: 0 : if (vgd->vg_status & VG_EXPORTED)
234 : 0 : vg->status |= EXPORTED_VG;
235 : :
236 [ # # ]: 0 : if (vgd->vg_status & VG_EXTENDABLE)
237 : 0 : vg->status |= RESIZEABLE_VG;
238 : :
239 [ # # ]: 0 : if (vgd->vg_access & VG_READ)
240 : 0 : vg->status |= LVM_READ;
241 : :
242 [ # # ]: 0 : if (vgd->vg_access & VG_WRITE)
243 : 0 : vg->status |= LVM_WRITE;
244 : :
245 [ # # ]: 0 : if (vgd->vg_access & VG_CLUSTERED)
246 : 0 : vg->status |= CLUSTERED;
247 : :
248 [ # # ]: 0 : if (vgd->vg_access & VG_SHARED)
249 : 0 : vg->status |= SHARED;
250 : :
251 : 0 : vg->extent_size = vgd->pe_size;
252 : 0 : vg->extent_count = vgd->pe_total;
253 : 0 : vg->free_count = vgd->pe_total;
254 : 0 : vg->max_lv = vgd->lv_max;
255 : 0 : vg->max_pv = vgd->pv_max;
256 : 0 : vg->alloc = ALLOC_NORMAL;
257 : :
258 : 0 : return 1;
259 : : }
260 : :
261 : 0 : int export_vg(struct vg_disk *vgd, struct volume_group *vg)
262 : : {
263 : 0 : memset(vgd, 0, sizeof(*vgd));
264 : 0 : memcpy(vgd->vg_uuid, vg->id.uuid, ID_LEN);
265 : :
266 [ # # ]: 0 : if (vg->status & LVM_READ)
267 : 0 : vgd->vg_access |= VG_READ;
268 : :
269 [ # # ]: 0 : if (vg->status & LVM_WRITE)
270 : 0 : vgd->vg_access |= VG_WRITE;
271 : :
272 [ # # ]: 0 : if (vg_is_clustered(vg))
273 : 0 : vgd->vg_access |= VG_CLUSTERED;
274 : :
275 [ # # ]: 0 : if (vg->status & SHARED)
276 : 0 : vgd->vg_access |= VG_SHARED;
277 : :
278 [ # # ]: 0 : if (vg_is_exported(vg))
279 : 0 : vgd->vg_status |= VG_EXPORTED;
280 : :
281 [ # # ]: 0 : if (vg_is_resizeable(vg))
282 : 0 : vgd->vg_status |= VG_EXTENDABLE;
283 : :
284 : 0 : vgd->lv_max = vg->max_lv;
285 : 0 : vgd->lv_cur = vg_visible_lvs(vg) + snapshot_count(vg);
286 : :
287 : 0 : vgd->pv_max = vg->max_pv;
288 : 0 : vgd->pv_cur = vg->pv_count;
289 : :
290 : 0 : vgd->pe_size = vg->extent_size;
291 : 0 : vgd->pe_total = vg->extent_count;
292 : 0 : vgd->pe_allocated = vg->extent_count - vg->free_count;
293 : :
294 : 0 : return 1;
295 : : }
296 : :
297 : 0 : int import_lv(struct cmd_context *cmd, struct dm_pool *mem,
298 : : struct logical_volume *lv, struct lv_disk *lvd)
299 : : {
300 [ # # ]: 0 : if (!(lv->name = _create_lv_name(mem, (char *)lvd->lv_name)))
301 : 0 : return_0;
302 : :
303 : 0 : lv->status |= VISIBLE_LV;
304 : :
305 [ # # ]: 0 : if (lvd->lv_status & LV_SPINDOWN)
306 : 0 : lv->status |= SPINDOWN_LV;
307 : :
308 [ # # ]: 0 : if (lvd->lv_status & LV_PERSISTENT_MINOR) {
309 : 0 : lv->status |= FIXED_MINOR;
310 : 0 : lv->minor = MINOR(lvd->lv_dev);
311 : 0 : lv->major = MAJOR(lvd->lv_dev);
312 : : } else {
313 : 0 : lv->major = -1;
314 : 0 : lv->minor = -1;
315 : : }
316 : :
317 [ # # ]: 0 : if (lvd->lv_access & LV_READ)
318 : 0 : lv->status |= LVM_READ;
319 : :
320 [ # # ]: 0 : if (lvd->lv_access & LV_WRITE)
321 : 0 : lv->status |= LVM_WRITE;
322 : :
323 [ # # ]: 0 : if (lvd->lv_badblock)
324 : 0 : lv->status |= BADBLOCK_ON;
325 : :
326 : : /* Drop the unused LV_STRICT here */
327 [ # # ]: 0 : if (lvd->lv_allocation & LV_CONTIGUOUS)
328 : 0 : lv->alloc = ALLOC_CONTIGUOUS;
329 : : else
330 : 0 : lv->alloc = ALLOC_NORMAL;
331 : :
332 [ # # ]: 0 : if (!lvd->lv_read_ahead)
333 : 0 : lv->read_ahead = cmd->default_settings.read_ahead;
334 : : else
335 : 0 : lv->read_ahead = lvd->lv_read_ahead;
336 : :
337 : 0 : lv->size = lvd->lv_size;
338 : 0 : lv->le_count = lvd->lv_allocated_le;
339 : :
340 : 0 : return 1;
341 : : }
342 : :
343 : 0 : static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
344 : : struct logical_volume *lv, const char *dev_dir)
345 : : {
346 : 0 : memset(lvd, 0, sizeof(*lvd));
347 : 0 : snprintf((char *)lvd->lv_name, sizeof(lvd->lv_name), "%s%s/%s",
348 : : dev_dir, vg->name, lv->name);
349 : :
350 : 0 : strcpy((char *)lvd->vg_name, vg->name);
351 : :
352 [ # # ]: 0 : if (lv->status & LVM_READ)
353 : 0 : lvd->lv_access |= LV_READ;
354 : :
355 [ # # ]: 0 : if (lv->status & LVM_WRITE)
356 : 0 : lvd->lv_access |= LV_WRITE;
357 : :
358 [ # # ]: 0 : if (lv->status & SPINDOWN_LV)
359 : 0 : lvd->lv_status |= LV_SPINDOWN;
360 : :
361 [ # # ]: 0 : if (lv->status & FIXED_MINOR) {
362 : 0 : lvd->lv_status |= LV_PERSISTENT_MINOR;
363 : 0 : lvd->lv_dev = MKDEV(lv->major, lv->minor);
364 : : } else {
365 : 0 : lvd->lv_dev = MKDEV(LVM_BLK_MAJOR, lvnum_from_lvid(&lv->lvid));
366 : : }
367 : :
368 [ # # ][ # # ]: 0 : if (lv->read_ahead == DM_READ_AHEAD_AUTO ||
369 : 0 : lv->read_ahead == DM_READ_AHEAD_NONE)
370 : 0 : lvd->lv_read_ahead = 0;
371 : : else
372 : 0 : lvd->lv_read_ahead = lv->read_ahead;
373 : :
374 : 0 : lvd->lv_stripes =
375 : 0 : dm_list_item(lv->segments.n, struct lv_segment)->area_count;
376 : 0 : lvd->lv_stripesize =
377 : 0 : dm_list_item(lv->segments.n, struct lv_segment)->stripe_size;
378 : :
379 : 0 : lvd->lv_size = lv->size;
380 : 0 : lvd->lv_allocated_le = lv->le_count;
381 : :
382 [ # # ]: 0 : if (lv->status & BADBLOCK_ON)
383 : 0 : lvd->lv_badblock = LV_BADBLOCK_ON;
384 : :
385 [ # # ]: 0 : if (lv->alloc == ALLOC_CONTIGUOUS)
386 : 0 : lvd->lv_allocation |= LV_CONTIGUOUS;
387 : 0 : }
388 : :
389 : 0 : int export_extents(struct disk_list *dl, uint32_t lv_num,
390 : : struct logical_volume *lv, struct physical_volume *pv)
391 : : {
392 : : struct pe_disk *ped;
393 : : struct lv_segment *seg;
394 : : uint32_t pe, s;
395 : :
396 [ # # ]: 0 : dm_list_iterate_items(seg, &lv->segments) {
397 [ # # ]: 0 : for (s = 0; s < seg->area_count; s++) {
398 [ # # ]: 0 : if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
399 : 0 : log_error("Segment type %s in LV %s: "
400 : : "unsupported by format1",
401 : : seg->segtype->name, lv->name);
402 : 0 : return 0;
403 : : }
404 [ # # ]: 0 : if (seg_type(seg, s) != AREA_PV) {
405 : 0 : log_error("Non-PV stripe found in LV %s: "
406 : : "unsupported by format1", lv->name);
407 : 0 : return 0;
408 : : }
409 [ # # ]: 0 : if (seg_pv(seg, s) != pv)
410 : 0 : continue; /* not our pv */
411 : :
412 [ # # ]: 0 : for (pe = 0; pe < (seg->len / seg->area_count); pe++) {
413 : 0 : ped = &dl->extents[pe + seg_pe(seg, s)];
414 : 0 : ped->lv_num = lv_num;
415 : 0 : ped->le_num = (seg->le / seg->area_count) + pe +
416 : 0 : s * (lv->le_count / seg->area_count);
417 : : }
418 : : }
419 : : }
420 : :
421 : 0 : return 1;
422 : : }
423 : :
424 : 0 : int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
425 : : struct volume_group *vg, struct dm_list *pvds)
426 : : {
427 : : struct disk_list *dl;
428 : : struct pv_list *pvl;
429 : :
430 : 0 : vg->pv_count = 0;
431 [ # # ]: 0 : dm_list_iterate_items(dl, pvds) {
432 [ # # # # ]: 0 : if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
433 : 0 : !(pvl->pv = dm_pool_alloc(mem, sizeof(*pvl->pv))))
434 : 0 : return_0;
435 : :
436 [ # # ]: 0 : if (!import_pv(fmt, mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd))
437 : 0 : return_0;
438 : :
439 : 0 : pvl->pv->fmt = fmt;
440 : 0 : add_pvl_to_vgs(vg, pvl);
441 : : }
442 : :
443 : 0 : return 1;
444 : : }
445 : :
446 : 0 : static struct logical_volume *_add_lv(struct dm_pool *mem,
447 : : struct volume_group *vg,
448 : : struct lv_disk *lvd)
449 : : {
450 : : struct logical_volume *lv;
451 : :
452 [ # # ]: 0 : if (!(lv = alloc_lv(mem)))
453 : 0 : return_NULL;
454 : :
455 : 0 : lvid_from_lvnum(&lv->lvid, &vg->id, lvd->lv_number);
456 : :
457 [ # # ]: 0 : if (!import_lv(vg->cmd, mem, lv, lvd))
458 : 0 : goto_bad;
459 : :
460 [ # # ]: 0 : if (!link_lv_to_vg(vg, lv))
461 : 0 : goto_bad;
462 : :
463 : 0 : return lv;
464 : : bad:
465 : 0 : dm_pool_free(mem, lv);
466 : 0 : return NULL;
467 : : }
468 : :
469 : 0 : int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct dm_list *pvds)
470 : : {
471 : : struct disk_list *dl;
472 : : struct lvd_list *ll;
473 : : struct lv_disk *lvd;
474 : :
475 [ # # ]: 0 : dm_list_iterate_items(dl, pvds) {
476 [ # # ]: 0 : dm_list_iterate_items(ll, &dl->lvds) {
477 : 0 : lvd = &ll->lvd;
478 : :
479 [ # # # # ]: 0 : if (!find_lv(vg, (char *)lvd->lv_name) &&
480 : 0 : !_add_lv(mem, vg, lvd))
481 : 0 : return_0;
482 : : }
483 : : }
484 : :
485 : 0 : return 1;
486 : : }
487 : :
488 : : /* FIXME: tidy */
489 : 0 : int export_lvs(struct disk_list *dl, struct volume_group *vg,
490 : : struct physical_volume *pv, const char *dev_dir)
491 : : {
492 : 0 : int r = 0;
493 : : struct lv_list *ll;
494 : : struct lvd_list *lvdl;
495 : : size_t len;
496 : : uint32_t lv_num;
497 : : struct dm_hash_table *lvd_hash;
498 : :
499 [ # # ]: 0 : if (!_check_vg_name(vg->name))
500 : 0 : return_0;
501 : :
502 [ # # ]: 0 : if (!(lvd_hash = dm_hash_create(32)))
503 : 0 : return_0;
504 : :
505 : : /*
506 : : * setup the pv's extents array
507 : : */
508 : 0 : len = sizeof(struct pe_disk) * dl->pvd.pe_total;
509 [ # # ]: 0 : if (!(dl->extents = dm_pool_alloc(dl->mem, len)))
510 : 0 : goto_out;
511 : 0 : memset(dl->extents, 0, len);
512 : :
513 [ # # ]: 0 : dm_list_iterate_items(ll, &vg->lvs) {
514 [ # # ]: 0 : if (ll->lv->status & SNAPSHOT)
515 : 0 : continue;
516 : :
517 [ # # ]: 0 : if (!(lvdl = dm_pool_alloc(dl->mem, sizeof(*lvdl))))
518 : 0 : goto_out;
519 : :
520 : 0 : _export_lv(&lvdl->lvd, vg, ll->lv, dev_dir);
521 : :
522 : 0 : lv_num = lvnum_from_lvid(&ll->lv->lvid);
523 : 0 : lvdl->lvd.lv_number = lv_num;
524 : :
525 [ # # ]: 0 : if (!dm_hash_insert(lvd_hash, ll->lv->name, &lvdl->lvd))
526 : 0 : goto_out;
527 : :
528 [ # # ]: 0 : if (!export_extents(dl, lv_num + 1, ll->lv, pv))
529 : 0 : goto_out;
530 : :
531 [ # # ]: 0 : if (lv_is_origin(ll->lv))
532 : 0 : lvdl->lvd.lv_access |= LV_SNAPSHOT_ORG;
533 : :
534 [ # # ]: 0 : if (lv_is_cow(ll->lv)) {
535 : 0 : lvdl->lvd.lv_access |= LV_SNAPSHOT;
536 : 0 : lvdl->lvd.lv_chunk_size = ll->lv->snapshot->chunk_size;
537 : 0 : lvdl->lvd.lv_snapshot_minor =
538 : 0 : lvnum_from_lvid(&ll->lv->snapshot->origin->lvid);
539 : : }
540 : :
541 : 0 : dm_list_add(&dl->lvds, &lvdl->list);
542 : 0 : dl->pvd.lv_cur++;
543 : : }
544 : :
545 : 0 : r = 1;
546 : :
547 : : out:
548 : 0 : dm_hash_destroy(lvd_hash);
549 : 0 : return r;
550 : : }
551 : :
552 : : /*
553 : : * FIXME: More inefficient code.
554 : : */
555 : 0 : int import_snapshots(struct dm_pool *mem __attribute((unused)), struct volume_group *vg,
556 : : struct dm_list *pvds)
557 : : {
558 : : struct logical_volume *lvs[MAX_LV];
559 : : struct disk_list *dl;
560 : : struct lvd_list *ll;
561 : : struct lv_disk *lvd;
562 : : int lvnum;
563 : : struct logical_volume *org, *cow;
564 : :
565 : : /* build an index of lv numbers */
566 : 0 : memset(lvs, 0, sizeof(lvs));
567 [ # # ]: 0 : dm_list_iterate_items(dl, pvds) {
568 [ # # ]: 0 : dm_list_iterate_items(ll, &dl->lvds) {
569 : 0 : lvd = &ll->lvd;
570 : :
571 : 0 : lvnum = lvd->lv_number;
572 : :
573 [ # # ]: 0 : if (lvnum >= MAX_LV) {
574 : 0 : log_error("Logical volume number "
575 : : "out of bounds.");
576 : 0 : return 0;
577 : : }
578 : :
579 [ # # # # ]: 0 : if (!lvs[lvnum] &&
580 : 0 : !(lvs[lvnum] = find_lv(vg, (char *)lvd->lv_name))) {
581 : 0 : log_error("Couldn't find logical volume '%s'.",
582 : : lvd->lv_name);
583 : 0 : return 0;
584 : : }
585 : : }
586 : : }
587 : :
588 : : /*
589 : : * Now iterate through yet again adding the snapshots.
590 : : */
591 [ # # ]: 0 : dm_list_iterate_items(dl, pvds) {
592 [ # # ]: 0 : dm_list_iterate_items(ll, &dl->lvds) {
593 : 0 : lvd = &ll->lvd;
594 : :
595 [ # # ]: 0 : if (!(lvd->lv_access & LV_SNAPSHOT))
596 : 0 : continue;
597 : :
598 : 0 : lvnum = lvd->lv_number;
599 : 0 : cow = lvs[lvnum];
600 [ # # ]: 0 : if (!(org = lvs[lvd->lv_snapshot_minor])) {
601 : 0 : log_error("Couldn't find origin logical volume "
602 : : "for snapshot '%s'.", lvd->lv_name);
603 : 0 : return 0;
604 : : }
605 : :
606 : : /* we may have already added this snapshot */
607 [ # # ]: 0 : if (lv_is_cow(cow))
608 : 0 : continue;
609 : :
610 : : /* insert the snapshot */
611 [ # # ]: 0 : if (!vg_add_snapshot(org, cow, NULL,
612 : : org->le_count,
613 : 0 : lvd->lv_chunk_size)) {
614 : 0 : log_error("Couldn't add snapshot.");
615 : 0 : return 0;
616 : : }
617 : : }
618 : : }
619 : :
620 : 0 : return 1;
621 : : }
622 : :
623 : 0 : int export_uuids(struct disk_list *dl, struct volume_group *vg)
624 : : {
625 : : struct uuid_list *ul;
626 : : struct pv_list *pvl;
627 : :
628 [ # # ]: 0 : dm_list_iterate_items(pvl, &vg->pvs) {
629 [ # # ]: 0 : if (!(ul = dm_pool_alloc(dl->mem, sizeof(*ul))))
630 : 0 : return_0;
631 : :
632 : 0 : memset(ul->uuid, 0, sizeof(ul->uuid));
633 : 0 : memcpy(ul->uuid, pvl->pv->id.uuid, ID_LEN);
634 : :
635 : 0 : dm_list_add(&dl->uuids, &ul->list);
636 : : }
637 : 0 : return 1;
638 : : }
639 : :
640 : : /*
641 : : * This calculates the nasty pv_number field
642 : : * used by LVM1.
643 : : */
644 : 0 : void export_numbers(struct dm_list *pvds, struct volume_group *vg __attribute((unused)))
645 : : {
646 : : struct disk_list *dl;
647 : 0 : int pv_num = 1;
648 : :
649 [ # # ]: 0 : dm_list_iterate_items(dl, pvds)
650 : 0 : dl->pvd.pv_number = pv_num++;
651 : 0 : }
652 : :
653 : : /*
654 : : * Calculate vg_disk->pv_act.
655 : : */
656 : 0 : void export_pv_act(struct dm_list *pvds)
657 : : {
658 : : struct disk_list *dl;
659 : 0 : int act = 0;
660 : :
661 [ # # ]: 0 : dm_list_iterate_items(dl, pvds)
662 [ # # ]: 0 : if (dl->pvd.pv_status & PV_ACTIVE)
663 : 0 : act++;
664 : :
665 [ # # ]: 0 : dm_list_iterate_items(dl, pvds)
666 : 0 : dl->vgd.pv_act = act;
667 : 0 : }
668 : :
669 : 0 : int export_vg_number(struct format_instance *fid, struct dm_list *pvds,
670 : : const char *vg_name, struct dev_filter *filter)
671 : : {
672 : : struct disk_list *dl;
673 : : int vg_num;
674 : :
675 [ # # ]: 0 : if (!get_free_vg_number(fid, filter, vg_name, &vg_num))
676 : 0 : return_0;
677 : :
678 [ # # ]: 0 : dm_list_iterate_items(dl, pvds)
679 : 0 : dl->vgd.vg_number = vg_num;
680 : :
681 : 0 : return 1;
682 : : }
|