Re: [PATCH] target: pass sense_reason as a return value

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2012-10-30 at 11:07 -0400, Christoph Hellwig wrote:
> Pass the sense reason as an explicit return value from the I/O submission
> path instead of storing it in struct se_cmd and using negative return
> values.  This cleans up a lot of the code pathes, and with the sparse
> annotations for the new sense_reason_t type allows for much better
> error checking.
> 
> Signed-off-by: Christoph Hellwig <hch@xxxxxx>
> 

Hey Christoph,

Just getting back to this for-3.8 code..  Comments below.

> ---
>  drivers/infiniband/ulp/srpt/ib_srpt.c    |   43 -
>  drivers/scsi/qla2xxx/tcm_qla2xxx.c       |    4 
>  drivers/target/iscsi/iscsi_target.c      |   80 --
>  drivers/target/iscsi/iscsi_target_core.h |    2 
>  drivers/target/iscsi/iscsi_target_erl1.c |   11 
>  drivers/target/target_core_alua.c        |   98 +--
>  drivers/target/target_core_alua.h        |    6 
>  drivers/target/target_core_device.c      |   31 -
>  drivers/target/target_core_file.c        |   22 
>  drivers/target/target_core_iblock.c      |   55 -
>  drivers/target/target_core_internal.h    |    2 
>  drivers/target/target_core_pr.c          |  918 +++++++++++++------------------
>  drivers/target/target_core_pr.h          |   10 
>  drivers/target/target_core_pscsi.c       |   51 -
>  drivers/target/target_core_rd.c          |   10 
>  drivers/target/target_core_sbc.c         |   87 +-
>  drivers/target/target_core_spc.c         |  106 +--
>  drivers/target/target_core_transport.c   |  252 +++-----
>  drivers/target/target_core_ua.c          |   11 
>  drivers/target/target_core_ua.h          |    2 
>  drivers/vhost/tcm_vhost.c                |    4 
>  include/target/target_core_backend.h     |   16 
>  include/target/target_core_base.h        |   46 -
>  include/target/target_core_fabric.h      |   13 
>  24 files changed, 833 insertions(+), 1047 deletions(-)
> 

Btw, any chance to sync up the git stat output for future patches..?

That would make things easier to read + review.  ;)

<SNIP>

>  
> -static int iblock_execute_unmap(struct se_cmd *cmd)
> +static sense_reason_t
> +iblock_execute_unmap(struct se_cmd *cmd)
>  {
>  	struct se_device *dev = cmd->se_dev;
>  	struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
> @@ -307,17 +306,18 @@ static int iblock_execute_unmap(struct s
>  	sector_t lba;
>  	int size;
>  	u32 range;
> -	int ret = 0;
> -	int dl, bd_dl;
> +	sense_reason_t ret = 0;
> +	int dl, bd_dl, err;
>  
>  	if (cmd->data_length < 8) {commit 14150a6bb
>  		pr_warn("UNMAP parameter list length %u too small\n",
>  			cmd->data_length);
> -		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
> -		return -EINVAL;
> +		return TCM_INVALID_PARAMETER_LIST;
>  	}
>  
>  	buf = transport_kmap_data_sg(cmd);
> +	if (!buf)
> +		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
>  

Checking the return value here of transport_kmap_data_sg() looks like a
separate bugfix that needs to go-to stable as well, yes..?

> @@ -1052,24 +1053,21 @@ static int pscsi_execute_cmd(struct se_c
>  		if (!req || IS_ERR(req)) {
>  			pr_err("PSCSI: blk_get_request() failed: %ld\n",
>  					req ? IS_ERR(req) : -ENOMEM);
> -			cmd->scsi_sense_reason =
> -				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> +			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
>  			goto fail;
>  		}
>  	} else {
>  		BUG_ON(!cmd->data_length);
>  
>  		ret = pscsi_map_sg(cmd, sgl, sgl_nents, data_direction, &hbio);
> -		if (ret < 0) {
> -			cmd->scsi_sense_reason =
> -				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> +		if (ret)
>  			goto fail;
> -		}
>  
>  		req = blk_make_request(pdv->pdv_sd->request_queue, hbio,
>  				       GFP_KERNEL);
>  		if (IS_ERR(req)) {
>  			pr_err("pSCSI: blk_make_request() failed\n");
> +			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
>  			goto fail_free_bio;
>  		}
>  	}
> @@ -1100,10 +1098,10 @@ fail_free_bio:
>  		bio->bi_next = NULL;
>  		bio_endio(bio, 0);	/* XXX: should be error */
>  	}
> -	cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> +	ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
>  fail:
>  	kfree(pt);
> -	return -ENOMEM;
> +	return ret;
>  }
>  
>  /*	pscsi_get_device_type():
> @@ -1152,7 +1150,6 @@ static void pscsi_req_done(struct reques
>  		pr_debug("PSCSI Host Byte exception at cmd: %p CDB:"
>  			" 0x%02x Result: 0x%08x\n", cmd, pt->pscsi_cdb[0],
>  			pt->pscsi_result);
> -		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
>  		target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
>  		break;
>  	}

Mmmm, this special case results in a completion of an pSCSI
CHECK_CONDITION w/o a sense reason, as TCM_UNSUPPORTED_SCSI_OPCODE.

Changing this to use transport_generic_request_failure() directly, and
including a separate incremental patch for this..

> Index: lio-core/drivers/target/target_core_sbc.c
> ===================================================================
> --- lio-core.orig/drivers/target/target_core_sbc.c	2012-10-30 14:14:53.593253429 +0100
> +++ lio-core/drivers/target/target_core_sbc.c	2012-10-30 14:15:09.893253330 +0100
> @@ -37,7 +37,8 @@
>  #include "target_core_ua.h"
>  
> 
> -static int sbc_emulate_readcapacity(struct se_cmd *cmd)
> +static sense_reason_t
> +sbc_emulate_readcapacity(struct se_cmd *cmd)
>  {
>  	struct se_device *dev = cmd->se_dev;
>  	unsigned long long blocks_long = dev->transport->get_blocks(dev);
> @@ -60,16 +61,18 @@ static int sbc_emulate_readcapacity(stru
>  	buf[7] = dev->dev_attrib.block_size & 0xff;
>  
>  	rbuf = transport_kmap_data_sg(cmd);
> -	if (rbuf) {
> -		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
> -		transport_kunmap_data_sg(cmd);
> -	}
> +	if (!rbuf)
> +		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> +
> +	memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
> +	transport_kunmap_data_sg(cmd);
>  
>  	target_complete_cmd(cmd, GOOD);
>  	return 0;
>  }
>  

The proper handling of transport_kmap_data_sg() needs to be sent to
stable as well.  (Paolo CC'ed)

> -static int sbc_emulate_readcapacity_16(struct se_cmd *cmd)
> +static sense_reason_t
> +sbc_emulate_readcapacity_16(struct se_cmd *cmd)
>  {
>  	struct se_device *dev = cmd->se_dev;
>  	unsigned char *rbuf;
> @@ -97,10 +100,11 @@ static int sbc_emulate_readcapacity_16(s
>  		buf[14] = 0x80;
>  
>  	rbuf = transport_kmap_data_sg(cmd);
> -	if (rbuf) {
> -		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
> -		transport_kunmap_data_sg(cmd);
> -	}
> +	if (!rbuf)
> +		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> +
> +	memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
> +	transport_kunmap_data_sg(cmd);
>  
>  	target_complete_cmd(cmd, GOOD);
>  	return 0;

Ditto here..

<SNIP>

> +sense_reason_t
> +target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb)
>  {
>  	struct se_device *dev = cmd->se_dev;
>  	unsigned long flags;
> -	int ret;
> +	sense_reason_t ret;
>  
>  	/*
>  	 * Ensure that the received CDB is less than the max (252 + 8) bytes
> @@ -1113,9 +1106,7 @@ int target_setup_cmd_from_cdb(
>  		pr_err("Received SCSI CDB with command_size: %d that"
>  			" exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n",
>  			scsi_command_size(cdb), SCSI_MAX_VARLEN_CDB_SIZE);
> -		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
> -		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
> -		return -EINVAL;
> +		return TCM_INVALID_CDB_FIELD;
>  	}
>  	/*
>  	 * If the received CDB is larger than TCM_MAX_COMMAND_SIZE,
> @@ -1130,10 +1121,7 @@ int target_setup_cmd_from_cdb(
>  				" %u > sizeof(cmd->__t_task_cdb): %lu ops\n",
>  				scsi_command_size(cdb),
>  				(unsigned long)sizeof(cmd->__t_task_cdb));
> -			cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
> -			cmd->scsi_sense_reason =
> -					TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> -			return -ENOMEM;
> +			return TCM_OUT_OF_RESOURCES;
>  		}
>  	} else
>  		cmd->t_task_cdb = &cmd->__t_task_cdb[0];
> @@ -1145,50 +1133,30 @@ int target_setup_cmd_from_cdb(
>  	/*
>  	 * Check for an existing UNIT ATTENTION condition
>  	 */
> -	if (core_scsi3_ua_check(cmd, cdb) < 0) {
> -		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
> -		cmd->scsi_sense_reason = TCM_CHECK_CONDITION_UNIT_ATTENTION;
> -		return -EINVAL;
> -	}
> +	ret = target_scsi3_ua_check(cmd);
> +	if (ret)
> +		return ret;
>  
>  	ret = target_alua_state_check(cmd);
> -	if (ret) {
> -		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
> -		if (ret > 0)
> -			cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY;
> -		else
> -			cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
> -		return -EINVAL;
> -	}
> +	if (ret)
> +		return ret;
>  
> -	/*
> -	 * Check status for SPC-3 Persistent Reservations
> -	 */
>  	ret = target_check_reservation(cmd);
> -	if (ret) {
> -		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
> -		cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT;
> -		cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
> -		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
> +	if (ret)
>  		return ret;
> -	}
>  
>  	ret = dev->transport->parse_cdb(cmd);
> -	if (ret < 0)
> +	if (ret)
> +		return ret;
> +
> +	ret = transport_check_alloc_task_attr(cmd);
> +	if (ret)
>  		return ret;
>  

Nice work to get these all cleaned up in target_setup_cmd_from_cdb()

>  	spin_lock_irqsave(&cmd->t_state_lock, flags);
>  	cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE;
>  	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
>  
> -	/*
> -	 * Check for SAM Task Attribute Emulation
> -	 */
> -	if (transport_check_alloc_task_attr(cmd) < 0) {
> -		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
> -		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
> -		return -EINVAL;
> -	}
>  	spin_lock(&cmd->se_lun->lun_sep_lock);
>  	if (cmd->se_lun->lun_sep)
>  		cmd->se_lun->lun_sep->sep_stats.cmd_pdus++;

<SNIP>

>  /*
>   * target_submit_cmd_map_sgls - lookup unpacked lun and submit uninitialized
>   * 			 se_cmd + use pre-allocated SGL memory.
> @@ -1273,7 +1269,8 @@ int target_submit_cmd_map_sgls(struct se
>  		struct scatterlist *sgl_bidi, u32 sgl_bidi_count)
>  {
>  	struct se_portal_group *se_tpg;
> -	int rc;
> +	sense_reason_t rc;
> +	int ret;
>  
>  	se_tpg = se_sess->se_tpg;
>  	BUG_ON(!se_tpg);
> @@ -1294,9 +1291,9 @@ int target_submit_cmd_map_sgls(struct se
>  	 * for fabrics using TARGET_SCF_ACK_KREF that expect a second
>  	 * kref_put() to happen during fabric packet acknowledgement.
>  	 */
> -	rc = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
> -	if (rc)
> -		return rc;
> +	ret = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
> +	if (ret)
> +		return ret;
>  	/*
>  	 * Signal bidirectional data payloads to target-core
>  	 */
> @@ -1305,16 +1302,16 @@ int target_submit_cmd_map_sgls(struct se
>  	/*
>  	 * Locate se_lun pointer and attach it to struct se_cmd
>  	 */
> -	if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) {
> -		transport_send_check_condition_and_sense(se_cmd,
> -				se_cmd->scsi_sense_reason, 0);
> +	rc = transport_lookup_cmd_lun(se_cmd, unpacked_lun);
> +	if (rc) {
> +		transport_send_check_condition_and_sense(se_cmd, rc, 0);
>  		target_put_sess_cmd(se_sess, se_cmd);
>  		return 0;
>  	}
>  
>  	rc = target_setup_cmd_from_cdb(se_cmd, cdb);
>  	if (rc != 0) {
> -		transport_generic_request_failure(se_cmd);
> +		transport_generic_request_failure(se_cmd, rc);
>  		return 0;
>  	}
>  	/*
> @@ -1349,7 +1346,7 @@ int target_submit_cmd_map_sgls(struct se
>  		rc = transport_generic_map_mem_to_cmd(se_cmd, sgl, sgl_count,
>  				sgl_bidi, sgl_bidi_count);
>  		if (rc != 0) {
> -			transport_generic_request_failure(se_cmd);
> +			transport_generic_request_failure(se_cmd, rc);
>  			return 0;
>  		}
>  	}

So these changes look clean enough for main target_submit_cmd() I/O
path.

> @@ -2136,7 +2085,8 @@ out:
>   * might not have the payload yet, so notify the fabric via a call to
>   * ->write_pending instead. Otherwise place it on the execution queue.
>   */
> -int transport_generic_new_cmd(struct se_cmd *cmd)
> +sense_reason_t
> +transport_generic_new_cmd(struct se_cmd *cmd)
>  {
>  	int ret = 0;
>  
> @@ -2149,7 +2099,7 @@ int transport_generic_new_cmd(struct se_
>  	    cmd->data_length) {
>  		ret = transport_generic_get_mem(cmd);
>  		if (ret < 0)
> -			goto out_fail;
> +			return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
>  	}
>  
>  	atomic_inc(&cmd->t_fe_count);
> @@ -2175,14 +2125,11 @@ int transport_generic_new_cmd(struct se_
>  	if (ret == -EAGAIN || ret == -ENOMEM)
>  		goto queue_full;
>  
> -	if (ret < 0)
> -		return ret;
> -	return 1;
> +	/* fabric drivers should only return -EAGAIN or -ENOMEM as error */
> +	WARN_ON(ret);
> +
> +	return 0;
>  

Returning zero here for a failed WRITE_PENDING is definitely incorrect,
and would end up causing bad things to happen.  (Roland CC'ed)

Sending out a separate incremental patch to address this one.

> -out_fail:
> -	cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
> -	cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> -	return -EINVAL;
>  queue_full:
>  	pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
>  	cmd->t_state = TRANSPORT_COMPLETE_QF_WP;
> @@ -2626,10 +2573,9 @@ static int transport_get_sense_codes(
>  	return 0;
>  }

<SNIP>


> -static int spc_emulate_modesense(struct se_cmd *cmd)
> +static sense_reason_t
> +spc_emulate_modesense(struct se_cmd *cmd)
>  {
>  	struct se_device *dev = cmd->se_dev;
>  	char *cdb = cmd->t_task_cdb;
> @@ -798,8 +809,7 @@ static int spc_emulate_modesense(struct
>  	default:
>  		pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n",
>  		       cdb[2] & 0x3f, cdb[3]);
> -		cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE;
> -		return -EINVAL;
> +		return TCM_UNKNOWN_MODE_PAGE;
>  	}
>  	offset += length;
>  
> @@ -833,16 +843,18 @@ static int spc_emulate_modesense(struct
>  	}
>  
>  	rbuf = transport_kmap_data_sg(cmd);
> -	if (rbuf) {
> -		memcpy(rbuf, buf, min(offset, cmd->data_length));
> -		transport_kunmap_data_sg(cmd);
> -	}
> +	if (!rbuf)
> +		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> +
> +	memcpy(rbuf, buf, min(offset, cmd->data_length));
> +	transport_kunmap_data_sg(cmd);
>  
>  	target_complete_cmd(cmd, GOOD);
>  	return 0;
>  }
>  

Ok, this part conflicts with Roland's for-3.8 patch:

commit 717e44956bc230bca54a4e044ec4b1a4a8438e09
Author: Roland Dreier <roland@xxxxxxxxxxxxxxx>
Date:   Wed Oct 31 09:16:50 2012 -0700

    target: Add emulation for MODE SELECT

Fixing up the minor breakage here, and folding into your original patch.

<SNIP>

>  
> Index: lio-core/drivers/infiniband/ulp/srpt/ib_srpt.c
> ===================================================================
> --- lio-core.orig/drivers/infiniband/ulp/srpt/ib_srpt.c	2012-10-30 14:14:53.593253429 +0100
> +++ lio-core/drivers/infiniband/ulp/srpt/ib_srpt.c	2012-10-30 14:43:46.626576409 +0100
> @@ -1730,7 +1730,7 @@ static int srpt_handle_cmd(struct srpt_r
>  	uint64_t unpacked_lun;
>  	u64 data_len;
>  	enum dma_data_direction dir;
> -	int ret;
> +	sense_reason_t ret;
>  
>  	BUG_ON(!send_ioctx);
>  
> @@ -1755,12 +1755,10 @@ static int srpt_handle_cmd(struct srpt_r
>  		break;
>  	}
>  
> -	ret = srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len);
> -	if (ret) {
> +	if (srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len)) {
>  		printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n",
>  		       srp_cmd->tag);
> -		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
> -		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
> +		ret = TCM_INVALID_CDB_FIELD;
>  		kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
>  		goto send_sense;
>  	}
> @@ -1769,26 +1767,26 @@ static int srpt_handle_cmd(struct srpt_r
>  	cmd->data_direction = dir;
>  	unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun,
>  				       sizeof(srp_cmd->lun));
> -	if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0) {
> +	ret = transport_lookup_cmd_lun(cmd, unpacked_lun);
> +	if (ret) {
>  		kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
>  		goto send_sense;
>  	}
>  	ret = target_setup_cmd_from_cdb(cmd, srp_cmd->cdb);
> -	if (ret < 0) {
> +	if (ret) {
>  		kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
> -		if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) {
> +		if (ret == TCM_RESERVATION_CONFLICT) {
>  			srpt_queue_status(cmd);
>  			return 0;
> -		} else
> -			goto send_sense;
> +		}
> +		goto send_sense;
>  	}
>  
>  	transport_handle_cdb_direct(cmd);
>  	return 0;
>  
>  send_sense:
> -	transport_send_check_condition_and_sense(cmd, cmd->scsi_sense_reason,
> -						 0);
> +	transport_send_check_condition_and_sense(cmd, ret, 0);
>  	return -1;
>  }
>  

So this looks reasonable to apply now to for-next ahead of finally
getting the target_submit_cmd() parts dusted off for ib_srpt.

> @@ -1882,16 +1880,14 @@ static void srpt_handle_tsk_mgmt(struct
>  	send_ioctx->tag = srp_tsk->tag;
>  	tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func);
>  	if (tcm_tmr < 0) {
> -		send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
>  		send_ioctx->cmd.se_tmr_req->response =
>  			TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED;
> -		goto process_tmr;
> +		goto fail;
>  	}
>  	res = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL);
>  	if (res < 0) {
> -		send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
>  		send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED;
> -		goto process_tmr;
> +		goto fail;
>  	}
>  
>  	unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun,
> @@ -1899,22 +1895,19 @@ static void srpt_handle_tsk_mgmt(struct
>  	res = transport_lookup_tmr_lun(&send_ioctx->cmd, unpacked_lun);
>  	if (res) {
>  		pr_debug("rejecting TMR for LUN %lld\n", unpacked_lun);
> -		send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
>  		send_ioctx->cmd.se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
> -		goto process_tmr;
> +		goto fail;
>  	}
>  
>  	if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK)
>  		srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag);
>  
> -process_tmr:
>  	kref_get(&send_ioctx->kref);
> -	if (!(send_ioctx->cmd.se_cmd_flags & SCF_SCSI_CDB_EXCEPTION))
> -		transport_generic_handle_tmr(&send_ioctx->cmd);
> -	else
> -		transport_send_check_condition_and_sense(cmd,
> -						cmd->scsi_sense_reason, 0);
> -
> +	transport_generic_handle_tmr(&send_ioctx->cmd);
> +	return;
> +fail:
> +	kref_get(&send_ioctx->kref);
> +	transport_send_check_condition_and_sense(cmd, 0, 0); // XXX:
>  }

Mmmmm, the use of transport_send_check_condition_and_sense() is because
ib_srpt uses srpt_queue_response() for both TFO->queue_data_in() +
TFO->queue_tm_rsp().  This also needs to be de-talged at some point for
target_submit_tmr() usage.

>  
> Index: lio-core/drivers/target/target_core_alua.c
> ===================================================================
> --- lio-core.orig/drivers/target/target_core_alua.c	2012-10-30 14:14:53.593253429 +0100
> +++ lio-core/drivers/target/target_core_alua.c	2012-10-30 14:15:09.903253331 +0100

<SNIP>

> @@ -200,7 +203,8 @@ int target_emulate_report_target_port_gr
>   *
>   * See spc4r17 section 6.35
>   */
> -int target_emulate_set_target_port_groups(struct se_cmd *cmd)
> +sense_reason_t
> +target_emulate_set_target_port_groups(struct se_cmd *cmd)
>  {
>  	struct se_device *dev = cmd->se_dev;
>  	struct se_port *port, *l_port = cmd->se_lun->lun_sep;
> @@ -209,22 +213,23 @@ int target_emulate_set_target_port_group
>  	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem;
>  	unsigned char *buf;
>  	unsigned char *ptr;
> +	sense_reason_t rc;
>  	u32 len = 4; /* Skip over RESERVED area in header */
> -	int alua_access_state, primary = 0, rc;
> +	int alua_access_state, primary = 0;
>  	u16 tg_pt_id, rtpi;
>  
> -	if (!l_port) {
> -		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> -		return -EINVAL;
> -	}
> +	if (!l_port)
> +		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> +
>  	if (cmd->data_length < 4) {
>  		pr_warn("SET TARGET PORT GROUPS parameter list length %u too"
>  			" small\n", cmd->data_length);
> -		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
> -		return -EINVAL;
> +		return TCM_INVALID_PARAMETER_LIST;
>  	}
>  
>  	buf = transport_kmap_data_sg(cmd);
> +	if (!buf)
> +		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
>  
>  	/*
>  	 * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed
> @@ -233,8 +238,7 @@ int target_emulate_set_target_port_group
>  	l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem;
>  	if (!l_tg_pt_gp_mem) {
>  		pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n");
> -		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
> -		rc = -EINVAL;
> +		rc = TCM_UNSUPPORTED_SCSI_OPCODE;
>  		goto out;
>  	}
>  	spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
> @@ -242,24 +246,22 @@ int target_emulate_set_target_port_group
>  	if (!l_tg_pt_gp) {
>  		spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
>  		pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n");
> -		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
> -		rc = -EINVAL;
> +		rc = TCM_UNSUPPORTED_SCSI_OPCODE;
>  		goto out;
>  	}
> -	rc = (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA);
>  	spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
>  
> -	if (!rc) {
> +	if (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA) {
>  		pr_debug("Unable to process SET_TARGET_PORT_GROUPS"
>  				" while TPGS_EXPLICT_ALUA is disabled\n");

This change is wrong.

Fixing up the incorrect inversion check here for TPGS_EXPLICT_ALUA with
a separate patch.

> -		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
> -		rc = -EINVAL;
> +		rc = TCM_UNSUPPORTED_SCSI_OPCODE;
>  		goto out;
>  	}
>  
>  	ptr = &buf[4]; /* Skip over RESERVED area in header */
>  
>  	while (len < cmd->data_length) {
> +		bool found = false;
>  		alua_access_state = (ptr[0] & 0x0f);
>  		/*
>  		 * Check the received ALUA access state, and determine if
> @@ -267,7 +269,7 @@ int target_emulate_set_target_port_group
>  		 * access state.
>  		 */
>  		rc = core_alua_check_transition(alua_access_state, &primary);
> -		if (rc != 0) {
> +		if (rc) {
>  			/*
>  			 * If the SET TARGET PORT GROUPS attempts to establish
>  			 * an invalid combination of target port asymmetric
> @@ -278,11 +280,9 @@ int target_emulate_set_target_port_group
>  			 * REQUEST, and the additional sense code set to INVALID
>  			 * FIELD IN PARAMETER LIST.
>  			 */
> -			cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
> -			rc = -EINVAL;
>  			goto out;
>  		}
> -		rc = -1;
> +
>  		/*
>  		 * If the ASYMMETRIC ACCESS STATE field (see table 267)
>  		 * specifies a primary target port asymmetric access state,
> @@ -314,11 +314,13 @@ int target_emulate_set_target_port_group
>  
>  				atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
>  				smp_mb__after_atomic_inc();
> +
>  				spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
>  
> -				rc = core_alua_do_port_transition(tg_pt_gp,
> +				if (!core_alua_do_port_transition(tg_pt_gp,
>  						dev, l_port, nacl,
> -						alua_access_state, 1);
> +						alua_access_state, 1))
> +					found = true;
>  
>  				spin_lock(&dev->t10_alua.tg_pt_gps_lock);
>  				atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
> @@ -326,15 +328,6 @@ int target_emulate_set_target_port_group
>  				break;
>  			}
>  			spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
> -			/*
> -			 * If not matching target port group ID can be located
> -			 * throw an exception with ASCQ: INVALID_PARAMETER_LIST
> -			 */
> -			if (rc != 0) {
> -				cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
> -				rc = -EINVAL;
> -				goto out;
> -			}
>  		} else {
>  			/*
>  			 * Extact the RELATIVE TARGET PORT IDENTIFIER to identify
> @@ -353,25 +346,22 @@ int target_emulate_set_target_port_group
>  					continue;
>  
>  				tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
> +
>  				spin_unlock(&dev->se_port_lock);
>  
> -				rc = core_alua_set_tg_pt_secondary_state(
> -						tg_pt_gp_mem, port, 1, 1);
> +				if (!core_alua_set_tg_pt_secondary_state(
> +						tg_pt_gp_mem, port, 1, 1))
> +					found = true;
>  
>  				spin_lock(&dev->se_port_lock);
>  				break;
>  			}
>  			spin_unlock(&dev->se_port_lock);
> -			/*
> -			 * If not matching relative target port identifier can
> -			 * be located, throw an exception with ASCQ:
> -			 * INVALID_PARAMETER_LIST
> -			 */
> -			if (rc != 0) {
> -				cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
> -				rc = -EINVAL;
> -				goto out;
> -			}
> +		}
> +
> +		if (!found) {
> +			rc = TCM_INVALID_PARAMETER_LIST;
> +			goto out;
>  		}
>  
>  		ptr += 4;

<SNIP>

> Index: lio-core/drivers/target/target_core_device.c
> ===================================================================
> --- lio-core.orig/drivers/target/target_core_device.c	2012-10-30 14:14:53.593253429 +0100
> +++ lio-core/drivers/target/target_core_device.c	2012-10-30 14:15:09.903253331 +0100
> @@ -54,18 +54,16 @@ static struct se_hba *lun0_hba;
>  /* not static, needed by tpg.c */
>  struct se_device *g_lun0_dev;
>  
> -int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
> +sense_reason_t
> +transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
>  {
>  	struct se_lun *se_lun = NULL;
>  	struct se_session *se_sess = se_cmd->se_sess;
>  	struct se_device *dev;
>  	unsigned long flags;
>  
> -	if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) {
> -		se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN;
> -		se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
> -		return -ENODEV;
> -	}
> +	if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG)
> +		return TCM_NON_EXISTENT_LUN;
>  
>  	spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags);
>  	se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun];
> @@ -77,14 +75,12 @@ int transport_lookup_cmd_lun(struct se_c
>  
>  		if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
>  		    (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) {
> -			se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED;
> -			se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
>  			pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN"
>  				" Access for 0x%08x\n",
>  				se_cmd->se_tfo->get_fabric_name(),
>  				unpacked_lun);
>  			spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags);
> -			return -EACCES;
> +			return TCM_WRITE_PROTECTED;
>  		}
>  
>  		if (se_cmd->data_direction == DMA_TO_DEVICE)
> @@ -109,23 +105,18 @@ int transport_lookup_cmd_lun(struct se_c
>  		 * MappedLUN=0 exists for this Initiator Port.
>  		 */
>  		if (unpacked_lun != 0) {
> -			se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN;
> -			se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
>  			pr_err("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN"
>  				" Access for 0x%08x\n",
>  				se_cmd->se_tfo->get_fabric_name(),
>  				unpacked_lun);
> -			return -ENODEV;
> +			return TCM_NON_EXISTENT_LUN;
>  		}
>  		/*
>  		 * Force WRITE PROTECT for virtual LUN 0
>  		 */
>  		if ((se_cmd->data_direction != DMA_FROM_DEVICE) &&
> -		    (se_cmd->data_direction != DMA_NONE)) {
> -			se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED;
> -			se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
> -			return -EACCES;
> -		}
> +		    (se_cmd->data_direction != DMA_NONE))
> +			return TCM_WRITE_PROTECTED;
>  

The transport_lookup_cmd_lun changes look reasonable enough..

> Index: lio-core/drivers/target/target_core_pr.c
> ===================================================================
> --- lio-core.orig/drivers/target/target_core_pr.c	2012-10-30 14:14:53.593253429 +0100
> +++ lio-core/drivers/target/target_core_pr.c	2012-10-30 14:15:09.909919998 +0100
> -static int core_scsi3_emulate_pro_register(
> -	struct se_cmd *cmd,
> -	u64 res_key,
> -	u64 sa_res_key,
> -	int aptpl,
> -	int all_tg_pt,
> -	int spec_i_pt,
> -	int ignore_key)
> +static sense_reason_t
> +core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
> +		int aptpl, int all_tg_pt, int spec_i_pt, int ignore_key)
>  {
>  	struct se_session *se_sess = cmd->se_sess;
>  	struct se_device *dev = cmd->se_dev;
> @@ -2079,12 +2054,12 @@ static int core_scsi3_emulate_pro_regist
>  	/* Used for APTPL metadata w/ UNREGISTER */
>  	unsigned char *pr_aptpl_buf = NULL;
>  	unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL;
> -	int pr_holder = 0, ret = 0, type;
> +	sense_reason_t ret;
> +	int pr_holder = 0, type;
>  

<SNIP>


> +static sense_reason_t
> +core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
> +		u64 res_key)
>  {
>  	struct se_device *dev = cmd->se_dev;
>  	struct se_session *se_sess = cmd->se_sess;
>  	struct se_lun *se_lun = cmd->se_lun;
>  	struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder;
>  	struct t10_reservation *pr_tmpl = &dev->t10_pr;
> -	int ret, all_reg = 0;
> +	int all_reg = 0;
> +	sense_reason_t ret = 0;
>  
>  	if (!se_sess || !se_lun) {
>  		pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
> -		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> -		return -EINVAL;
> +		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
>  	}
>  	/*
>  	 * Locate the existing *pr_reg via struct se_node_acl pointers
> @@ -2637,8 +2583,7 @@ static int core_scsi3_emulate_pro_releas
>  	if (!pr_reg) {
>  		pr_err("SPC-3 PR: Unable to locate"
>  			" PR_REGISTERED *pr_reg for RELEASE\n");
> -		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> -		return -EINVAL;
> +		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
>  	}
>  	/*
>  	 * From spc4r17 Section 5.7.11.2 Releasing:
> @@ -2659,7 +2604,6 @@ static int core_scsi3_emulate_pro_releas
>  		 * No persistent reservation, return GOOD status.
>  		 */
>  		spin_unlock(&dev->dev_reservation_lock);
> -		core_scsi3_put_pr_reg(pr_reg);
>  		return 0;
>  	}

This is a bug to not put the newly allocated pr_reg before returning.

<SNIP>

>  
>  /*
> - * Used by transport_send_check_condition_and_sense() and se_cmd->scsi_sense_reason
> + * Used by transport_send_check_condition_and_sense()
>   * to signal which ASC/ASCQ sense payload should be built.
>   */
> +typedef unsigned __bitwise__ sense_reason_t;
> +
>  enum tcm_sense_reason_table {
> -	TCM_NON_EXISTENT_LUN			= 0x01,
> -	TCM_UNSUPPORTED_SCSI_OPCODE		= 0x02,
> -	TCM_INCORRECT_AMOUNT_OF_DATA		= 0x03,
> -	TCM_UNEXPECTED_UNSOLICITED_DATA		= 0x04,
> -	TCM_SERVICE_CRC_ERROR			= 0x05,
> -	TCM_SNACK_REJECTED			= 0x06,
> -	TCM_SECTOR_COUNT_TOO_MANY		= 0x07,
> -	TCM_INVALID_CDB_FIELD			= 0x08,
> -	TCM_INVALID_PARAMETER_LIST		= 0x09,
> -	TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE	= 0x0a,
> -	TCM_UNKNOWN_MODE_PAGE			= 0x0b,
> -	TCM_WRITE_PROTECTED			= 0x0c,
> -	TCM_CHECK_CONDITION_ABORT_CMD		= 0x0d,
> -	TCM_CHECK_CONDITION_UNIT_ATTENTION	= 0x0e,
> -	TCM_CHECK_CONDITION_NOT_READY		= 0x0f,
> -	TCM_RESERVATION_CONFLICT		= 0x10,
> -	TCM_ADDRESS_OUT_OF_RANGE		= 0x11,
> +#define R(x)	(__force sense_reason_t )(x)
> +	TCM_NON_EXISTENT_LUN			= R(0x01),
> +	TCM_UNSUPPORTED_SCSI_OPCODE		= R(0x02),
> +	TCM_INCORRECT_AMOUNT_OF_DATA		= R(0x03),
> +	TCM_UNEXPECTED_UNSOLICITED_DATA		= R(0x04),
> +	TCM_SERVICE_CRC_ERROR			= R(0x05),
> +	TCM_SNACK_REJECTED			= R(0x06),
> +	TCM_SECTOR_COUNT_TOO_MANY		= R(0x07),
> +	TCM_INVALID_CDB_FIELD			= R(0x08),
> +	TCM_INVALID_PARAMETER_LIST		= R(0x09),
> +	TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE	= R(0x0a),
> +	TCM_UNKNOWN_MODE_PAGE			= R(0x0b),
> +	TCM_WRITE_PROTECTED			= R(0x0c),
> +	TCM_CHECK_CONDITION_ABORT_CMD		= R(0x0d),
> +	TCM_CHECK_CONDITION_UNIT_ATTENTION	= R(0x0e),
> +	TCM_CHECK_CONDITION_NOT_READY		= R(0x0f),
> +	TCM_RESERVATION_CONFLICT		= R(0x10),
> +	TCM_ADDRESS_OUT_OF_RANGE		= R(0x11),
> +	TCM_OUT_OF_RESOURCES			= R(0x12),
> +#undef R
>  };
>
> Index: lio-core/drivers/target/iscsi/iscsi_target.c
> ===================================================================
> --- lio-core.orig/drivers/target/iscsi/iscsi_target.c	2012-10-30 14:14:53.593253429 +0100
> +++ lio-core/drivers/target/iscsi/iscsi_target.c	2012-10-30 15:00:48.453236971 +0100
> @@ -767,9 +767,8 @@ static int iscsit_handle_scsi_cmd(
>  	struct iscsi_conn *conn,
>  	unsigned char *buf)
>  {

<SNIP>

> @@ -1050,19 +1035,17 @@ attach_cmd:
>  	 * thread.  They are processed in CmdSN order by
>  	 * iscsit_check_received_cmdsn() below.
>  	 */
> -	if (send_check_condition) {
> +	if (cmd->sense_reason) {
>  		immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
> -		dump_immediate_data = 1;
>  		goto after_immediate_data;
>  	}
>  	/*
>  	 * Call directly into transport_generic_new_cmd() to perform
>  	 * the backend memory allocation.
>  	 */
> -	ret = transport_generic_new_cmd(&cmd->se_cmd);
> -	if (ret < 0) {
> +	cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd);
> +	if (cmd->sense_reason) {
>  		immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
> -		dump_immediate_data = 1;
>  		goto after_immediate_data;
>  	}
>  
> @@ -1079,7 +1062,7 @@ after_immediate_data:
>  		 * Special case for Unsupported SAM WRITE Opcodes
>  		 * and ImmediateData=Yes.
>  		 */
> -		if (dump_immediate_data) {
> +		if (cmd->sense_reason) {
>  			if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
>  				return -1;
>  		} else if (cmd->unsolicited_data) {

Nice work to get rid of send_check_condition and dump_immediate_data !

> @@ -1272,8 +1255,7 @@ static int iscsit_handle_data_out(struct
>  		spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
>  
>  		spin_lock_irqsave(&se_cmd->t_state_lock, flags);
> -		if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) ||
> -		     (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION))
> +		if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE))
>  			dump_unsolicited_data = 1;
>  		spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
>  

Should not this include a cmd->sense_reason check as well, if it was
previously checking SCF_SCSI_CDB_EXCEPTION..?

Adding this a separate increment patch going out shortly as well.

This large of a change obviously will require alot more testing from the
fabrics exception paths, but overall for target core I think it's worth
making the change within for-3.8 code..

Nice work Christoph !

--nab

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux