1 /* 2 * blk-integrity.c - Block layer data integrity extensions 3 * 4 * Copyright (C) 2007, 2008 Oracle Corporation 5 * Written by: Martin K. Petersen <martin.petersen@oracle.com> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License version 9 * 2 as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; see the file COPYING. If not, write to 18 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 19 * USA. 20 * 21 */ 22 23 #include <linux/blkdev.h> 24 #include <linux/backing-dev.h> 25 #include <linux/mempool.h> 26 #include <linux/bio.h> 27 #include <linux/scatterlist.h> 28 #include <linux/export.h> 29 #include <linux/slab.h> 30 31 #include "blk.h" 32 33 /** 34 * blk_rq_count_integrity_sg - Count number of integrity scatterlist elements 35 * @q: request queue 36 * @bio: bio with integrity metadata attached 37 * 38 * Description: Returns the number of elements required in a 39 * scatterlist corresponding to the integrity metadata in a bio. 40 */ 41 int blk_rq_count_integrity_sg(struct request_queue *q, struct bio *bio) 42 { 43 struct bio_vec iv, ivprv = { NULL }; 44 unsigned int segments = 0; 45 unsigned int seg_size = 0; 46 struct bvec_iter iter; 47 int prev = 0; 48 49 bio_for_each_integrity_vec(iv, bio, iter) { 50 51 if (prev) { 52 if (!biovec_phys_mergeable(q, &ivprv, &iv)) 53 goto new_segment; 54 if (seg_size + iv.bv_len > queue_max_segment_size(q)) 55 goto new_segment; 56 57 seg_size += iv.bv_len; 58 } else { 59 new_segment: 60 segments++; 61 seg_size = iv.bv_len; 62 } 63 64 prev = 1; 65 ivprv = iv; 66 } 67 68 return segments; 69 } 70 EXPORT_SYMBOL(blk_rq_count_integrity_sg); 71 72 /** 73 * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist 74 * @q: request queue 75 * @bio: bio with integrity metadata attached 76 * @sglist: target scatterlist 77 * 78 * Description: Map the integrity vectors in request into a 79 * scatterlist. The scatterlist must be big enough to hold all 80 * elements. I.e. sized using blk_rq_count_integrity_sg(). 81 */ 82 int blk_rq_map_integrity_sg(struct request_queue *q, struct bio *bio, 83 struct scatterlist *sglist) 84 { 85 struct bio_vec iv, ivprv = { NULL }; 86 struct scatterlist *sg = NULL; 87 unsigned int segments = 0; 88 struct bvec_iter iter; 89 int prev = 0; 90 91 bio_for_each_integrity_vec(iv, bio, iter) { 92 93 if (prev) { 94 if (!biovec_phys_mergeable(q, &ivprv, &iv)) 95 goto new_segment; 96 if (sg->length + iv.bv_len > queue_max_segment_size(q)) 97 goto new_segment; 98 99 sg->length += iv.bv_len; 100 } else { 101 new_segment: 102 if (!sg) 103 sg = sglist; 104 else { 105 sg_unmark_end(sg); 106 sg = sg_next(sg); 107 } 108 109 sg_set_page(sg, iv.bv_page, iv.bv_len, iv.bv_offset); 110 segments++; 111 } 112 113 prev = 1; 114 ivprv = iv; 115 } 116 117 if (sg) 118 sg_mark_end(sg); 119 120 return segments; 121 } 122 EXPORT_SYMBOL(blk_rq_map_integrity_sg); 123 124 /** 125 * blk_integrity_compare - Compare integrity profile of two disks 126 * @gd1: Disk to compare 127 * @gd2: Disk to compare 128 * 129 * Description: Meta-devices like DM and MD need to verify that all 130 * sub-devices use the same integrity format before advertising to 131 * upper layers that they can send/receive integrity metadata. This 132 * function can be used to check whether two gendisk devices have 133 * compatible integrity formats. 134 */ 135 int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2) 136 { 137 struct blk_integrity *b1 = &gd1->queue->integrity; 138 struct blk_integrity *b2 = &gd2->queue->integrity; 139 140 if (!b1->profile && !b2->profile) 141 return 0; 142 143 if (!b1->profile || !b2->profile) 144 return -1; 145 146 if (b1->interval_exp != b2->interval_exp) { 147 pr_err("%s: %s/%s protection interval %u != %u\n", 148 __func__, gd1->disk_name, gd2->disk_name, 149 1 << b1->interval_exp, 1 << b2->interval_exp); 150 return -1; 151 } 152 153 if (b1->tuple_size != b2->tuple_size) { 154 pr_err("%s: %s/%s tuple sz %u != %u\n", __func__, 155 gd1->disk_name, gd2->disk_name, 156 b1->tuple_size, b2->tuple_size); 157 return -1; 158 } 159 160 if (b1->tag_size && b2->tag_size && (b1->tag_size != b2->tag_size)) { 161 pr_err("%s: %s/%s tag sz %u != %u\n", __func__, 162 gd1->disk_name, gd2->disk_name, 163 b1->tag_size, b2->tag_size); 164 return -1; 165 } 166 167 if (b1->profile != b2->profile) { 168 pr_err("%s: %s/%s type %s != %s\n", __func__, 169 gd1->disk_name, gd2->disk_name, 170 b1->profile->name, b2->profile->name); 171 return -1; 172 } 173 174 return 0; 175 } 176 EXPORT_SYMBOL(blk_integrity_compare); 177 178 bool blk_integrity_merge_rq(struct request_queue *q, struct request *req, 179 struct request *next) 180 { 181 if (blk_integrity_rq(req) == 0 && blk_integrity_rq(next) == 0) 182 return true; 183 184 if (blk_integrity_rq(req) == 0 || blk_integrity_rq(next) == 0) 185 return false; 186 187 if (bio_integrity(req->bio)->bip_flags != 188 bio_integrity(next->bio)->bip_flags) 189 return false; 190 191 if (req->nr_integrity_segments + next->nr_integrity_segments > 192 q->limits.max_integrity_segments) 193 return false; 194 195 if (integrity_req_gap_back_merge(req, next->bio)) 196 return false; 197 198 return true; 199 } 200 EXPORT_SYMBOL(blk_integrity_merge_rq); 201 202 bool blk_integrity_merge_bio(struct request_queue *q, struct request *req, 203 struct bio *bio) 204 { 205 int nr_integrity_segs; 206 struct bio *next = bio->bi_next; 207 208 if (blk_integrity_rq(req) == 0 && bio_integrity(bio) == NULL) 209 return true; 210 211 if (blk_integrity_rq(req) == 0 || bio_integrity(bio) == NULL) 212 return false; 213 214 if (bio_integrity(req->bio)->bip_flags != bio_integrity(bio)->bip_flags) 215 return false; 216 217 bio->bi_next = NULL; 218 nr_integrity_segs = blk_rq_count_integrity_sg(q, bio); 219 bio->bi_next = next; 220 221 if (req->nr_integrity_segments + nr_integrity_segs > 222 q->limits.max_integrity_segments) 223 return false; 224 225 req->nr_integrity_segments += nr_integrity_segs; 226 227 return true; 228 } 229 EXPORT_SYMBOL(blk_integrity_merge_bio); 230 231 struct integrity_sysfs_entry { 232 struct attribute attr; 233 ssize_t (*show)(struct blk_integrity *, char *); 234 ssize_t (*store)(struct blk_integrity *, const char *, size_t); 235 }; 236 237 static ssize_t integrity_attr_show(struct kobject *kobj, struct attribute *attr, 238 char *page) 239 { 240 struct gendisk *disk = container_of(kobj, struct gendisk, integrity_kobj); 241 struct blk_integrity *bi = &disk->queue->integrity; 242 struct integrity_sysfs_entry *entry = 243 container_of(attr, struct integrity_sysfs_entry, attr); 244 245 return entry->show(bi, page); 246 } 247 248 static ssize_t integrity_attr_store(struct kobject *kobj, 249 struct attribute *attr, const char *page, 250 size_t count) 251 { 252 struct gendisk *disk = container_of(kobj, struct gendisk, integrity_kobj); 253 struct blk_integrity *bi = &disk->queue->integrity; 254 struct integrity_sysfs_entry *entry = 255 container_of(attr, struct integrity_sysfs_entry, attr); 256 ssize_t ret = 0; 257 258 if (entry->store) 259 ret = entry->store(bi, page, count); 260 261 return ret; 262 } 263 264 static ssize_t integrity_format_show(struct blk_integrity *bi, char *page) 265 { 266 if (bi->profile && bi->profile->name) 267 return sprintf(page, "%s\n", bi->profile->name); 268 else 269 return sprintf(page, "none\n"); 270 } 271 272 static ssize_t integrity_tag_size_show(struct blk_integrity *bi, char *page) 273 { 274 return sprintf(page, "%u\n", bi->tag_size); 275 } 276 277 static ssize_t integrity_interval_show(struct blk_integrity *bi, char *page) 278 { 279 return sprintf(page, "%u\n", 280 bi->interval_exp ? 1 << bi->interval_exp : 0); 281 } 282 283 static ssize_t integrity_verify_store(struct blk_integrity *bi, 284 const char *page, size_t count) 285 { 286 char *p = (char *) page; 287 unsigned long val = simple_strtoul(p, &p, 10); 288 289 if (val) 290 bi->flags |= BLK_INTEGRITY_VERIFY; 291 else 292 bi->flags &= ~BLK_INTEGRITY_VERIFY; 293 294 return count; 295 } 296 297 static ssize_t integrity_verify_show(struct blk_integrity *bi, char *page) 298 { 299 return sprintf(page, "%d\n", (bi->flags & BLK_INTEGRITY_VERIFY) != 0); 300 } 301 302 static ssize_t integrity_generate_store(struct blk_integrity *bi, 303 const char *page, size_t count) 304 { 305 char *p = (char *) page; 306 unsigned long val = simple_strtoul(p, &p, 10); 307 308 if (val) 309 bi->flags |= BLK_INTEGRITY_GENERATE; 310 else 311 bi->flags &= ~BLK_INTEGRITY_GENERATE; 312 313 return count; 314 } 315 316 static ssize_t integrity_generate_show(struct blk_integrity *bi, char *page) 317 { 318 return sprintf(page, "%d\n", (bi->flags & BLK_INTEGRITY_GENERATE) != 0); 319 } 320 321 static ssize_t integrity_device_show(struct blk_integrity *bi, char *page) 322 { 323 return sprintf(page, "%u\n", 324 (bi->flags & BLK_INTEGRITY_DEVICE_CAPABLE) != 0); 325 } 326 327 static struct integrity_sysfs_entry integrity_format_entry = { 328 .attr = { .name = "format", .mode = 0444 }, 329 .show = integrity_format_show, 330 }; 331 332 static struct integrity_sysfs_entry integrity_tag_size_entry = { 333 .attr = { .name = "tag_size", .mode = 0444 }, 334 .show = integrity_tag_size_show, 335 }; 336 337 static struct integrity_sysfs_entry integrity_interval_entry = { 338 .attr = { .name = "protection_interval_bytes", .mode = 0444 }, 339 .show = integrity_interval_show, 340 }; 341 342 static struct integrity_sysfs_entry integrity_verify_entry = { 343 .attr = { .name = "read_verify", .mode = 0644 }, 344 .show = integrity_verify_show, 345 .store = integrity_verify_store, 346 }; 347 348 static struct integrity_sysfs_entry integrity_generate_entry = { 349 .attr = { .name = "write_generate", .mode = 0644 }, 350 .show = integrity_generate_show, 351 .store = integrity_generate_store, 352 }; 353 354 static struct integrity_sysfs_entry integrity_device_entry = { 355 .attr = { .name = "device_is_integrity_capable", .mode = 0444 }, 356 .show = integrity_device_show, 357 }; 358 359 static struct attribute *integrity_attrs[] = { 360 &integrity_format_entry.attr, 361 &integrity_tag_size_entry.attr, 362 &integrity_interval_entry.attr, 363 &integrity_verify_entry.attr, 364 &integrity_generate_entry.attr, 365 &integrity_device_entry.attr, 366 NULL, 367 }; 368 369 static const struct sysfs_ops integrity_ops = { 370 .show = &integrity_attr_show, 371 .store = &integrity_attr_store, 372 }; 373 374 static struct kobj_type integrity_ktype = { 375 .default_attrs = integrity_attrs, 376 .sysfs_ops = &integrity_ops, 377 }; 378 379 static blk_status_t blk_integrity_nop_fn(struct blk_integrity_iter *iter) 380 { 381 return BLK_STS_OK; 382 } 383 384 static const struct blk_integrity_profile nop_profile = { 385 .name = "nop", 386 .generate_fn = blk_integrity_nop_fn, 387 .verify_fn = blk_integrity_nop_fn, 388 }; 389 390 /** 391 * blk_integrity_register - Register a gendisk as being integrity-capable 392 * @disk: struct gendisk pointer to make integrity-aware 393 * @template: block integrity profile to register 394 * 395 * Description: When a device needs to advertise itself as being able to 396 * send/receive integrity metadata it must use this function to register 397 * the capability with the block layer. The template is a blk_integrity 398 * struct with values appropriate for the underlying hardware. See 399 * Documentation/block/data-integrity.txt. 400 */ 401 void blk_integrity_register(struct gendisk *disk, struct blk_integrity *template) 402 { 403 struct blk_integrity *bi = &disk->queue->integrity; 404 405 bi->flags = BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE | 406 template->flags; 407 bi->interval_exp = template->interval_exp ? : 408 ilog2(queue_logical_block_size(disk->queue)); 409 bi->profile = template->profile ? template->profile : &nop_profile; 410 bi->tuple_size = template->tuple_size; 411 bi->tag_size = template->tag_size; 412 413 disk->queue->backing_dev_info->capabilities |= BDI_CAP_STABLE_WRITES; 414 } 415 EXPORT_SYMBOL(blk_integrity_register); 416 417 /** 418 * blk_integrity_unregister - Unregister block integrity profile 419 * @disk: disk whose integrity profile to unregister 420 * 421 * Description: This function unregisters the integrity capability from 422 * a block device. 423 */ 424 void blk_integrity_unregister(struct gendisk *disk) 425 { 426 disk->queue->backing_dev_info->capabilities &= ~BDI_CAP_STABLE_WRITES; 427 memset(&disk->queue->integrity, 0, sizeof(struct blk_integrity)); 428 } 429 EXPORT_SYMBOL(blk_integrity_unregister); 430 431 void blk_integrity_add(struct gendisk *disk) 432 { 433 if (kobject_init_and_add(&disk->integrity_kobj, &integrity_ktype, 434 &disk_to_dev(disk)->kobj, "%s", "integrity")) 435 return; 436 437 kobject_uevent(&disk->integrity_kobj, KOBJ_ADD); 438 } 439 440 void blk_integrity_del(struct gendisk *disk) 441 { 442 kobject_uevent(&disk->integrity_kobj, KOBJ_REMOVE); 443 kobject_del(&disk->integrity_kobj); 444 kobject_put(&disk->integrity_kobj); 445 } 446