blk-integrity.c 12 KB

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