Beispiel #1
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;
	}
Beispiel #2
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;
}