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/mempool.h> 25 #include <linux/bio.h> 26 #include <linux/scatterlist.h> 27 #include <linux/slab.h> 28 29 #include "blk.h" 30 31 static struct kmem_cache *integrity_cachep; 32 33 /** 34 * blk_rq_count_integrity_sg - Count number of integrity scatterlist elements 35 * @rq: request with integrity metadata attached 36 * 37 * Description: Returns the number of elements required in a 38 * scatterlist corresponding to the integrity metadata in a request. 39 */ 40 int blk_rq_count_integrity_sg(struct request *rq) 41 { 42 struct bio_vec *iv, *ivprv; 43 struct req_iterator iter; 44 unsigned int segments; 45 46 ivprv = NULL; 47 segments = 0; 48 49 rq_for_each_integrity_segment(iv, rq, iter) { 50 51 if (!ivprv || !BIOVEC_PHYS_MERGEABLE(ivprv, iv)) 52 segments++; 53 54 ivprv = iv; 55 } 56 57 return segments; 58 } 59 EXPORT_SYMBOL(blk_rq_count_integrity_sg); 60 61 /** 62 * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist 63 * @rq: request with integrity metadata attached 64 * @sglist: target scatterlist 65 * 66 * Description: Map the integrity vectors in request into a 67 * scatterlist. The scatterlist must be big enough to hold all 68 * elements. I.e. sized using blk_rq_count_integrity_sg(). 69 */ 70 int blk_rq_map_integrity_sg(struct request *rq, struct scatterlist *sglist) 71 { 72 struct bio_vec *iv, *ivprv; 73 struct req_iterator iter; 74 struct scatterlist *sg; 75 unsigned int segments; 76 77 ivprv = NULL; 78 sg = NULL; 79 segments = 0; 80 81 rq_for_each_integrity_segment(iv, rq, iter) { 82 83 if (ivprv) { 84 if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv)) 85 goto new_segment; 86 87 sg->length += iv->bv_len; 88 } else { 89 new_segment: 90 if (!sg) 91 sg = sglist; 92 else { 93 sg->page_link &= ~0x02; 94 sg = sg_next(sg); 95 } 96 97 sg_set_page(sg, iv->bv_page, iv->bv_len, iv->bv_offset); 98 segments++; 99 } 100 101 ivprv = iv; 102 } 103 104 if (sg) 105 sg_mark_end(sg); 106 107 return segments; 108 } 109 EXPORT_SYMBOL(blk_rq_map_integrity_sg); 110 111 /** 112 * blk_integrity_compare - Compare integrity profile of two disks 113 * @gd1: Disk to compare 114 * @gd2: Disk to compare 115 * 116 * Description: Meta-devices like DM and MD need to verify that all 117 * sub-devices use the same integrity format before advertising to 118 * upper layers that they can send/receive integrity metadata. This 119 * function can be used to check whether two gendisk devices have 120 * compatible integrity formats. 121 */ 122 int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2) 123 { 124 struct blk_integrity *b1 = gd1->integrity; 125 struct blk_integrity *b2 = gd2->integrity; 126 127 if (!b1 && !b2) 128 return 0; 129 130 if (!b1 || !b2) 131 return -1; 132 133 if (b1->sector_size != b2->sector_size) { 134 printk(KERN_ERR "%s: %s/%s sector sz %u != %u\n", __func__, 135 gd1->disk_name, gd2->disk_name, 136 b1->sector_size, b2->sector_size); 137 return -1; 138 } 139 140 if (b1->tuple_size != b2->tuple_size) { 141 printk(KERN_ERR "%s: %s/%s tuple sz %u != %u\n", __func__, 142 gd1->disk_name, gd2->disk_name, 143 b1->tuple_size, b2->tuple_size); 144 return -1; 145 } 146 147 if (b1->tag_size && b2->tag_size && (b1->tag_size != b2->tag_size)) { 148 printk(KERN_ERR "%s: %s/%s tag sz %u != %u\n", __func__, 149 gd1->disk_name, gd2->disk_name, 150 b1->tag_size, b2->tag_size); 151 return -1; 152 } 153 154 if (strcmp(b1->name, b2->name)) { 155 printk(KERN_ERR "%s: %s/%s type %s != %s\n", __func__, 156 gd1->disk_name, gd2->disk_name, 157 b1->name, b2->name); 158 return -1; 159 } 160 161 return 0; 162 } 163 EXPORT_SYMBOL(blk_integrity_compare); 164 165 struct integrity_sysfs_entry { 166 struct attribute attr; 167 ssize_t (*show)(struct blk_integrity *, char *); 168 ssize_t (*store)(struct blk_integrity *, const char *, size_t); 169 }; 170 171 static ssize_t integrity_attr_show(struct kobject *kobj, struct attribute *attr, 172 char *page) 173 { 174 struct blk_integrity *bi = 175 container_of(kobj, struct blk_integrity, kobj); 176 struct integrity_sysfs_entry *entry = 177 container_of(attr, struct integrity_sysfs_entry, attr); 178 179 return entry->show(bi, page); 180 } 181 182 static ssize_t integrity_attr_store(struct kobject *kobj, 183 struct attribute *attr, const char *page, 184 size_t count) 185 { 186 struct blk_integrity *bi = 187 container_of(kobj, struct blk_integrity, kobj); 188 struct integrity_sysfs_entry *entry = 189 container_of(attr, struct integrity_sysfs_entry, attr); 190 ssize_t ret = 0; 191 192 if (entry->store) 193 ret = entry->store(bi, page, count); 194 195 return ret; 196 } 197 198 static ssize_t integrity_format_show(struct blk_integrity *bi, char *page) 199 { 200 if (bi != NULL && bi->name != NULL) 201 return sprintf(page, "%s\n", bi->name); 202 else 203 return sprintf(page, "none\n"); 204 } 205 206 static ssize_t integrity_tag_size_show(struct blk_integrity *bi, char *page) 207 { 208 if (bi != NULL) 209 return sprintf(page, "%u\n", bi->tag_size); 210 else 211 return sprintf(page, "0\n"); 212 } 213 214 static ssize_t integrity_read_store(struct blk_integrity *bi, 215 const char *page, size_t count) 216 { 217 char *p = (char *) page; 218 unsigned long val = simple_strtoul(p, &p, 10); 219 220 if (val) 221 bi->flags |= INTEGRITY_FLAG_READ; 222 else 223 bi->flags &= ~INTEGRITY_FLAG_READ; 224 225 return count; 226 } 227 228 static ssize_t integrity_read_show(struct blk_integrity *bi, char *page) 229 { 230 return sprintf(page, "%d\n", (bi->flags & INTEGRITY_FLAG_READ) != 0); 231 } 232 233 static ssize_t integrity_write_store(struct blk_integrity *bi, 234 const char *page, size_t count) 235 { 236 char *p = (char *) page; 237 unsigned long val = simple_strtoul(p, &p, 10); 238 239 if (val) 240 bi->flags |= INTEGRITY_FLAG_WRITE; 241 else 242 bi->flags &= ~INTEGRITY_FLAG_WRITE; 243 244 return count; 245 } 246 247 static ssize_t integrity_write_show(struct blk_integrity *bi, char *page) 248 { 249 return sprintf(page, "%d\n", (bi->flags & INTEGRITY_FLAG_WRITE) != 0); 250 } 251 252 static struct integrity_sysfs_entry integrity_format_entry = { 253 .attr = { .name = "format", .mode = S_IRUGO }, 254 .show = integrity_format_show, 255 }; 256 257 static struct integrity_sysfs_entry integrity_tag_size_entry = { 258 .attr = { .name = "tag_size", .mode = S_IRUGO }, 259 .show = integrity_tag_size_show, 260 }; 261 262 static struct integrity_sysfs_entry integrity_read_entry = { 263 .attr = { .name = "read_verify", .mode = S_IRUGO | S_IWUSR }, 264 .show = integrity_read_show, 265 .store = integrity_read_store, 266 }; 267 268 static struct integrity_sysfs_entry integrity_write_entry = { 269 .attr = { .name = "write_generate", .mode = S_IRUGO | S_IWUSR }, 270 .show = integrity_write_show, 271 .store = integrity_write_store, 272 }; 273 274 static struct attribute *integrity_attrs[] = { 275 &integrity_format_entry.attr, 276 &integrity_tag_size_entry.attr, 277 &integrity_read_entry.attr, 278 &integrity_write_entry.attr, 279 NULL, 280 }; 281 282 static const struct sysfs_ops integrity_ops = { 283 .show = &integrity_attr_show, 284 .store = &integrity_attr_store, 285 }; 286 287 static int __init blk_dev_integrity_init(void) 288 { 289 integrity_cachep = kmem_cache_create("blkdev_integrity", 290 sizeof(struct blk_integrity), 291 0, SLAB_PANIC, NULL); 292 return 0; 293 } 294 subsys_initcall(blk_dev_integrity_init); 295 296 static void blk_integrity_release(struct kobject *kobj) 297 { 298 struct blk_integrity *bi = 299 container_of(kobj, struct blk_integrity, kobj); 300 301 kmem_cache_free(integrity_cachep, bi); 302 } 303 304 static struct kobj_type integrity_ktype = { 305 .default_attrs = integrity_attrs, 306 .sysfs_ops = &integrity_ops, 307 .release = blk_integrity_release, 308 }; 309 310 /** 311 * blk_integrity_register - Register a gendisk as being integrity-capable 312 * @disk: struct gendisk pointer to make integrity-aware 313 * @template: optional integrity profile to register 314 * 315 * Description: When a device needs to advertise itself as being able 316 * to send/receive integrity metadata it must use this function to 317 * register the capability with the block layer. The template is a 318 * blk_integrity struct with values appropriate for the underlying 319 * hardware. If template is NULL the new profile is allocated but 320 * not filled out. See Documentation/block/data-integrity.txt. 321 */ 322 int blk_integrity_register(struct gendisk *disk, struct blk_integrity *template) 323 { 324 struct blk_integrity *bi; 325 326 BUG_ON(disk == NULL); 327 328 if (disk->integrity == NULL) { 329 bi = kmem_cache_alloc(integrity_cachep, 330 GFP_KERNEL | __GFP_ZERO); 331 if (!bi) 332 return -1; 333 334 if (kobject_init_and_add(&bi->kobj, &integrity_ktype, 335 &disk_to_dev(disk)->kobj, 336 "%s", "integrity")) { 337 kmem_cache_free(integrity_cachep, bi); 338 return -1; 339 } 340 341 kobject_uevent(&bi->kobj, KOBJ_ADD); 342 343 bi->flags |= INTEGRITY_FLAG_READ | INTEGRITY_FLAG_WRITE; 344 bi->sector_size = queue_logical_block_size(disk->queue); 345 disk->integrity = bi; 346 } else 347 bi = disk->integrity; 348 349 /* Use the provided profile as template */ 350 if (template != NULL) { 351 bi->name = template->name; 352 bi->generate_fn = template->generate_fn; 353 bi->verify_fn = template->verify_fn; 354 bi->tuple_size = template->tuple_size; 355 bi->set_tag_fn = template->set_tag_fn; 356 bi->get_tag_fn = template->get_tag_fn; 357 bi->tag_size = template->tag_size; 358 } else 359 bi->name = "unsupported"; 360 361 return 0; 362 } 363 EXPORT_SYMBOL(blk_integrity_register); 364 365 /** 366 * blk_integrity_unregister - Remove block integrity profile 367 * @disk: disk whose integrity profile to deallocate 368 * 369 * Description: This function frees all memory used by the block 370 * integrity profile. To be called at device teardown. 371 */ 372 void blk_integrity_unregister(struct gendisk *disk) 373 { 374 struct blk_integrity *bi; 375 376 if (!disk || !disk->integrity) 377 return; 378 379 bi = disk->integrity; 380 381 kobject_uevent(&bi->kobj, KOBJ_REMOVE); 382 kobject_del(&bi->kobj); 383 kobject_put(&bi->kobj); 384 kmem_cache_free(integrity_cachep, bi); 385 disk->integrity = NULL; 386 } 387 EXPORT_SYMBOL(blk_integrity_unregister); 388