Add support for sending user-meta buffer. Set tags to be checked using flags specified by user/block-layer user and underlying DIF/DIX configuration. Introduce BLK_INTEGRITY_APP_TAG to specify apptag. This provides a way for upper layers to specify apptag checking. Signed-off-by: Anuj Gupta <anuj20.g@xxxxxxxxxxx> --- block/bio-integrity.c | 2 ++ drivers/scsi/sd.c | 25 +++++++++++++++++++++++-- drivers/scsi/sd_dif.c | 2 +- include/linux/blk-integrity.h | 1 + 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/block/bio-integrity.c b/block/bio-integrity.c index 02b766c2e57d..ff7de4fe74c4 100644 --- a/block/bio-integrity.c +++ b/block/bio-integrity.c @@ -492,6 +492,8 @@ bool bio_integrity_prep(struct bio *bio) bip->bip_flags |= BIP_CHECK_GUARD; if (bi->flags & BLK_INTEGRITY_REF_TAG) bip->bip_flags |= BIP_CHECK_REFTAG; + if (bi->flags & BLK_INTEGRITY_APP_TAG) + bip->bip_flags |= BIP_CHECK_APPTAG; if (bio_integrity_add_page(bio, virt_to_page(buf), len, offset_in_page(buf)) < len) { printk(KERN_ERR "could not attach integrity payload\n"); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 699f4f9674d9..6ebef140cec2 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -803,6 +803,23 @@ static unsigned int sd_prot_flag_mask(unsigned int prot_op) return flag_mask[prot_op]; } +/* + * Can't check reftag alone or apptag alone + */ +static bool sd_prot_flags_valid(struct scsi_cmnd *scmd) +{ + struct request *rq = scsi_cmd_to_rq(scmd); + struct bio *bio = rq->bio; + + if (bio_integrity_flagged(bio, BIP_CHECK_REFTAG) && + !bio_integrity_flagged(bio, BIP_CHECK_APPTAG)) + return false; + if (!bio_integrity_flagged(bio, BIP_CHECK_REFTAG) && + bio_integrity_flagged(bio, BIP_CHECK_APPTAG)) + return false; + return true; +} + static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd, unsigned int dix, unsigned int dif) { @@ -815,14 +832,16 @@ static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd, if (bio_integrity_flagged(bio, BIP_IP_CHECKSUM)) scmd->prot_flags |= SCSI_PROT_IP_CHECKSUM; - if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false) + if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false && + (bio_integrity_flagged(bio, BIP_CHECK_GUARD))) scmd->prot_flags |= SCSI_PROT_GUARD_CHECK; } if (dif != T10_PI_TYPE3_PROTECTION) { /* DIX/DIF Type 0, 1, 2 */ scmd->prot_flags |= SCSI_PROT_REF_INCREMENT; - if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false) + if ((bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false) && + (!dix || bio_integrity_flagged(bio, BIP_CHECK_REFTAG))) scmd->prot_flags |= SCSI_PROT_REF_CHECK; } @@ -1374,6 +1393,8 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) dif = scsi_host_dif_capable(cmd->device->host, sdkp->protection_type); dld = sd_cdl_dld(sdkp, cmd); + if (!sd_prot_flags_valid(cmd)) + goto fail; if (dif || dix) protect = sd_setup_protect_cmnd(cmd, dix, dif); else diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c index ae6ce6f5d622..6c53e3b9d7d7 100644 --- a/drivers/scsi/sd_dif.c +++ b/drivers/scsi/sd_dif.c @@ -50,7 +50,7 @@ void sd_dif_config_host(struct scsi_disk *sdkp, struct queue_limits *lim) bi->csum_type = BLK_INTEGRITY_CSUM_CRC; if (type != T10_PI_TYPE3_PROTECTION) - bi->flags |= BLK_INTEGRITY_REF_TAG; + bi->flags |= BLK_INTEGRITY_REF_TAG | BLK_INTEGRITY_APP_TAG; bi->tuple_size = sizeof(struct t10_pi_tuple); diff --git a/include/linux/blk-integrity.h b/include/linux/blk-integrity.h index 2ff65c933c50..865e0c4a7255 100644 --- a/include/linux/blk-integrity.h +++ b/include/linux/blk-integrity.h @@ -13,6 +13,7 @@ enum blk_integrity_flags { BLK_INTEGRITY_DEVICE_CAPABLE = 1 << 2, BLK_INTEGRITY_REF_TAG = 1 << 3, BLK_INTEGRITY_STACKED = 1 << 4, + BLK_INTEGRITY_APP_TAG = 1 << 5, }; const char *blk_integrity_profile_name(struct blk_integrity *bi); -- 2.25.1