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