brintos

brintos / linux-shallow public Read only

0
0
Text · 35.7 KiB · fe8beb7 Raw
1398 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * SCSI Block Commands (SBC) parsing and emulation.4 *5 * (c) Copyright 2002-2013 Datera, Inc.6 *7 * Nicholas A. Bellinger <nab@kernel.org>8 */9 10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/ratelimit.h>13#include <linux/crc-t10dif.h>14#include <linux/t10-pi.h>15#include <linux/unaligned.h>16#include <scsi/scsi_proto.h>17#include <scsi/scsi_tcq.h>18 19#include <target/target_core_base.h>20#include <target/target_core_backend.h>21#include <target/target_core_fabric.h>22 23#include "target_core_internal.h"24#include "target_core_ua.h"25#include "target_core_alua.h"26 27static sense_reason_t28sbc_check_prot(struct se_device *, struct se_cmd *, unsigned char, u32, bool);29static sense_reason_t sbc_execute_unmap(struct se_cmd *cmd);30 31static sense_reason_t32sbc_emulate_readcapacity(struct se_cmd *cmd)33{34	struct se_device *dev = cmd->se_dev;35	unsigned char *cdb = cmd->t_task_cdb;36	unsigned long long blocks_long = dev->transport->get_blocks(dev);37	unsigned char *rbuf;38	unsigned char buf[8];39	u32 blocks;40 41	/*42	 * SBC-2 says:43	 *   If the PMI bit is set to zero and the LOGICAL BLOCK44	 *   ADDRESS field is not set to zero, the device server shall45	 *   terminate the command with CHECK CONDITION status with46	 *   the sense key set to ILLEGAL REQUEST and the additional47	 *   sense code set to INVALID FIELD IN CDB.48	 *49	 * In SBC-3, these fields are obsolete, but some SCSI50	 * compliance tests actually check this, so we might as well51	 * follow SBC-2.52	 */53	if (!(cdb[8] & 1) && !!(cdb[2] | cdb[3] | cdb[4] | cdb[5]))54		return TCM_INVALID_CDB_FIELD;55 56	if (blocks_long >= 0x00000000ffffffff)57		blocks = 0xffffffff;58	else59		blocks = (u32)blocks_long;60 61	put_unaligned_be32(blocks, &buf[0]);62	put_unaligned_be32(dev->dev_attrib.block_size, &buf[4]);63 64	rbuf = transport_kmap_data_sg(cmd);65	if (rbuf) {66		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));67		transport_kunmap_data_sg(cmd);68	}69 70	target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, 8);71	return 0;72}73 74static sense_reason_t75sbc_emulate_readcapacity_16(struct se_cmd *cmd)76{77	struct se_device *dev = cmd->se_dev;78	struct se_session *sess = cmd->se_sess;79	int pi_prot_type = dev->dev_attrib.pi_prot_type;80 81	unsigned char *rbuf;82	unsigned char buf[32];83	unsigned long long blocks = dev->transport->get_blocks(dev);84 85	memset(buf, 0, sizeof(buf));86	put_unaligned_be64(blocks, &buf[0]);87	put_unaligned_be32(dev->dev_attrib.block_size, &buf[8]);88	/*89	 * Set P_TYPE and PROT_EN bits for DIF support90	 */91	if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) {92		/*93		 * Only override a device's pi_prot_type if no T10-PI is94		 * available, and sess_prot_type has been explicitly enabled.95		 */96		if (!pi_prot_type)97			pi_prot_type = sess->sess_prot_type;98 99		if (pi_prot_type)100			buf[12] = (pi_prot_type - 1) << 1 | 0x1;101	}102 103	if (dev->transport->get_lbppbe)104		buf[13] = dev->transport->get_lbppbe(dev) & 0x0f;105 106	if (dev->transport->get_alignment_offset_lbas) {107		u16 lalba = dev->transport->get_alignment_offset_lbas(dev);108 109		put_unaligned_be16(lalba, &buf[14]);110	}111 112	/*113	 * Set Thin Provisioning Enable bit following sbc3r22 in section114	 * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled.115	 */116	if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws) {117		buf[14] |= 0x80;118 119		/*120		 * LBPRZ signifies that zeroes will be read back from an LBA after121		 * an UNMAP or WRITE SAME w/ unmap bit (sbc3r36 5.16.2)122		 */123		if (dev->dev_attrib.unmap_zeroes_data)124			buf[14] |= 0x40;125	}126 127	rbuf = transport_kmap_data_sg(cmd);128	if (rbuf) {129		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));130		transport_kunmap_data_sg(cmd);131	}132 133	target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, 32);134	return 0;135}136 137static sense_reason_t138sbc_emulate_startstop(struct se_cmd *cmd)139{140	unsigned char *cdb = cmd->t_task_cdb;141 142	/*143	 * See sbc3r36 section 5.25144	 * Immediate bit should be set since there is nothing to complete145	 * POWER CONDITION MODIFIER 0h146	 */147	if (!(cdb[1] & 1) || cdb[2] || cdb[3])148		return TCM_INVALID_CDB_FIELD;149 150	/*151	 * See sbc3r36 section 5.25152	 * POWER CONDITION 0h START_VALID - process START and LOEJ153	 */154	if (cdb[4] >> 4 & 0xf)155		return TCM_INVALID_CDB_FIELD;156 157	/*158	 * See sbc3r36 section 5.25159	 * LOEJ 0h - nothing to load or unload160	 * START 1h - we are ready161	 */162	if (!(cdb[4] & 1) || (cdb[4] & 2) || (cdb[4] & 4))163		return TCM_INVALID_CDB_FIELD;164 165	target_complete_cmd(cmd, SAM_STAT_GOOD);166	return 0;167}168 169sector_t sbc_get_write_same_sectors(struct se_cmd *cmd)170{171	u32 num_blocks;172 173	if (cmd->t_task_cdb[0] == WRITE_SAME)174		num_blocks = get_unaligned_be16(&cmd->t_task_cdb[7]);175	else if (cmd->t_task_cdb[0] == WRITE_SAME_16)176		num_blocks = get_unaligned_be32(&cmd->t_task_cdb[10]);177	else /* WRITE_SAME_32 via VARIABLE_LENGTH_CMD */178		num_blocks = get_unaligned_be32(&cmd->t_task_cdb[28]);179 180	/*181	 * Use the explicit range when non zero is supplied, otherwise calculate182	 * the remaining range based on ->get_blocks() - starting LBA.183	 */184	if (num_blocks)185		return num_blocks;186 187	return cmd->se_dev->transport->get_blocks(cmd->se_dev) -188		cmd->t_task_lba + 1;189}190EXPORT_SYMBOL(sbc_get_write_same_sectors);191 192static sense_reason_t193sbc_execute_write_same_unmap(struct se_cmd *cmd)194{195	struct exec_cmd_ops *ops = cmd->protocol_data;196	sector_t nolb = sbc_get_write_same_sectors(cmd);197	sense_reason_t ret;198 199	if (nolb) {200		ret = ops->execute_unmap(cmd, cmd->t_task_lba, nolb);201		if (ret)202			return ret;203	}204 205	target_complete_cmd(cmd, SAM_STAT_GOOD);206	return 0;207}208 209static sense_reason_t210sbc_emulate_noop(struct se_cmd *cmd)211{212	target_complete_cmd(cmd, SAM_STAT_GOOD);213	return 0;214}215 216static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)217{218	return cmd->se_dev->dev_attrib.block_size * sectors;219}220 221static inline u32 transport_get_sectors_6(unsigned char *cdb)222{223	/*224	 * Use 8-bit sector value.  SBC-3 says:225	 *226	 *   A TRANSFER LENGTH field set to zero specifies that 256227	 *   logical blocks shall be written.  Any other value228	 *   specifies the number of logical blocks that shall be229	 *   written.230	 */231	return cdb[4] ? : 256;232}233 234static inline u32 transport_get_sectors_10(unsigned char *cdb)235{236	return get_unaligned_be16(&cdb[7]);237}238 239static inline u32 transport_get_sectors_12(unsigned char *cdb)240{241	return get_unaligned_be32(&cdb[6]);242}243 244static inline u32 transport_get_sectors_16(unsigned char *cdb)245{246	return get_unaligned_be32(&cdb[10]);247}248 249/*250 * Used for VARIABLE_LENGTH_CDB WRITE_32 and READ_32 variants251 */252static inline u32 transport_get_sectors_32(unsigned char *cdb)253{254	return get_unaligned_be32(&cdb[28]);255 256}257 258static inline u32 transport_lba_21(unsigned char *cdb)259{260	return get_unaligned_be24(&cdb[1]) & 0x1fffff;261}262 263static inline u32 transport_lba_32(unsigned char *cdb)264{265	return get_unaligned_be32(&cdb[2]);266}267 268static inline unsigned long long transport_lba_64(unsigned char *cdb)269{270	return get_unaligned_be64(&cdb[2]);271}272 273static sense_reason_t274sbc_setup_write_same(struct se_cmd *cmd, unsigned char flags,275		     struct exec_cmd_ops *ops)276{277	struct se_device *dev = cmd->se_dev;278	sector_t end_lba = dev->transport->get_blocks(dev) + 1;279	unsigned int sectors = sbc_get_write_same_sectors(cmd);280	sense_reason_t ret;281 282	if ((flags & 0x04) || (flags & 0x02)) {283		pr_err("WRITE_SAME PBDATA and LBDATA"284			" bits not supported for Block Discard"285			" Emulation\n");286		return TCM_UNSUPPORTED_SCSI_OPCODE;287	}288	if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) {289		pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: %u\n",290			sectors, cmd->se_dev->dev_attrib.max_write_same_len);291		return TCM_INVALID_CDB_FIELD;292	}293	/*294	 * Sanity check for LBA wrap and request past end of device.295	 */296	if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) ||297	    ((cmd->t_task_lba + sectors) > end_lba)) {298		pr_err("WRITE_SAME exceeds last lba %llu (lba %llu, sectors %u)\n",299		       (unsigned long long)end_lba, cmd->t_task_lba, sectors);300		return TCM_ADDRESS_OUT_OF_RANGE;301	}302 303	/* We always have ANC_SUP == 0 so setting ANCHOR is always an error */304	if (flags & 0x10) {305		pr_warn("WRITE SAME with ANCHOR not supported\n");306		return TCM_INVALID_CDB_FIELD;307	}308 309	if (flags & 0x01) {310		pr_warn("WRITE SAME with NDOB not supported\n");311		return TCM_INVALID_CDB_FIELD;312	}313 314	/*315	 * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting316	 * translated into block discard requests within backend code.317	 */318	if (flags & 0x08) {319		if (!ops->execute_unmap)320			return TCM_UNSUPPORTED_SCSI_OPCODE;321 322		if (!dev->dev_attrib.emulate_tpws) {323			pr_err("Got WRITE_SAME w/ UNMAP=1, but backend device"324			       " has emulate_tpws disabled\n");325			return TCM_UNSUPPORTED_SCSI_OPCODE;326		}327		cmd->execute_cmd = sbc_execute_write_same_unmap;328		return 0;329	}330	if (!ops->execute_write_same)331		return TCM_UNSUPPORTED_SCSI_OPCODE;332 333	ret = sbc_check_prot(dev, cmd, flags >> 5, sectors, true);334	if (ret)335		return ret;336 337	cmd->execute_cmd = ops->execute_write_same;338	return 0;339}340 341static sense_reason_t342sbc_execute_rw(struct se_cmd *cmd)343{344	struct exec_cmd_ops *ops = cmd->protocol_data;345 346	return ops->execute_rw(cmd, cmd->t_data_sg, cmd->t_data_nents,347			       cmd->data_direction);348}349 350static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success,351					     int *post_ret)352{353	struct se_device *dev = cmd->se_dev;354	sense_reason_t ret = TCM_NO_SENSE;355 356	spin_lock_irq(&cmd->t_state_lock);357	if (success) {358		*post_ret = 1;359 360		if (cmd->scsi_status == SAM_STAT_CHECK_CONDITION)361			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;362	}363	spin_unlock_irq(&cmd->t_state_lock);364 365	/*366	 * Unlock ->caw_sem originally obtained during sbc_compare_and_write()367	 * before the original READ I/O submission.368	 */369	up(&dev->caw_sem);370 371	return ret;372}373 374/*375 * compare @cmp_len bytes of @read_sgl with @cmp_sgl. On miscompare, fill376 * @miscmp_off and return TCM_MISCOMPARE_VERIFY.377 */378static sense_reason_t379compare_and_write_do_cmp(struct scatterlist *read_sgl, unsigned int read_nents,380			 struct scatterlist *cmp_sgl, unsigned int cmp_nents,381			 unsigned int cmp_len, unsigned int *miscmp_off)382{383	unsigned char *buf = NULL;384	struct scatterlist *sg;385	sense_reason_t ret;386	unsigned int offset;387	size_t rc;388	int sg_cnt;389 390	buf = kzalloc(cmp_len, GFP_KERNEL);391	if (!buf) {392		ret = TCM_OUT_OF_RESOURCES;393		goto out;394	}395 396	rc = sg_copy_to_buffer(cmp_sgl, cmp_nents, buf, cmp_len);397	if (!rc) {398		pr_err("sg_copy_to_buffer() failed for compare_and_write\n");399		ret = TCM_OUT_OF_RESOURCES;400		goto out;401	}402	/*403	 * Compare SCSI READ payload against verify payload404	 */405	offset = 0;406	ret = TCM_NO_SENSE;407	for_each_sg(read_sgl, sg, read_nents, sg_cnt) {408		unsigned int len = min(sg->length, cmp_len);409		unsigned char *addr = kmap_atomic(sg_page(sg));410 411		if (memcmp(addr, buf + offset, len)) {412			unsigned int i;413 414			for (i = 0; i < len && addr[i] == buf[offset + i]; i++)415				;416			*miscmp_off = offset + i;417			pr_warn("Detected MISCOMPARE at offset %u\n",418				*miscmp_off);419			ret = TCM_MISCOMPARE_VERIFY;420		}421		kunmap_atomic(addr);422		if (ret != TCM_NO_SENSE)423			goto out;424 425		offset += len;426		cmp_len -= len;427		if (!cmp_len)428			break;429	}430	pr_debug("COMPARE AND WRITE read data matches compare data\n");431out:432	kfree(buf);433	return ret;434}435 436static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success,437						 int *post_ret)438{439	struct se_device *dev = cmd->se_dev;440	struct sg_table write_tbl = { };441	struct scatterlist *write_sg;442	struct sg_mapping_iter m;443	unsigned int len;444	unsigned int block_size = dev->dev_attrib.block_size;445	unsigned int compare_len = (cmd->t_task_nolb * block_size);446	unsigned int miscmp_off = 0;447	sense_reason_t ret = TCM_NO_SENSE;448	int i;449 450	if (!success) {451		/*452		 * Handle early failure in transport_generic_request_failure(),453		 * which will not have taken ->caw_sem yet..454		 */455		if (!cmd->t_data_sg || !cmd->t_bidi_data_sg)456			return TCM_NO_SENSE;457 458		/*459		 * The command has been stopped or aborted so460		 * we don't have to perform the write operation.461		 */462		WARN_ON(!(cmd->transport_state &463			(CMD_T_ABORTED | CMD_T_STOP)));464		goto out;465	}466	/*467	 * Handle special case for zero-length COMPARE_AND_WRITE468	 */469	if (!cmd->data_length)470		goto out;471	/*472	 * Immediately exit + release dev->caw_sem if command has already473	 * been failed with a non-zero SCSI status.474	 */475	if (cmd->scsi_status) {476		pr_debug("compare_and_write_callback: non zero scsi_status:"477			" 0x%02x\n", cmd->scsi_status);478		*post_ret = 1;479		if (cmd->scsi_status == SAM_STAT_CHECK_CONDITION)480			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;481		goto out;482	}483 484	ret = compare_and_write_do_cmp(cmd->t_bidi_data_sg,485				       cmd->t_bidi_data_nents,486				       cmd->t_data_sg,487				       cmd->t_data_nents,488				       compare_len,489				       &miscmp_off);490	if (ret == TCM_MISCOMPARE_VERIFY) {491		/*492		 * SBC-4 r15: 5.3 COMPARE AND WRITE command493		 * In the sense data (see 4.18 and SPC-5) the offset from the494		 * start of the Data-Out Buffer to the first byte of data that495		 * was not equal shall be reported in the INFORMATION field.496		 */497		cmd->sense_info = miscmp_off;498		goto out;499	} else if (ret)500		goto out;501 502	if (sg_alloc_table(&write_tbl, cmd->t_data_nents, GFP_KERNEL) < 0) {503		pr_err("Unable to allocate compare_and_write sg\n");504		ret = TCM_OUT_OF_RESOURCES;505		goto out;506	}507	write_sg = write_tbl.sgl;508 509	i = 0;510	len = compare_len;511	sg_miter_start(&m, cmd->t_data_sg, cmd->t_data_nents, SG_MITER_TO_SG);512	/*513	 * Currently assumes NoLB=1 and SGLs are PAGE_SIZE..514	 */515	while (len) {516		sg_miter_next(&m);517 518		if (block_size < PAGE_SIZE) {519			sg_set_page(&write_sg[i], m.page, block_size,520				    m.piter.sg->offset + block_size);521		} else {522			sg_miter_next(&m);523			sg_set_page(&write_sg[i], m.page, block_size,524				    m.piter.sg->offset);525		}526		len -= block_size;527		i++;528	}529	sg_miter_stop(&m);530	/*531	 * Save the original SGL + nents values before updating to new532	 * assignments, to be released in transport_free_pages() ->533	 * transport_reset_sgl_orig()534	 */535	cmd->t_data_sg_orig = cmd->t_data_sg;536	cmd->t_data_sg = write_sg;537	cmd->t_data_nents_orig = cmd->t_data_nents;538	cmd->t_data_nents = 1;539 540	cmd->sam_task_attr = TCM_HEAD_TAG;541	cmd->transport_complete_callback = compare_and_write_post;542	/*543	 * Now reset ->execute_cmd() to the normal sbc_execute_rw() handler544	 * for submitting the adjusted SGL to write instance user-data.545	 */546	cmd->execute_cmd = sbc_execute_rw;547 548	spin_lock_irq(&cmd->t_state_lock);549	cmd->t_state = TRANSPORT_PROCESSING;550	cmd->transport_state |= CMD_T_ACTIVE | CMD_T_SENT;551	spin_unlock_irq(&cmd->t_state_lock);552 553	__target_execute_cmd(cmd, false);554 555	return ret;556 557out:558	/*559	 * In the MISCOMPARE or failure case, unlock ->caw_sem obtained in560	 * sbc_compare_and_write() before the original READ I/O submission.561	 */562	up(&dev->caw_sem);563	sg_free_table(&write_tbl);564	return ret;565}566 567static sense_reason_t568sbc_compare_and_write(struct se_cmd *cmd)569{570	struct exec_cmd_ops *ops = cmd->protocol_data;571	struct se_device *dev = cmd->se_dev;572	sense_reason_t ret;573	int rc;574	/*575	 * Submit the READ first for COMPARE_AND_WRITE to perform the576	 * comparision using SGLs at cmd->t_bidi_data_sg..577	 */578	rc = down_interruptible(&dev->caw_sem);579	if (rc != 0) {580		cmd->transport_complete_callback = NULL;581		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;582	}583	/*584	 * Reset cmd->data_length to individual block_size in order to not585	 * confuse backend drivers that depend on this value matching the586	 * size of the I/O being submitted.587	 */588	cmd->data_length = cmd->t_task_nolb * dev->dev_attrib.block_size;589 590	ret = ops->execute_rw(cmd, cmd->t_bidi_data_sg, cmd->t_bidi_data_nents,591			      DMA_FROM_DEVICE);592	if (ret) {593		cmd->transport_complete_callback = NULL;594		up(&dev->caw_sem);595		return ret;596	}597	/*598	 * Unlock of dev->caw_sem to occur in compare_and_write_callback()599	 * upon MISCOMPARE, or in compare_and_write_done() upon completion600	 * of WRITE instance user-data.601	 */602	return TCM_NO_SENSE;603}604 605static int606sbc_set_prot_op_checks(u8 protect, bool fabric_prot, enum target_prot_type prot_type,607		       bool is_write, struct se_cmd *cmd)608{609	if (is_write) {610		cmd->prot_op = fabric_prot ? TARGET_PROT_DOUT_STRIP :611			       protect ? TARGET_PROT_DOUT_PASS :612			       TARGET_PROT_DOUT_INSERT;613		switch (protect) {614		case 0x0:615		case 0x3:616			cmd->prot_checks = 0;617			break;618		case 0x1:619		case 0x5:620			cmd->prot_checks = TARGET_DIF_CHECK_GUARD;621			if (prot_type == TARGET_DIF_TYPE1_PROT)622				cmd->prot_checks |= TARGET_DIF_CHECK_REFTAG;623			break;624		case 0x2:625			if (prot_type == TARGET_DIF_TYPE1_PROT)626				cmd->prot_checks = TARGET_DIF_CHECK_REFTAG;627			break;628		case 0x4:629			cmd->prot_checks = TARGET_DIF_CHECK_GUARD;630			break;631		default:632			pr_err("Unsupported protect field %d\n", protect);633			return -EINVAL;634		}635	} else {636		cmd->prot_op = fabric_prot ? TARGET_PROT_DIN_INSERT :637			       protect ? TARGET_PROT_DIN_PASS :638			       TARGET_PROT_DIN_STRIP;639		switch (protect) {640		case 0x0:641		case 0x1:642		case 0x5:643			cmd->prot_checks = TARGET_DIF_CHECK_GUARD;644			if (prot_type == TARGET_DIF_TYPE1_PROT)645				cmd->prot_checks |= TARGET_DIF_CHECK_REFTAG;646			break;647		case 0x2:648			if (prot_type == TARGET_DIF_TYPE1_PROT)649				cmd->prot_checks = TARGET_DIF_CHECK_REFTAG;650			break;651		case 0x3:652			cmd->prot_checks = 0;653			break;654		case 0x4:655			cmd->prot_checks = TARGET_DIF_CHECK_GUARD;656			break;657		default:658			pr_err("Unsupported protect field %d\n", protect);659			return -EINVAL;660		}661	}662 663	return 0;664}665 666static sense_reason_t667sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char protect,668	       u32 sectors, bool is_write)669{670	int sp_ops = cmd->se_sess->sup_prot_ops;671	int pi_prot_type = dev->dev_attrib.pi_prot_type;672	bool fabric_prot = false;673 674	if (!cmd->t_prot_sg || !cmd->t_prot_nents) {675		if (unlikely(protect &&676		    !dev->dev_attrib.pi_prot_type && !cmd->se_sess->sess_prot_type)) {677			pr_err("CDB contains protect bit, but device + fabric does"678			       " not advertise PROTECT=1 feature bit\n");679			return TCM_INVALID_CDB_FIELD;680		}681		if (cmd->prot_pto)682			return TCM_NO_SENSE;683	}684 685	switch (dev->dev_attrib.pi_prot_type) {686	case TARGET_DIF_TYPE3_PROT:687		cmd->reftag_seed = 0xffffffff;688		break;689	case TARGET_DIF_TYPE2_PROT:690		if (protect)691			return TCM_INVALID_CDB_FIELD;692 693		cmd->reftag_seed = cmd->t_task_lba;694		break;695	case TARGET_DIF_TYPE1_PROT:696		cmd->reftag_seed = cmd->t_task_lba;697		break;698	case TARGET_DIF_TYPE0_PROT:699		/*700		 * See if the fabric supports T10-PI, and the session has been701		 * configured to allow export PROTECT=1 feature bit with backend702		 * devices that don't support T10-PI.703		 */704		fabric_prot = is_write ?705			      !!(sp_ops & (TARGET_PROT_DOUT_PASS | TARGET_PROT_DOUT_STRIP)) :706			      !!(sp_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DIN_INSERT));707 708		if (fabric_prot && cmd->se_sess->sess_prot_type) {709			pi_prot_type = cmd->se_sess->sess_prot_type;710			break;711		}712		if (!protect)713			return TCM_NO_SENSE;714		fallthrough;715	default:716		pr_err("Unable to determine pi_prot_type for CDB: 0x%02x "717		       "PROTECT: 0x%02x\n", cmd->t_task_cdb[0], protect);718		return TCM_INVALID_CDB_FIELD;719	}720 721	if (sbc_set_prot_op_checks(protect, fabric_prot, pi_prot_type, is_write, cmd))722		return TCM_INVALID_CDB_FIELD;723 724	cmd->prot_type = pi_prot_type;725	cmd->prot_length = dev->prot_length * sectors;726 727	/**728	 * In case protection information exists over the wire729	 * we modify command data length to describe pure data.730	 * The actual transfer length is data length + protection731	 * length732	 **/733	if (protect)734		cmd->data_length = sectors * dev->dev_attrib.block_size;735 736	pr_debug("%s: prot_type=%d, data_length=%d, prot_length=%d "737		 "prot_op=%d prot_checks=%d\n",738		 __func__, cmd->prot_type, cmd->data_length, cmd->prot_length,739		 cmd->prot_op, cmd->prot_checks);740 741	return TCM_NO_SENSE;742}743 744static int745sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)746{747	if (cdb[1] & 0x10) {748		/* see explanation in spc_emulate_modesense */749		if (!target_check_fua(dev)) {750			pr_err("Got CDB: 0x%02x with DPO bit set, but device"751			       " does not advertise support for DPO\n", cdb[0]);752			return -EINVAL;753		}754	}755	if (cdb[1] & 0x8) {756		if (!target_check_fua(dev)) {757			pr_err("Got CDB: 0x%02x with FUA bit set, but device"758			       " does not advertise support for FUA write\n",759			       cdb[0]);760			return -EINVAL;761		}762		cmd->se_cmd_flags |= SCF_FUA;763	}764	return 0;765}766 767sense_reason_t768sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops)769{770	struct se_device *dev = cmd->se_dev;771	unsigned char *cdb = cmd->t_task_cdb;772	unsigned int size;773	u32 sectors = 0;774	sense_reason_t ret;775 776	cmd->protocol_data = ops;777 778	switch (cdb[0]) {779	case READ_6:780		sectors = transport_get_sectors_6(cdb);781		cmd->t_task_lba = transport_lba_21(cdb);782		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;783		cmd->execute_cmd = sbc_execute_rw;784		break;785	case READ_10:786		sectors = transport_get_sectors_10(cdb);787		cmd->t_task_lba = transport_lba_32(cdb);788 789		if (sbc_check_dpofua(dev, cmd, cdb))790			return TCM_INVALID_CDB_FIELD;791 792		ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, false);793		if (ret)794			return ret;795 796		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;797		cmd->execute_cmd = sbc_execute_rw;798		break;799	case READ_12:800		sectors = transport_get_sectors_12(cdb);801		cmd->t_task_lba = transport_lba_32(cdb);802 803		if (sbc_check_dpofua(dev, cmd, cdb))804			return TCM_INVALID_CDB_FIELD;805 806		ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, false);807		if (ret)808			return ret;809 810		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;811		cmd->execute_cmd = sbc_execute_rw;812		break;813	case READ_16:814		sectors = transport_get_sectors_16(cdb);815		cmd->t_task_lba = transport_lba_64(cdb);816 817		if (sbc_check_dpofua(dev, cmd, cdb))818			return TCM_INVALID_CDB_FIELD;819 820		ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, false);821		if (ret)822			return ret;823 824		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;825		cmd->execute_cmd = sbc_execute_rw;826		break;827	case WRITE_6:828		sectors = transport_get_sectors_6(cdb);829		cmd->t_task_lba = transport_lba_21(cdb);830		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;831		cmd->execute_cmd = sbc_execute_rw;832		break;833	case WRITE_10:834	case WRITE_VERIFY:835		sectors = transport_get_sectors_10(cdb);836		cmd->t_task_lba = transport_lba_32(cdb);837 838		if (sbc_check_dpofua(dev, cmd, cdb))839			return TCM_INVALID_CDB_FIELD;840 841		ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, true);842		if (ret)843			return ret;844 845		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;846		cmd->execute_cmd = sbc_execute_rw;847		break;848	case WRITE_12:849		sectors = transport_get_sectors_12(cdb);850		cmd->t_task_lba = transport_lba_32(cdb);851 852		if (sbc_check_dpofua(dev, cmd, cdb))853			return TCM_INVALID_CDB_FIELD;854 855		ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, true);856		if (ret)857			return ret;858 859		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;860		cmd->execute_cmd = sbc_execute_rw;861		break;862	case WRITE_16:863	case WRITE_VERIFY_16:864		sectors = transport_get_sectors_16(cdb);865		cmd->t_task_lba = transport_lba_64(cdb);866 867		if (sbc_check_dpofua(dev, cmd, cdb))868			return TCM_INVALID_CDB_FIELD;869 870		ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, true);871		if (ret)872			return ret;873 874		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;875		cmd->execute_cmd = sbc_execute_rw;876		break;877	case VARIABLE_LENGTH_CMD:878	{879		u16 service_action = get_unaligned_be16(&cdb[8]);880		switch (service_action) {881		case WRITE_SAME_32:882			sectors = transport_get_sectors_32(cdb);883			if (!sectors) {884				pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"885				       " supported\n");886				return TCM_INVALID_CDB_FIELD;887			}888 889			size = sbc_get_size(cmd, 1);890			cmd->t_task_lba = get_unaligned_be64(&cdb[12]);891 892			ret = sbc_setup_write_same(cmd, cdb[10], ops);893			if (ret)894				return ret;895			break;896		default:897			pr_err("VARIABLE_LENGTH_CMD service action"898				" 0x%04x not supported\n", service_action);899			return TCM_UNSUPPORTED_SCSI_OPCODE;900		}901		break;902	}903	case COMPARE_AND_WRITE:904		if (!dev->dev_attrib.emulate_caw) {905			pr_err_ratelimited("se_device %s/%s (vpd_unit_serial %s) reject COMPARE_AND_WRITE\n",906					   dev->se_hba->backend->ops->name,907					   config_item_name(&dev->dev_group.cg_item),908					   dev->t10_wwn.unit_serial);909			return TCM_UNSUPPORTED_SCSI_OPCODE;910		}911		sectors = cdb[13];912		/*913		 * Currently enforce COMPARE_AND_WRITE for a single sector914		 */915		if (sectors > 1) {916			pr_err("COMPARE_AND_WRITE contains NoLB: %u greater"917			       " than 1\n", sectors);918			return TCM_INVALID_CDB_FIELD;919		}920		if (sbc_check_dpofua(dev, cmd, cdb))921			return TCM_INVALID_CDB_FIELD;922 923		/*924		 * Double size because we have two buffers, note that925		 * zero is not an error..926		 */927		size = 2 * sbc_get_size(cmd, sectors);928		cmd->t_task_lba = get_unaligned_be64(&cdb[2]);929		cmd->t_task_nolb = sectors;930		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB | SCF_COMPARE_AND_WRITE;931		cmd->execute_cmd = sbc_compare_and_write;932		cmd->transport_complete_callback = compare_and_write_callback;933		break;934	case READ_CAPACITY:935		size = READ_CAP_LEN;936		cmd->execute_cmd = sbc_emulate_readcapacity;937		break;938	case SERVICE_ACTION_IN_16:939		switch (cmd->t_task_cdb[1] & 0x1f) {940		case SAI_READ_CAPACITY_16:941			cmd->execute_cmd = sbc_emulate_readcapacity_16;942			break;943		case SAI_REPORT_REFERRALS:944			cmd->execute_cmd = target_emulate_report_referrals;945			break;946		default:947			pr_err("Unsupported SA: 0x%02x\n",948				cmd->t_task_cdb[1] & 0x1f);949			return TCM_INVALID_CDB_FIELD;950		}951		size = get_unaligned_be32(&cdb[10]);952		break;953	case SYNCHRONIZE_CACHE:954	case SYNCHRONIZE_CACHE_16:955		if (cdb[0] == SYNCHRONIZE_CACHE) {956			sectors = transport_get_sectors_10(cdb);957			cmd->t_task_lba = transport_lba_32(cdb);958		} else {959			sectors = transport_get_sectors_16(cdb);960			cmd->t_task_lba = transport_lba_64(cdb);961		}962		if (ops->execute_sync_cache) {963			cmd->execute_cmd = ops->execute_sync_cache;964			goto check_lba;965		}966		size = 0;967		cmd->execute_cmd = sbc_emulate_noop;968		break;969	case UNMAP:970		if (!ops->execute_unmap)971			return TCM_UNSUPPORTED_SCSI_OPCODE;972 973		if (!dev->dev_attrib.emulate_tpu) {974			pr_err("Got UNMAP, but backend device has"975			       " emulate_tpu disabled\n");976			return TCM_UNSUPPORTED_SCSI_OPCODE;977		}978		size = get_unaligned_be16(&cdb[7]);979		cmd->execute_cmd = sbc_execute_unmap;980		break;981	case WRITE_SAME_16:982		sectors = transport_get_sectors_16(cdb);983		if (!sectors) {984			pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");985			return TCM_INVALID_CDB_FIELD;986		}987 988		size = sbc_get_size(cmd, 1);989		cmd->t_task_lba = get_unaligned_be64(&cdb[2]);990 991		ret = sbc_setup_write_same(cmd, cdb[1], ops);992		if (ret)993			return ret;994		break;995	case WRITE_SAME:996		sectors = transport_get_sectors_10(cdb);997		if (!sectors) {998			pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");999			return TCM_INVALID_CDB_FIELD;1000		}1001 1002		size = sbc_get_size(cmd, 1);1003		cmd->t_task_lba = get_unaligned_be32(&cdb[2]);1004 1005		/*1006		 * Follow sbcr26 with WRITE_SAME (10) and check for the existence1007		 * of byte 1 bit 3 UNMAP instead of original reserved field1008		 */1009		ret = sbc_setup_write_same(cmd, cdb[1], ops);1010		if (ret)1011			return ret;1012		break;1013	case VERIFY:1014	case VERIFY_16:1015		size = 0;1016		if (cdb[0] == VERIFY) {1017			sectors = transport_get_sectors_10(cdb);1018			cmd->t_task_lba = transport_lba_32(cdb);1019		} else {1020			sectors = transport_get_sectors_16(cdb);1021			cmd->t_task_lba = transport_lba_64(cdb);1022		}1023		cmd->execute_cmd = sbc_emulate_noop;1024		goto check_lba;1025	case REZERO_UNIT:1026	case SEEK_6:1027	case SEEK_10:1028		/*1029		 * There are still clients out there which use these old SCSI-21030		 * commands. This mainly happens when running VMs with legacy1031		 * guest systems, connected via SCSI command pass-through to1032		 * iSCSI targets. Make them happy and return status GOOD.1033		 */1034		size = 0;1035		cmd->execute_cmd = sbc_emulate_noop;1036		break;1037	case START_STOP:1038		size = 0;1039		cmd->execute_cmd = sbc_emulate_startstop;1040		break;1041	default:1042		ret = spc_parse_cdb(cmd, &size);1043		if (ret)1044			return ret;1045	}1046 1047	/* reject any command that we don't have a handler for */1048	if (!cmd->execute_cmd)1049		return TCM_UNSUPPORTED_SCSI_OPCODE;1050 1051	if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {1052		unsigned long long end_lba;1053check_lba:1054		end_lba = dev->transport->get_blocks(dev) + 1;1055		if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) ||1056		    ((cmd->t_task_lba + sectors) > end_lba)) {1057			pr_err("cmd exceeds last lba %llu "1058				"(lba %llu, sectors %u)\n",1059				end_lba, cmd->t_task_lba, sectors);1060			return TCM_ADDRESS_OUT_OF_RANGE;1061		}1062 1063		if (!(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE))1064			size = sbc_get_size(cmd, sectors);1065	}1066 1067	return target_cmd_size_check(cmd, size);1068}1069EXPORT_SYMBOL(sbc_parse_cdb);1070 1071u32 sbc_get_device_type(struct se_device *dev)1072{1073	return TYPE_DISK;1074}1075EXPORT_SYMBOL(sbc_get_device_type);1076 1077static sense_reason_t1078sbc_execute_unmap(struct se_cmd *cmd)1079{1080	struct exec_cmd_ops *ops = cmd->protocol_data;1081	struct se_device *dev = cmd->se_dev;1082	unsigned char *buf, *ptr = NULL;1083	sector_t lba;1084	int size;1085	u32 range;1086	sense_reason_t ret = 0;1087	int dl, bd_dl;1088 1089	/* We never set ANC_SUP */1090	if (cmd->t_task_cdb[1])1091		return TCM_INVALID_CDB_FIELD;1092 1093	if (cmd->data_length == 0) {1094		target_complete_cmd(cmd, SAM_STAT_GOOD);1095		return 0;1096	}1097 1098	if (cmd->data_length < 8) {1099		pr_warn("UNMAP parameter list length %u too small\n",1100			cmd->data_length);1101		return TCM_PARAMETER_LIST_LENGTH_ERROR;1102	}1103 1104	buf = transport_kmap_data_sg(cmd);1105	if (!buf)1106		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;1107 1108	dl = get_unaligned_be16(&buf[0]);1109	bd_dl = get_unaligned_be16(&buf[2]);1110 1111	size = cmd->data_length - 8;1112	if (bd_dl > size)1113		pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n",1114			cmd->data_length, bd_dl);1115	else1116		size = bd_dl;1117 1118	if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) {1119		ret = TCM_INVALID_PARAMETER_LIST;1120		goto err;1121	}1122 1123	/* First UNMAP block descriptor starts at 8 byte offset */1124	ptr = &buf[8];1125	pr_debug("UNMAP: Sub: %s Using dl: %u bd_dl: %u size: %u"1126		" ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr);1127 1128	while (size >= 16) {1129		lba = get_unaligned_be64(&ptr[0]);1130		range = get_unaligned_be32(&ptr[8]);1131		pr_debug("UNMAP: Using lba: %llu and range: %u\n",1132				 (unsigned long long)lba, range);1133 1134		if (range > dev->dev_attrib.max_unmap_lba_count) {1135			ret = TCM_INVALID_PARAMETER_LIST;1136			goto err;1137		}1138 1139		if (lba + range > dev->transport->get_blocks(dev) + 1) {1140			ret = TCM_ADDRESS_OUT_OF_RANGE;1141			goto err;1142		}1143 1144		if (range) {1145			ret = ops->execute_unmap(cmd, lba, range);1146			if (ret)1147				goto err;1148		}1149 1150		ptr += 16;1151		size -= 16;1152	}1153 1154err:1155	transport_kunmap_data_sg(cmd);1156	if (!ret)1157		target_complete_cmd(cmd, SAM_STAT_GOOD);1158	return ret;1159}1160 1161void1162sbc_dif_generate(struct se_cmd *cmd)1163{1164	struct se_device *dev = cmd->se_dev;1165	struct t10_pi_tuple *sdt;1166	struct scatterlist *dsg = cmd->t_data_sg, *psg;1167	sector_t sector = cmd->t_task_lba;1168	void *daddr, *paddr;1169	int i, j, offset = 0;1170	unsigned int block_size = dev->dev_attrib.block_size;1171 1172	for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) {1173		paddr = kmap_atomic(sg_page(psg)) + psg->offset;1174		daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;1175 1176		for (j = 0; j < psg->length;1177				j += sizeof(*sdt)) {1178			__u16 crc;1179			unsigned int avail;1180 1181			if (offset >= dsg->length) {1182				offset -= dsg->length;1183				kunmap_atomic(daddr - dsg->offset);1184				dsg = sg_next(dsg);1185				if (!dsg) {1186					kunmap_atomic(paddr - psg->offset);1187					return;1188				}1189				daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;1190			}1191 1192			sdt = paddr + j;1193			avail = min(block_size, dsg->length - offset);1194			crc = crc_t10dif(daddr + offset, avail);1195			if (avail < block_size) {1196				kunmap_atomic(daddr - dsg->offset);1197				dsg = sg_next(dsg);1198				if (!dsg) {1199					kunmap_atomic(paddr - psg->offset);1200					return;1201				}1202				daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;1203				offset = block_size - avail;1204				crc = crc_t10dif_update(crc, daddr, offset);1205			} else {1206				offset += block_size;1207			}1208 1209			sdt->guard_tag = cpu_to_be16(crc);1210			if (cmd->prot_type == TARGET_DIF_TYPE1_PROT)1211				sdt->ref_tag = cpu_to_be32(sector & 0xffffffff);1212			sdt->app_tag = 0;1213 1214			pr_debug("DIF %s INSERT sector: %llu guard_tag: 0x%04x"1215				 " app_tag: 0x%04x ref_tag: %u\n",1216				 (cmd->data_direction == DMA_TO_DEVICE) ?1217				 "WRITE" : "READ", (unsigned long long)sector,1218				 sdt->guard_tag, sdt->app_tag,1219				 be32_to_cpu(sdt->ref_tag));1220 1221			sector++;1222		}1223 1224		kunmap_atomic(daddr - dsg->offset);1225		kunmap_atomic(paddr - psg->offset);1226	}1227}1228 1229static sense_reason_t1230sbc_dif_v1_verify(struct se_cmd *cmd, struct t10_pi_tuple *sdt,1231		  __u16 crc, sector_t sector, unsigned int ei_lba)1232{1233	__be16 csum;1234 1235	if (!(cmd->prot_checks & TARGET_DIF_CHECK_GUARD))1236		goto check_ref;1237 1238	csum = cpu_to_be16(crc);1239 1240	if (sdt->guard_tag != csum) {1241		pr_err("DIFv1 checksum failed on sector %llu guard tag 0x%04x"1242			" csum 0x%04x\n", (unsigned long long)sector,1243			be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum));1244		return TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED;1245	}1246 1247check_ref:1248	if (!(cmd->prot_checks & TARGET_DIF_CHECK_REFTAG))1249		return 0;1250 1251	if (cmd->prot_type == TARGET_DIF_TYPE1_PROT &&1252	    be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {1253		pr_err("DIFv1 Type 1 reference failed on sector: %llu tag: 0x%08x"1254		       " sector MSB: 0x%08x\n", (unsigned long long)sector,1255		       be32_to_cpu(sdt->ref_tag), (u32)(sector & 0xffffffff));1256		return TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;1257	}1258 1259	if (cmd->prot_type == TARGET_DIF_TYPE2_PROT &&1260	    be32_to_cpu(sdt->ref_tag) != ei_lba) {1261		pr_err("DIFv1 Type 2 reference failed on sector: %llu tag: 0x%08x"1262		       " ei_lba: 0x%08x\n", (unsigned long long)sector,1263			be32_to_cpu(sdt->ref_tag), ei_lba);1264		return TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;1265	}1266 1267	return 0;1268}1269 1270void sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read,1271		       struct scatterlist *sg, int sg_off)1272{1273	struct se_device *dev = cmd->se_dev;1274	struct scatterlist *psg;1275	void *paddr, *addr;1276	unsigned int i, len, left;1277	unsigned int offset = sg_off;1278 1279	if (!sg)1280		return;1281 1282	left = sectors * dev->prot_length;1283 1284	for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) {1285		unsigned int psg_len, copied = 0;1286 1287		paddr = kmap_atomic(sg_page(psg)) + psg->offset;1288		psg_len = min(left, psg->length);1289		while (psg_len) {1290			len = min(psg_len, sg->length - offset);1291			addr = kmap_atomic(sg_page(sg)) + sg->offset + offset;1292 1293			if (read)1294				memcpy(paddr + copied, addr, len);1295			else1296				memcpy(addr, paddr + copied, len);1297 1298			left -= len;1299			offset += len;1300			copied += len;1301			psg_len -= len;1302 1303			kunmap_atomic(addr - sg->offset - offset);1304 1305			if (offset >= sg->length) {1306				sg = sg_next(sg);1307				offset = 0;1308			}1309		}1310		kunmap_atomic(paddr - psg->offset);1311	}1312}1313EXPORT_SYMBOL(sbc_dif_copy_prot);1314 1315sense_reason_t1316sbc_dif_verify(struct se_cmd *cmd, sector_t start, unsigned int sectors,1317	       unsigned int ei_lba, struct scatterlist *psg, int psg_off)1318{1319	struct se_device *dev = cmd->se_dev;1320	struct t10_pi_tuple *sdt;1321	struct scatterlist *dsg = cmd->t_data_sg;1322	sector_t sector = start;1323	void *daddr, *paddr;1324	int i;1325	sense_reason_t rc;1326	int dsg_off = 0;1327	unsigned int block_size = dev->dev_attrib.block_size;1328 1329	for (; psg && sector < start + sectors; psg = sg_next(psg)) {1330		paddr = kmap_atomic(sg_page(psg)) + psg->offset;1331		daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;1332 1333		for (i = psg_off; i < psg->length &&1334				sector < start + sectors;1335				i += sizeof(*sdt)) {1336			__u16 crc;1337			unsigned int avail;1338 1339			if (dsg_off >= dsg->length) {1340				dsg_off -= dsg->length;1341				kunmap_atomic(daddr - dsg->offset);1342				dsg = sg_next(dsg);1343				if (!dsg) {1344					kunmap_atomic(paddr - psg->offset);1345					return 0;1346				}1347				daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;1348			}1349 1350			sdt = paddr + i;1351 1352			pr_debug("DIF READ sector: %llu guard_tag: 0x%04x"1353				 " app_tag: 0x%04x ref_tag: %u\n",1354				 (unsigned long long)sector, sdt->guard_tag,1355				 sdt->app_tag, be32_to_cpu(sdt->ref_tag));1356 1357			if (sdt->app_tag == T10_PI_APP_ESCAPE) {1358				dsg_off += block_size;1359				goto next;1360			}1361 1362			avail = min(block_size, dsg->length - dsg_off);1363			crc = crc_t10dif(daddr + dsg_off, avail);1364			if (avail < block_size) {1365				kunmap_atomic(daddr - dsg->offset);1366				dsg = sg_next(dsg);1367				if (!dsg) {1368					kunmap_atomic(paddr - psg->offset);1369					return 0;1370				}1371				daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;1372				dsg_off = block_size - avail;1373				crc = crc_t10dif_update(crc, daddr, dsg_off);1374			} else {1375				dsg_off += block_size;1376			}1377 1378			rc = sbc_dif_v1_verify(cmd, sdt, crc, sector, ei_lba);1379			if (rc) {1380				kunmap_atomic(daddr - dsg->offset);1381				kunmap_atomic(paddr - psg->offset);1382				cmd->sense_info = sector;1383				return rc;1384			}1385next:1386			sector++;1387			ei_lba++;1388		}1389 1390		psg_off = 0;1391		kunmap_atomic(daddr - dsg->offset);1392		kunmap_atomic(paddr - psg->offset);1393	}1394 1395	return 0;1396}1397EXPORT_SYMBOL(sbc_dif_verify);1398