int 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) { uint64_t size; memset(pv, 0, sizeof(*pv)); memcpy(&pv->id, pvd->pv_uuid, ID_LEN); pv->dev = dev; if (!*pvd->vg_name) pv->vg_name = fmt->orphan_vg_name; else if (!(pv->vg_name = dm_pool_strdup(mem, (char *)pvd->vg_name))) { log_error("Volume Group name allocation failed."); return 0; } memcpy(&pv->vgid, vgd->vg_uuid, sizeof(vg->id)); /* Store system_id from first PV if PV belongs to a VG */ if (vg && !*vg->lvm1_system_id) strncpy(vg->lvm1_system_id, (char *)pvd->system_id, NAME_LEN); if (vg && strncmp(vg->lvm1_system_id, (char *)pvd->system_id, sizeof(pvd->system_id))) log_very_verbose("System ID %s on %s differs from %s for " "volume group", pvd->system_id, pv_dev_name(pv), vg->lvm1_system_id); /* * If exported, we still need to flag in pv->status too because * we don't always have a struct volume_group when we need this. */ if (pvd->pv_status & VG_EXPORTED) pv->status |= EXPORTED_VG; if (pvd->pv_allocatable) pv->status |= ALLOCATABLE_PV; pv->size = pvd->pv_size; pv->pe_size = pvd->pe_size; pv->pe_start = pvd->pe_start; pv->pe_count = pvd->pe_total; pv->pe_alloc_count = 0; pv->pe_align = 0; pv->is_labelled = 0; /* format1 PVs have no label */ pv->label_sector = 0; /* Fix up pv size if missing or impossibly large */ if (!pv->size || pv->size > (1ULL << 62)) { if (!dev_get_size(dev, &pv->size)) { log_error("%s: Couldn't get size.", pv_dev_name(pv)); return 0; } log_verbose("Fixing up missing format1 size (%s) " "for PV %s", display_size(fmt->cmd, pv->size), pv_dev_name(pv)); if (vg) { size = pv->pe_count * (uint64_t) vg->extent_size + pv->pe_start; if (size > pv->size) log_warn("WARNING: Physical Volume %s is too " "large for underlying device", pv_dev_name(pv)); } } dm_list_init(&pv->tags); dm_list_init(&pv->segments); if (!alloc_pv_segment_whole_pv(mem, pv)) return_0; return 1; }
* This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License v.2.1. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "tools.h" static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg, struct physical_volume *pv, void *handle __attribute__((unused))) { const char *pv_name = pv_dev_name(pv); char uuid[64] __attribute__((aligned(8))); int allocatable = 0; int tagargs = 0; int mda_ignore = 0; tagargs = arg_count(cmd, addtag_ARG) + arg_count(cmd, deltag_ARG); if (arg_count(cmd, allocatable_ARG)) allocatable = !strcmp(arg_str_value(cmd, allocatable_ARG, "n"), "y"); if (arg_count(cmd, metadataignore_ARG)) mda_ignore = !strcmp(arg_str_value(cmd, metadataignore_ARG, "n"), "y");
static int _pv_resize_single(struct cmd_context *cmd, struct volume_group *vg, struct physical_volume *pv, const uint64_t new_size) { struct pv_list *pvl; uint64_t size = 0; uint32_t new_pe_count = 0; int r = 0; struct dm_list mdas; const char *pv_name = pv_dev_name(pv); const char *vg_name; struct lvmcache_info *info; int mda_count = 0; struct volume_group *old_vg = vg; dm_list_init(&mdas); if (is_orphan_vg(pv_vg_name(pv))) { vg_name = VG_ORPHANS; if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) { log_error("Can't get lock for orphans"); return 0; } if (!(pv = pv_read(cmd, pv_name, &mdas, NULL, 1, 0))) { unlock_vg(cmd, vg_name); log_error("Unable to read PV \"%s\"", pv_name); return 0; } mda_count = dm_list_size(&mdas); } else { vg_name = pv_vg_name(pv); vg = vg_read_for_update(cmd, vg_name, NULL, 0); if (vg_read_error(vg)) goto bad; if (!(pvl = find_pv_in_vg(vg, pv_name))) { log_error("Unable to find \"%s\" in volume group \"%s\"", pv_name, vg->name); goto bad; } pv = pvl->pv; if (!(info = info_from_pvid(pv->dev->pvid, 0))) { log_error("Can't get info for PV %s in volume group %s", pv_name, vg->name); goto bad; } mda_count = dm_list_size(&info->mdas); if (!archive(vg)) goto bad; } /* FIXME Create function to test compatibility properly */ if (mda_count > 1) { log_error("%s: too many metadata areas for pvresize", pv_name); goto bad; } if (!(pv->fmt->features & FMT_RESIZE_PV)) { log_error("Physical volume %s format does not support resizing.", pv_name); goto bad; } /* Get new size */ if (!dev_get_size(pv_dev(pv), &size)) { log_error("%s: Couldn't get size.", pv_name); goto bad; } if (new_size) { if (new_size > size) log_warn("WARNING: %s: Overriding real size. " "You could lose data.", pv_name); log_verbose("%s: Pretending size is %" PRIu64 " not %" PRIu64 " sectors.", pv_name, new_size, pv_size(pv)); size = new_size; } if (size < PV_MIN_SIZE) { log_error("%s: Size must exceed minimum of %ld sectors.", pv_name, PV_MIN_SIZE); goto bad; } if (size < pv_pe_start(pv)) { log_error("%s: Size must exceed physical extent start of " "%" PRIu64 " sectors.", pv_name, pv_pe_start(pv)); goto bad; } pv->size = size; if (vg) { pv->size -= pv_pe_start(pv); new_pe_count = pv_size(pv) / vg->extent_size; if (!new_pe_count) { log_error("%s: Size must leave space for at " "least one physical extent of " "%" PRIu32 " sectors.", pv_name, pv_pe_size(pv)); goto bad; } if (!pv_resize(pv, vg, new_pe_count)) goto_bad; } log_verbose("Resizing volume \"%s\" to %" PRIu64 " sectors.", pv_name, pv_size(pv)); log_verbose("Updating physical volume \"%s\"", pv_name); if (!is_orphan_vg(pv_vg_name(pv))) { if (!vg_write(vg) || !vg_commit(vg)) { log_error("Failed to store physical volume \"%s\" in " "volume group \"%s\"", pv_name, vg->name); goto bad; } backup(vg); } else if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) { log_error("Failed to store physical volume \"%s\"", pv_name); goto bad;; } log_print("Physical volume \"%s\" changed", pv_name); r = 1; bad: unlock_vg(cmd, vg_name); if (!old_vg) vg_release(vg); return r; }