aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-integrity.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/blk-integrity.c')
-rw-r--r--block/blk-integrity.c106
1 files changed, 83 insertions, 23 deletions
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index edce1ef7933d..129b9e209a3b 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -30,26 +30,41 @@
30 30
31static struct kmem_cache *integrity_cachep; 31static struct kmem_cache *integrity_cachep;
32 32
33static const char *bi_unsupported_name = "unsupported";
34
33/** 35/**
34 * blk_rq_count_integrity_sg - Count number of integrity scatterlist elements 36 * blk_rq_count_integrity_sg - Count number of integrity scatterlist elements
35 * @rq: request with integrity metadata attached 37 * @q: request queue
38 * @bio: bio with integrity metadata attached
36 * 39 *
37 * Description: Returns the number of elements required in a 40 * Description: Returns the number of elements required in a
38 * scatterlist corresponding to the integrity metadata in a request. 41 * scatterlist corresponding to the integrity metadata in a bio.
39 */ 42 */
40int blk_rq_count_integrity_sg(struct request *rq) 43int blk_rq_count_integrity_sg(struct request_queue *q, struct bio *bio)
41{ 44{
42 struct bio_vec *iv, *ivprv; 45 struct bio_vec *iv, *ivprv = NULL;
43 struct req_iterator iter; 46 unsigned int segments = 0;
44 unsigned int segments; 47 unsigned int seg_size = 0;
48 unsigned int i = 0;
49
50 bio_for_each_integrity_vec(iv, bio, i) {
51
52 if (ivprv) {
53 if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv))
54 goto new_segment;
45 55
46 ivprv = NULL; 56 if (!BIOVEC_SEG_BOUNDARY(q, ivprv, iv))
47 segments = 0; 57 goto new_segment;
48 58
49 rq_for_each_integrity_segment(iv, rq, iter) { 59 if (seg_size + iv->bv_len > queue_max_segment_size(q))
60 goto new_segment;
50 61
51 if (!ivprv || !BIOVEC_PHYS_MERGEABLE(ivprv, iv)) 62 seg_size += iv->bv_len;
63 } else {
64new_segment:
52 segments++; 65 segments++;
66 seg_size = iv->bv_len;
67 }
53 68
54 ivprv = iv; 69 ivprv = iv;
55 } 70 }
@@ -60,30 +75,34 @@ EXPORT_SYMBOL(blk_rq_count_integrity_sg);
60 75
61/** 76/**
62 * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist 77 * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist
63 * @rq: request with integrity metadata attached 78 * @q: request queue
79 * @bio: bio with integrity metadata attached
64 * @sglist: target scatterlist 80 * @sglist: target scatterlist
65 * 81 *
66 * Description: Map the integrity vectors in request into a 82 * Description: Map the integrity vectors in request into a
67 * scatterlist. The scatterlist must be big enough to hold all 83 * scatterlist. The scatterlist must be big enough to hold all
68 * elements. I.e. sized using blk_rq_count_integrity_sg(). 84 * elements. I.e. sized using blk_rq_count_integrity_sg().
69 */ 85 */
70int blk_rq_map_integrity_sg(struct request *rq, struct scatterlist *sglist) 86int blk_rq_map_integrity_sg(struct request_queue *q, struct bio *bio,
87 struct scatterlist *sglist)
71{ 88{
72 struct bio_vec *iv, *ivprv; 89 struct bio_vec *iv, *ivprv = NULL;
73 struct req_iterator iter; 90 struct scatterlist *sg = NULL;
74 struct scatterlist *sg; 91 unsigned int segments = 0;
75 unsigned int segments; 92 unsigned int i = 0;
76
77 ivprv = NULL;
78 sg = NULL;
79 segments = 0;
80 93
81 rq_for_each_integrity_segment(iv, rq, iter) { 94 bio_for_each_integrity_vec(iv, bio, i) {
82 95
83 if (ivprv) { 96 if (ivprv) {
84 if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv)) 97 if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv))
85 goto new_segment; 98 goto new_segment;
86 99
100 if (!BIOVEC_SEG_BOUNDARY(q, ivprv, iv))
101 goto new_segment;
102
103 if (sg->length + iv->bv_len > queue_max_segment_size(q))
104 goto new_segment;
105
87 sg->length += iv->bv_len; 106 sg->length += iv->bv_len;
88 } else { 107 } else {
89new_segment: 108new_segment:
@@ -162,6 +181,40 @@ int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2)
162} 181}
163EXPORT_SYMBOL(blk_integrity_compare); 182EXPORT_SYMBOL(blk_integrity_compare);
164 183
184int blk_integrity_merge_rq(struct request_queue *q, struct request *req,
185 struct request *next)
186{
187 if (blk_integrity_rq(req) != blk_integrity_rq(next))
188 return -1;
189
190 if (req->nr_integrity_segments + next->nr_integrity_segments >
191 q->limits.max_integrity_segments)
192 return -1;
193
194 return 0;
195}
196EXPORT_SYMBOL(blk_integrity_merge_rq);
197
198int blk_integrity_merge_bio(struct request_queue *q, struct request *req,
199 struct bio *bio)
200{
201 int nr_integrity_segs;
202 struct bio *next = bio->bi_next;
203
204 bio->bi_next = NULL;
205 nr_integrity_segs = blk_rq_count_integrity_sg(q, bio);
206 bio->bi_next = next;
207
208 if (req->nr_integrity_segments + nr_integrity_segs >
209 q->limits.max_integrity_segments)
210 return -1;
211
212 req->nr_integrity_segments += nr_integrity_segs;
213
214 return 0;
215}
216EXPORT_SYMBOL(blk_integrity_merge_bio);
217
165struct integrity_sysfs_entry { 218struct integrity_sysfs_entry {
166 struct attribute attr; 219 struct attribute attr;
167 ssize_t (*show)(struct blk_integrity *, char *); 220 ssize_t (*show)(struct blk_integrity *, char *);
@@ -307,6 +360,14 @@ static struct kobj_type integrity_ktype = {
307 .release = blk_integrity_release, 360 .release = blk_integrity_release,
308}; 361};
309 362
363bool blk_integrity_is_initialized(struct gendisk *disk)
364{
365 struct blk_integrity *bi = blk_get_integrity(disk);
366
367 return (bi && bi->name && strcmp(bi->name, bi_unsupported_name) != 0);
368}
369EXPORT_SYMBOL(blk_integrity_is_initialized);
370
310/** 371/**
311 * blk_integrity_register - Register a gendisk as being integrity-capable 372 * blk_integrity_register - Register a gendisk as being integrity-capable
312 * @disk: struct gendisk pointer to make integrity-aware 373 * @disk: struct gendisk pointer to make integrity-aware
@@ -356,7 +417,7 @@ int blk_integrity_register(struct gendisk *disk, struct blk_integrity *template)
356 bi->get_tag_fn = template->get_tag_fn; 417 bi->get_tag_fn = template->get_tag_fn;
357 bi->tag_size = template->tag_size; 418 bi->tag_size = template->tag_size;
358 } else 419 } else
359 bi->name = "unsupported"; 420 bi->name = bi_unsupported_name;
360 421
361 return 0; 422 return 0;
362} 423}
@@ -381,7 +442,6 @@ void blk_integrity_unregister(struct gendisk *disk)
381 kobject_uevent(&bi->kobj, KOBJ_REMOVE); 442 kobject_uevent(&bi->kobj, KOBJ_REMOVE);
382 kobject_del(&bi->kobj); 443 kobject_del(&bi->kobj);
383 kobject_put(&bi->kobj); 444 kobject_put(&bi->kobj);
384 kmem_cache_free(integrity_cachep, bi);
385 disk->integrity = NULL; 445 disk->integrity = NULL;
386} 446}
387EXPORT_SYMBOL(blk_integrity_unregister); 447EXPORT_SYMBOL(blk_integrity_unregister);