aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2009-01-05 22:05:09 -0500
committerAlasdair G Kergon <agk@redhat.com>2009-01-05 22:05:09 -0500
commitab4c1424882be9cd70b89abf2b484add355712fa (patch)
tree8baed3606be67900df9f02e42fcdb091b78c5def
parent7d76345da6ed3927c9cbf5d3f7a7021e8bba7374 (diff)
dm: support barriers on simple devices
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. NB. Any DM device might cease to support barriers if it gets reconfigured so code must continue to allow for a possible -EOPNOTSUPP on every barrier bio submitted. - agk Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r--drivers/md/dm-linear.c1
-rw-r--r--drivers/md/dm-table.c19
-rw-r--r--drivers/md/dm.c15
-rw-r--r--drivers/md/dm.h1
-rw-r--r--include/linux/device-mapper.h7
5 files changed, 33 insertions, 10 deletions
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 79fb53e51c70..bfa107f59d96 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -142,6 +142,7 @@ static struct target_type linear_target = {
142 .status = linear_status, 142 .status = linear_status,
143 .ioctl = linear_ioctl, 143 .ioctl = linear_ioctl,
144 .merge = linear_merge, 144 .merge = linear_merge,
145 .features = DM_TARGET_SUPPORTS_BARRIERS,
145}; 146};
146 147
147int __init dm_linear_init(void) 148int __init dm_linear_init(void)
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 04e5fd742c2c..ebaaf72cd822 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -38,6 +38,8 @@ struct dm_table {
38 sector_t *highs; 38 sector_t *highs;
39 struct dm_target *targets; 39 struct dm_target *targets;
40 40
41 unsigned barriers_supported:1;
42
41 /* 43 /*
42 * Indicates the rw permissions for the new logical 44 * Indicates the rw permissions for the new logical
43 * device. This should be a combination of FMODE_READ 45 * device. This should be a combination of FMODE_READ
@@ -227,6 +229,7 @@ int dm_table_create(struct dm_table **result, fmode_t mode,
227 229
228 INIT_LIST_HEAD(&t->devices); 230 INIT_LIST_HEAD(&t->devices);
229 atomic_set(&t->holders, 1); 231 atomic_set(&t->holders, 1);
232 t->barriers_supported = 1;
230 233
231 if (!num_targets) 234 if (!num_targets)
232 num_targets = KEYS_PER_NODE; 235 num_targets = KEYS_PER_NODE;
@@ -728,6 +731,10 @@ int dm_table_add_target(struct dm_table *t, const char *type,
728 /* FIXME: the plan is to combine high here and then have 731 /* FIXME: the plan is to combine high here and then have
729 * the merge fn apply the target level restrictions. */ 732 * the merge fn apply the target level restrictions. */
730 combine_restrictions_low(&t->limits, &tgt->limits); 733 combine_restrictions_low(&t->limits, &tgt->limits);
734
735 if (!(tgt->type->features & DM_TARGET_SUPPORTS_BARRIERS))
736 t->barriers_supported = 0;
737
731 return 0; 738 return 0;
732 739
733 bad: 740 bad:
@@ -772,6 +779,12 @@ int dm_table_complete(struct dm_table *t)
772 779
773 check_for_valid_limits(&t->limits); 780 check_for_valid_limits(&t->limits);
774 781
782 /*
783 * We only support barriers if there is exactly one underlying device.
784 */
785 if (!list_is_singular(&t->devices))
786 t->barriers_supported = 0;
787
775 /* how many indexes will the btree have ? */ 788 /* how many indexes will the btree have ? */
776 leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE); 789 leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE);
777 t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE); 790 t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE);
@@ -986,6 +999,12 @@ struct mapped_device *dm_table_get_md(struct dm_table *t)
986 return t->md; 999 return t->md;
987} 1000}
988 1001
1002int dm_table_barrier_ok(struct dm_table *t)
1003{
1004 return t->barriers_supported;
1005}
1006EXPORT_SYMBOL(dm_table_barrier_ok);
1007
989EXPORT_SYMBOL(dm_vcalloc); 1008EXPORT_SYMBOL(dm_vcalloc);
990EXPORT_SYMBOL(dm_get_device); 1009EXPORT_SYMBOL(dm_get_device);
991EXPORT_SYMBOL(dm_put_device); 1010EXPORT_SYMBOL(dm_put_device);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 4882ce7e88a3..dd953b189f45 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -835,7 +835,11 @@ static int __split_bio(struct mapped_device *md, struct bio *bio)
835 ci.map = dm_get_table(md); 835 ci.map = dm_get_table(md);
836 if (unlikely(!ci.map)) 836 if (unlikely(!ci.map))
837 return -EIO; 837 return -EIO;
838 838 if (unlikely(bio_barrier(bio) && !dm_table_barrier_ok(ci.map))) {
839 dm_table_put(ci.map);
840 bio_endio(bio, -EOPNOTSUPP);
841 return 0;
842 }
839 ci.md = md; 843 ci.md = md;
840 ci.bio = bio; 844 ci.bio = bio;
841 ci.io = alloc_io(md); 845 ci.io = alloc_io(md);
@@ -919,15 +923,6 @@ static int dm_request(struct request_queue *q, struct bio *bio)
919 struct mapped_device *md = q->queuedata; 923 struct mapped_device *md = q->queuedata;
920 int cpu; 924 int cpu;
921 925
922 /*
923 * There is no use in forwarding any barrier request since we can't
924 * guarantee it is (or can be) handled by the targets correctly.
925 */
926 if (unlikely(bio_barrier(bio))) {
927 bio_endio(bio, -EOPNOTSUPP);
928 return 0;
929 }
930
931 down_read(&md->io_lock); 926 down_read(&md->io_lock);
932 927
933 cpu = part_stat_lock(); 928 cpu = part_stat_lock();
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 0ade60cdef42..5b5d08ba9e92 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -51,6 +51,7 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits);
51 * To check the return value from dm_table_find_target(). 51 * To check the return value from dm_table_find_target().
52 */ 52 */
53#define dm_target_is_valid(t) ((t)->table) 53#define dm_target_is_valid(t) ((t)->table)
54int dm_table_barrier_ok(struct dm_table *t);
54 55
55/*----------------------------------------------------------------- 56/*-----------------------------------------------------------------
56 * A registry of target types. 57 * A registry of target types.
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index c1ba76c7c0e5..8209e08969f9 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -112,7 +112,14 @@ void dm_put_device(struct dm_target *ti, struct dm_dev *d);
112/* 112/*
113 * Information about a target type 113 * Information about a target type
114 */ 114 */
115
116/*
117 * Target features
118 */
119#define DM_TARGET_SUPPORTS_BARRIERS 0x00000001
120
115struct target_type { 121struct target_type {
122 uint64_t features;
116 const char *name; 123 const char *name;
117 struct module *module; 124 struct module *module;
118 unsigned version[3]; 125 unsigned version[3];