]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.suse/dm-block-integrity
Reenabled linux-xen, added patches for Xen Kernel Version 2.6.27.31,
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / dm-block-integrity
1 From: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
2 Subject: Block integrity support for DM and MD
3 References: FATE#304345
4
5 This patch adds Data integrity support to DM and MD.
6 It has been reworked to support request-based multipathing.
7
8 Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
9 Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
10 Cc: Martin K. Petersen <martin.petersen@oracle.com>
11 Signed-off-by: Hannes Reinecke <hare@suse.de>
12
13 ---
14 drivers/md/dm-table.c | 37 +++++++++++++++++++++++++++++++++++++
15 drivers/md/dm.c | 22 ++++++++++++++++++++++
16 drivers/md/dm.h | 1 +
17 drivers/md/md.c | 34 ++++++++++++++++++++++++++++++++++
18 fs/bio-integrity.c | 5 +++--
19 fs/bio.c | 2 +-
20 include/linux/bio.h | 4 ++--
21 7 files changed, 100 insertions(+), 5 deletions(-)
22
23 --- a/drivers/md/dm-table.c
24 +++ b/drivers/md/dm-table.c
25 @@ -951,6 +951,43 @@ void dm_table_set_restrictions(struct dm
26 queue_flag_set_unlocked(QUEUE_FLAG_STACKABLE, q);
27 }
28
29 +void dm_table_set_integrity(struct dm_table *t, struct mapped_device *md)
30 +{
31 + struct list_head *devices = dm_table_get_devices(t);
32 + struct dm_dev *prev, *cur;
33 +
34 + /*
35 + * Run through all devices to ensure they have matching
36 + * integrity profile
37 + */
38 + cur = prev = NULL;
39 +
40 + list_for_each_entry(cur, devices, list) {
41 +
42 + if (prev && blk_integrity_compare(prev->bdev->bd_disk,
43 + cur->bdev->bd_disk) < 0) {
44 + printk(KERN_ERR "%s: %s %s Integrity mismatch!\n",
45 + __func__, prev->bdev->bd_disk->disk_name,
46 + cur->bdev->bd_disk->disk_name);
47 + return;
48 + }
49 + prev = cur;
50 + }
51 +
52 + /* Register dm device as being integrity capable */
53 + if (prev && bdev_get_integrity(prev->bdev)) {
54 + struct gendisk *disk = dm_disk(md);
55 +
56 + if (blk_integrity_register(dm_disk(md),
57 + bdev_get_integrity(prev->bdev)))
58 + printk(KERN_ERR "%s: %s Could not register integrity!\n",
59 + __func__, disk->disk_name);
60 + else
61 + printk(KERN_INFO "Enabling data integrity on %s\n",
62 + disk->disk_name);
63 + }
64 +}
65 +
66 unsigned int dm_table_get_num_targets(struct dm_table *t)
67 {
68 return t->num_targets;
69 --- a/drivers/md/dm.c
70 +++ b/drivers/md/dm.c
71 @@ -1022,6 +1022,13 @@ static struct bio *split_bvec(struct bio
72 clone->bi_size = to_bytes(len);
73 clone->bi_io_vec->bv_offset = offset;
74 clone->bi_io_vec->bv_len = clone->bi_size;
75 + clone->bi_flags |= 1 << BIO_CLONED;
76 +
77 + if (bio_integrity(bio)) {
78 + bio_integrity_clone(clone, bio, GFP_NOIO, bs);
79 + bio_integrity_trim(clone,
80 + bio_sector_offset(bio, idx, offset), len);
81 + }
82
83 return clone;
84 }
85 @@ -1044,6 +1051,14 @@ static struct bio *clone_bio(struct bio
86 clone->bi_size = to_bytes(len);
87 clone->bi_flags &= ~(1 << BIO_SEG_VALID);
88
89 + if (bio_integrity(bio)) {
90 + bio_integrity_clone(clone, bio, GFP_NOIO, bs);
91 +
92 + if (idx != bio->bi_idx || clone->bi_size < bio->bi_size)
93 + bio_integrity_trim(clone,
94 + bio_sector_offset(bio, idx, 0), len);
95 + }
96 +
97 return clone;
98 }
99
100 @@ -1365,6 +1380,11 @@ static int clone_request_bios(struct req
101 }
102
103 __bio_clone(clone_bio, bio);
104 + if (bio_integrity(bio))
105 + if (bio_integrity_clone(clone_bio, bio, GFP_ATOMIC,
106 + md->bs) < 0)
107 + goto free_and_out;
108 +
109 clone_bio->bi_destructor = dm_bio_destructor;
110 clone_bio->bi_end_io = end_clone_bio;
111 info->rq = clone;
112 @@ -1835,6 +1855,7 @@ static void free_dev(struct mapped_devic
113 mempool_destroy(md->io_pool);
114 if (md->bs)
115 bioset_free(md->bs);
116 + blk_integrity_unregister(md->disk);
117 del_gendisk(md->disk);
118 free_minor(minor);
119
120 @@ -1910,6 +1931,7 @@ static int __bind(struct mapped_device *
121 write_lock(&md->map_lock);
122 md->map = t;
123 dm_table_set_restrictions(t, q);
124 + dm_table_set_integrity(t, md);
125 if (!(dm_table_get_mode(t) & FMODE_WRITE)) {
126 set_disk_ro(md->disk, 1);
127 } else {
128 --- a/drivers/md/dm.h
129 +++ b/drivers/md/dm.h
130 @@ -51,6 +51,7 @@ void dm_table_event_callback(struct dm_t
131 struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index);
132 struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector);
133 void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q);
134 +void dm_table_set_integrity(struct dm_table *t, struct mapped_device *md);
135 struct list_head *dm_table_get_devices(struct dm_table *t);
136 void dm_table_presuspend_targets(struct dm_table *t);
137 void dm_table_postsuspend_targets(struct dm_table *t);
138 --- a/drivers/md/md.c
139 +++ b/drivers/md/md.c
140 @@ -1411,6 +1411,38 @@ static int match_mddev_units(mddev_t *md
141
142 static LIST_HEAD(pending_raid_disks);
143
144 +static void md_integrity_check(mdk_rdev_t *rdev, mddev_t *mddev)
145 +{
146 + struct mdk_personality *pers = mddev->pers;
147 + struct gendisk *disk = mddev->gendisk;
148 + struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev);
149 + struct blk_integrity *bi_mddev = blk_get_integrity(disk);
150 +
151 + /* Data integrity passthrough not supported on RAID 4, 5 and 6 */
152 + if (pers && pers->level >= 4 && pers->level <= 6)
153 + return;
154 +
155 + /* If rdev is integrity capable, register profile for mddev */
156 + if (!bi_mddev && bi_rdev) {
157 + if (blk_integrity_register(disk, bi_rdev))
158 + printk(KERN_ERR "%s: %s Could not register integrity!\n",
159 + __func__, disk->disk_name);
160 + else
161 + printk(KERN_NOTICE "Enabling data integrity on %s\n",
162 + disk->disk_name);
163 + return;
164 + }
165 +
166 + /* Check that mddev and rdev have matching profiles */
167 + if (blk_integrity_compare(disk, rdev->bdev->bd_disk) < 0) {
168 + printk(KERN_ERR "%s: %s/%s integrity mismatch!\n", __func__,
169 + disk->disk_name, rdev->bdev->bd_disk->disk_name);
170 + printk(KERN_NOTICE "Disabling data integrity on %s\n",
171 + disk->disk_name);
172 + blk_integrity_unregister(disk);
173 + }
174 +}
175 +
176 static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
177 {
178 char b[BDEVNAME_SIZE];
179 @@ -1479,6 +1511,7 @@ static int bind_rdev_to_array(mdk_rdev_t
180 }
181 list_add_rcu(&rdev->same_set, &mddev->disks);
182 bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk);
183 + md_integrity_check(rdev, mddev);
184 return 0;
185
186 fail:
187 @@ -3967,6 +4000,7 @@ static int do_md_stop(mddev_t * mddev, i
188 printk(KERN_INFO "md: %s switched to read-only mode.\n",
189 mdname(mddev));
190 err = 0;
191 + blk_integrity_unregister(disk);
192 md_new_event(mddev);
193 sysfs_notify(&mddev->kobj, NULL, "array_state");
194 out:
195 --- a/fs/bio-integrity.c
196 +++ b/fs/bio-integrity.c
197 @@ -655,19 +655,20 @@ EXPORT_SYMBOL(bio_integrity_split);
198 * bio_integrity_clone - Callback for cloning bios with integrity metadata
199 * @bio: New bio
200 * @bio_src: Original bio
201 + * @gfp_mask: Memory allocation mask
202 * @bs: bio_set to allocate bip from
203 *
204 * Description: Called to allocate a bip when cloning a bio
205 */
206 int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
207 - struct bio_set *bs)
208 + gfp_t gfp_mask, struct bio_set *bs)
209 {
210 struct bio_integrity_payload *bip_src = bio_src->bi_integrity;
211 struct bio_integrity_payload *bip;
212
213 BUG_ON(bip_src == NULL);
214
215 - bip = bio_integrity_alloc_bioset(bio, GFP_NOIO, bip_src->bip_vcnt, bs);
216 + bip = bio_integrity_alloc_bioset(bio, gfp_mask, bip_src->bip_vcnt, bs);
217
218 if (bip == NULL)
219 return -EIO;
220 --- a/fs/bio.c
221 +++ b/fs/bio.c
222 @@ -256,7 +256,7 @@ struct bio *bio_clone(struct bio *bio, g
223 if (bio_integrity(bio)) {
224 int ret;
225
226 - ret = bio_integrity_clone(b, bio, fs_bio_set);
227 + ret = bio_integrity_clone(b, bio, gfp_mask, fs_bio_set);
228
229 if (ret < 0)
230 return NULL;
231 --- a/include/linux/bio.h
232 +++ b/include/linux/bio.h
233 @@ -501,7 +501,7 @@ extern void bio_integrity_endio(struct b
234 extern void bio_integrity_advance(struct bio *, unsigned int);
235 extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int);
236 extern void bio_integrity_split(struct bio *, struct bio_pair *, int);
237 -extern int bio_integrity_clone(struct bio *, struct bio *, struct bio_set *);
238 +extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t, struct bio_set *);
239 extern int bioset_integrity_create(struct bio_set *, int);
240 extern void bioset_integrity_free(struct bio_set *);
241 extern void bio_integrity_init_slab(void);
242 @@ -512,7 +512,7 @@ extern void bio_integrity_init_slab(void
243 #define bioset_integrity_create(a, b) (0)
244 #define bio_integrity_prep(a) (0)
245 #define bio_integrity_enabled(a) (0)
246 -#define bio_integrity_clone(a, b, c) (0)
247 +#define bio_integrity_clone(a, b, c, d) (0)
248 #define bioset_integrity_free(a) do { } while (0)
249 #define bio_integrity_free(a, b) do { } while (0)
250 #define bio_integrity_endio(a, b) do { } while (0)