1 This adds optional integrity functions for given bio, they are
2 passsed to bio_integrity_prep and initialized in
4 The optional integrity generate/verify functions take priority
5 over the ones registered on the block device.
7 It brings flexibility to bio integrity handling. e.g. a network
8 filesystem with integrity support would have integrity
9 generation happen on the clients, and send them over the wire.
10 On the server side once we receive the integrity bits and pass
11 the network layer checksums we would merely pass it on to the
12 block devices have integrity support, so we don't have to
13 calculate the integrity again.
14 Verification shares the same principle: on the server we just
15 copy the integrity bits from the device and send them through
16 the wire, then the verification happens on the clients.
18 Index: linux-3.10.0-862.9.1.el7/fs/bio-integrity.c
19 ===================================================================
20 --- linux-3.10.0-862.9.1.el7.orig/fs/bio-integrity.c
21 +++ linux-3.10.0-862.9.1.el7/fs/bio-integrity.c
22 @@ -38,7 +38,7 @@ void blk_flush_integrity(void)
26 - * bio_integrity_alloc - Allocate integrity payload and attach it to bio
27 + * bio_integrity_alloc_fn - Allocate integrity payload and attach it to bio
28 * @bio: bio to attach integrity metadata to
29 * @gfp_mask: Memory allocation mask
30 * @nr_vecs: Number of integrity metadata scatter-gather elements
31 @@ -47,9 +47,11 @@ void blk_flush_integrity(void)
32 * metadata. nr_vecs specifies the maximum number of pages containing
33 * integrity metadata that can be attached.
35 -struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
37 - unsigned int nr_vecs)
38 +struct bio_integrity_payload *bio_integrity_alloc_fn(struct bio *bio,
40 + unsigned int nr_vecs,
41 + integrity_gen_fn *generate_fn,
42 + integrity_vrfy_fn *verify_fn)
44 struct bio_integrity_payload *bip;
45 struct bio_set *bs = bio->bi_pool;
46 @@ -81,6 +83,8 @@ struct bio_integrity_payload *bio_integr
50 + bip->bip_generate_fn = generate_fn;
51 + bip->bip_verify_fn = verify_fn;
52 bio->bi_integrity = bip;
55 @@ -88,7 +92,7 @@ err:
56 mempool_free(bip, bs->bio_integrity_pool);
59 -EXPORT_SYMBOL(bio_integrity_alloc);
60 +EXPORT_SYMBOL(bio_integrity_alloc_fn);
63 * bio_integrity_free - Free bio integrity payload
64 @@ -312,10 +316,13 @@ static void bio_integrity_generate(struc
66 struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
67 struct blk_integrity_exchg bix;
68 + struct bio_integrity_payload *bip = bio->bi_integrity;
70 sector_t sector = bio->bi_sector;
71 unsigned int i, sectors, total;
72 void *prot_buf = bio->bi_integrity->bip_buf;
73 + integrity_gen_fn *generate_fn = bip->bip_generate_fn ?:
77 bix.disk_name = bio->bi_bdev->bd_disk->disk_name;
78 @@ -328,7 +335,7 @@ static void bio_integrity_generate(struc
79 bix.prot_buf = prot_buf;
82 - bi->generate_fn(&bix);
85 sectors = bv->bv_len / bi->sector_size;
87 @@ -349,7 +356,7 @@ static inline unsigned short blk_integri
91 - * bio_integrity_prep - Prepare bio for integrity I/O
92 + * bio_integrity_prep_fn - Prepare bio for integrity I/O
93 * @bio: bio to prepare
95 * Description: Allocates a buffer for integrity metadata, maps the
96 @@ -359,7 +366,8 @@ static inline unsigned short blk_integri
97 * block device's integrity function. In the READ case, the buffer
98 * will be prepared for DMA and a suitable end_io handler set up.
100 -int bio_integrity_prep(struct bio *bio)
101 +int bio_integrity_prep_fn(struct bio *bio, integrity_gen_fn *generate_fn,
102 + integrity_vrfy_fn *verify_fn)
104 struct bio_integrity_payload *bip;
105 struct blk_integrity *bi;
106 @@ -390,7 +398,8 @@ int bio_integrity_prep(struct bio *bio)
107 nr_pages = end - start;
109 /* Allocate bio integrity payload and integrity vectors */
110 - bip = bio_integrity_alloc(bio, GFP_NOIO, nr_pages);
111 + bip = bio_integrity_alloc_fn(bio, GFP_NOIO, nr_pages,
112 + generate_fn, verify_fn);
113 if (unlikely(bip == NULL)) {
114 printk(KERN_ERR "could not allocate data integrity bioset\n");
116 @@ -440,7 +449,7 @@ int bio_integrity_prep(struct bio *bio)
120 -EXPORT_SYMBOL(bio_integrity_prep);
121 +EXPORT_SYMBOL(bio_integrity_prep_fn);
124 * bio_integrity_verify - Verify integrity metadata for a bio
125 @@ -454,10 +463,13 @@ static int bio_integrity_verify(struct b
127 struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
128 struct blk_integrity_exchg bix;
129 + struct bio_integrity_payload *bip = bio->bi_integrity;
131 sector_t sector = bio->bi_integrity->bip_sector;
132 unsigned int i, sectors, total, ret;
133 void *prot_buf = bio->bi_integrity->bip_buf;
134 + integrity_vrfy_fn *verify_fn = bip->bip_verify_fn ?:
138 bix.disk_name = bio->bi_bdev->bd_disk->disk_name;
139 @@ -474,7 +486,7 @@ static int bio_integrity_verify(struct b
140 bix.prot_buf = prot_buf;
143 - ret = bi->verify_fn(&bix);
144 + ret = verify_fn(&bix);
147 kunmap_atomic(kaddr);
148 @@ -711,7 +723,9 @@ int bio_integrity_clone(struct bio *bio,
150 BUG_ON(bip_src == NULL);
152 - bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
153 + bip = bio_integrity_alloc_fn(bio, gfp_mask, bip_src->bip_vcnt,
154 + bip_src->bip_generate_fn,
155 + bip_src->bip_verify_fn);
159 Index: linux-3.10.0-862.9.1.el7/include/linux/bio.h
160 ===================================================================
161 --- linux-3.10.0-862.9.1.el7.orig/include/linux/bio.h
162 +++ linux-3.10.0-862.9.1.el7/include/linux/bio.h
163 @@ -194,6 +194,9 @@ struct bio_integrity_payload {
165 struct work_struct bip_work; /* I/O completion */
167 + integrity_gen_fn *bip_generate_fn;
168 + integrity_vrfy_fn *bip_verify_fn;
170 struct bio_vec *bip_vec;
171 struct bio_vec bip_inline_vecs[0];/* embedded bvec array */
173 @@ -617,13 +620,28 @@ struct biovec_slab {
175 #define bio_integrity(bio) (bio->bi_integrity != NULL)
177 -extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int);
178 +extern struct bio_integrity_payload *bio_integrity_alloc_fn(struct bio *, gfp_t,
180 + integrity_gen_fn *,
181 + integrity_vrfy_fn *);
182 +static inline struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
186 + return bio_integrity_alloc_fn(bio, gfp, nr, NULL, NULL);
188 extern void bio_integrity_free(struct bio *);
189 extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int);
190 extern int bio_integrity_enabled(struct bio *bio);
191 extern int bio_integrity_set_tag(struct bio *, void *, unsigned int);
192 extern int bio_integrity_get_tag(struct bio *, void *, unsigned int);
193 -extern int bio_integrity_prep(struct bio *);
194 +extern int bio_integrity_prep_fn(struct bio *,
195 + integrity_gen_fn *,
196 + integrity_vrfy_fn *);
197 +static inline int bio_integrity_prep(struct bio *bio)
199 + return bio_integrity_prep_fn(bio, NULL, NULL);
201 extern void bio_integrity_endio(struct bio *, int);
202 extern void bio_integrity_advance(struct bio *, unsigned int);
203 extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int);
204 Index: linux-3.10.0-862.9.1.el7/include/linux/blk_types.h
205 ===================================================================
206 --- linux-3.10.0-862.9.1.el7.orig/include/linux/blk_types.h
207 +++ linux-3.10.0-862.9.1.el7/include/linux/blk_types.h
208 @@ -16,8 +16,11 @@ struct page;
211 struct cgroup_subsys_state;
212 +struct blk_integrity_exchg;
213 typedef void (bio_end_io_t) (struct bio *, int);
214 typedef void (bio_destructor_t) (struct bio *);
215 +typedef void (integrity_gen_fn) (struct blk_integrity_exchg *);
216 +typedef int (integrity_vrfy_fn) (struct blk_integrity_exchg *);
219 * was unsigned short, but we might as well be ready for > 64kB I/O pages
220 Index: linux-3.10.0-862.9.1.el7/include/linux/blkdev.h
221 ===================================================================
222 --- linux-3.10.0-862.9.1.el7.orig/include/linux/blkdev.h
223 +++ linux-3.10.0-862.9.1.el7/include/linux/blkdev.h
224 @@ -1702,8 +1702,6 @@ struct blk_integrity_exchg {
225 const char *disk_name;
228 -typedef void (integrity_gen_fn) (struct blk_integrity_exchg *);
229 -typedef int (integrity_vrfy_fn) (struct blk_integrity_exchg *);
230 typedef void (integrity_set_tag_fn) (void *, void *, unsigned int);
231 typedef void (integrity_get_tag_fn) (void *, void *, unsigned int);