diff options
Diffstat (limited to 'block/bio-integrity.c')
| -rw-r--r-- | block/bio-integrity.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/block/bio-integrity.c b/block/bio-integrity.c index 20f5d301d32d..0955be90038b 100644 --- a/block/bio-integrity.c +++ b/block/bio-integrity.c @@ -7,6 +7,7 @@ */ #include <linux/blk-integrity.h> +#include <linux/t10-pi.h> #include "blk.h" struct bio_integrity_alloc { @@ -16,6 +17,53 @@ struct bio_integrity_alloc { static mempool_t integrity_buf_pool; +static bool bi_offload_capable(struct blk_integrity *bi) +{ + return bi->metadata_size == bi->pi_tuple_size; +} + +unsigned int __bio_integrity_action(struct bio *bio) +{ + struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); + + if (WARN_ON_ONCE(bio_has_crypt_ctx(bio))) + return 0; + + switch (bio_op(bio)) { + case REQ_OP_READ: + if (bi->flags & BLK_INTEGRITY_NOVERIFY) { + if (bi_offload_capable(bi)) + return 0; + return BI_ACT_BUFFER; + } + return BI_ACT_BUFFER | BI_ACT_CHECK; + case REQ_OP_WRITE: + /* + * Flush masquerading as write? + */ + if (!bio_sectors(bio)) + return 0; + + /* + * Zero the memory allocated to not leak uninitialized kernel + * memory to disk for non-integrity metadata where nothing else + * initializes the memory. + */ + if (bi->flags & BLK_INTEGRITY_NOGENERATE) { + if (bi_offload_capable(bi)) + return 0; + return BI_ACT_BUFFER | BI_ACT_ZERO; + } + + if (bi->metadata_size > bi->pi_tuple_size) + return BI_ACT_BUFFER | BI_ACT_CHECK | BI_ACT_ZERO; + return BI_ACT_BUFFER | BI_ACT_CHECK; + default: + return 0; + } +} +EXPORT_SYMBOL_GPL(__bio_integrity_action); + void bio_integrity_alloc_buf(struct bio *bio, bool zero_buffer) { struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); |
