Commit ab4c1424882be9cd70b89abf2b484add355712fa
Committed by
Alasdair G Kergon
1 parent
7d76345da6
Exists in
master
and in
7 other branches
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>
Showing 5 changed files with 33 additions and 10 deletions Side-by-side Diff
drivers/md/dm-linear.c
drivers/md/dm-table.c
... | ... | @@ -38,6 +38,8 @@ |
38 | 38 | sector_t *highs; |
39 | 39 | struct dm_target *targets; |
40 | 40 | |
41 | + unsigned barriers_supported:1; | |
42 | + | |
41 | 43 | /* |
42 | 44 | * Indicates the rw permissions for the new logical |
43 | 45 | * device. This should be a combination of FMODE_READ |
... | ... | @@ -227,6 +229,7 @@ |
227 | 229 | |
228 | 230 | INIT_LIST_HEAD(&t->devices); |
229 | 231 | atomic_set(&t->holders, 1); |
232 | + t->barriers_supported = 1; | |
230 | 233 | |
231 | 234 | if (!num_targets) |
232 | 235 | num_targets = KEYS_PER_NODE; |
... | ... | @@ -728,6 +731,10 @@ |
728 | 731 | /* FIXME: the plan is to combine high here and then have |
729 | 732 | * the merge fn apply the target level restrictions. */ |
730 | 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 | 738 | return 0; |
732 | 739 | |
733 | 740 | bad: |
... | ... | @@ -772,6 +779,12 @@ |
772 | 779 | |
773 | 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 | 788 | /* how many indexes will the btree have ? */ |
776 | 789 | leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE); |
777 | 790 | t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE); |
... | ... | @@ -985,6 +998,12 @@ |
985 | 998 | |
986 | 999 | return t->md; |
987 | 1000 | } |
1001 | + | |
1002 | +int dm_table_barrier_ok(struct dm_table *t) | |
1003 | +{ | |
1004 | + return t->barriers_supported; | |
1005 | +} | |
1006 | +EXPORT_SYMBOL(dm_table_barrier_ok); | |
988 | 1007 | |
989 | 1008 | EXPORT_SYMBOL(dm_vcalloc); |
990 | 1009 | EXPORT_SYMBOL(dm_get_device); |
drivers/md/dm.c
... | ... | @@ -835,7 +835,11 @@ |
835 | 835 | ci.map = dm_get_table(md); |
836 | 836 | if (unlikely(!ci.map)) |
837 | 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 | 843 | ci.md = md; |
840 | 844 | ci.bio = bio; |
841 | 845 | ci.io = alloc_io(md); |
... | ... | @@ -918,15 +922,6 @@ |
918 | 922 | int rw = bio_data_dir(bio); |
919 | 923 | struct mapped_device *md = q->queuedata; |
920 | 924 | int cpu; |
921 | - | |
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 | 925 | |
931 | 926 | down_read(&md->io_lock); |
932 | 927 |
drivers/md/dm.h
... | ... | @@ -51,6 +51,7 @@ |
51 | 51 | * To check the return value from dm_table_find_target(). |
52 | 52 | */ |
53 | 53 | #define dm_target_is_valid(t) ((t)->table) |
54 | +int dm_table_barrier_ok(struct dm_table *t); | |
54 | 55 | |
55 | 56 | /*----------------------------------------------------------------- |
56 | 57 | * A registry of target types. |
include/linux/device-mapper.h
... | ... | @@ -112,7 +112,14 @@ |
112 | 112 | /* |
113 | 113 | * Information about a target type |
114 | 114 | */ |
115 | + | |
116 | +/* | |
117 | + * Target features | |
118 | + */ | |
119 | +#define DM_TARGET_SUPPORTS_BARRIERS 0x00000001 | |
120 | + | |
115 | 121 | struct target_type { |
122 | + uint64_t features; | |
116 | 123 | const char *name; |
117 | 124 | struct module *module; |
118 | 125 | unsigned version[3]; |