Skip to content

Commit c0820cf

Browse files
Mikulas Patockakergon
Mikulas Patocka
authored andcommitted
dm: introduce per_bio_data
Introduce a field per_bio_data_size in struct dm_target. Targets can set this field in the constructor. If a target sets this field to a non-zero value, "per_bio_data_size" bytes of auxiliary data are allocated for each bio submitted to the target. These data can be used for any purpose by the target and help us improve performance by removing some per-target mempools. Per-bio data is accessed with dm_per_bio_data. The argument data_size must be the same as the value per_bio_data_size in dm_target. If the target has a pointer to per_bio_data, it can get a pointer to the bio with dm_bio_from_per_bio_data() function (data_size must be the same as the value passed to dm_per_bio_data). Signed-off-by: Mikulas Patocka <[email protected]> Signed-off-by: Alasdair G Kergon <[email protected]>
1 parent 70d6c40 commit c0820cf

File tree

4 files changed

+56
-20
lines changed

4 files changed

+56
-20
lines changed

drivers/md/dm-table.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -967,13 +967,22 @@ bool dm_table_request_based(struct dm_table *t)
967967
int dm_table_alloc_md_mempools(struct dm_table *t)
968968
{
969969
unsigned type = dm_table_get_type(t);
970+
unsigned per_bio_data_size = 0;
971+
struct dm_target *tgt;
972+
unsigned i;
970973

971974
if (unlikely(type == DM_TYPE_NONE)) {
972975
DMWARN("no table type is set, can't allocate mempools");
973976
return -EINVAL;
974977
}
975978

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);
977986
if (!t->mempools)
978987
return -ENOMEM;
979988

drivers/md/dm.c

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,6 @@ struct dm_io {
6262
spinlock_t endio_lock;
6363
};
6464

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-
7765
/*
7866
* For request-based dm.
7967
* One of these is allocated per request.
@@ -1980,13 +1968,20 @@ static void free_dev(struct mapped_device *md)
19801968

19811969
static void __bind_mempools(struct mapped_device *md, struct dm_table *t)
19821970
{
1983-
struct dm_md_mempools *p;
1971+
struct dm_md_mempools *p = dm_table_get_md_mempools(t);
19841972

1985-
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 */
1973+
if (md->io_pool && (md->tio_pool || dm_table_get_type(t) == DM_TYPE_BIO_BASED) && md->bs) {
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;
19871982
goto out;
1983+
}
19881984

1989-
p = dm_table_get_md_mempools(t);
19901985
BUG_ON(!p || md->io_pool || md->tio_pool || md->bs);
19911986

19921987
md->io_pool = p->io_pool;
@@ -2745,14 +2740,16 @@ int dm_noflush_suspending(struct dm_target *ti)
27452740
}
27462741
EXPORT_SYMBOL_GPL(dm_noflush_suspending);
27472742

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)
27492744
{
27502745
struct dm_md_mempools *pools = kmalloc(sizeof(*pools), GFP_KERNEL);
27512746
unsigned int pool_size = (type == DM_TYPE_BIO_BASED) ? 16 : MIN_IOS;
27522747

27532748
if (!pools)
27542749
return NULL;
27552750

2751+
per_bio_data_size = roundup(per_bio_data_size, __alignof__(struct dm_target_io));
2752+
27562753
pools->io_pool = (type == DM_TYPE_BIO_BASED) ?
27572754
mempool_create_slab_pool(MIN_IOS, _io_cache) :
27582755
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)
27682765

27692766
pools->bs = (type == DM_TYPE_BIO_BASED) ?
27702767
bioset_create(pool_size,
2771-
offsetof(struct dm_target_io, clone)) :
2768+
per_bio_data_size + offsetof(struct dm_target_io, clone)) :
27722769
bioset_create(pool_size,
27732770
offsetof(struct dm_rq_clone_bio_info, clone));
27742771
if (!pools->bs)

drivers/md/dm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ void dm_kcopyd_exit(void);
159159
/*
160160
* Mempool operations
161161
*/
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);
163163
void dm_free_md_mempools(struct dm_md_mempools *pools);
164164

165165
#endif

include/linux/device-mapper.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@ struct dm_target {
210210
*/
211211
unsigned num_write_same_requests;
212212

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+
213219
/* target specific data */
214220
void *private;
215221

@@ -246,6 +252,30 @@ struct dm_target_callbacks {
246252
int (*congested_fn) (struct dm_target_callbacks *, int);
247253
};
248254

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+
249279
int dm_register_target(struct target_type *t);
250280
void dm_unregister_target(struct target_type *t);
251281

0 commit comments

Comments
 (0)