/* Create list of PVs for allocation of replacement extents */ static struct dm_list *_get_allocatable_pvs(struct cmd_context *cmd, int argc, char **argv, struct volume_group *vg, struct physical_volume *pv, alloc_policy_t alloc) { struct dm_list *allocatable_pvs, *pvht, *pvh; struct pv_list *pvl; if (argc) allocatable_pvs = create_pv_list(cmd->mem, vg, argc, argv, 1); else allocatable_pvs = clone_pv_list(cmd->mem, &vg->pvs); if (!allocatable_pvs) return_NULL; dm_list_iterate_safe(pvh, pvht, allocatable_pvs) { pvl = dm_list_item(pvh, struct pv_list); /* Don't allocate onto the PV we're clearing! */ if ((alloc != ALLOC_ANYWHERE) && (pvl->pv->dev == pv_dev(pv))) { dm_list_del(&pvl->list); continue; } /* Remove PV if full */ if (pvl->pv->pe_count == pvl->pv->pe_alloc_count) dm_list_del(&pvl->list); }
/* * Update extents parameters based on other parameters which affect the size * calculation. * NOTE: We must do this here because of the percent_t typedef and because we * need the vg. */ static int _update_extents_params(struct volume_group *vg, struct lvcreate_params *lp, struct lvcreate_cmdline_params *lcp) { uint32_t pv_extent_count; struct logical_volume *origin = NULL; int changed = 0; uint32_t size_rest; uint32_t stripesize_extents; if (lcp->size && !(lp->extents = extents_from_size(vg->cmd, lcp->size, vg->extent_size))) return_0; if (lp->voriginsize && !(lp->voriginextents = extents_from_size(vg->cmd, lp->voriginsize, vg->extent_size))) return_0; /* * Create the pv list before we parse lcp->percent - might be * PERCENT_PVSs */ if (lcp->pv_count) { if (!(lp->pvh = create_pv_list(vg->cmd->mem, vg, lcp->pv_count, lcp->pvs, 1))) return_0; } else lp->pvh = &vg->pvs; switch(lcp->percent) { case PERCENT_VG: lp->extents = percent_of_extents(lp->extents, vg->extent_count, 0); break; case PERCENT_FREE: lp->extents = percent_of_extents(lp->extents, vg->free_count, 0); break; case PERCENT_PVS: if (!lcp->pv_count) lp->extents = percent_of_extents(lp->extents, vg->extent_count, 0); else { pv_extent_count = pv_list_extents_free(lp->pvh); lp->extents = percent_of_extents(lp->extents, pv_extent_count, 0); } break; case PERCENT_LV: log_error("Please express size as %%VG, %%PVS, or " "%%FREE."); return 0; case PERCENT_ORIGIN: if (lp->snapshot && lp->origin && !(origin = find_lv(vg, lp->origin))) { log_error("Couldn't find origin volume '%s'.", lp->origin); return 0; } if (!origin) { log_error(INTERNAL_ERROR "Couldn't find origin volume."); return 0; } lp->extents = percent_of_extents(lp->extents, origin->le_count, 0); break; case PERCENT_NONE: break; } if (!(stripesize_extents = lp->stripe_size / vg->extent_size)) stripesize_extents = 1; if ((lcp->percent != PERCENT_NONE) && lp->stripes && (size_rest = lp->extents % (lp->stripes * stripesize_extents)) && (vg->free_count < lp->extents - size_rest + (lp->stripes * stripesize_extents))) { log_print("Rounding size (%d extents) down to stripe boundary " "size (%d extents)", lp->extents, lp->extents - size_rest); lp->extents = lp->extents - size_rest; } if (lp->create_thin_pool) { if (!arg_count(vg->cmd, poolmetadatasize_ARG)) { /* Defaults to nr_pool_blocks * 64b */ lp->poolmetadatasize = (uint64_t) lp->extents * vg->extent_size / (uint64_t) (lp->chunk_size * (SECTOR_SIZE / UINT64_C(64))); /* Check if we could eventually use bigger chunk size */ if (!arg_count(vg->cmd, chunksize_ARG)) { while ((lp->poolmetadatasize > (DEFAULT_THIN_POOL_OPTIMAL_SIZE / SECTOR_SIZE)) && (lp->chunk_size < DM_THIN_MAX_DATA_BLOCK_SIZE)) { lp->chunk_size <<= 1; lp->poolmetadatasize >>= 1; changed++; } if (changed) log_verbose("Changed chunksize to %u sectors.", lp->chunk_size); } } if (lp->poolmetadatasize > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) { if (arg_count(vg->cmd, poolmetadatasize_ARG)) log_warn("WARNING: Maximum supported pool metadata size is 16GB."); lp->poolmetadatasize = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE; } else if (lp->poolmetadatasize < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE)) { if (arg_count(vg->cmd, poolmetadatasize_ARG)) log_warn("WARNING: Minimum supported pool metadata size is 2M."); lp->poolmetadatasize = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE; } log_verbose("Setting pool metadata size to %" PRIu64 " sectors.", lp->poolmetadatasize); if (!(lp->poolmetadataextents = extents_from_size(vg->cmd, lp->poolmetadatasize, vg->extent_size))) return_0; }
/* * Update extents parameters based on other parameters which affect the size * calculation. * NOTE: We must do this here because of the dm_percent_t typedef and because we * need the vg. */ static int _update_extents_params(struct volume_group *vg, struct lvcreate_params *lp, struct lvcreate_cmdline_params *lcp) { uint32_t pv_extent_count; struct logical_volume *origin = NULL; uint32_t size_rest; uint32_t stripesize_extents; uint32_t extents; if (lcp->size && !(lp->extents = extents_from_size(vg->cmd, lcp->size, vg->extent_size))) return_0; if (lp->voriginsize && !(lp->voriginextents = extents_from_size(vg->cmd, lp->voriginsize, vg->extent_size))) return_0; /* * Create the pv list before we parse lcp->percent - might be * PERCENT_PVSs */ if (lcp->pv_count) { if (!(lp->pvh = create_pv_list(vg->cmd->mem, vg, lcp->pv_count, lcp->pvs, 1))) return_0; } else lp->pvh = &vg->pvs; switch (lcp->percent) { case PERCENT_VG: extents = percent_of_extents(lp->extents, vg->extent_count, 0); break; case PERCENT_FREE: extents = percent_of_extents(lp->extents, vg->free_count, 0); break; case PERCENT_PVS: if (lcp->pv_count) { pv_extent_count = pv_list_extents_free(lp->pvh); extents = percent_of_extents(lp->extents, pv_extent_count, 0); } else extents = percent_of_extents(lp->extents, vg->extent_count, 0); break; case PERCENT_LV: log_error("Please express size as %s%%VG, %%PVS, " "or %%FREE.", (lp->snapshot) ? "%ORIGIN, " : ""); return 0; case PERCENT_ORIGIN: if (lp->snapshot && lp->origin && !(origin = find_lv(vg, lp->origin))) { log_error("Couldn't find origin volume '%s'.", lp->origin); return 0; } if (!origin) { log_error(INTERNAL_ERROR "Couldn't find origin volume."); return 0; } /* Add whole metadata size estimation */ extents = cow_max_extents(origin, lp->chunk_size) - origin->le_count + percent_of_extents(lp->extents, origin->le_count, 1); break; case PERCENT_NONE: extents = lp->extents; break; default: log_error(INTERNAL_ERROR "Unsupported percent type %u.", lcp->percent); return 0; } if (lcp->percent) { /* FIXME Don't do the adjustment for parallel allocation with PERCENT_ORIGIN! */ lp->approx_alloc = 1; log_verbose("Converted %" PRIu32 "%%%s into %" PRIu32 " extents.", lp->extents, get_percent_string(lcp->percent), extents); lp->extents = extents; } if (lp->snapshot && lp->origin && lp->extents) { if (!lp->chunk_size) { log_error(INTERNAL_ERROR "Missing snapshot chunk size."); return 0; } if (!origin && !(origin = find_lv(vg, lp->origin))) { log_error("Couldn't find origin volume '%s'.", lp->origin); return 0; } extents = cow_max_extents(origin, lp->chunk_size); if (extents < lp->extents) { log_print_unless_silent("Reducing COW size %s down to maximum usable size %s.", display_size(vg->cmd, (uint64_t) vg->extent_size * lp->extents), display_size(vg->cmd, (uint64_t) vg->extent_size * extents)); lp->extents = extents; } } if (!(stripesize_extents = lp->stripe_size / vg->extent_size)) stripesize_extents = 1; if ((lcp->percent != PERCENT_NONE) && lp->stripes && (size_rest = lp->extents % (lp->stripes * stripesize_extents)) && (vg->free_count < lp->extents - size_rest + (lp->stripes * stripesize_extents))) { log_print_unless_silent("Rounding size (%d extents) down to stripe boundary " "size (%d extents)", lp->extents, lp->extents - size_rest); lp->extents = lp->extents - size_rest; } if (lp->create_pool) { if (!_lvcreate_update_pool_params(vg, lp)) return_0; if (!(lp->poolmetadataextents = extents_from_size(vg->cmd, lp->poolmetadatasize, vg->extent_size))) return_0; if (lcp->percent == PERCENT_FREE) { if (lp->extents <= (2 * lp->poolmetadataextents)) { log_error("Not enough space for thin pool creation."); return 0; } /* FIXME: persistent hidden space in VG wanted */ lp->extents -= (2 * lp->poolmetadataextents); } } return 1; }
/* * Update extents parameters based on other parameters which affect the size * calcuation. * NOTE: We must do this here because of the percent_t typedef and because we * need the vg. */ static int _update_extents_params(struct volume_group *vg, struct lvcreate_params *lp, struct lvcreate_cmdline_params *lcp) { uint32_t pv_extent_count; struct logical_volume *origin = NULL; if (lcp->size && !(lp->extents = extents_from_size(vg->cmd, lcp->size, vg->extent_size))) return_0; if (lp->voriginsize && !(lp->voriginextents = extents_from_size(vg->cmd, lp->voriginsize, vg->extent_size))) return_0; /* * Create the pv list before we parse lcp->percent - might be * PERCENT_PVSs */ if (lcp->pv_count) { if (!(lp->pvh = create_pv_list(vg->cmd->mem, vg, lcp->pv_count, lcp->pvs, 1))) return_0; } else lp->pvh = &vg->pvs; switch(lcp->percent) { case PERCENT_VG: lp->extents = lp->extents * vg->extent_count / 100; break; case PERCENT_FREE: lp->extents = lp->extents * vg->free_count / 100; break; case PERCENT_PVS: if (!lcp->pv_count) lp->extents = lp->extents * vg->extent_count / 100; else { pv_extent_count = pv_list_extents_free(lp->pvh); lp->extents = lp->extents * pv_extent_count / 100; } break; case PERCENT_LV: log_error("Please express size as %%VG, %%PVS, or " "%%FREE."); return 0; case PERCENT_ORIGIN: if (lp->snapshot && lp->origin && !(origin = find_lv(vg, lp->origin))) { log_error("Couldn't find origin volume '%s'.", lp->origin); return 0; } lp->extents = lp->extents * origin->le_count / 100; break; case PERCENT_NONE: break; } return 1; }