示例#1
0
文件: pvmove.c 项目: andyvand/cyglvm2
/* 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);
	}
示例#2
0
/*
 * 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;
	}
示例#3
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;
}
示例#4
0
/*
 * 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;
}