From 3cc5d2a6b9a2fd1bf024aa5e52dd22961eecaf13 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 13 Jul 2012 18:18:04 -0700 Subject: tcm_fc: Fix crash seen with aborts and large reads This patch fixes a crash seen when large reads have their exchange aborted by either timing out or being reset. Because the exchange abort results in the seq pointer being set to NULL, because the sequence is no longer valid, it must not be dereferenced. This patch changes the function ft_get_task_tag to return ~0 if it is unable to get the tag for this reason. Because the get_task_tag interface provides no means of returning an error, this seems like the best way to fix this issue at the moment. Signed-off-by: Mark Rustad Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/tcm_fc/tfc_cmd.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/target/tcm_fc/tfc_cmd.c') diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index f03fb9730f5b..5b65f33939a8 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -230,6 +230,8 @@ u32 ft_get_task_tag(struct se_cmd *se_cmd) { struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd); + if (cmd->aborted) + return ~0; return fc_seq_exch(cmd->seq)->rxid; } -- cgit v1.2.3 From 64f1db38c65fa634f4aa21e0f70480a6b8b4d47c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 20 May 2012 11:59:11 -0400 Subject: target: remove control CDB flags We don't need three flags to classifiy the CDB as we can check for a NULL S/G list for a dataless command, and can infer from the absence of the data flag that we deal with a control CDB. Also remove the _SG_IO from the data CDB flag as all I/O is dont on S/G lists now. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/loopback/tcm_loop.c | 9 ++- drivers/target/target_core_pscsi.c | 2 +- drivers/target/target_core_transport.c | 109 ++++++++++----------------------- drivers/target/tcm_fc/tfc_cmd.c | 2 +- include/target/target_core_base.h | 35 +++++------ 5 files changed, 56 insertions(+), 101 deletions(-) (limited to 'drivers/target/tcm_fc/tfc_cmd.c') diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index 38dfac2b0a1c..f65dc9db8596 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -211,12 +211,11 @@ static void tcm_loop_submission_work(struct work_struct *work) /* * Because some userspace code via scsi-generic do not memset their * associated read buffers, go ahead and do that here for type - * SCF_SCSI_CONTROL_SG_IO_CDB. Also note that this is currently - * guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB - * by target core in target_setup_cmd_from_cdb() -> - * transport_generic_cmd_sequencer(). + * non-data CDBs. Also note that this is currently guaranteed to be a + * single SGL for this case by target core in + * target_setup_cmd_from_cdb() -> transport_generic_cmd_sequencer(). */ - if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB && + if (!(se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && se_cmd->data_direction == DMA_FROM_DEVICE) { struct scatterlist *sg = scsi_sglist(sc); unsigned char *buf = kmap(sg_page(sg)) + sg->offset; diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 4ce2cf642fce..bfc72327370c 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -1042,7 +1042,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl, memcpy(pt->pscsi_cdb, cmd->t_task_cdb, scsi_command_size(cmd->t_task_cdb)); - if (cmd->se_cmd_flags & SCF_SCSI_NON_DATA_CDB) { + if (!sgl) { req = blk_get_request(pdv->pdv_sd->request_queue, (data_direction == DMA_TO_DEVICE), GFP_KERNEL); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index bb19223faa46..a181951a7aca 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2446,7 +2446,7 @@ static int transport_generic_cmd_sequencer( goto out_unsupported_cdb; size = transport_get_size(sectors, cdb, cmd); cmd->t_task_lba = transport_lba_21(cdb); - cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; + cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; break; case READ_10: sectors = transport_get_sectors_10(cdb, cmd, §or_ret); @@ -2454,7 +2454,7 @@ static int transport_generic_cmd_sequencer( goto out_unsupported_cdb; size = transport_get_size(sectors, cdb, cmd); cmd->t_task_lba = transport_lba_32(cdb); - cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; + cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; break; case READ_12: sectors = transport_get_sectors_12(cdb, cmd, §or_ret); @@ -2462,7 +2462,7 @@ static int transport_generic_cmd_sequencer( goto out_unsupported_cdb; size = transport_get_size(sectors, cdb, cmd); cmd->t_task_lba = transport_lba_32(cdb); - cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; + cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; break; case READ_16: sectors = transport_get_sectors_16(cdb, cmd, §or_ret); @@ -2470,7 +2470,7 @@ static int transport_generic_cmd_sequencer( goto out_unsupported_cdb; size = transport_get_size(sectors, cdb, cmd); cmd->t_task_lba = transport_lba_64(cdb); - cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; + cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; break; case WRITE_6: sectors = transport_get_sectors_6(cdb, cmd, §or_ret); @@ -2478,7 +2478,7 @@ static int transport_generic_cmd_sequencer( goto out_unsupported_cdb; size = transport_get_size(sectors, cdb, cmd); cmd->t_task_lba = transport_lba_21(cdb); - cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; + cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; break; case WRITE_10: case WRITE_VERIFY: @@ -2489,7 +2489,7 @@ static int transport_generic_cmd_sequencer( cmd->t_task_lba = transport_lba_32(cdb); if (cdb[1] & 0x8) cmd->se_cmd_flags |= SCF_FUA; - cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; + cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; break; case WRITE_12: sectors = transport_get_sectors_12(cdb, cmd, §or_ret); @@ -2499,7 +2499,7 @@ static int transport_generic_cmd_sequencer( cmd->t_task_lba = transport_lba_32(cdb); if (cdb[1] & 0x8) cmd->se_cmd_flags |= SCF_FUA; - cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; + cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; break; case WRITE_16: sectors = transport_get_sectors_16(cdb, cmd, §or_ret); @@ -2509,7 +2509,7 @@ static int transport_generic_cmd_sequencer( cmd->t_task_lba = transport_lba_64(cdb); if (cdb[1] & 0x8) cmd->se_cmd_flags |= SCF_FUA; - cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; + cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; break; case XDWRITEREAD_10: if ((cmd->data_direction != DMA_TO_DEVICE) || @@ -2520,7 +2520,7 @@ static int transport_generic_cmd_sequencer( goto out_unsupported_cdb; size = transport_get_size(sectors, cdb, cmd); cmd->t_task_lba = transport_lba_32(cdb); - cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; + cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; /* * Do now allow BIDI commands for passthrough mode. @@ -2548,7 +2548,7 @@ static int transport_generic_cmd_sequencer( * XDWRITE_READ_32 logic. */ cmd->t_task_lba = transport_lba_64_ext(cdb); - cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; + cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; /* * Do now allow BIDI commands for passthrough mode. @@ -2578,7 +2578,6 @@ static int transport_generic_cmd_sequencer( } cmd->t_task_lba = get_unaligned_be64(&cdb[12]); - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; if (target_check_write_same_discard(&cdb[10], dev) < 0) goto out_unsupported_cdb; @@ -2608,25 +2607,20 @@ static int transport_generic_cmd_sequencer( /* GPCMD_SEND_KEY from multi media commands */ size = (cdb[8] << 8) + cdb[9]; } - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case MODE_SELECT: size = cdb[4]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case MODE_SELECT_10: size = (cdb[7] << 8) + cdb[8]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case MODE_SENSE: size = cdb[4]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; if (!passthrough) cmd->execute_cmd = target_emulate_modesense; break; case MODE_SENSE_10: size = (cdb[7] << 8) + cdb[8]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; if (!passthrough) cmd->execute_cmd = target_emulate_modesense; break; @@ -2635,39 +2629,32 @@ static int transport_generic_cmd_sequencer( case LOG_SELECT: case LOG_SENSE: size = (cdb[7] << 8) + cdb[8]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case READ_BLOCK_LIMITS: size = READ_BLOCK_LEN; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case GPCMD_GET_CONFIGURATION: case GPCMD_READ_FORMAT_CAPACITIES: case GPCMD_READ_DISC_INFO: case GPCMD_READ_TRACK_RZONE_INFO: size = (cdb[7] << 8) + cdb[8]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case PERSISTENT_RESERVE_IN: if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) cmd->execute_cmd = target_scsi3_emulate_pr_in; size = (cdb[7] << 8) + cdb[8]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case PERSISTENT_RESERVE_OUT: if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) cmd->execute_cmd = target_scsi3_emulate_pr_out; size = (cdb[7] << 8) + cdb[8]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case GPCMD_MECHANISM_STATUS: case GPCMD_READ_DVD_STRUCTURE: size = (cdb[8] << 8) + cdb[9]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case READ_POSITION: size = READ_POSITION_LEN; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case MAINTENANCE_OUT: if (dev->transport->get_device_type(dev) != TYPE_ROM) { @@ -2687,7 +2674,6 @@ static int transport_generic_cmd_sequencer( /* GPCMD_REPORT_KEY from multi media commands */ size = (cdb[8] << 8) + cdb[9]; } - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case INQUIRY: size = (cdb[3] << 8) + cdb[4]; @@ -2697,17 +2683,14 @@ static int transport_generic_cmd_sequencer( */ if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) cmd->sam_task_attr = MSG_HEAD_TAG; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; if (!passthrough) cmd->execute_cmd = target_emulate_inquiry; break; case READ_BUFFER: size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case READ_CAPACITY: size = READ_CAP_LEN; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; if (!passthrough) cmd->execute_cmd = target_emulate_readcapacity; break; @@ -2715,7 +2698,6 @@ static int transport_generic_cmd_sequencer( case SECURITY_PROTOCOL_IN: case SECURITY_PROTOCOL_OUT: size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case SERVICE_ACTION_IN: switch (cmd->t_task_cdb[1] & 0x1f) { @@ -2741,38 +2723,31 @@ static int transport_generic_cmd_sequencer( case WRITE_ATTRIBUTE: size = (cdb[10] << 24) | (cdb[11] << 16) | (cdb[12] << 8) | cdb[13]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case RECEIVE_DIAGNOSTIC: case SEND_DIAGNOSTIC: size = (cdb[3] << 8) | cdb[4]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; /* #warning FIXME: Figure out correct GPCMD_READ_CD blocksize. */ #if 0 case GPCMD_READ_CD: sectors = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8]; size = (2336 * sectors); - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; #endif case READ_TOC: size = cdb[8]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case REQUEST_SENSE: size = cdb[4]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; if (!passthrough) cmd->execute_cmd = target_emulate_request_sense; break; case READ_ELEMENT_STATUS: size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case WRITE_BUFFER: size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case RESERVE: case RESERVE_10: @@ -2794,7 +2769,6 @@ static int transport_generic_cmd_sequencer( */ if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) cmd->execute_cmd = target_scsi2_reservation_reserve; - cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; break; case RELEASE: case RELEASE_10: @@ -2809,7 +2783,6 @@ static int transport_generic_cmd_sequencer( if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) cmd->execute_cmd = target_scsi2_reservation_release; - cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; break; case SYNCHRONIZE_CACHE: case SYNCHRONIZE_CACHE_16: @@ -2827,7 +2800,6 @@ static int transport_generic_cmd_sequencer( goto out_unsupported_cdb; size = transport_get_size(sectors, cdb, cmd); - cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; if (passthrough) break; @@ -2844,7 +2816,6 @@ static int transport_generic_cmd_sequencer( break; case UNMAP: size = get_unaligned_be16(&cdb[7]); - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; if (!passthrough) cmd->execute_cmd = target_emulate_unmap; break; @@ -2861,7 +2832,6 @@ static int transport_generic_cmd_sequencer( } cmd->t_task_lba = get_unaligned_be64(&cdb[2]); - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; if (target_check_write_same_discard(&cdb[1], dev) < 0) goto out_unsupported_cdb; @@ -2881,7 +2851,6 @@ static int transport_generic_cmd_sequencer( } cmd->t_task_lba = get_unaligned_be32(&cdb[2]); - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; /* * Follow sbcr26 with WRITE_SAME (10) and check for the existence * of byte 1 bit 3 UNMAP instead of original reserved field @@ -2900,7 +2869,6 @@ static int transport_generic_cmd_sequencer( case TEST_UNIT_READY: case VERIFY: case WRITE_FILEMARKS: - cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; if (!passthrough) cmd->execute_cmd = target_emulate_noop; break; @@ -2909,7 +2877,6 @@ static int transport_generic_cmd_sequencer( case GPCMD_LOAD_UNLOAD: case GPCMD_SET_SPEED: case MOVE_MEDIUM: - cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; break; case REPORT_LUNS: cmd->execute_cmd = target_report_luns; @@ -2920,11 +2887,9 @@ static int transport_generic_cmd_sequencer( */ if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) cmd->sam_task_attr = MSG_HEAD_TAG; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case GET_EVENT_STATUS_NOTIFICATION: size = (cdb[7] << 8) | cdb[8]; - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case ATA_16: /* Only support ATA passthrough to pSCSI backends.. */ @@ -2956,7 +2921,6 @@ static int transport_generic_cmd_sequencer( /* BYTE */ size = sectors; } - cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; default: pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode" @@ -2983,7 +2947,7 @@ static int transport_generic_cmd_sequencer( } /* * Reject READ_* or WRITE_* with overflow/underflow for - * type SCF_SCSI_DATA_SG_IO_CDB. + * type SCF_SCSI_DATA_CDB. */ if (dev->se_sub_dev->se_dev_attrib.block_size != 512) { pr_err("Failing OVERFLOW/UNDERFLOW for LBA op" @@ -3003,7 +2967,7 @@ static int transport_generic_cmd_sequencer( cmd->data_length = size; } - if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) { + if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { if (sectors > su_dev->se_dev_attrib.fabric_max_sectors) { printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" " big sectors %u exceeds fabric_max_sectors:" @@ -3022,7 +2986,7 @@ static int transport_generic_cmd_sequencer( /* reject any command that we don't have a handler for */ if (!(passthrough || cmd->execute_cmd || - (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB))) + (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB))) goto out_unsupported_cdb; return 0; @@ -3357,31 +3321,27 @@ int transport_generic_map_mem_to_cmd( if (!sgl || !sgl_count) return 0; - if ((cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) || - (cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB)) { - /* - * Reject SCSI data overflow with map_mem_to_cmd() as incoming - * scatterlists already have been set to follow what the fabric - * passes for the original expected data transfer length. - */ - if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { - pr_warn("Rejecting SCSI DATA overflow for fabric using" - " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n"); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; - } + /* + * Reject SCSI data overflow with map_mem_to_cmd() as incoming + * scatterlists already have been set to follow what the fabric + * passes for the original expected data transfer length. + */ + if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { + pr_warn("Rejecting SCSI DATA overflow for fabric using" + " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n"); + cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; + } - cmd->t_data_sg = sgl; - cmd->t_data_nents = sgl_count; + cmd->t_data_sg = sgl; + cmd->t_data_nents = sgl_count; - if (sgl_bidi && sgl_bidi_count) { - cmd->t_bidi_data_sg = sgl_bidi; - cmd->t_bidi_data_nents = sgl_bidi_count; - } - cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC; + if (sgl_bidi && sgl_bidi_count) { + cmd->t_bidi_data_sg = sgl_bidi; + cmd->t_bidi_data_nents = sgl_bidi_count; } - + cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC; return 0; } EXPORT_SYMBOL(transport_generic_map_mem_to_cmd); @@ -3453,7 +3413,7 @@ transport_generic_get_mem(struct se_cmd *cmd) cmd->t_data_nents = nents; sg_init_table(cmd->t_data_sg, nents); - zero_flag = cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB ? 0 : __GFP_ZERO; + zero_flag = cmd->se_cmd_flags & SCF_SCSI_DATA_CDB ? 0 : __GFP_ZERO; while (length) { u32 page_len = min_t(u32, length, PAGE_SIZE); @@ -3500,8 +3460,7 @@ int transport_generic_new_cmd(struct se_cmd *cmd) } /* Workaround for handling zero-length control CDBs */ - if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) && - !cmd->data_length) { + if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->data_length) { spin_lock_irq(&cmd->t_state_lock); cmd->t_state = TRANSPORT_COMPLETE; cmd->transport_state |= CMD_T_ACTIVE; @@ -3519,7 +3478,7 @@ int transport_generic_new_cmd(struct se_cmd *cmd) return 0; } - if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) { + if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { struct se_dev_attrib *attr = &dev->se_sub_dev->se_dev_attrib; if (transport_cmd_get_valid_sectors(cmd) < 0) diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 5b65f33939a8..4ad58ac823e5 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -215,7 +215,7 @@ int ft_write_pending(struct se_cmd *se_cmd) */ if ((ep->xid <= lport->lro_xid) && (fh->fh_r_ctl == FC_RCTL_DD_DATA_DESC)) { - if ((se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) && + if ((se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && lport->tt.ddp_target(lport, ep->xid, se_cmd->t_data_sg, se_cmd->t_data_nents)) diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index dc35d8660aa6..abda19d6cbd2 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -160,25 +160,22 @@ enum se_cmd_flags_table { SCF_SUPPORTED_SAM_OPCODE = 0x00000001, SCF_TRANSPORT_TASK_SENSE = 0x00000002, SCF_EMULATED_TASK_SENSE = 0x00000004, - SCF_SCSI_DATA_SG_IO_CDB = 0x00000008, - SCF_SCSI_CONTROL_SG_IO_CDB = 0x00000010, - SCF_SCSI_NON_DATA_CDB = 0x00000020, - SCF_SCSI_TMR_CDB = 0x00000040, - SCF_SCSI_CDB_EXCEPTION = 0x00000080, - SCF_SCSI_RESERVATION_CONFLICT = 0x00000100, - SCF_FUA = 0x00000200, - SCF_SE_LUN_CMD = 0x00000800, - SCF_SE_ALLOW_EOO = 0x00001000, - SCF_BIDI = 0x00002000, - SCF_SENT_CHECK_CONDITION = 0x00004000, - SCF_OVERFLOW_BIT = 0x00008000, - SCF_UNDERFLOW_BIT = 0x00010000, - SCF_SENT_DELAYED_TAS = 0x00020000, - SCF_ALUA_NON_OPTIMIZED = 0x00040000, - SCF_DELAYED_CMD_FROM_SAM_ATTR = 0x00080000, - SCF_UNUSED = 0x00100000, - SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00200000, - SCF_ACK_KREF = 0x00400000, + SCF_SCSI_DATA_CDB = 0x00000008, + SCF_SCSI_TMR_CDB = 0x00000010, + SCF_SCSI_CDB_EXCEPTION = 0x00000020, + SCF_SCSI_RESERVATION_CONFLICT = 0x00000040, + SCF_FUA = 0x00000080, + SCF_SE_LUN_CMD = 0x00000100, + SCF_SE_ALLOW_EOO = 0x00000200, + SCF_BIDI = 0x00000400, + SCF_SENT_CHECK_CONDITION = 0x00000800, + SCF_OVERFLOW_BIT = 0x00001000, + SCF_UNDERFLOW_BIT = 0x00002000, + SCF_SENT_DELAYED_TAS = 0x00004000, + SCF_ALUA_NON_OPTIMIZED = 0x00008000, + SCF_DELAYED_CMD_FROM_SAM_ATTR = 0x00010000, + SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000, + SCF_ACK_KREF = 0x00040000, }; /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */ -- cgit v1.2.3 From d6dfc868bcf329392abd1ecfa7357eb51ebf8c30 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 16 Jul 2012 11:04:39 -0700 Subject: target: Allow for target_submit_cmd() returning errors We want it to be possible for target_submit_cmd() to return errors up to its fabric module callers. For now just update the prototype to return an int, and update all callers to handle non-zero return values as an error. This is immediately useful for tcm_qla2xxx to fix a long-standing active I/O session shutdown race, but tcm_fc, usb-gadget, and sbp-target the fabric maintainers need to check + ACK that handling a target_submit_cmd() failure due to session shutdown does not introduce regressions (nab: Respin against for-next after initial NACK + update docbook comment + fix double se_cmd init in exception path for usb-gadget) Cc: Chad Dupuis Cc: Arun Easi Cc: Chris Boot Cc: Stefan Richter Cc: Mark Rustad Cc: Sebastian Andrzej Siewior Cc: Felipe Balbi Cc: Andy Grover Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 3 +-- drivers/target/sbp/sbp_target.c | 8 +++++--- drivers/target/target_core_transport.c | 14 ++++++++----- drivers/target/tcm_fc/tfc_cmd.c | 8 +++++--- drivers/usb/gadget/tcm_usb_gadget.c | 36 +++++++++++++++++++++------------- include/target/target_core_fabric.h | 2 +- 6 files changed, 43 insertions(+), 28 deletions(-) (limited to 'drivers/target/tcm_fc/tfc_cmd.c') diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 65a7ed9ac81d..4752f65a9272 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -597,10 +597,9 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, return -EINVAL; } - target_submit_cmd(se_cmd, se_sess, cdb, &cmd->sense_buffer[0], + return target_submit_cmd(se_cmd, se_sess, cdb, &cmd->sense_buffer[0], cmd->unpacked_lun, data_length, fcp_task_attr, data_dir, flags); - return 0; } static void tcm_qla2xxx_handle_data_work(struct work_struct *work) diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c index e10e6223e96c..39ddba584b30 100644 --- a/drivers/target/sbp/sbp_target.c +++ b/drivers/target/sbp/sbp_target.c @@ -1235,9 +1235,11 @@ static void sbp_handle_command(struct sbp_target_request *req) pr_debug("sbp_handle_command ORB:0x%llx unpacked_lun:%d data_len:%d data_dir:%d\n", req->orb_pointer, unpacked_lun, data_length, data_dir); - target_submit_cmd(&req->se_cmd, sess->se_sess, req->cmd_buf, - req->sense_buf, unpacked_lun, data_length, - MSG_SIMPLE_TAG, data_dir, 0); + if (target_submit_cmd(&req->se_cmd, sess->se_sess, req->cmd_buf, + req->sense_buf, unpacked_lun, data_length, + MSG_SIMPLE_TAG, data_dir, 0)) + goto err; + return; err: diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 14e54b48fb8c..7647ecafbcc7 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1447,10 +1447,14 @@ EXPORT_SYMBOL(transport_handle_cdb_direct); * @data_dir: DMA data direction * @flags: flags for command submission from target_sc_flags_tables * + * Returns non zero to signal active I/O shutdown failure. All other + * setup exceptions will be returned as a SCSI CHECK_CONDITION response, + * but still return zero here. + * * This may only be called from process context, and also currently * assumes internal allocation of fabric payload buffer by target-core. **/ -void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, +int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, unsigned char *cdb, unsigned char *sense, u32 unpacked_lun, u32 data_length, int task_attr, int data_dir, int flags) { @@ -1478,7 +1482,7 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, */ rc = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF)); if (rc) - return; + return rc; /* * Signal bidirectional data payloads to target-core */ @@ -1491,13 +1495,13 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, transport_send_check_condition_and_sense(se_cmd, se_cmd->scsi_sense_reason, 0); target_put_sess_cmd(se_sess, se_cmd); - return; + return 0; } rc = target_setup_cmd_from_cdb(se_cmd, cdb); if (rc != 0) { transport_generic_request_failure(se_cmd); - return; + return 0; } /* @@ -1507,7 +1511,7 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, core_alua_check_nonop_delay(se_cmd); transport_handle_cdb_direct(se_cmd); - return; + return 0; } EXPORT_SYMBOL(target_submit_cmd); diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 4ad58ac823e5..b9cb5006177e 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -543,9 +543,11 @@ static void ft_send_work(struct work_struct *work) * Use a single se_cmd->cmd_kref as we expect to release se_cmd * directly from ft_check_stop_free callback in response path. */ - target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb, - &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun), - ntohl(fcp->fc_dl), task_attr, data_dir, 0); + if (target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb, + &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun), + ntohl(fcp->fc_dl), task_attr, data_dir, 0)) + goto err; + pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl); return; diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 02ace18fca0b..5444866e13ef 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -1065,16 +1065,20 @@ static void usbg_cmd_work(struct work_struct *work) tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo, tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE, cmd->prio_attr, cmd->sense_iu.sense); - - transport_send_check_condition_and_sense(se_cmd, - TCM_UNSUPPORTED_SCSI_OPCODE, 1); - usbg_cleanup_cmd(cmd); - return; + goto out; } - target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess, + if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess, cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun, - 0, cmd->prio_attr, dir, TARGET_SCF_UNKNOWN_SIZE); + 0, cmd->prio_attr, dir, TARGET_SCF_UNKNOWN_SIZE) < 0) + goto out; + + return; + +out: + transport_send_check_condition_and_sense(se_cmd, + TCM_UNSUPPORTED_SCSI_OPCODE, 1); + usbg_cleanup_cmd(cmd); } static int usbg_submit_command(struct f_uas *fu, @@ -1177,16 +1181,20 @@ static void bot_cmd_work(struct work_struct *work) tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo, tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE, cmd->prio_attr, cmd->sense_iu.sense); - - transport_send_check_condition_and_sense(se_cmd, - TCM_UNSUPPORTED_SCSI_OPCODE, 1); - usbg_cleanup_cmd(cmd); - return; + goto out; } - target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess, + if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess, cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun, - cmd->data_len, cmd->prio_attr, dir, 0); + cmd->data_len, cmd->prio_attr, dir, 0) < 0) + goto out; + + return; + +out: + transport_send_check_condition_and_sense(se_cmd, + TCM_UNSUPPORTED_SCSI_OPCODE, 1); + usbg_cleanup_cmd(cmd); } static int bot_submit_command(struct f_uas *fu, diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 815e064028c9..69fb3cfd02d7 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h @@ -102,7 +102,7 @@ void transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *, struct se_session *, u32, int, int, unsigned char *); int transport_lookup_cmd_lun(struct se_cmd *, u32); int target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *); -void target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *, +int target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *, unsigned char *, u32, u32, int, int, int); int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, unsigned char *sense, u32 unpacked_lun, -- cgit v1.2.3