Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

block: factor out a bio_integrity_action helper

Split the logic to see if a bio needs integrity metadata from
bio_integrity_prep into a reusable helper than can be called from
file system code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Anuj Gupta <anuj20.g@samsung.com>
Reviewed-by: Kanchan Joshi <joshi.k@samsung.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Tested-by: Anuj Gupta <anuj20.g@samsung.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Christoph Hellwig and committed by
Jens Axboe
7ea25eaa 6de23f81

+89 -63
+8 -56
block/bio-integrity-auto.c
··· 50 50 return bip->bip_flags & BIP_CHECK_FLAGS; 51 51 } 52 52 53 - static bool bi_offload_capable(struct blk_integrity *bi) 54 - { 55 - return bi->metadata_size == bi->pi_tuple_size; 56 - } 57 - 58 53 /** 59 54 * __bio_integrity_endio - Integrity I/O completion function 60 55 * @bio: Protected bio ··· 79 84 /** 80 85 * bio_integrity_prep - Prepare bio for integrity I/O 81 86 * @bio: bio to prepare 87 + * @action: preparation action needed (BI_ACT_*) 82 88 * 83 - * Checks if the bio already has an integrity payload attached. If it does, the 84 - * payload has been generated by another kernel subsystem, and we just pass it 85 - * through. 86 - * Otherwise allocates integrity payload and for writes the integrity metadata 87 - * will be generated. For reads, the completion handler will verify the 88 - * metadata. 89 + * Allocate the integrity payload. For writes, generate the integrity metadata 90 + * and for reads, setup the completion handler to verify the metadata. 91 + * 92 + * This is used for bios that do not have user integrity payloads attached. 89 93 */ 90 - bool bio_integrity_prep(struct bio *bio) 94 + void bio_integrity_prep(struct bio *bio, unsigned int action) 91 95 { 92 96 struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); 93 97 struct bio_integrity_data *bid; 94 - bool set_flags = true; 95 - gfp_t gfp = GFP_NOIO; 96 - 97 - if (!bi) 98 - return true; 99 - 100 - if (!bio_sectors(bio)) 101 - return true; 102 - 103 - /* Already protected? */ 104 - if (bio_integrity(bio)) 105 - return true; 106 - 107 - switch (bio_op(bio)) { 108 - case REQ_OP_READ: 109 - if (bi->flags & BLK_INTEGRITY_NOVERIFY) { 110 - if (bi_offload_capable(bi)) 111 - return true; 112 - set_flags = false; 113 - } 114 - break; 115 - case REQ_OP_WRITE: 116 - /* 117 - * Zero the memory allocated to not leak uninitialized kernel 118 - * memory to disk for non-integrity metadata where nothing else 119 - * initializes the memory. 120 - */ 121 - if (bi->flags & BLK_INTEGRITY_NOGENERATE) { 122 - if (bi_offload_capable(bi)) 123 - return true; 124 - set_flags = false; 125 - gfp |= __GFP_ZERO; 126 - } else if (bi->metadata_size > bi->pi_tuple_size) 127 - gfp |= __GFP_ZERO; 128 - break; 129 - default: 130 - return true; 131 - } 132 - 133 - if (WARN_ON_ONCE(bio_has_crypt_ctx(bio))) 134 - return true; 135 98 136 99 bid = mempool_alloc(&bid_pool, GFP_NOIO); 137 100 bio_integrity_init(bio, &bid->bip, &bid->bvec, 1); 138 101 bid->bio = bio; 139 102 bid->bip.bip_flags |= BIP_BLOCK_INTEGRITY; 140 - bio_integrity_alloc_buf(bio, gfp & __GFP_ZERO); 103 + bio_integrity_alloc_buf(bio, action & BI_ACT_ZERO); 141 104 142 105 bip_set_seed(&bid->bip, bio->bi_iter.bi_sector); 143 106 144 - if (set_flags) { 107 + if (action & BI_ACT_CHECK) { 145 108 if (bi->csum_type == BLK_INTEGRITY_CSUM_IP) 146 109 bid->bip.bip_flags |= BIP_IP_CHECKSUM; 147 110 if (bi->csum_type) ··· 113 160 blk_integrity_generate(bio); 114 161 else 115 162 bid->saved_bio_iter = bio->bi_iter; 116 - return true; 117 163 } 118 164 EXPORT_SYMBOL(bio_integrity_prep); 119 165
+48
block/bio-integrity.c
··· 7 7 */ 8 8 9 9 #include <linux/blk-integrity.h> 10 + #include <linux/t10-pi.h> 10 11 #include "blk.h" 11 12 12 13 struct bio_integrity_alloc { ··· 16 15 }; 17 16 18 17 static mempool_t integrity_buf_pool; 18 + 19 + static bool bi_offload_capable(struct blk_integrity *bi) 20 + { 21 + return bi->metadata_size == bi->pi_tuple_size; 22 + } 23 + 24 + unsigned int __bio_integrity_action(struct bio *bio) 25 + { 26 + struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); 27 + 28 + if (WARN_ON_ONCE(bio_has_crypt_ctx(bio))) 29 + return 0; 30 + 31 + switch (bio_op(bio)) { 32 + case REQ_OP_READ: 33 + if (bi->flags & BLK_INTEGRITY_NOVERIFY) { 34 + if (bi_offload_capable(bi)) 35 + return 0; 36 + return BI_ACT_BUFFER; 37 + } 38 + return BI_ACT_BUFFER | BI_ACT_CHECK; 39 + case REQ_OP_WRITE: 40 + /* 41 + * Flush masquerading as write? 42 + */ 43 + if (!bio_sectors(bio)) 44 + return 0; 45 + 46 + /* 47 + * Zero the memory allocated to not leak uninitialized kernel 48 + * memory to disk for non-integrity metadata where nothing else 49 + * initializes the memory. 50 + */ 51 + if (bi->flags & BLK_INTEGRITY_NOGENERATE) { 52 + if (bi_offload_capable(bi)) 53 + return 0; 54 + return BI_ACT_BUFFER | BI_ACT_ZERO; 55 + } 56 + 57 + if (bi->metadata_size > bi->pi_tuple_size) 58 + return BI_ACT_BUFFER | BI_ACT_CHECK | BI_ACT_ZERO; 59 + return BI_ACT_BUFFER | BI_ACT_CHECK; 60 + default: 61 + return 0; 62 + } 63 + } 64 + EXPORT_SYMBOL_GPL(__bio_integrity_action); 19 65 20 66 void bio_integrity_alloc_buf(struct bio *bio, bool zero_buffer) 21 67 {
+4 -2
block/blk-mq.c
··· 3143 3143 struct request_queue *q = bdev_get_queue(bio->bi_bdev); 3144 3144 struct blk_plug *plug = current->plug; 3145 3145 const int is_sync = op_is_sync(bio->bi_opf); 3146 + unsigned int integrity_action; 3146 3147 struct blk_mq_hw_ctx *hctx; 3147 3148 unsigned int nr_segs; 3148 3149 struct request *rq; ··· 3196 3195 if (!bio) 3197 3196 goto queue_exit; 3198 3197 3199 - if (!bio_integrity_prep(bio)) 3200 - goto queue_exit; 3198 + integrity_action = bio_integrity_action(bio); 3199 + if (integrity_action) 3200 + bio_integrity_prep(bio, integrity_action); 3201 3201 3202 3202 blk_mq_bio_issue_init(q, bio); 3203 3203 if (blk_mq_attempt_bio_merge(q, bio, nr_segs))
+4 -2
drivers/nvdimm/btt.c
··· 1435 1435 { 1436 1436 struct bio_integrity_payload *bip = bio_integrity(bio); 1437 1437 struct btt *btt = bio->bi_bdev->bd_disk->private_data; 1438 + unsigned int integrity_action; 1438 1439 struct bvec_iter iter; 1439 1440 unsigned long start; 1440 1441 struct bio_vec bvec; 1441 1442 int err = 0; 1442 1443 bool do_acct; 1443 1444 1444 - if (!bio_integrity_prep(bio)) 1445 - return; 1445 + integrity_action = bio_integrity_action(bio); 1446 + if (integrity_action) 1447 + bio_integrity_prep(bio, integrity_action); 1446 1448 1447 1449 do_acct = blk_queue_io_stat(bio->bi_bdev->bd_disk->queue); 1448 1450 if (do_acct)
+2 -3
include/linux/bio-integrity.h
··· 78 78 int bio_integrity_map_user(struct bio *bio, struct iov_iter *iter); 79 79 int bio_integrity_map_iter(struct bio *bio, struct uio_meta *meta); 80 80 void bio_integrity_unmap_user(struct bio *bio); 81 - bool bio_integrity_prep(struct bio *bio); 81 + void bio_integrity_prep(struct bio *bio, unsigned int action); 82 82 void bio_integrity_advance(struct bio *bio, unsigned int bytes_done); 83 83 void bio_integrity_trim(struct bio *bio); 84 84 int bio_integrity_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp_mask); ··· 104 104 { 105 105 } 106 106 107 - static inline bool bio_integrity_prep(struct bio *bio) 107 + static inline void bio_integrity_prep(struct bio *bio, unsigned int action) 108 108 { 109 - return true; 110 109 } 111 110 112 111 static inline int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
+23
include/linux/blk-integrity.h
··· 180 180 } 181 181 #endif /* CONFIG_BLK_DEV_INTEGRITY */ 182 182 183 + enum bio_integrity_action { 184 + BI_ACT_BUFFER = (1u << 0), /* allocate buffer */ 185 + BI_ACT_CHECK = (1u << 1), /* generate / verify PI */ 186 + BI_ACT_ZERO = (1u << 2), /* zero buffer */ 187 + }; 188 + 189 + /** 190 + * bio_integrity_action - return the integrity action needed for a bio 191 + * @bio: bio to operate on 192 + * 193 + * Returns the mask of integrity actions (BI_ACT_*) that need to be performed 194 + * for @bio. 195 + */ 196 + unsigned int __bio_integrity_action(struct bio *bio); 197 + static inline unsigned int bio_integrity_action(struct bio *bio) 198 + { 199 + if (!blk_get_integrity(bio->bi_bdev->bd_disk)) 200 + return 0; 201 + if (bio_integrity(bio)) 202 + return 0; 203 + return __bio_integrity_action(bio); 204 + } 205 + 183 206 #endif /* _LINUX_BLK_INTEGRITY_H */