]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Andi Kleen <ak@suse.de> |
2 | Subject: Implement barrier support for single device DM devices | |
3 | Patch-mainline: 2.6.28 | |
4 | References: FATE#304489 | |
5 | ||
6 | This patch implements barrier support in DM for the common case of dm linear | |
7 | just remapping a single underlying device. In this case we can safely | |
8 | pass the barrier through because there can be no reordering between | |
9 | devices. | |
10 | ||
11 | Signed-off-by: Andi Kleen <ak@suse.de> | |
12 | ||
13 | This patch is slightly different from the one which made it to the mainline. | |
14 | But this is not replaced by that as it would break kABI. The mainline | |
15 | commit is ab4c1424882be9cd70b89abf2b484add355712fa | |
16 | ||
17 | Acked-by: Nikanth Karthikesan <knikanth@suse.de> | |
18 | ||
19 | --- | |
20 | drivers/md/dm-linear.c | 1 + | |
21 | drivers/md/dm-table.c | 26 +++++++++++++++++++++++++- | |
22 | drivers/md/dm.c | 14 ++++---------- | |
23 | drivers/md/dm.h | 2 ++ | |
24 | 4 files changed, 32 insertions(+), 11 deletions(-) | |
25 | ||
26 | Index: linux-2.6.27/drivers/md/dm.c | |
27 | =================================================================== | |
28 | --- linux-2.6.27.orig/drivers/md/dm.c | |
29 | +++ linux-2.6.27/drivers/md/dm.c | |
30 | @@ -1149,7 +1149,11 @@ static int __split_bio(struct mapped_dev | |
31 | ci.map = dm_get_table(md); | |
32 | if (unlikely(!ci.map)) | |
33 | return -EIO; | |
34 | - | |
35 | + if (unlikely(bio_barrier(bio) && !dm_table_barrier_ok(ci.map))) { | |
36 | + bio_endio(bio, -EOPNOTSUPP); | |
37 | + dm_table_put(ci.map); | |
38 | + return 0; | |
39 | + } | |
40 | ci.md = md; | |
41 | ci.bio = bio; | |
42 | ci.io = alloc_io(md); | |
43 | @@ -1232,15 +1236,6 @@ static int _dm_request(struct request_qu | |
44 | int rw = bio_data_dir(bio); | |
45 | struct mapped_device *md = q->queuedata; | |
46 | ||
47 | - /* | |
48 | - * There is no use in forwarding any barrier request since we can't | |
49 | - * guarantee it is (or can be) handled by the targets correctly. | |
50 | - */ | |
51 | - if (unlikely(bio_barrier(bio))) { | |
52 | - bio_endio(bio, -EOPNOTSUPP); | |
53 | - return 0; | |
54 | - } | |
55 | - | |
56 | down_read(&md->io_lock); | |
57 | ||
58 | disk_stat_inc(dm_disk(md), ios[rw]); | |
59 | Index: linux-2.6.27/drivers/md/dm.h | |
60 | =================================================================== | |
61 | --- linux-2.6.27.orig/drivers/md/dm.h | |
62 | +++ linux-2.6.27/drivers/md/dm.h | |
63 | @@ -66,6 +66,8 @@ void dm_table_unplug_all(struct dm_table | |
64 | * To check the return value from dm_table_find_target(). | |
65 | */ | |
66 | #define dm_target_is_valid(t) ((t)->table) | |
67 | +int dm_table_barrier_ok(struct dm_table *t); | |
68 | +void dm_table_support_barrier(struct dm_table *t); | |
69 | ||
70 | /*----------------------------------------------------------------- | |
71 | * A registry of target types. | |
72 | Index: linux-2.6.27/drivers/md/dm-linear.c | |
73 | =================================================================== | |
74 | --- linux-2.6.27.orig/drivers/md/dm-linear.c | |
75 | +++ linux-2.6.27/drivers/md/dm-linear.c | |
76 | @@ -52,6 +52,7 @@ static int linear_ctr(struct dm_target * | |
77 | ti->error = "dm-linear: Device lookup failed"; | |
78 | goto bad; | |
79 | } | |
80 | + dm_table_support_barrier(ti->table); | |
81 | ||
82 | ti->private = lc; | |
83 | return 0; | |
84 | Index: linux-2.6.27/drivers/md/dm-table.c | |
85 | =================================================================== | |
86 | --- linux-2.6.27.orig/drivers/md/dm-table.c | |
87 | +++ linux-2.6.27/drivers/md/dm-table.c | |
88 | @@ -38,6 +38,9 @@ struct dm_table { | |
89 | sector_t *highs; | |
90 | struct dm_target *targets; | |
91 | ||
92 | + unsigned single_device : 1; | |
93 | + unsigned barrier_supported : 1; | |
94 | + | |
95 | /* | |
96 | * Indicates the rw permissions for the new logical | |
97 | * device. This should be a combination of FMODE_READ | |
98 | @@ -532,12 +535,21 @@ EXPORT_SYMBOL_GPL(dm_set_device_limits); | |
99 | int dm_get_device(struct dm_target *ti, const char *path, sector_t start, | |
100 | sector_t len, int mode, struct dm_dev **result) | |
101 | { | |
102 | - int r = __table_get_device(ti->table, ti, path, | |
103 | + struct dm_table *t = ti->table; | |
104 | + int r = __table_get_device(t, ti, path, | |
105 | start, len, mode, result); | |
106 | ||
107 | if (!r) | |
108 | dm_set_device_limits(ti, (*result)->bdev); | |
109 | ||
110 | + if (!r) { | |
111 | + /* Only got single device? */ | |
112 | + if (t->devices.next->next == &t->devices) | |
113 | + t->single_device = 1; | |
114 | + else | |
115 | + t->single_device = 0; | |
116 | + } | |
117 | + | |
118 | return r; | |
119 | } | |
120 | ||
121 | @@ -1050,6 +1062,16 @@ struct mapped_device *dm_table_get_md(st | |
122 | return t->md; | |
123 | } | |
124 | ||
125 | +int dm_table_barrier_ok(struct dm_table *t) | |
126 | +{ | |
127 | + return t->single_device && t->barrier_supported; | |
128 | +} | |
129 | + | |
130 | +void dm_table_support_barrier(struct dm_table *t) | |
131 | +{ | |
132 | + t->barrier_supported = 1; | |
133 | +} | |
134 | + | |
135 | EXPORT_SYMBOL(dm_vcalloc); | |
136 | EXPORT_SYMBOL(dm_get_device); | |
137 | EXPORT_SYMBOL(dm_put_device); | |
138 | @@ -1060,3 +1082,5 @@ EXPORT_SYMBOL(dm_table_get_md); | |
139 | EXPORT_SYMBOL(dm_table_put); | |
140 | EXPORT_SYMBOL(dm_table_get); | |
141 | EXPORT_SYMBOL(dm_table_unplug_all); | |
142 | +EXPORT_SYMBOL(dm_table_barrier_ok); | |
143 | +EXPORT_SYMBOL(dm_table_support_barrier); |