[dm-devel] [PATCH] Implement barrier support for single device DM devices

Andi Kleen andi at firstfloor.org
Fri Feb 15 12:08:21 UTC 2008


Implement barrier support for single device DM devices

This patch implements barrier support in DM for the common case of dm linear
just remapping a single underlying device. In this case we can safely
pass the barrier through because there can be no reordering between
devices.

Signed-off-by: Andi Kleen <ak at suse.de>

---
 drivers/md/dm-linear.c |    1 +
 drivers/md/dm-table.c  |   27 ++++++++++++++++++++++++++-
 drivers/md/dm.c        |   14 ++++----------
 drivers/md/dm.h        |    2 ++
 4 files changed, 33 insertions(+), 11 deletions(-)

Index: linux/drivers/md/dm-table.c
===================================================================
--- linux.orig/drivers/md/dm-table.c
+++ linux/drivers/md/dm-table.c
@@ -38,6 +38,9 @@ struct dm_table {
 	sector_t *highs;
 	struct dm_target *targets;
 
+	unsigned single_device : 1;
+	unsigned barrier_supported : 1;
+
 	/*
 	 * Indicates the rw permissions for the new logical
 	 * device.  This should be a combination of FMODE_READ
@@ -584,12 +587,21 @@ EXPORT_SYMBOL_GPL(dm_set_device_limits);
 int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
 		  sector_t len, int mode, struct dm_dev **result)
 {
-	int r = __table_get_device(ti->table, ti, path,
+	struct dm_table *t = ti->table;
+	int r = __table_get_device(t, ti, path,
 				   start, len, mode, result);
 
 	if (!r)
 		dm_set_device_limits(ti, (*result)->bdev);
 
+	if (!r) {
+		/* Only got single device? */
+		if (t->devices.next->next == &t->devices)
+			t->single_device = 1;
+		else
+			t->single_device = 0;
+	}
+
 	return r;
 }
 
@@ -1023,6 +1035,16 @@ struct mapped_device *dm_table_get_md(st
 	return t->md;
 }
 
+int dm_table_barrier_ok(struct dm_table *t)
+{
+	return t->single_device && t->barrier_supported;
+}
+
+void dm_table_support_barrier(struct dm_table *t)
+{
+	t->barrier_supported = 1;
+}
+
 EXPORT_SYMBOL(dm_vcalloc);
 EXPORT_SYMBOL(dm_get_device);
 EXPORT_SYMBOL(dm_put_device);
@@ -1033,3 +1055,5 @@ EXPORT_SYMBOL(dm_table_get_md);
 EXPORT_SYMBOL(dm_table_put);
 EXPORT_SYMBOL(dm_table_get);
 EXPORT_SYMBOL(dm_table_unplug_all);
+EXPORT_SYMBOL(dm_table_barrier_ok);
+EXPORT_SYMBOL(dm_table_support_barrier);
Index: linux/drivers/md/dm.c
===================================================================
--- linux.orig/drivers/md/dm.c
+++ linux/drivers/md/dm.c
@@ -801,7 +801,10 @@ static int __split_bio(struct mapped_dev
 	ci.map = dm_get_table(md);
 	if (unlikely(!ci.map))
 		return -EIO;
-
+	if (unlikely(bio_barrier(bio) && !dm_table_barrier_ok(ci.map))) {
+		bio_endio(bio, -EOPNOTSUPP);
+		return 0;
+	}
 	ci.md = md;
 	ci.bio = bio;
 	ci.io = alloc_io(md);
@@ -837,15 +840,6 @@ static int dm_request(struct request_que
 	int rw = bio_data_dir(bio);
 	struct mapped_device *md = q->queuedata;
 
-	/*
-	 * There is no use in forwarding any barrier request since we can't
-	 * guarantee it is (or can be) handled by the targets correctly.
-	 */
-	if (unlikely(bio_barrier(bio))) {
-		bio_endio(bio, -EOPNOTSUPP);
-		return 0;
-	}
-
 	down_read(&md->io_lock);
 
 	disk_stat_inc(dm_disk(md), ios[rw]);
Index: linux/drivers/md/dm.h
===================================================================
--- linux.orig/drivers/md/dm.h
+++ linux/drivers/md/dm.h
@@ -116,6 +116,8 @@ void dm_table_unplug_all(struct dm_table
  * To check the return value from dm_table_find_target().
  */
 #define dm_target_is_valid(t) ((t)->table)
+int dm_table_barrier_ok(struct dm_table *t);
+void dm_table_support_barrier(struct dm_table *t);
 
 /*-----------------------------------------------------------------
  * A registry of target types.
Index: linux/drivers/md/dm-linear.c
===================================================================
--- linux.orig/drivers/md/dm-linear.c
+++ linux/drivers/md/dm-linear.c
@@ -52,6 +52,7 @@ static int linear_ctr(struct dm_target *
 		ti->error = "dm-linear: Device lookup failed";
 		goto bad;
 	}
+	dm_table_support_barrier(ti->table);
 
 	ti->private = lc;
 	return 0;




More information about the dm-devel mailing list