[PATCH] Implement barrier support for single device DM devices

From: Andi Kleen
Date: Fri Feb 15 2008 - 07:08:37 EST


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@xxxxxxx>

---
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;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/