[dm-devel] [PATCH 1/4] dm: introduce per request data

Mikulas Patocka mpatocka at redhat.com
Tue Oct 23 01:01:31 UTC 2012


dm: introduce per request data

Introduce a field per_request_data in struct dm_target.

Targets can set this field in the constructor. If a target sets this
field to non-zero value, "per_request_data" bytes of auxliliary data is
allocated for each bio submitted to the target. These data can be used
for any purpose by the target.

Per-request data is accessed with dm_bio_get_per_request_data. The
argument data_size must be the same as the value per_request_data in
dm_target.

If the target has a pointer to per request data, it can get a pointer to
the bio with dm_per_request_data_get_bio function (data_size must be the
same ast the value passed to dm_bio_get_per_request_data).

Signed-off-by: Mikulas Patocka <mpatocka at redhat.com>

---
 drivers/md/dm-table.c         |   12 +++++++++++-
 drivers/md/dm.c               |   33 +++++++++++++++------------------
 drivers/md/dm.h               |    2 +-
 include/linux/device-mapper.h |   30 ++++++++++++++++++++++++++++++
 4 files changed, 57 insertions(+), 20 deletions(-)

Index: linux-3.6.2-fast/drivers/md/dm.c
===================================================================
--- linux-3.6.2-fast.orig/drivers/md/dm.c	2012-10-16 21:20:04.000000000 +0200
+++ linux-3.6.2-fast/drivers/md/dm.c	2012-10-16 21:20:04.000000000 +0200
@@ -63,18 +63,6 @@ struct dm_io {
 };
 
 /*
- * For bio-based dm.
- * One of these is allocated per target within a bio.  Hopefully
- * this will be simplified out one day.
- */
-struct dm_target_io {
-	struct dm_io *io;
-	struct dm_target *ti;
-	union map_info info;
-	struct bio clone;
-};
-
-/*
  * For request-based dm.
  * One of these is allocated per request.
  */
@@ -1997,13 +1985,20 @@ static void free_dev(struct mapped_devic
 
 static void __bind_mempools(struct mapped_device *md, struct dm_table *t)
 {
-	struct dm_md_mempools *p;
+	struct dm_md_mempools *p = dm_table_get_md_mempools(t);
 
-	if (md->io_pool && (md->tio_pool || dm_table_get_type(t) == DM_TYPE_BIO_BASED) && md->bs)
-		/* the md already has necessary mempools */
+	if (md->io_pool && (md->tio_pool || dm_table_get_type(t) == DM_TYPE_BIO_BASED) && md->bs) {
+		/*
+		 * The md already has necessary mempools. Reload just the
+		 * bioset because front_pad may have changed because
+		 * a different table was loaded.
+		 */
+		bioset_free(md->bs);
+		md->bs = p->bs;
+		p->bs = NULL;
 		goto out;
+	}
 
-	p = dm_table_get_md_mempools(t);
 	BUG_ON(!p || md->io_pool || md->tio_pool || md->bs);
 
 	md->io_pool = p->io_pool;
@@ -2753,7 +2748,7 @@ int dm_noflush_suspending(struct dm_targ
 }
 EXPORT_SYMBOL_GPL(dm_noflush_suspending);
 
-struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity)
+struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, unsigned per_request_data)
 {
 	struct dm_md_mempools *pools = kmalloc(sizeof(*pools), GFP_KERNEL);
 	unsigned int pool_size = (type == DM_TYPE_BIO_BASED) ?
@@ -2762,6 +2757,8 @@ struct dm_md_mempools *dm_alloc_md_mempo
 	if (!pools)
 		return NULL;
 
+	per_request_data = roundup(per_request_data, __alignof__(struct dm_target_io));
+
 	pools->io_pool = (type == DM_TYPE_BIO_BASED) ?
 			 mempool_create_slab_pool(pool_size, _io_cache) :
 			 mempool_create_slab_pool(pool_size, _rq_bio_info_cache);
@@ -2776,7 +2773,7 @@ struct dm_md_mempools *dm_alloc_md_mempo
 	}
 
 	pools->bs = bioset_create(pool_size, (type == DM_TYPE_BIO_BASED) ?
-		offsetof(struct dm_target_io, clone) : 0);
+		per_request_data + offsetof(struct dm_target_io, clone) : 0);
 	if (!pools->bs)
 		goto free_tio_pool_and_out;
 
Index: linux-3.6.2-fast/drivers/md/dm-table.c
===================================================================
--- linux-3.6.2-fast.orig/drivers/md/dm-table.c	2012-10-16 21:20:01.000000000 +0200
+++ linux-3.6.2-fast/drivers/md/dm-table.c	2012-10-16 23:55:19.000000000 +0200
@@ -932,13 +932,23 @@ bool dm_table_request_based(struct dm_ta
 int dm_table_alloc_md_mempools(struct dm_table *t)
 {
 	unsigned type = dm_table_get_type(t);
+	unsigned per_request_data = 0;
 
 	if (unlikely(type == DM_TYPE_NONE)) {
 		DMWARN("no table type is set, can't allocate mempools");
 		return -EINVAL;
 	}
 
-	t->mempools = dm_alloc_md_mempools(type, t->integrity_supported);
+	if (type == DM_TYPE_BIO_BASED) {
+		unsigned i;
+		for (i = 0; i < t->num_targets; i++) {
+			struct dm_target *tgt = t->targets + i;
+			if (tgt->per_request_data > per_request_data)
+				per_request_data = tgt->per_request_data;
+		}
+	}
+
+	t->mempools = dm_alloc_md_mempools(type, t->integrity_supported, per_request_data);
 	if (!t->mempools)
 		return -ENOMEM;
 
Index: linux-3.6.2-fast/drivers/md/dm.h
===================================================================
--- linux-3.6.2-fast.orig/drivers/md/dm.h	2012-10-16 21:13:41.000000000 +0200
+++ linux-3.6.2-fast/drivers/md/dm.h	2012-10-16 21:20:04.000000000 +0200
@@ -159,7 +159,7 @@ void dm_kcopyd_exit(void);
 /*
  * Mempool operations
  */
-struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity);
+struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, unsigned per_request_data);
 void dm_free_md_mempools(struct dm_md_mempools *pools);
 
 #endif
Index: linux-3.6.2-fast/include/linux/device-mapper.h
===================================================================
--- linux-3.6.2-fast.orig/include/linux/device-mapper.h	2012-10-16 21:20:01.000000000 +0200
+++ linux-3.6.2-fast/include/linux/device-mapper.h	2012-10-17 00:33:39.000000000 +0200
@@ -205,6 +205,12 @@ struct dm_target {
 	 */
 	unsigned num_discard_requests;
 
+	/*
+	 * The size of data allocated for every bio sent to the target.
+	 * The data is accessible with function dm_bio_get_per_request_data.
+	 */
+	unsigned per_request_data;
+
 	/* target specific data */
 	void *private;
 
@@ -241,6 +247,30 @@ struct dm_target_callbacks {
 	int (*congested_fn) (struct dm_target_callbacks *, int);
 };
 
+/*
+ * For bio-based dm.
+ * One of these is allocated per target within a bio.
+ * This structure shouldn't be touched by target drivers, it is here
+ * so that we can inline dm_bio_get_per_request_data and
+ * dm_per_request_data_get_bio.
+ */
+struct dm_target_io {
+	struct dm_io *io;
+	struct dm_target *ti;
+	union map_info info;
+	struct bio clone;
+};
+
+static inline void *dm_bio_get_per_request_data(struct bio *bio, size_t data_size)
+{
+	return (char *)bio - offsetof(struct dm_target_io, clone) - data_size;
+}
+
+static inline struct bio *dm_per_request_data_get_bio(void *data, size_t data_size)
+{
+	return (struct bio *)((char *)data + data_size + offsetof(struct dm_target_io, clone));
+}
+
 int dm_register_target(struct target_type *t);
 void dm_unregister_target(struct target_type *t);
 




More information about the dm-devel mailing list