===================================================================
@@ -231,6 +231,7 @@ struct pool {
struct dm_target *ti; /* Only set if a pool target is bound */
struct mapped_device *pool_md;
+ struct block_device *data_dev;
struct block_device *md_dev;
struct dm_pool_metadata *pmd;
@@ -2933,6 +2934,7 @@ static struct kmem_cache *_new_mapping_c
static struct pool *pool_create(struct mapped_device *pool_md,
struct block_device *metadata_dev,
+ struct block_device *data_dev,
unsigned long block_size,
int read_only, char **error)
{
@@ -3040,6 +3042,7 @@ static struct pool *pool_create(struct m
pool->last_commit_jiffies = jiffies;
pool->pool_md = pool_md;
pool->md_dev = metadata_dev;
+ pool->data_dev = data_dev;
__pool_table_insert(pool);
return pool;
@@ -3081,6 +3084,7 @@ static void __pool_dec(struct pool *pool
static struct pool *__pool_find(struct mapped_device *pool_md,
struct block_device *metadata_dev,
+ struct block_device *data_dev,
unsigned long block_size, int read_only,
char **error, int *created)
{
@@ -3091,6 +3095,10 @@ static struct pool *__pool_find(struct m
*error = "metadata device already in use by a pool";
return ERR_PTR(-EBUSY);
}
+ if (pool->data_dev != data_dev) {
+ *error = "data device already in use by a pool";
+ return ERR_PTR(-EBUSY);
+ }
__pool_inc(pool);
} else {
@@ -3100,10 +3108,14 @@ static struct pool *__pool_find(struct m
*error = "different pool cannot replace a pool";
return ERR_PTR(-EINVAL);
}
+ if (pool->data_dev != data_dev) {
+ *error = "different pool cannot replace a pool";
+ return ERR_PTR(-EINVAL);
+ }
__pool_inc(pool);
} else {
- pool = pool_create(pool_md, metadata_dev, block_size, read_only, error);
+ pool = pool_create(pool_md, metadata_dev, data_dev, block_size, read_only, error);
*created = 1;
}
}
@@ -3356,7 +3368,7 @@ static int pool_ctr(struct dm_target *ti
goto out;
}
- pool = __pool_find(dm_table_get_md(ti->table), metadata_dev->bdev,
+ pool = __pool_find(dm_table_get_md(ti->table), metadata_dev->bdev, data_dev->bdev,
block_size, pf.mode == PM_READ_ONLY, &ti->error, &pool_created);
if (IS_ERR(pool)) {
r = PTR_ERR(pool);
The existing code allow changing the data device when the dm-thin-pool target is reloaded. This can cause crashes like the one reported here: https://bugzilla.redhat.com/show_bug.cgi?id=1788596 where the kernel tries to issue a flush bio located in a structure that was already freed. Locking the data device would be quite tricky, so a better solution is to disallow changing it - it is set in pool_create and it can never be changed for the given pool. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Cc: stable@vger.kernel.org Fixes: 694cfe7f31db ("dm thin: Flush data device before committing metadata") --- drivers/md/dm-thin.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) -- dm-devel mailing list dm-devel@redhat.com https://www.redhat.com/mailman/listinfo/dm-devel