Merge tag 'kgdb-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/danielt...
[linux-2.6-microblaze.git] / drivers / md / dm-thin.c
index 57626c2..fa8d546 100644 (file)
@@ -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;
 
@@ -281,6 +282,8 @@ struct pool {
        struct dm_bio_prison_cell **cell_sort_array;
 
        mempool_t mapping_pool;
+
+       struct bio flush_bio;
 };
 
 static void metadata_operation_failed(struct pool *pool, const char *op, int r);
@@ -328,7 +331,6 @@ struct pool_c {
        dm_block_t low_water_blocks;
        struct pool_features requested_pf; /* Features requested during table load */
        struct pool_features adjusted_pf;  /* Features used after adjusting for constituent devices */
-       struct bio flush_bio;
 };
 
 /*
@@ -2924,6 +2926,7 @@ static void __pool_destroy(struct pool *pool)
        if (pool->next_mapping)
                mempool_free(pool->next_mapping, &pool->mapping_pool);
        mempool_exit(&pool->mapping_pool);
+       bio_uninit(&pool->flush_bio);
        dm_deferred_set_destroy(pool->shared_read_ds);
        dm_deferred_set_destroy(pool->all_io_ds);
        kfree(pool);
@@ -2933,6 +2936,7 @@ static struct kmem_cache *_new_mapping_cache;
 
 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)
 {
@@ -3003,6 +3007,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
        pool->low_water_triggered = false;
        pool->suspended = true;
        pool->out_of_data_space = false;
+       bio_init(&pool->flush_bio, NULL, 0);
 
        pool->shared_read_ds = dm_deferred_set_create();
        if (!pool->shared_read_ds) {
@@ -3040,6 +3045,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
        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 +3087,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,19 +3098,23 @@ static struct pool *__pool_find(struct mapped_device *pool_md,
                        *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 {
                pool = __pool_table_lookup(pool_md);
                if (pool) {
-                       if (pool->md_dev != metadata_dev) {
+                       if (pool->md_dev != metadata_dev || 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;
                }
        }
@@ -3124,7 +3135,6 @@ static void pool_dtr(struct dm_target *ti)
        __pool_dec(pt->pool);
        dm_put_device(ti, pt->metadata_dev);
        dm_put_device(ti, pt->data_dev);
-       bio_uninit(&pt->flush_bio);
        kfree(pt);
 
        mutex_unlock(&dm_thin_pool_table.mutex);
@@ -3203,11 +3213,11 @@ static void metadata_low_callback(void *context)
  */
 static int metadata_pre_commit_callback(void *context)
 {
-       struct pool_c *pt = context;
-       struct bio *flush_bio = &pt->flush_bio;
+       struct pool *pool = context;
+       struct bio *flush_bio = &pool->flush_bio;
 
        bio_reset(flush_bio);
-       bio_set_dev(flush_bio, pt->data_dev->bdev);
+       bio_set_dev(flush_bio, pool->data_dev);
        flush_bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
 
        return submit_bio_wait(flush_bio);
@@ -3356,7 +3366,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
                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);
@@ -3381,7 +3391,6 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        pt->data_dev = data_dev;
        pt->low_water_blocks = low_water_blocks;
        pt->adjusted_pf = pt->requested_pf = pf;
-       bio_init(&pt->flush_bio, NULL, 0);
        ti->num_flush_bios = 1;
 
        /*
@@ -3408,9 +3417,8 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        if (r)
                goto out_flags_changed;
 
-       dm_pool_register_pre_commit_callback(pt->pool->pmd,
-                                            metadata_pre_commit_callback,
-                                            pt);
+       dm_pool_register_pre_commit_callback(pool->pmd,
+                                            metadata_pre_commit_callback, pool);
 
        pt->callbacks.congested_fn = pool_is_congested;
        dm_table_add_target_callbacks(ti->table, &pt->callbacks);
@@ -4099,7 +4107,7 @@ static struct target_type pool_target = {
        .name = "thin-pool",
        .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
                    DM_TARGET_IMMUTABLE,
-       .version = {1, 21, 0},
+       .version = {1, 22, 0},
        .module = THIS_MODULE,
        .ctr = pool_ctr,
        .dtr = pool_dtr,
@@ -4476,7 +4484,7 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
 static struct target_type thin_target = {
        .name = "thin",
-       .version = {1, 21, 0},
+       .version = {1, 22, 0},
        .module = THIS_MODULE,
        .ctr = thin_ctr,
        .dtr = thin_dtr,