[dm-devel] [PATCH 3/3] dm: allow error target to replace immutable target

Mikulas Patocka mpatocka at redhat.com
Thu Aug 29 14:37:30 UTC 2013


As I said - I think it would be better to remove the immutable flag than 
to create more flags to bypass it.

Mikulas

On Wed, 28 Aug 2013, Mike Snitzer wrote:

> Introduce DM_TARGET_ALWAYS_RETURNS_IO_ERROR to indicate that a target
> always returns IO error.  Because the target will error all IO it can
> safely replace any target (including an immutable target) as along as
> the associated mapped device is not open.  If an error target replaces
> an immutable target it is elevated to the mapped device's immutable
> target type.
> 
> The "error" target can now replace an immutable target like the thin
> provisioning pool ("thin-pool") target.
> 
> Signed-off-by: Mike Snitzer <snitzer at redhat.com>
> ---
>  drivers/md/dm-ioctl.c         | 27 ++++++++++++++++++++++++++-
>  drivers/md/dm-table.c         |  9 ++++++++-
>  drivers/md/dm-target.c        |  1 +
>  include/linux/device-mapper.h | 10 ++++++++++
>  4 files changed, 45 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
> index 301e0a5..08186cb 100644
> --- a/drivers/md/dm-ioctl.c
> +++ b/drivers/md/dm-ioctl.c
> @@ -1248,6 +1248,30 @@ static int populate_table(struct dm_table *table,
>  	return dm_table_complete(table);
>  }
>  
> +static bool immutable_target_type_is_valid(struct mapped_device *md,
> +					   struct target_type *immutable_tt,
> +					   struct target_type *table_immutable_tt)
> +{
> +	if (immutable_tt == table_immutable_tt)
> +		return true;
> +
> +	if (!table_immutable_tt)
> +		return false;
> +
> +	if (dm_target_always_returns_io_error(table_immutable_tt)) {
> +		/*
> +		 * Only allow a transition to an error target_type if
> +		 * the mapped_device is no longer open.
> +		 */
> +		if (!dm_open_count(md))
> +			return true;
> +
> +		DMERR("can't change target type to error while device is in use");
> +	}
> +
> +	return false;
> +}
> +
>  static int table_load(struct dm_ioctl *param, size_t param_size)
>  {
>  	int r;
> @@ -1272,7 +1296,8 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
>  
>  	immutable_target_type = dm_get_immutable_target_type(md);
>  	if (immutable_target_type &&
> -	    (immutable_target_type != dm_table_get_immutable_target_type(t))) {
> +	    !immutable_target_type_is_valid(md, immutable_target_type,
> +					    dm_table_get_immutable_target_type(t))) {
>  		DMWARN("can't replace immutable target type %s",
>  		       immutable_target_type->name);
>  		r = -EINVAL;
> diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
> index 8f87835..70d3067 100644
> --- a/drivers/md/dm-table.c
> +++ b/drivers/md/dm-table.c
> @@ -745,7 +745,14 @@ int dm_table_add_target(struct dm_table *t, const char *type,
>  		return -EINVAL;
>  	}
>  
> -	if (t->immutable_target_type) {
> +	if (dm_target_always_returns_io_error(tgt->type) &&
> +	    dm_get_immutable_target_type(t->md)) {
> +		/*
> +		 * This error target must be upgraded to immutable because
> +		 * the mapped device is already using an immutable target.
> +		 */
> +		t->immutable_target_type = tgt->type;
> +	} else if (t->immutable_target_type) {
>  		if (t->immutable_target_type != tgt->type) {
>  			DMERR("%s: immutable target type %s cannot be mixed with other target types",
>  			      dm_device_name(t->md), t->immutable_target_type->name);
> diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c
> index 242e3ce..3b9a988 100644
> --- a/drivers/md/dm-target.c
> +++ b/drivers/md/dm-target.c
> @@ -139,6 +139,7 @@ static int io_err_map_rq(struct dm_target *ti, struct request *clone,
>  
>  static struct target_type error_target = {
>  	.name = "error",
> +	.features = DM_TARGET_ALWAYS_RETURNS_IO_ERROR,
>  	.version = {1, 2, 0},
>  	.ctr  = io_err_ctr,
>  	.dtr  = io_err_dtr,
> diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
> index 653073d..2451e6b 100644
> --- a/include/linux/device-mapper.h
> +++ b/include/linux/device-mapper.h
> @@ -192,6 +192,16 @@ struct target_type {
>  #define dm_target_is_immutable(type)	((type)->features & DM_TARGET_IMMUTABLE)
>  
>  /*
> + * Indicates that a target always returns IO error.  Because the target will error
> + * all IO it can safely replace any target (including an immutable target) as long
> + * as the associated mapped device is not open.  If an error target replaces an
> + * immutable target it is elevated to the mapped device's immutable target type.
> + */
> +#define DM_TARGET_ALWAYS_RETURNS_IO_ERROR	0x00000008
> +#define dm_target_always_returns_io_error(type) \
> +		((type)->features & DM_TARGET_ALWAYS_RETURNS_IO_ERROR)
> +
> +/*
>   * Some targets need to be sent the same WRITE bio severals times so
>   * that they can send copies of it to different devices.  This function
>   * examines any supplied bio and returns the number of copies of it the
> -- 
> 1.8.1.4
> 
> --
> dm-devel mailing list
> dm-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/dm-devel
> 




More information about the dm-devel mailing list