]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | Subject: Block integrity update |
2 | From: Martin K. Petersen <martin.petersen@oracle.com> | |
3 | Date: Mon Dec 8 09:36:35 2008 +0100: | |
4 | References: FATE#304345 | |
5 | ||
6 | This patch series contains block layer integrity updates for 2.6.28. | |
7 | ||
8 | There are a few fixes to the core bits, including a switch from | |
9 | block_device to gendisk in the integrity compare function. I also had | |
10 | to add a helper to access a gendisk's integrity profile. This is used | |
11 | by MD. | |
12 | ||
13 | Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> | |
14 | Signed-off-by: Hannes Reinecke <hare@suse.de> | |
15 | ||
16 | --- | |
17 | block/blk-integrity.c | 30 +++++++++++++++--------------- | |
18 | fs/bio-integrity.c | 3 ++- | |
19 | fs/bio.c | 36 ++++++++++++++++++++++++++++++++++++ | |
20 | include/linux/bio.h | 2 ++ | |
21 | include/linux/blkdev.h | 8 +++++++- | |
22 | 5 files changed, 62 insertions(+), 17 deletions(-) | |
23 | ||
24 | --- a/block/blk-integrity.c | |
25 | +++ b/block/blk-integrity.c | |
26 | @@ -108,51 +108,51 @@ new_segment: | |
27 | EXPORT_SYMBOL(blk_rq_map_integrity_sg); | |
28 | ||
29 | /** | |
30 | - * blk_integrity_compare - Compare integrity profile of two block devices | |
31 | - * @bd1: Device to compare | |
32 | - * @bd2: Device to compare | |
33 | + * blk_integrity_compare - Compare integrity profile of two disks | |
34 | + * @gd1: Disk to compare | |
35 | + * @gd2: Disk to compare | |
36 | * | |
37 | * Description: Meta-devices like DM and MD need to verify that all | |
38 | * sub-devices use the same integrity format before advertising to | |
39 | * upper layers that they can send/receive integrity metadata. This | |
40 | - * function can be used to check whether two block devices have | |
41 | + * function can be used to check whether two gendisk devices have | |
42 | * compatible integrity formats. | |
43 | */ | |
44 | -int blk_integrity_compare(struct block_device *bd1, struct block_device *bd2) | |
45 | +int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2) | |
46 | { | |
47 | - struct blk_integrity *b1 = bd1->bd_disk->integrity; | |
48 | - struct blk_integrity *b2 = bd2->bd_disk->integrity; | |
49 | + struct blk_integrity *b1 = gd1->integrity; | |
50 | + struct blk_integrity *b2 = gd2->integrity; | |
51 | ||
52 | - BUG_ON(bd1->bd_disk == NULL); | |
53 | - BUG_ON(bd2->bd_disk == NULL); | |
54 | + if (!b1 && !b2) | |
55 | + return 0; | |
56 | ||
57 | if (!b1 || !b2) | |
58 | - return 0; | |
59 | + return -1; | |
60 | ||
61 | if (b1->sector_size != b2->sector_size) { | |
62 | printk(KERN_ERR "%s: %s/%s sector sz %u != %u\n", __func__, | |
63 | - bd1->bd_disk->disk_name, bd2->bd_disk->disk_name, | |
64 | + gd1->disk_name, gd2->disk_name, | |
65 | b1->sector_size, b2->sector_size); | |
66 | return -1; | |
67 | } | |
68 | ||
69 | if (b1->tuple_size != b2->tuple_size) { | |
70 | printk(KERN_ERR "%s: %s/%s tuple sz %u != %u\n", __func__, | |
71 | - bd1->bd_disk->disk_name, bd2->bd_disk->disk_name, | |
72 | + gd1->disk_name, gd2->disk_name, | |
73 | b1->tuple_size, b2->tuple_size); | |
74 | return -1; | |
75 | } | |
76 | ||
77 | if (b1->tag_size && b2->tag_size && (b1->tag_size != b2->tag_size)) { | |
78 | printk(KERN_ERR "%s: %s/%s tag sz %u != %u\n", __func__, | |
79 | - bd1->bd_disk->disk_name, bd2->bd_disk->disk_name, | |
80 | + gd1->disk_name, gd2->disk_name, | |
81 | b1->tag_size, b2->tag_size); | |
82 | return -1; | |
83 | } | |
84 | ||
85 | if (strcmp(b1->name, b2->name)) { | |
86 | printk(KERN_ERR "%s: %s/%s type %s != %s\n", __func__, | |
87 | - bd1->bd_disk->disk_name, bd2->bd_disk->disk_name, | |
88 | + gd1->disk_name, gd2->disk_name, | |
89 | b1->name, b2->name); | |
90 | return -1; | |
91 | } | |
92 | @@ -375,7 +375,7 @@ void blk_integrity_unregister(struct gen | |
93 | ||
94 | kobject_uevent(&bi->kobj, KOBJ_REMOVE); | |
95 | kobject_del(&bi->kobj); | |
96 | - kobject_put(&disk->dev.kobj); | |
97 | kmem_cache_free(integrity_cachep, bi); | |
98 | + disk->integrity = NULL; | |
99 | } | |
100 | EXPORT_SYMBOL(blk_integrity_unregister); | |
101 | --- a/fs/bio.c | |
102 | +++ b/fs/bio.c | |
103 | @@ -1274,6 +1274,42 @@ struct bio_pair *bio_split(struct bio *b | |
104 | return bp; | |
105 | } | |
106 | ||
107 | +/** | |
108 | + * bio_sector_offset - Find hardware sector offset in bio | |
109 | + * @bio: bio to inspect | |
110 | + * @index: bio_vec index | |
111 | + * @offset: offset in bv_page | |
112 | + * | |
113 | + * Return the number of hardware sectors between beginning of bio | |
114 | + * and an end point indicated by a bio_vec index and an offset | |
115 | + * within that vector's page. | |
116 | + */ | |
117 | +sector_t bio_sector_offset(struct bio *bio, unsigned short index, | |
118 | + unsigned int offset) | |
119 | +{ | |
120 | + unsigned int sector_sz = queue_hardsect_size(bio->bi_bdev->bd_disk->queue); | |
121 | + struct bio_vec *bv; | |
122 | + sector_t sectors; | |
123 | + int i; | |
124 | + | |
125 | + sectors = 0; | |
126 | + | |
127 | + if (index >= bio->bi_idx) | |
128 | + index = bio->bi_vcnt - 1; | |
129 | + | |
130 | + __bio_for_each_segment(bv, bio, i, 0) { | |
131 | + if (i == index) { | |
132 | + if (offset > bv->bv_offset) | |
133 | + sectors += (offset - bv->bv_offset) / sector_sz; | |
134 | + break; | |
135 | + } | |
136 | + | |
137 | + sectors += bv->bv_len / sector_sz; | |
138 | + } | |
139 | + | |
140 | + return sectors; | |
141 | +} | |
142 | +EXPORT_SYMBOL(bio_sector_offset); | |
143 | ||
144 | /* | |
145 | * create memory pools for biovec's in a bio_set. | |
146 | --- a/fs/bio-integrity.c | |
147 | +++ b/fs/bio-integrity.c | |
148 | @@ -107,7 +107,8 @@ void bio_integrity_free(struct bio *bio, | |
149 | BUG_ON(bip == NULL); | |
150 | ||
151 | /* A cloned bio doesn't own the integrity metadata */ | |
152 | - if (!bio_flagged(bio, BIO_CLONED) && bip->bip_buf != NULL) | |
153 | + if (!bio_flagged(bio, BIO_CLONED) && !bio_flagged(bio, BIO_FS_INTEGRITY) | |
154 | + && bip->bip_buf != NULL) | |
155 | kfree(bip->bip_buf); | |
156 | ||
157 | mempool_free(bip->bip_vec, bs->bvec_pools[bip->bip_pool]); | |
158 | --- a/include/linux/bio.h | |
159 | +++ b/include/linux/bio.h | |
160 | @@ -115,6 +115,7 @@ struct bio { | |
161 | #define BIO_USER_MAPPED 6 /* contains user pages */ | |
162 | #define BIO_EOPNOTSUPP 7 /* not supported */ | |
163 | #define BIO_CPU_AFFINE 8 /* complete bio on same CPU as submitted */ | |
164 | +#define BIO_FS_INTEGRITY 10 /* fs owns integrity data, not block layer */ | |
165 | #define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag))) | |
166 | ||
167 | /* | |
168 | @@ -331,6 +332,7 @@ extern int bio_add_page(struct bio *, st | |
169 | extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *, | |
170 | unsigned int, unsigned int); | |
171 | extern int bio_get_nr_vecs(struct block_device *); | |
172 | +extern sector_t bio_sector_offset(struct bio *, unsigned short, unsigned int); | |
173 | extern struct bio *bio_map_user(struct request_queue *, struct block_device *, | |
174 | unsigned long, unsigned int, int); | |
175 | struct sg_iovec; | |
176 | --- a/include/linux/blkdev.h | |
177 | +++ b/include/linux/blkdev.h | |
178 | @@ -980,7 +980,7 @@ struct blk_integrity { | |
179 | ||
180 | extern int blk_integrity_register(struct gendisk *, struct blk_integrity *); | |
181 | extern void blk_integrity_unregister(struct gendisk *); | |
182 | -extern int blk_integrity_compare(struct block_device *, struct block_device *); | |
183 | +extern int blk_integrity_compare(struct gendisk *, struct gendisk *); | |
184 | extern int blk_rq_map_integrity_sg(struct request *, struct scatterlist *); | |
185 | extern int blk_rq_count_integrity_sg(struct request *); | |
186 | ||
187 | @@ -997,6 +997,11 @@ static inline struct blk_integrity *bdev | |
188 | return bdev->bd_disk->integrity; | |
189 | } | |
190 | ||
191 | +static inline struct blk_integrity *blk_get_integrity(struct gendisk *disk) | |
192 | +{ | |
193 | + return disk->integrity; | |
194 | +} | |
195 | + | |
196 | static inline unsigned int bdev_get_tag_size(struct block_device *bdev) | |
197 | { | |
198 | struct blk_integrity *bi = bdev_get_integrity(bdev); | |
199 | @@ -1039,6 +1044,7 @@ static inline int blk_integrity_rq(struc | |
200 | #define blk_rq_count_integrity_sg(a) (0) | |
201 | #define blk_rq_map_integrity_sg(a, b) (0) | |
202 | #define bdev_get_integrity(a) (0) | |
203 | +#define blk_get_integrity(a) (0) | |
204 | #define bdev_get_tag_size(a) (0) | |
205 | #define blk_integrity_compare(a, b) (0) | |
206 | #define blk_integrity_register(a, b) (0) |