diff options
-rw-r--r-- | drivers/md/dm-table.c | 11 | ||||
-rw-r--r-- | drivers/md/dm.c | 33 | ||||
-rw-r--r-- | drivers/md/dm.h | 2 | ||||
-rw-r--r-- | include/linux/device-mapper.h | 30 |
4 files changed, 56 insertions, 20 deletions
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 6be58b696377..daf25d0890b3 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -967,13 +967,22 @@ bool dm_table_request_based(struct dm_table *t) | |||
967 | int dm_table_alloc_md_mempools(struct dm_table *t) | 967 | int dm_table_alloc_md_mempools(struct dm_table *t) |
968 | { | 968 | { |
969 | unsigned type = dm_table_get_type(t); | 969 | unsigned type = dm_table_get_type(t); |
970 | unsigned per_bio_data_size = 0; | ||
971 | struct dm_target *tgt; | ||
972 | unsigned i; | ||
970 | 973 | ||
971 | if (unlikely(type == DM_TYPE_NONE)) { | 974 | if (unlikely(type == DM_TYPE_NONE)) { |
972 | DMWARN("no table type is set, can't allocate mempools"); | 975 | DMWARN("no table type is set, can't allocate mempools"); |
973 | return -EINVAL; | 976 | return -EINVAL; |
974 | } | 977 | } |
975 | 978 | ||
976 | t->mempools = dm_alloc_md_mempools(type, t->integrity_supported); | 979 | if (type == DM_TYPE_BIO_BASED) |
980 | for (i = 0; i < t->num_targets; i++) { | ||
981 | tgt = t->targets + i; | ||
982 | per_bio_data_size = max(per_bio_data_size, tgt->per_bio_data_size); | ||
983 | } | ||
984 | |||
985 | t->mempools = dm_alloc_md_mempools(type, t->integrity_supported, per_bio_data_size); | ||
977 | if (!t->mempools) | 986 | if (!t->mempools) |
978 | return -ENOMEM; | 987 | return -ENOMEM; |
979 | 988 | ||
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 5401cdce0fc5..2765cf2ba0ff 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -63,18 +63,6 @@ struct dm_io { | |||
63 | }; | 63 | }; |
64 | 64 | ||
65 | /* | 65 | /* |
66 | * For bio-based dm. | ||
67 | * One of these is allocated per target within a bio. Hopefully | ||
68 | * this will be simplified out one day. | ||
69 | */ | ||
70 | struct dm_target_io { | ||
71 | struct dm_io *io; | ||
72 | struct dm_target *ti; | ||
73 | union map_info info; | ||
74 | struct bio clone; | ||
75 | }; | ||
76 | |||
77 | /* | ||
78 | * For request-based dm. | 66 | * For request-based dm. |
79 | * One of these is allocated per request. | 67 | * One of these is allocated per request. |
80 | */ | 68 | */ |
@@ -1980,13 +1968,20 @@ static void free_dev(struct mapped_device *md) | |||
1980 | 1968 | ||
1981 | static void __bind_mempools(struct mapped_device *md, struct dm_table *t) | 1969 | static void __bind_mempools(struct mapped_device *md, struct dm_table *t) |
1982 | { | 1970 | { |
1983 | struct dm_md_mempools *p; | 1971 | struct dm_md_mempools *p = dm_table_get_md_mempools(t); |
1984 | 1972 | ||
1985 | if (md->io_pool && (md->tio_pool || dm_table_get_type(t) == DM_TYPE_BIO_BASED) && md->bs) | 1973 | if (md->io_pool && (md->tio_pool || dm_table_get_type(t) == DM_TYPE_BIO_BASED) && md->bs) { |
1986 | /* the md already has necessary mempools */ | 1974 | /* |
1975 | * The md already has necessary mempools. Reload just the | ||
1976 | * bioset because front_pad may have changed because | ||
1977 | * a different table was loaded. | ||
1978 | */ | ||
1979 | bioset_free(md->bs); | ||
1980 | md->bs = p->bs; | ||
1981 | p->bs = NULL; | ||
1987 | goto out; | 1982 | goto out; |
1983 | } | ||
1988 | 1984 | ||
1989 | p = dm_table_get_md_mempools(t); | ||
1990 | BUG_ON(!p || md->io_pool || md->tio_pool || md->bs); | 1985 | BUG_ON(!p || md->io_pool || md->tio_pool || md->bs); |
1991 | 1986 | ||
1992 | md->io_pool = p->io_pool; | 1987 | md->io_pool = p->io_pool; |
@@ -2745,7 +2740,7 @@ int dm_noflush_suspending(struct dm_target *ti) | |||
2745 | } | 2740 | } |
2746 | EXPORT_SYMBOL_GPL(dm_noflush_suspending); | 2741 | EXPORT_SYMBOL_GPL(dm_noflush_suspending); |
2747 | 2742 | ||
2748 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity) | 2743 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, unsigned per_bio_data_size) |
2749 | { | 2744 | { |
2750 | struct dm_md_mempools *pools = kmalloc(sizeof(*pools), GFP_KERNEL); | 2745 | struct dm_md_mempools *pools = kmalloc(sizeof(*pools), GFP_KERNEL); |
2751 | unsigned int pool_size = (type == DM_TYPE_BIO_BASED) ? 16 : MIN_IOS; | 2746 | unsigned int pool_size = (type == DM_TYPE_BIO_BASED) ? 16 : MIN_IOS; |
@@ -2753,6 +2748,8 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity) | |||
2753 | if (!pools) | 2748 | if (!pools) |
2754 | return NULL; | 2749 | return NULL; |
2755 | 2750 | ||
2751 | per_bio_data_size = roundup(per_bio_data_size, __alignof__(struct dm_target_io)); | ||
2752 | |||
2756 | pools->io_pool = (type == DM_TYPE_BIO_BASED) ? | 2753 | pools->io_pool = (type == DM_TYPE_BIO_BASED) ? |
2757 | mempool_create_slab_pool(MIN_IOS, _io_cache) : | 2754 | mempool_create_slab_pool(MIN_IOS, _io_cache) : |
2758 | mempool_create_slab_pool(MIN_IOS, _rq_bio_info_cache); | 2755 | mempool_create_slab_pool(MIN_IOS, _rq_bio_info_cache); |
@@ -2768,7 +2765,7 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity) | |||
2768 | 2765 | ||
2769 | pools->bs = (type == DM_TYPE_BIO_BASED) ? | 2766 | pools->bs = (type == DM_TYPE_BIO_BASED) ? |
2770 | bioset_create(pool_size, | 2767 | bioset_create(pool_size, |
2771 | offsetof(struct dm_target_io, clone)) : | 2768 | per_bio_data_size + offsetof(struct dm_target_io, clone)) : |
2772 | bioset_create(pool_size, | 2769 | bioset_create(pool_size, |
2773 | offsetof(struct dm_rq_clone_bio_info, clone)); | 2770 | offsetof(struct dm_rq_clone_bio_info, clone)); |
2774 | if (!pools->bs) | 2771 | if (!pools->bs) |
diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 6a99fefaa743..45b97da1bd06 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h | |||
@@ -159,7 +159,7 @@ void dm_kcopyd_exit(void); | |||
159 | /* | 159 | /* |
160 | * Mempool operations | 160 | * Mempool operations |
161 | */ | 161 | */ |
162 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity); | 162 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, unsigned per_bio_data_size); |
163 | void dm_free_md_mempools(struct dm_md_mempools *pools); | 163 | void dm_free_md_mempools(struct dm_md_mempools *pools); |
164 | 164 | ||
165 | #endif | 165 | #endif |
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index d1f6cd8486f2..6f0e73b4a80d 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h | |||
@@ -210,6 +210,12 @@ struct dm_target { | |||
210 | */ | 210 | */ |
211 | unsigned num_write_same_requests; | 211 | unsigned num_write_same_requests; |
212 | 212 | ||
213 | /* | ||
214 | * The minimum number of extra bytes allocated in each bio for the | ||
215 | * target to use. dm_per_bio_data returns the data location. | ||
216 | */ | ||
217 | unsigned per_bio_data_size; | ||
218 | |||
213 | /* target specific data */ | 219 | /* target specific data */ |
214 | void *private; | 220 | void *private; |
215 | 221 | ||
@@ -246,6 +252,30 @@ struct dm_target_callbacks { | |||
246 | int (*congested_fn) (struct dm_target_callbacks *, int); | 252 | int (*congested_fn) (struct dm_target_callbacks *, int); |
247 | }; | 253 | }; |
248 | 254 | ||
255 | /* | ||
256 | * For bio-based dm. | ||
257 | * One of these is allocated for each bio. | ||
258 | * This structure shouldn't be touched directly by target drivers. | ||
259 | * It is here so that we can inline dm_per_bio_data and | ||
260 | * dm_bio_from_per_bio_data | ||
261 | */ | ||
262 | struct dm_target_io { | ||
263 | struct dm_io *io; | ||
264 | struct dm_target *ti; | ||
265 | union map_info info; | ||
266 | struct bio clone; | ||
267 | }; | ||
268 | |||
269 | static inline void *dm_per_bio_data(struct bio *bio, size_t data_size) | ||
270 | { | ||
271 | return (char *)bio - offsetof(struct dm_target_io, clone) - data_size; | ||
272 | } | ||
273 | |||
274 | static inline struct bio *dm_bio_from_per_bio_data(void *data, size_t data_size) | ||
275 | { | ||
276 | return (struct bio *)((char *)data + data_size + offsetof(struct dm_target_io, clone)); | ||
277 | } | ||
278 | |||
249 | int dm_register_target(struct target_type *t); | 279 | int dm_register_target(struct target_type *t); |
250 | void dm_unregister_target(struct target_type *t); | 280 | void dm_unregister_target(struct target_type *t); |
251 | 281 | ||