aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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];