From 36a0456fbf2d9680bf9af81b39daf4a8e22cb1b8 Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Mon, 31 Oct 2011 20:19:04 +0000 Subject: dm table: add immutable feature Introduce DM_TARGET_IMMUTABLE to indicate that the target type cannot be mixed with any other target type, and once loaded into a device, it cannot be replaced with a table containing a different type. The thin provisioning pool device will use this. Signed-off-by: Alasdair G Kergon --- drivers/md/dm-ioctl.c | 11 +++++++++++ drivers/md/dm-table.c | 21 +++++++++++++++++++++ drivers/md/dm.c | 9 +++++++++ drivers/md/dm.h | 2 ++ 4 files changed, 43 insertions(+) (limited to 'drivers/md') diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 2e9a3ca37bd..31c2dc25886 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1215,6 +1215,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) struct hash_cell *hc; struct dm_table *t; struct mapped_device *md; + struct target_type *immutable_target_type; md = find_device(param); if (!md) @@ -1230,6 +1231,16 @@ static int table_load(struct dm_ioctl *param, size_t param_size) goto out; } + immutable_target_type = dm_get_immutable_target_type(md); + if (immutable_target_type && + (immutable_target_type != dm_table_get_immutable_target_type(t))) { + DMWARN("can't replace immutable target type %s", + immutable_target_type->name); + dm_table_destroy(t); + r = -EINVAL; + goto out; + } + /* Protect md->type and md->queue against concurrent table loads. */ dm_lock_md_type(md); if (dm_get_md_type(md) == DM_TYPE_NONE) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 9917141729e..8e913213014 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -54,6 +54,7 @@ struct dm_table { sector_t *highs; struct dm_target *targets; + struct target_type *immutable_target_type; unsigned integrity_supported:1; unsigned singleton:1; @@ -780,6 +781,21 @@ int dm_table_add_target(struct dm_table *t, const char *type, return -EINVAL; } + 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); + return -EINVAL; + } + } else if (dm_target_is_immutable(tgt->type)) { + if (t->num_targets) { + DMERR("%s: immutable target type %s cannot be mixed with other target types", + dm_device_name(t->md), tgt->type->name); + return -EINVAL; + } + t->immutable_target_type = tgt->type; + } + tgt->table = t; tgt->begin = start; tgt->len = len; @@ -937,6 +953,11 @@ unsigned dm_table_get_type(struct dm_table *t) return t->type; } +struct target_type *dm_table_get_immutable_target_type(struct dm_table *t) +{ + return t->immutable_target_type; +} + bool dm_table_request_based(struct dm_table *t) { return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 2fe3017ba97..9836324e211 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -140,6 +140,8 @@ struct mapped_device { /* Protect queue and type against concurrent access. */ struct mutex type_lock; + struct target_type *immutable_target_type; + struct gendisk *disk; char name[16]; @@ -2096,6 +2098,8 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, write_lock_irqsave(&md->map_lock, flags); old_map = md->map; md->map = t; + md->immutable_target_type = dm_table_get_immutable_target_type(t); + dm_table_set_restrictions(t, q, limits); if (merge_is_optional) set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags); @@ -2166,6 +2170,11 @@ unsigned dm_get_md_type(struct mapped_device *md) return md->type; } +struct target_type *dm_get_immutable_target_type(struct mapped_device *md) +{ + return md->immutable_target_type; +} + /* * Fully initialize a request-based queue (->elevator, ->request_fn, etc). */ diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 6745dbd278a..b7dacd59d8d 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -60,6 +60,7 @@ int dm_table_resume_targets(struct dm_table *t); int dm_table_any_congested(struct dm_table *t, int bdi_bits); int dm_table_any_busy_target(struct dm_table *t); unsigned dm_table_get_type(struct dm_table *t); +struct target_type *dm_table_get_immutable_target_type(struct dm_table *t); bool dm_table_request_based(struct dm_table *t); bool dm_table_supports_discards(struct dm_table *t); int dm_table_alloc_md_mempools(struct dm_table *t); @@ -72,6 +73,7 @@ void dm_lock_md_type(struct mapped_device *md); void dm_unlock_md_type(struct mapped_device *md); void dm_set_md_type(struct mapped_device *md, unsigned type); unsigned dm_get_md_type(struct mapped_device *md); +struct target_type *dm_get_immutable_target_type(struct mapped_device *md); int dm_setup_md_queue(struct mapped_device *md); -- cgit v1.2.3