1*730681d8Sjoerg /* $NetBSD: import-export.c,v 1.2 2014/11/15 01:24:53 joerg Exp $ */
256a34939Shaad
356a34939Shaad /*
456a34939Shaad * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
556a34939Shaad * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
656a34939Shaad *
756a34939Shaad * This file is part of LVM2.
856a34939Shaad *
956a34939Shaad * This copyrighted material is made available to anyone wishing to use,
1056a34939Shaad * modify, copy, or redistribute it subject to the terms and conditions
1156a34939Shaad * of the GNU Lesser General Public License v.2.1.
1256a34939Shaad *
1356a34939Shaad * You should have received a copy of the GNU Lesser General Public License
1456a34939Shaad * along with this program; if not, write to the Free Software Foundation,
1556a34939Shaad * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1656a34939Shaad */
1756a34939Shaad
1856a34939Shaad /*
1956a34939Shaad * Translates between disk and in-core formats.
2056a34939Shaad */
2156a34939Shaad
2256a34939Shaad #include "lib.h"
2356a34939Shaad #include "disk-rep.h"
2456a34939Shaad #include "lvm-string.h"
2556a34939Shaad #include "filter.h"
2656a34939Shaad #include "toolcontext.h"
2756a34939Shaad #include "segtype.h"
2856a34939Shaad #include "pv_alloc.h"
2956a34939Shaad #include "display.h"
3056a34939Shaad #include "lvmcache.h"
3156a34939Shaad #include "metadata.h"
3256a34939Shaad
3356a34939Shaad #include <time.h>
3456a34939Shaad
_check_vg_name(const char * name)3556a34939Shaad static int _check_vg_name(const char *name)
3656a34939Shaad {
3756a34939Shaad return strlen(name) < NAME_LEN;
3856a34939Shaad }
3956a34939Shaad
4056a34939Shaad /*
4156a34939Shaad * Extracts the last part of a path.
4256a34939Shaad */
_create_lv_name(struct dm_pool * mem,const char * full_name)4356a34939Shaad static char *_create_lv_name(struct dm_pool *mem, const char *full_name)
4456a34939Shaad {
4556a34939Shaad const char *ptr = strrchr(full_name, '/');
4656a34939Shaad
4756a34939Shaad if (!ptr)
4856a34939Shaad ptr = full_name;
4956a34939Shaad else
5056a34939Shaad ptr++;
5156a34939Shaad
5256a34939Shaad return dm_pool_strdup(mem, ptr);
5356a34939Shaad }
5456a34939Shaad
import_pv(const struct format_type * fmt,struct dm_pool * mem,struct device * dev,struct volume_group * vg,struct physical_volume * pv,struct pv_disk * pvd,struct vg_disk * vgd)5556a34939Shaad int import_pv(const struct format_type *fmt, struct dm_pool *mem,
5656a34939Shaad struct device *dev, struct volume_group *vg,
5756a34939Shaad struct physical_volume *pv, struct pv_disk *pvd,
5856a34939Shaad struct vg_disk *vgd)
5956a34939Shaad {
6056a34939Shaad uint64_t size;
6156a34939Shaad
6256a34939Shaad memset(pv, 0, sizeof(*pv));
6356a34939Shaad memcpy(&pv->id, pvd->pv_uuid, ID_LEN);
6456a34939Shaad
6556a34939Shaad pv->dev = dev;
6656a34939Shaad if (!*pvd->vg_name)
6756a34939Shaad pv->vg_name = fmt->orphan_vg_name;
6856a34939Shaad else if (!(pv->vg_name = dm_pool_strdup(mem, (char *)pvd->vg_name))) {
6956a34939Shaad log_error("Volume Group name allocation failed.");
7056a34939Shaad return 0;
7156a34939Shaad }
7256a34939Shaad
7356a34939Shaad memcpy(&pv->vgid, vgd->vg_uuid, sizeof(vg->id));
7456a34939Shaad
7556a34939Shaad /* Store system_id from first PV if PV belongs to a VG */
7656a34939Shaad if (vg && !*vg->system_id)
7756a34939Shaad strncpy(vg->system_id, (char *)pvd->system_id, NAME_LEN);
7856a34939Shaad
7956a34939Shaad if (vg &&
8056a34939Shaad strncmp(vg->system_id, (char *)pvd->system_id, sizeof(pvd->system_id)))
8156a34939Shaad log_very_verbose("System ID %s on %s differs from %s for "
8256a34939Shaad "volume group", pvd->system_id,
8356a34939Shaad pv_dev_name(pv), vg->system_id);
8456a34939Shaad
8556a34939Shaad /*
8656a34939Shaad * If exported, we still need to flag in pv->status too because
8756a34939Shaad * we don't always have a struct volume_group when we need this.
8856a34939Shaad */
8956a34939Shaad if (pvd->pv_status & VG_EXPORTED)
9056a34939Shaad pv->status |= EXPORTED_VG;
9156a34939Shaad
9256a34939Shaad if (pvd->pv_allocatable)
9356a34939Shaad pv->status |= ALLOCATABLE_PV;
9456a34939Shaad
9556a34939Shaad pv->size = pvd->pv_size;
9656a34939Shaad pv->pe_size = pvd->pe_size;
9756a34939Shaad pv->pe_start = pvd->pe_start;
9856a34939Shaad pv->pe_count = pvd->pe_total;
9956a34939Shaad pv->pe_alloc_count = 0;
10056a34939Shaad pv->pe_align = 0;
10156a34939Shaad
10256a34939Shaad /* Fix up pv size if missing or impossibly large */
10356a34939Shaad if (!pv->size || pv->size > (1ULL << 62)) {
10456a34939Shaad if (!dev_get_size(dev, &pv->size)) {
10556a34939Shaad log_error("%s: Couldn't get size.", pv_dev_name(pv));
10656a34939Shaad return 0;
10756a34939Shaad }
10856a34939Shaad log_verbose("Fixing up missing format1 size (%s) "
10956a34939Shaad "for PV %s", display_size(fmt->cmd, pv->size),
11056a34939Shaad pv_dev_name(pv));
11156a34939Shaad if (vg) {
11256a34939Shaad size = pv->pe_count * (uint64_t) vg->extent_size +
11356a34939Shaad pv->pe_start;
11456a34939Shaad if (size > pv->size)
11556a34939Shaad log_error("WARNING: Physical Volume %s is too "
11656a34939Shaad "large for underlying device",
11756a34939Shaad pv_dev_name(pv));
11856a34939Shaad }
11956a34939Shaad }
12056a34939Shaad
12156a34939Shaad dm_list_init(&pv->tags);
12256a34939Shaad dm_list_init(&pv->segments);
12356a34939Shaad
12456a34939Shaad if (!alloc_pv_segment_whole_pv(mem, pv))
12556a34939Shaad return_0;
12656a34939Shaad
12756a34939Shaad return 1;
12856a34939Shaad }
12956a34939Shaad
_system_id(struct cmd_context * cmd,char * s,const char * prefix)13056a34939Shaad static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
13156a34939Shaad {
13256a34939Shaad
13356a34939Shaad if (dm_snprintf(s, NAME_LEN, "%s%s%lu",
13456a34939Shaad prefix, cmd->hostname, time(NULL)) < 0) {
13556a34939Shaad log_error("Generated system_id too long");
13656a34939Shaad return 0;
13756a34939Shaad }
13856a34939Shaad
13956a34939Shaad return 1;
14056a34939Shaad }
14156a34939Shaad
export_pv(struct cmd_context * cmd,struct dm_pool * mem __attribute ((unused)),struct volume_group * vg,struct pv_disk * pvd,struct physical_volume * pv)14256a34939Shaad int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute((unused)),
14356a34939Shaad struct volume_group *vg,
14456a34939Shaad struct pv_disk *pvd, struct physical_volume *pv)
14556a34939Shaad {
14656a34939Shaad memset(pvd, 0, sizeof(*pvd));
14756a34939Shaad
14856a34939Shaad pvd->id[0] = 'H';
14956a34939Shaad pvd->id[1] = 'M';
15056a34939Shaad pvd->version = 1;
15156a34939Shaad
15256a34939Shaad memcpy(pvd->pv_uuid, pv->id.uuid, ID_LEN);
15356a34939Shaad
15456a34939Shaad if (pv->vg_name && !is_orphan(pv)) {
15556a34939Shaad if (!_check_vg_name(pv->vg_name))
15656a34939Shaad return_0;
15756a34939Shaad strncpy((char *)pvd->vg_name, pv->vg_name, sizeof(pvd->vg_name));
15856a34939Shaad }
15956a34939Shaad
16056a34939Shaad /* Preserve existing system_id if it exists */
16156a34939Shaad if (vg && *vg->system_id)
16256a34939Shaad strncpy((char *)pvd->system_id, vg->system_id, sizeof(pvd->system_id));
16356a34939Shaad
16456a34939Shaad /* Is VG already exported or being exported? */
1657c604eeaShaad if (vg && vg_is_exported(vg)) {
16656a34939Shaad /* Does system_id need setting? */
16756a34939Shaad if (!*vg->system_id ||
16856a34939Shaad strncmp(vg->system_id, EXPORTED_TAG,
16956a34939Shaad sizeof(EXPORTED_TAG) - 1)) {
17056a34939Shaad if (!_system_id(cmd, (char *)pvd->system_id, EXPORTED_TAG))
17156a34939Shaad return_0;
17256a34939Shaad }
17356a34939Shaad if (strlen((char *)pvd->vg_name) + sizeof(EXPORTED_TAG) >
17456a34939Shaad sizeof(pvd->vg_name)) {
17556a34939Shaad log_error("Volume group name %s too long to export",
17656a34939Shaad pvd->vg_name);
17756a34939Shaad return 0;
17856a34939Shaad }
17956a34939Shaad strcat((char *)pvd->vg_name, EXPORTED_TAG);
18056a34939Shaad }
18156a34939Shaad
18256a34939Shaad /* Is VG being imported? */
1837c604eeaShaad if (vg && !vg_is_exported(vg) && *vg->system_id &&
18456a34939Shaad !strncmp(vg->system_id, EXPORTED_TAG, sizeof(EXPORTED_TAG) - 1)) {
18556a34939Shaad if (!_system_id(cmd, (char *)pvd->system_id, IMPORTED_TAG))
18656a34939Shaad return_0;
18756a34939Shaad }
18856a34939Shaad
18956a34939Shaad /* Generate system_id if PV is in VG */
190*730681d8Sjoerg if (!pvd->system_id[0])
19156a34939Shaad if (!_system_id(cmd, (char *)pvd->system_id, ""))
19256a34939Shaad return_0;
19356a34939Shaad
19456a34939Shaad /* Update internal system_id if we changed it */
19556a34939Shaad if (vg &&
19656a34939Shaad (!*vg->system_id ||
19756a34939Shaad strncmp(vg->system_id, (char *)pvd->system_id, sizeof(pvd->system_id))))
19856a34939Shaad strncpy(vg->system_id, (char *)pvd->system_id, NAME_LEN);
19956a34939Shaad
20056a34939Shaad //pvd->pv_major = MAJOR(pv->dev);
20156a34939Shaad
20256a34939Shaad if (pv->status & ALLOCATABLE_PV)
20356a34939Shaad pvd->pv_allocatable = PV_ALLOCATABLE;
20456a34939Shaad
20556a34939Shaad pvd->pv_size = pv->size;
20656a34939Shaad pvd->lv_cur = 0; /* this is set when exporting the lv list */
20756a34939Shaad if (vg)
20856a34939Shaad pvd->pe_size = vg->extent_size;
20956a34939Shaad else
21056a34939Shaad pvd->pe_size = pv->pe_size;
21156a34939Shaad pvd->pe_total = pv->pe_count;
21256a34939Shaad pvd->pe_allocated = pv->pe_alloc_count;
21356a34939Shaad pvd->pe_start = pv->pe_start;
21456a34939Shaad
21556a34939Shaad return 1;
21656a34939Shaad }
21756a34939Shaad
import_vg(struct dm_pool * mem,struct volume_group * vg,struct disk_list * dl)21856a34939Shaad int import_vg(struct dm_pool *mem,
21956a34939Shaad struct volume_group *vg, struct disk_list *dl)
22056a34939Shaad {
22156a34939Shaad struct vg_disk *vgd = &dl->vgd;
22256a34939Shaad memcpy(vg->id.uuid, vgd->vg_uuid, ID_LEN);
22356a34939Shaad
22456a34939Shaad if (!_check_vg_name((char *)dl->pvd.vg_name))
22556a34939Shaad return_0;
22656a34939Shaad
22756a34939Shaad if (!(vg->name = dm_pool_strdup(mem, (char *)dl->pvd.vg_name)))
22856a34939Shaad return_0;
22956a34939Shaad
23056a34939Shaad if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN)))
23156a34939Shaad return_0;
23256a34939Shaad
23356a34939Shaad *vg->system_id = '\0';
23456a34939Shaad
23556a34939Shaad if (vgd->vg_status & VG_EXPORTED)
23656a34939Shaad vg->status |= EXPORTED_VG;
23756a34939Shaad
23856a34939Shaad if (vgd->vg_status & VG_EXTENDABLE)
23956a34939Shaad vg->status |= RESIZEABLE_VG;
24056a34939Shaad
24156a34939Shaad if (vgd->vg_access & VG_READ)
24256a34939Shaad vg->status |= LVM_READ;
24356a34939Shaad
24456a34939Shaad if (vgd->vg_access & VG_WRITE)
24556a34939Shaad vg->status |= LVM_WRITE;
24656a34939Shaad
24756a34939Shaad if (vgd->vg_access & VG_CLUSTERED)
24856a34939Shaad vg->status |= CLUSTERED;
24956a34939Shaad
25056a34939Shaad if (vgd->vg_access & VG_SHARED)
25156a34939Shaad vg->status |= SHARED;
25256a34939Shaad
25356a34939Shaad vg->extent_size = vgd->pe_size;
25456a34939Shaad vg->extent_count = vgd->pe_total;
25556a34939Shaad vg->free_count = vgd->pe_total;
25656a34939Shaad vg->max_lv = vgd->lv_max;
25756a34939Shaad vg->max_pv = vgd->pv_max;
25856a34939Shaad vg->alloc = ALLOC_NORMAL;
25956a34939Shaad
26056a34939Shaad return 1;
26156a34939Shaad }
26256a34939Shaad
export_vg(struct vg_disk * vgd,struct volume_group * vg)26356a34939Shaad int export_vg(struct vg_disk *vgd, struct volume_group *vg)
26456a34939Shaad {
26556a34939Shaad memset(vgd, 0, sizeof(*vgd));
26656a34939Shaad memcpy(vgd->vg_uuid, vg->id.uuid, ID_LEN);
26756a34939Shaad
26856a34939Shaad if (vg->status & LVM_READ)
26956a34939Shaad vgd->vg_access |= VG_READ;
27056a34939Shaad
27156a34939Shaad if (vg->status & LVM_WRITE)
27256a34939Shaad vgd->vg_access |= VG_WRITE;
27356a34939Shaad
27456a34939Shaad if (vg_is_clustered(vg))
27556a34939Shaad vgd->vg_access |= VG_CLUSTERED;
27656a34939Shaad
27756a34939Shaad if (vg->status & SHARED)
27856a34939Shaad vgd->vg_access |= VG_SHARED;
27956a34939Shaad
2807c604eeaShaad if (vg_is_exported(vg))
28156a34939Shaad vgd->vg_status |= VG_EXPORTED;
28256a34939Shaad
2837c604eeaShaad if (vg_is_resizeable(vg))
28456a34939Shaad vgd->vg_status |= VG_EXTENDABLE;
28556a34939Shaad
28656a34939Shaad vgd->lv_max = vg->max_lv;
2877c604eeaShaad vgd->lv_cur = vg_visible_lvs(vg) + snapshot_count(vg);
28856a34939Shaad
28956a34939Shaad vgd->pv_max = vg->max_pv;
29056a34939Shaad vgd->pv_cur = vg->pv_count;
29156a34939Shaad
29256a34939Shaad vgd->pe_size = vg->extent_size;
29356a34939Shaad vgd->pe_total = vg->extent_count;
29456a34939Shaad vgd->pe_allocated = vg->extent_count - vg->free_count;
29556a34939Shaad
29656a34939Shaad return 1;
29756a34939Shaad }
29856a34939Shaad
import_lv(struct cmd_context * cmd,struct dm_pool * mem,struct logical_volume * lv,struct lv_disk * lvd)2997c604eeaShaad int import_lv(struct cmd_context *cmd, struct dm_pool *mem,
3007c604eeaShaad struct logical_volume *lv, struct lv_disk *lvd)
30156a34939Shaad {
30256a34939Shaad if (!(lv->name = _create_lv_name(mem, (char *)lvd->lv_name)))
30356a34939Shaad return_0;
30456a34939Shaad
30556a34939Shaad lv->status |= VISIBLE_LV;
30656a34939Shaad
30756a34939Shaad if (lvd->lv_status & LV_SPINDOWN)
30856a34939Shaad lv->status |= SPINDOWN_LV;
30956a34939Shaad
31056a34939Shaad if (lvd->lv_status & LV_PERSISTENT_MINOR) {
31156a34939Shaad lv->status |= FIXED_MINOR;
31256a34939Shaad lv->minor = MINOR(lvd->lv_dev);
31356a34939Shaad lv->major = MAJOR(lvd->lv_dev);
31456a34939Shaad } else {
31556a34939Shaad lv->major = -1;
31656a34939Shaad lv->minor = -1;
31756a34939Shaad }
31856a34939Shaad
31956a34939Shaad if (lvd->lv_access & LV_READ)
32056a34939Shaad lv->status |= LVM_READ;
32156a34939Shaad
32256a34939Shaad if (lvd->lv_access & LV_WRITE)
32356a34939Shaad lv->status |= LVM_WRITE;
32456a34939Shaad
32556a34939Shaad if (lvd->lv_badblock)
32656a34939Shaad lv->status |= BADBLOCK_ON;
32756a34939Shaad
32856a34939Shaad /* Drop the unused LV_STRICT here */
32956a34939Shaad if (lvd->lv_allocation & LV_CONTIGUOUS)
33056a34939Shaad lv->alloc = ALLOC_CONTIGUOUS;
33156a34939Shaad else
33256a34939Shaad lv->alloc = ALLOC_NORMAL;
33356a34939Shaad
33456a34939Shaad if (!lvd->lv_read_ahead)
3357c604eeaShaad lv->read_ahead = cmd->default_settings.read_ahead;
33656a34939Shaad else
33756a34939Shaad lv->read_ahead = lvd->lv_read_ahead;
33856a34939Shaad
33956a34939Shaad lv->size = lvd->lv_size;
34056a34939Shaad lv->le_count = lvd->lv_allocated_le;
34156a34939Shaad
34256a34939Shaad return 1;
34356a34939Shaad }
34456a34939Shaad
_export_lv(struct lv_disk * lvd,struct volume_group * vg,struct logical_volume * lv,const char * dev_dir)34556a34939Shaad static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
34656a34939Shaad struct logical_volume *lv, const char *dev_dir)
34756a34939Shaad {
34856a34939Shaad memset(lvd, 0, sizeof(*lvd));
34956a34939Shaad snprintf((char *)lvd->lv_name, sizeof(lvd->lv_name), "%s%s/%s",
35056a34939Shaad dev_dir, vg->name, lv->name);
35156a34939Shaad
35256a34939Shaad strcpy((char *)lvd->vg_name, vg->name);
35356a34939Shaad
35456a34939Shaad if (lv->status & LVM_READ)
35556a34939Shaad lvd->lv_access |= LV_READ;
35656a34939Shaad
35756a34939Shaad if (lv->status & LVM_WRITE)
35856a34939Shaad lvd->lv_access |= LV_WRITE;
35956a34939Shaad
36056a34939Shaad if (lv->status & SPINDOWN_LV)
36156a34939Shaad lvd->lv_status |= LV_SPINDOWN;
36256a34939Shaad
36356a34939Shaad if (lv->status & FIXED_MINOR) {
36456a34939Shaad lvd->lv_status |= LV_PERSISTENT_MINOR;
36556a34939Shaad lvd->lv_dev = MKDEV(lv->major, lv->minor);
36656a34939Shaad } else {
36756a34939Shaad lvd->lv_dev = MKDEV(LVM_BLK_MAJOR, lvnum_from_lvid(&lv->lvid));
36856a34939Shaad }
36956a34939Shaad
37056a34939Shaad if (lv->read_ahead == DM_READ_AHEAD_AUTO ||
37156a34939Shaad lv->read_ahead == DM_READ_AHEAD_NONE)
37256a34939Shaad lvd->lv_read_ahead = 0;
37356a34939Shaad else
37456a34939Shaad lvd->lv_read_ahead = lv->read_ahead;
37556a34939Shaad
37656a34939Shaad lvd->lv_stripes =
37756a34939Shaad dm_list_item(lv->segments.n, struct lv_segment)->area_count;
37856a34939Shaad lvd->lv_stripesize =
37956a34939Shaad dm_list_item(lv->segments.n, struct lv_segment)->stripe_size;
38056a34939Shaad
38156a34939Shaad lvd->lv_size = lv->size;
38256a34939Shaad lvd->lv_allocated_le = lv->le_count;
38356a34939Shaad
38456a34939Shaad if (lv->status & BADBLOCK_ON)
38556a34939Shaad lvd->lv_badblock = LV_BADBLOCK_ON;
38656a34939Shaad
38756a34939Shaad if (lv->alloc == ALLOC_CONTIGUOUS)
38856a34939Shaad lvd->lv_allocation |= LV_CONTIGUOUS;
38956a34939Shaad }
39056a34939Shaad
export_extents(struct disk_list * dl,uint32_t lv_num,struct logical_volume * lv,struct physical_volume * pv)39156a34939Shaad int export_extents(struct disk_list *dl, uint32_t lv_num,
39256a34939Shaad struct logical_volume *lv, struct physical_volume *pv)
39356a34939Shaad {
39456a34939Shaad struct pe_disk *ped;
39556a34939Shaad struct lv_segment *seg;
39656a34939Shaad uint32_t pe, s;
39756a34939Shaad
39856a34939Shaad dm_list_iterate_items(seg, &lv->segments) {
39956a34939Shaad for (s = 0; s < seg->area_count; s++) {
40056a34939Shaad if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
40156a34939Shaad log_error("Segment type %s in LV %s: "
40256a34939Shaad "unsupported by format1",
40356a34939Shaad seg->segtype->name, lv->name);
40456a34939Shaad return 0;
40556a34939Shaad }
40656a34939Shaad if (seg_type(seg, s) != AREA_PV) {
40756a34939Shaad log_error("Non-PV stripe found in LV %s: "
40856a34939Shaad "unsupported by format1", lv->name);
40956a34939Shaad return 0;
41056a34939Shaad }
41156a34939Shaad if (seg_pv(seg, s) != pv)
41256a34939Shaad continue; /* not our pv */
41356a34939Shaad
41456a34939Shaad for (pe = 0; pe < (seg->len / seg->area_count); pe++) {
41556a34939Shaad ped = &dl->extents[pe + seg_pe(seg, s)];
41656a34939Shaad ped->lv_num = lv_num;
41756a34939Shaad ped->le_num = (seg->le / seg->area_count) + pe +
41856a34939Shaad s * (lv->le_count / seg->area_count);
41956a34939Shaad }
42056a34939Shaad }
42156a34939Shaad }
42256a34939Shaad
42356a34939Shaad return 1;
42456a34939Shaad }
42556a34939Shaad
import_pvs(const struct format_type * fmt,struct dm_pool * mem,struct volume_group * vg,struct dm_list * pvds,struct dm_list * results,uint32_t * count)42656a34939Shaad int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
42756a34939Shaad struct volume_group *vg,
42856a34939Shaad struct dm_list *pvds, struct dm_list *results, uint32_t *count)
42956a34939Shaad {
43056a34939Shaad struct disk_list *dl;
43156a34939Shaad struct pv_list *pvl;
43256a34939Shaad
43356a34939Shaad *count = 0;
43456a34939Shaad dm_list_iterate_items(dl, pvds) {
43556a34939Shaad if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
43656a34939Shaad !(pvl->pv = dm_pool_alloc(mem, sizeof(*pvl->pv))))
43756a34939Shaad return_0;
43856a34939Shaad
43956a34939Shaad if (!import_pv(fmt, mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd))
44056a34939Shaad return_0;
44156a34939Shaad
44256a34939Shaad pvl->pv->fmt = fmt;
44356a34939Shaad dm_list_add(results, &pvl->list);
44456a34939Shaad (*count)++;
44556a34939Shaad }
44656a34939Shaad
44756a34939Shaad return 1;
44856a34939Shaad }
44956a34939Shaad
_add_lv(struct dm_pool * mem,struct volume_group * vg,struct lv_disk * lvd)45056a34939Shaad static struct logical_volume *_add_lv(struct dm_pool *mem,
45156a34939Shaad struct volume_group *vg,
45256a34939Shaad struct lv_disk *lvd)
45356a34939Shaad {
45456a34939Shaad struct logical_volume *lv;
45556a34939Shaad
4567c604eeaShaad if (!(lv = alloc_lv(mem)))
45756a34939Shaad return_NULL;
45856a34939Shaad
4597c604eeaShaad lvid_from_lvnum(&lv->lvid, &vg->id, lvd->lv_number);
4607c604eeaShaad
4617c604eeaShaad if (!import_lv(vg->cmd, mem, lv, lvd))
4627c604eeaShaad goto_bad;
4637c604eeaShaad
4647c604eeaShaad if (!link_lv_to_vg(vg, lv))
4657c604eeaShaad goto_bad;
46656a34939Shaad
46756a34939Shaad return lv;
4687c604eeaShaad bad:
4697c604eeaShaad dm_pool_free(mem, lv);
4707c604eeaShaad return NULL;
47156a34939Shaad }
47256a34939Shaad
import_lvs(struct dm_pool * mem,struct volume_group * vg,struct dm_list * pvds)47356a34939Shaad int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct dm_list *pvds)
47456a34939Shaad {
47556a34939Shaad struct disk_list *dl;
47656a34939Shaad struct lvd_list *ll;
47756a34939Shaad struct lv_disk *lvd;
47856a34939Shaad
47956a34939Shaad dm_list_iterate_items(dl, pvds) {
48056a34939Shaad dm_list_iterate_items(ll, &dl->lvds) {
48156a34939Shaad lvd = &ll->lvd;
48256a34939Shaad
48356a34939Shaad if (!find_lv(vg, (char *)lvd->lv_name) &&
48456a34939Shaad !_add_lv(mem, vg, lvd))
48556a34939Shaad return_0;
48656a34939Shaad }
48756a34939Shaad }
48856a34939Shaad
48956a34939Shaad return 1;
49056a34939Shaad }
49156a34939Shaad
49256a34939Shaad /* FIXME: tidy */
export_lvs(struct disk_list * dl,struct volume_group * vg,struct physical_volume * pv,const char * dev_dir)49356a34939Shaad int export_lvs(struct disk_list *dl, struct volume_group *vg,
49456a34939Shaad struct physical_volume *pv, const char *dev_dir)
49556a34939Shaad {
49656a34939Shaad int r = 0;
49756a34939Shaad struct lv_list *ll;
49856a34939Shaad struct lvd_list *lvdl;
49956a34939Shaad size_t len;
50056a34939Shaad uint32_t lv_num;
50156a34939Shaad struct dm_hash_table *lvd_hash;
50256a34939Shaad
50356a34939Shaad if (!_check_vg_name(vg->name))
50456a34939Shaad return_0;
50556a34939Shaad
50656a34939Shaad if (!(lvd_hash = dm_hash_create(32)))
50756a34939Shaad return_0;
50856a34939Shaad
50956a34939Shaad /*
51056a34939Shaad * setup the pv's extents array
51156a34939Shaad */
51256a34939Shaad len = sizeof(struct pe_disk) * dl->pvd.pe_total;
51356a34939Shaad if (!(dl->extents = dm_pool_alloc(dl->mem, len)))
51456a34939Shaad goto_out;
51556a34939Shaad memset(dl->extents, 0, len);
51656a34939Shaad
51756a34939Shaad dm_list_iterate_items(ll, &vg->lvs) {
51856a34939Shaad if (ll->lv->status & SNAPSHOT)
51956a34939Shaad continue;
52056a34939Shaad
52156a34939Shaad if (!(lvdl = dm_pool_alloc(dl->mem, sizeof(*lvdl))))
52256a34939Shaad goto_out;
52356a34939Shaad
52456a34939Shaad _export_lv(&lvdl->lvd, vg, ll->lv, dev_dir);
52556a34939Shaad
52656a34939Shaad lv_num = lvnum_from_lvid(&ll->lv->lvid);
52756a34939Shaad lvdl->lvd.lv_number = lv_num;
52856a34939Shaad
52956a34939Shaad if (!dm_hash_insert(lvd_hash, ll->lv->name, &lvdl->lvd))
53056a34939Shaad goto_out;
53156a34939Shaad
53256a34939Shaad if (!export_extents(dl, lv_num + 1, ll->lv, pv))
53356a34939Shaad goto_out;
53456a34939Shaad
53556a34939Shaad if (lv_is_origin(ll->lv))
53656a34939Shaad lvdl->lvd.lv_access |= LV_SNAPSHOT_ORG;
53756a34939Shaad
53856a34939Shaad if (lv_is_cow(ll->lv)) {
53956a34939Shaad lvdl->lvd.lv_access |= LV_SNAPSHOT;
54056a34939Shaad lvdl->lvd.lv_chunk_size = ll->lv->snapshot->chunk_size;
54156a34939Shaad lvdl->lvd.lv_snapshot_minor =
54256a34939Shaad lvnum_from_lvid(&ll->lv->snapshot->origin->lvid);
54356a34939Shaad }
54456a34939Shaad
54556a34939Shaad dm_list_add(&dl->lvds, &lvdl->list);
54656a34939Shaad dl->pvd.lv_cur++;
54756a34939Shaad }
54856a34939Shaad
54956a34939Shaad r = 1;
55056a34939Shaad
55156a34939Shaad out:
55256a34939Shaad dm_hash_destroy(lvd_hash);
55356a34939Shaad return r;
55456a34939Shaad }
55556a34939Shaad
55656a34939Shaad /*
55756a34939Shaad * FIXME: More inefficient code.
55856a34939Shaad */
import_snapshots(struct dm_pool * mem __attribute ((unused)),struct volume_group * vg,struct dm_list * pvds)55956a34939Shaad int import_snapshots(struct dm_pool *mem __attribute((unused)), struct volume_group *vg,
56056a34939Shaad struct dm_list *pvds)
56156a34939Shaad {
56256a34939Shaad struct logical_volume *lvs[MAX_LV];
56356a34939Shaad struct disk_list *dl;
56456a34939Shaad struct lvd_list *ll;
56556a34939Shaad struct lv_disk *lvd;
56656a34939Shaad int lvnum;
56756a34939Shaad struct logical_volume *org, *cow;
56856a34939Shaad
56956a34939Shaad /* build an index of lv numbers */
57056a34939Shaad memset(lvs, 0, sizeof(lvs));
57156a34939Shaad dm_list_iterate_items(dl, pvds) {
57256a34939Shaad dm_list_iterate_items(ll, &dl->lvds) {
57356a34939Shaad lvd = &ll->lvd;
57456a34939Shaad
57556a34939Shaad lvnum = lvd->lv_number;
57656a34939Shaad
57756a34939Shaad if (lvnum >= MAX_LV) {
5787c604eeaShaad log_error("Logical volume number "
57956a34939Shaad "out of bounds.");
58056a34939Shaad return 0;
58156a34939Shaad }
58256a34939Shaad
58356a34939Shaad if (!lvs[lvnum] &&
58456a34939Shaad !(lvs[lvnum] = find_lv(vg, (char *)lvd->lv_name))) {
5857c604eeaShaad log_error("Couldn't find logical volume '%s'.",
58656a34939Shaad lvd->lv_name);
58756a34939Shaad return 0;
58856a34939Shaad }
58956a34939Shaad }
59056a34939Shaad }
59156a34939Shaad
59256a34939Shaad /*
59356a34939Shaad * Now iterate through yet again adding the snapshots.
59456a34939Shaad */
59556a34939Shaad dm_list_iterate_items(dl, pvds) {
59656a34939Shaad dm_list_iterate_items(ll, &dl->lvds) {
59756a34939Shaad lvd = &ll->lvd;
59856a34939Shaad
59956a34939Shaad if (!(lvd->lv_access & LV_SNAPSHOT))
60056a34939Shaad continue;
60156a34939Shaad
60256a34939Shaad lvnum = lvd->lv_number;
60356a34939Shaad cow = lvs[lvnum];
60456a34939Shaad if (!(org = lvs[lvd->lv_snapshot_minor])) {
6057c604eeaShaad log_error("Couldn't find origin logical volume "
60656a34939Shaad "for snapshot '%s'.", lvd->lv_name);
60756a34939Shaad return 0;
60856a34939Shaad }
60956a34939Shaad
61056a34939Shaad /* we may have already added this snapshot */
61156a34939Shaad if (lv_is_cow(cow))
61256a34939Shaad continue;
61356a34939Shaad
61456a34939Shaad /* insert the snapshot */
6157c604eeaShaad if (!vg_add_snapshot(org, cow, NULL,
61656a34939Shaad org->le_count,
61756a34939Shaad lvd->lv_chunk_size)) {
6187c604eeaShaad log_error("Couldn't add snapshot.");
61956a34939Shaad return 0;
62056a34939Shaad }
62156a34939Shaad }
62256a34939Shaad }
62356a34939Shaad
62456a34939Shaad return 1;
62556a34939Shaad }
62656a34939Shaad
export_uuids(struct disk_list * dl,struct volume_group * vg)62756a34939Shaad int export_uuids(struct disk_list *dl, struct volume_group *vg)
62856a34939Shaad {
62956a34939Shaad struct uuid_list *ul;
63056a34939Shaad struct pv_list *pvl;
63156a34939Shaad
63256a34939Shaad dm_list_iterate_items(pvl, &vg->pvs) {
63356a34939Shaad if (!(ul = dm_pool_alloc(dl->mem, sizeof(*ul))))
63456a34939Shaad return_0;
63556a34939Shaad
63656a34939Shaad memset(ul->uuid, 0, sizeof(ul->uuid));
63756a34939Shaad memcpy(ul->uuid, pvl->pv->id.uuid, ID_LEN);
63856a34939Shaad
63956a34939Shaad dm_list_add(&dl->uuids, &ul->list);
64056a34939Shaad }
64156a34939Shaad return 1;
64256a34939Shaad }
64356a34939Shaad
64456a34939Shaad /*
64556a34939Shaad * This calculates the nasty pv_number field
64656a34939Shaad * used by LVM1.
64756a34939Shaad */
export_numbers(struct dm_list * pvds,struct volume_group * vg __attribute ((unused)))64856a34939Shaad void export_numbers(struct dm_list *pvds, struct volume_group *vg __attribute((unused)))
64956a34939Shaad {
65056a34939Shaad struct disk_list *dl;
65156a34939Shaad int pv_num = 1;
65256a34939Shaad
65356a34939Shaad dm_list_iterate_items(dl, pvds)
65456a34939Shaad dl->pvd.pv_number = pv_num++;
65556a34939Shaad }
65656a34939Shaad
65756a34939Shaad /*
65856a34939Shaad * Calculate vg_disk->pv_act.
65956a34939Shaad */
export_pv_act(struct dm_list * pvds)66056a34939Shaad void export_pv_act(struct dm_list *pvds)
66156a34939Shaad {
66256a34939Shaad struct disk_list *dl;
66356a34939Shaad int act = 0;
66456a34939Shaad
66556a34939Shaad dm_list_iterate_items(dl, pvds)
66656a34939Shaad if (dl->pvd.pv_status & PV_ACTIVE)
66756a34939Shaad act++;
66856a34939Shaad
66956a34939Shaad dm_list_iterate_items(dl, pvds)
67056a34939Shaad dl->vgd.pv_act = act;
67156a34939Shaad }
67256a34939Shaad
export_vg_number(struct format_instance * fid,struct dm_list * pvds,const char * vg_name,struct dev_filter * filter)67356a34939Shaad int export_vg_number(struct format_instance *fid, struct dm_list *pvds,
67456a34939Shaad const char *vg_name, struct dev_filter *filter)
67556a34939Shaad {
67656a34939Shaad struct disk_list *dl;
67756a34939Shaad int vg_num;
67856a34939Shaad
67956a34939Shaad if (!get_free_vg_number(fid, filter, vg_name, &vg_num))
68056a34939Shaad return_0;
68156a34939Shaad
68256a34939Shaad dm_list_iterate_items(dl, pvds)
68356a34939Shaad dl->vgd.vg_number = vg_num;
68456a34939Shaad
68556a34939Shaad return 1;
68656a34939Shaad }
687