All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zdenek Kabelac <zkabelac@redhat.com>
To: lvm-devel@redhat.com
Subject: [PATCH] RFC: lvm2app: Add thin and thin pool lv creation
Date: Thu, 02 May 2013 13:13:34 +0200	[thread overview]
Message-ID: <51824A5E.5010603@redhat.com> (raw)
In-Reply-To: <1367263243-17331-1-git-send-email-tasleson@redhat.com>

Dne 29.4.2013 21:20, Tony Asleson napsal(a):
> From: "M. Mohan Kumar" <mohan@in.ibm.com>
>
> Add thin and thin pool lv creation support to lvm library
>
> This is Mohan's patch, re-worked to include suggestions
> from Zdenek.
>
> Is this closer to what we are looking for?
>
> --Tony
>
> Signed-off-by: Tony Asleson <tasleson@redhat.com>
> ---
>   liblvm/lvm2app.h | 116 +++++++++++++++++++++++++++++++
>   liblvm/lvm_lv.c  | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 321 insertions(+)
>
> diff --git a/liblvm/lvm2app.h b/liblvm/lvm2app.h
> index 93a78c3..bbdc037 100644
> --- a/liblvm/lvm2app.h
> +++ b/liblvm/lvm2app.h
> @@ -97,6 +97,7 @@ struct volume_group;
>   struct logical_volume;
>   struct lv_segment;
>   struct pv_segment;
> +struct lvm_lv_create_params;
>
>   /**
>    * \class lvm_t
> @@ -153,6 +154,14 @@ typedef struct lv_segment *lvseg_t;
>   typedef struct pv_segment *pvseg_t;
>
>   /**
> + * \class lv_create_params
> + *
> + * This lv_create_params represents the plethora of available options when
> + * creating a logical volume
> + */
> +typedef struct lvm_lv_create_params *lv_create_params_t;
> +
> +/**
>    * Logical Volume object list.
>    *
>    * Lists of these structures are returned by lvm_vg_list_lvs().
> @@ -1400,6 +1409,113 @@ int lvm_lv_resize(const lv_t lv, uint64_t new_size);
>    */
>   lv_t lvm_lv_snapshot(const lv_t lv, const char *snap_name, uint64_t max_snap_size);
>
> +/**
> + * Thin provisioning discard policies
> + */
> +typedef enum {
> +	LVM_THIN_DISCARDS_IGNORE,
> +	LVM_THIN_DISCARDS_NO_PASSDOWN,
> +	LVM_THIN_DISCARDS_PASSDOWN,
> +} lvm_thin_discards_t;
> +
> +/**
> + * Create a thinpool parameter passing object for the specified VG
> + *
> + * \param   vg
> + * Volume Group handle.
> + *
> + * \param   pool_name
> + * Name of the pool.
> + *
> + * \param   size
> + * size of the pool
> + *
> + * \param   chunk_size
> + * data block size of the pool
> + * Default value is DEFAULT_THIN_POOL_CHUNK_SIZE * 2 when 0 passed as chunk_size
> + * DM_THIN_MIN_DATA_BLOCK_SIZE < chunk_size < DM_THIN_MAX_DATA_BLOCK_SIZE
> + *
> + * \param meta_size
> + * Size of thin pool's metadata logical volume. Allowed range is 2MB-16GB.
> + * Default value (ie if 0) pool size / pool chunk size * 64
> + *
> + * \param discard
> + * Thin discard policy
> + * Note: THIN_DISCARDS_PASSDOWN is the default.
> + *
> + * \return
> + * Valid lv_create_params pointer on success, else NULL on error.
> + * Note: Memory is associated with the vg, it will get reclaimed when vg is
> + * closed.
> + *
> + */
> +lv_create_params_t lvm_lv_params_create_thin_pool(const vg_t vg,
> +		const char *pool_name, uint64_t size, uint32_t chunk_size,
> +		uint64_t meta_size, lvm_thin_discards_t discard);
> +
> +#define lvm_lv_params_create_thin_pool_default(vg, pool_name, size) \
> +			lvm_lv_params_create_thin_pool((vg), (pool_name), (size), 0, 0, \
> +			LVM_THIN_DISCARDS_PASSDOWN)
> +
> +
> +/**
> + * Set the value of zero skip for the lv_create_params
> + *
> + * \param params
> + * lv_create_prams to change
> + *
> + * \param skip
> + * Value of skip zero to be set (0 == zero, 1 == skip zero)
> + *
> + * \return
> + * 0 on success, else -1
> + */
> +int lvm_lv_params_skip_zero_set(lv_create_params_t params, int skip);
> +
> +/**
> + * Get the value of zero skip for the lv_create_params
> + *
> + * \param params
> + * lv_create_prams to query
> + *
> + * \return
> + * -1 on error, else 0 == zero, 1 == skip zero
> + */
> +int lvm_lv_params_skip_zero_get(lv_create_params_t params);
> +
> +/**
> + * Create a thin LV creation parameters in a given VG & thin pool
> + *
> + * \param   vg
> + * Volume Group handle.
> + *
> + * \param   pool_name
> + * Name of the pool.
> + *
> + * \param lvname
> + * Name of the LV to create
> + *
> + * \param   size
> + * Size of logical volume
> + *
> + * \return
> + * Valid lv_create_params pointer on success, else NULL on error.
> + * Note: Memory is associated with the vg, it will get reclaimed when vg is
> + * closed.
> + *
> + */
> +lv_create_params_t lvm_lv_params_create_thin(const vg_t vg, const char *pool_name,
> +									const char *lvname, uint64_t size);
> +/**
> + * Create the actual logical volume.
> + *
> + * \param	params		The parameters object for lv creation
> + *
> + * \return
> + * Valid lv pointer on success, else NULL on error.
> + */
> +lv_t lvm_lv_create(lv_create_params_t params);
> +
>   /************************** physical volume handling ************************/
>
>   /**
> diff --git a/liblvm/lvm_lv.c b/liblvm/lvm_lv.c
> index 91948a6..7e49cb3 100644
> --- a/liblvm/lvm_lv.c
> +++ b/liblvm/lvm_lv.c
> @@ -22,6 +22,15 @@
>   #include "lvm_misc.h"
>   #include "lvm2app.h"
>
> +struct lvm_lv_create_params
> +{
> +	uint32_t magic;
> +	vg_t vg;
> +	struct lvcreate_params lvp;
> +};
> +
> +#define LV_CREATE_PARAMS_MAGIC 0xFEED0001
> +
>   static int _lv_check_handle(const lv_t lv, const int vg_writeable)
>   {
>   	if (!lv || !lv->vg || vg_read_error(lv->vg))
> @@ -350,3 +359,199 @@ lv_t lvm_lv_snapshot(const lv_t lv, const char *snap_name, uint64_t max_snap_siz
>   		return NULL;
>   	return (lv_t) lvl->lv;
>   }
> +
> +/* Set defaults for thin pool specific LV parameters */
> +static void _lv_set_pool_params(struct lvcreate_params *lp,
> +				vg_t vg, const char *pool,
> +				uint64_t extents, uint64_t meta_size)
> +{
> +	_lv_set_default_params(lp, vg, NULL, extents);
> +
> +	lp->pool = pool;
> +
> +	lp->create_thin_pool = 1;
> +	lp->segtype = get_segtype_from_string(vg->cmd, "thin-pool");
> +	lp->stripes = 1;
> +
> +	if (!meta_size) {
> +		lp->poolmetadatasize = extents * vg->extent_size /
> +			(lp->chunk_size * (SECTOR_SIZE / 64));
> +		while ((lp->poolmetadatasize >
> +			(2 * DEFAULT_THIN_POOL_OPTIMAL_SIZE / SECTOR_SIZE)) &&
> +		       lp->chunk_size < DM_THIN_MAX_DATA_BLOCK_SIZE) {
> +			lp->chunk_size <<= 1;
> +			lp->poolmetadatasize >>= 1;
> +	         }
> +	} else
> +		lp->poolmetadatasize = meta_size;
> +
> +	if (lp->poolmetadatasize % vg->extent_size)
> +		lp->poolmetadatasize +=
> +			vg->extent_size - lp->poolmetadatasize % vg->extent_size;
> +
> +	lp->poolmetadataextents =
> +		extents_from_size(vg->cmd, lp->poolmetadatasize / SECTOR_SIZE,
> +						   vg->extent_size);
> +}
> +
> +lv_create_params_t lvm_lv_params_create_thin_pool(const vg_t vg,
> +		const char *pool_name, uint64_t size, uint32_t chunk_size,
> +		uint64_t meta_size, lvm_thin_discards_t discard)
> +{
> +	uint64_t extents = 0;
> +	struct lvm_lv_create_params *lvcp = NULL;
> +
> +	if (meta_size > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) {
> +		log_error("Invalid metadata size");
> +		return NULL;
> +	}
> +
> +	if (meta_size &&
> +		meta_size < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE)) {
> +		log_error("Invalid metadata size");
> +		return NULL;
> +	}
> +
> +	if (vg_read_error(vg))
> +		return NULL;
> +
> +	if (!vg_check_write_mode(vg))
> +		return NULL;
> +
> +	if (pool_name == NULL || !strlen(pool_name)) {
> +		log_error("pool_name invalid");
> +		return NULL;
> +	}
> +
> +	if (!(extents = extents_from_size(vg->cmd, size / SECTOR_SIZE,
> +					  vg->extent_size))) {
> +		log_error("Unable to create LV thin pool without size.");
> +		return NULL;
> +	}
> +
> +	lvcp = dm_pool_zalloc(vg->vgmem, sizeof (struct lvm_lv_create_params));
> +
> +	if (lvcp) {
> +		lvcp->vg = vg;
> +		lvcp->lvp.discards = discard;
> +
> +		if (chunk_size)
> +			lvcp->lvp.chunk_size = chunk_size;
> +		else
> +			lvcp->lvp.chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE * 2;
> +
> +		if (lvcp->lvp.chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE ||
> +				lvcp->lvp.chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE) {
> +			log_error("Invalid chunk_size");
> +			return NULL;
> +		}
> +
> +		_lv_set_pool_params(&lvcp->lvp, vg, pool_name, extents, meta_size);
> +
> +		lvcp->magic = LV_CREATE_PARAMS_MAGIC;
> +	}
> +	return lvcp;
> +}
> +
> +/* Set defaults for thin LV specific parameters */
> +static void _lv_set_thin_params(struct lvcreate_params *lp,
> +				vg_t vg, const char *pool,
> +				const char *lvname,
> +				uint64_t extents)
> +{
> +	_lv_set_default_params(lp, vg, lvname, extents);
> +
> +	lp->thin = 1;
> +	lp->pool = pool;
> +	lp->segtype = get_segtype_from_string(vg->cmd, "thin");
> +
> +	lp->voriginsize = extents * vg->extent_size;
> +	lp->voriginextents = extents_from_size(vg->cmd, lp->voriginsize,
> +						   vg->extent_size);
> +
> +	lp->stripes = 1;
> +}
> +
> +lv_create_params_t lvm_lv_params_create_thin(const vg_t vg, const char *pool_name,
> +									const char *lvname, uint64_t size)

Hmmm - here the vg doesn't remain unmodified - we use it's memory pool for 
lvcp - so I'd prefer to use it here without 'const'


> +{
> +	struct lvm_lv_create_params *lvcp = NULL;
> +	uint64_t extents = 0;
> +
> +	/* precondition checks */
> +	if (vg_read_error(vg))
> +		return NULL;
> +
> +	if (!vg_check_write_mode(vg))
> +		return NULL;
> +
> +	if (pool_name == NULL || !strlen(pool_name)) {
> +		log_error("pool_name invalid");
> +		return NULL;
> +	}
> +
> +	if (lvname == NULL || !strlen(lvname)) {
> +		log_error("lvname invalid");
> +		return NULL;
> +	}
> +
> +	if (!(extents = extents_from_size(vg->cmd, size / SECTOR_SIZE,
> +			vg->extent_size))) {
> +		log_error("Unable to create thin LV without size.");
> +		return NULL;
> +	}
> +
> +	lvcp = dm_pool_zalloc(vg->vgmem, sizeof (struct lvm_lv_create_params));
> +	if (lvcp) {
> +		lvcp->vg = vg;
> +		_lv_set_thin_params(&lvcp->lvp, vg, pool_name, lvname, extents);
> +		lvcp->magic = LV_CREATE_PARAMS_MAGIC;
> +	}
> +
> +	return lvcp;
> +}
> +
> +int lvm_lv_params_skip_zero_set(lv_create_params_t params, int skip)
> +{
> +	int rc = -1;
> +
> +	if (skip == 0 || skip == 1) {
> +		if (params && params->magic == LV_CREATE_PARAMS_MAGIC) {
> +			params->lvp.zero = skip;
> +			rc = 0;
> +		} else {
> +			log_error("Invalid lv_create_params parameter");
> +		}
> +	} else {
> +		log_error("Invalid skip value");
> +	}
> +	return rc;
> +}
> +
> +int lvm_lv_params_skip_zero_get(lv_create_params_t params)


add const for '_get()'

> +{
> +	if (params && params->magic == LV_CREATE_PARAMS_MAGIC) {
> +		return params->lvp.zero;
> +	}
> +	log_error("Invalid lv_create_params parameter");
> +	return -1;
> +}
> +
> +lv_t lvm_lv_create(lv_create_params_t params)
> +{
> +	struct lv_list *lvl = NULL;
> +
> +	if (params && params->magic == LV_CREATE_PARAMS_MAGIC) {
> +		if (!params->lvp.segtype) {
> +			log_error("segtype parameter is NULL");
> +			return_NULL;
> +		}
> +		if (!lv_create_single(params->vg, &params->lvp))
> +				return_NULL;
> +		if (!(lvl = find_lv_in_vg(params->vg, params->lvp.pool)))
> +			return_NULL;
> +		return (lv_t) lvl->lv;
> +	}
> +	log_error("Invalid lv_create_params parameter");
> +	return NULL;
> +}
>


Any API test case ?


Zdenek




  reply	other threads:[~2013-05-02 11:13 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-29 19:20 [PATCH] RFC: lvm2app: Add thin and thin pool lv creation Tony Asleson
2013-05-02 11:13 ` Zdenek Kabelac [this message]
2013-05-02 22:24   ` Tony Asleson
2013-05-03 13:29     ` Zdenek Kabelac

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=51824A5E.5010603@redhat.com \
    --to=zkabelac@redhat.com \
    --cc=lvm-devel@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.