diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2015-08-27 15:45:16 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2015-08-27 15:45:16 +1000 |
commit | eea0732ec6e942fe3a26e9f0b1f4661ca1c3bc6e (patch) | |
tree | ade9bac0601bed412e84a4b6dda437b32a001c4e | |
parent | d4f06e749b84f8d84e1a59570b7afafbac25c7d0 (diff) | |
parent | 109e2381749c1cfd94a0d22b2b54142539024973 (diff) |
Merge remote-tracking branch 'target-updates/for-next'
29 files changed, 466 insertions, 477 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 98d9bb6ff725..33c74d3436c9 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -853,12 +853,9 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, SAM_STAT_CHECK_CONDITION; scsi_build_sense_buffer(1, sc->sense_buffer, ILLEGAL_REQUEST, 0x10, ascq); - sc->sense_buffer[7] = 0xc; /* Additional sense length */ - sc->sense_buffer[8] = 0; /* Information desc type */ - sc->sense_buffer[9] = 0xa; /* Additional desc length */ - sc->sense_buffer[10] = 0x80; /* Validity bit */ - - put_unaligned_be64(sector, &sc->sense_buffer[12]); + scsi_set_sense_information(sc->sense_buffer, + SCSI_SENSE_BUFFERSIZE, + sector); goto out; } } diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index 33f60c92e20e..a0f732b138e4 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig @@ -32,10 +32,10 @@ config SCSI_QLA_FC They are also included in the linux-firmware tree as well. config TCM_QLA2XXX - tristate "TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs" + tristate "TCM_QLA2XXX fabric module for QLogic 24xx+ series target mode HBAs" depends on SCSI_QLA_FC && TARGET_CORE depends on LIBFC select BTREE default n ---help--- - Say Y here to enable the TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs + Say Y here to enable the TCM_QLA2XXX fabric module for QLogic 24xx+ series target mode HBAs diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 7ed7bae6172b..3747425770e7 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -1359,9 +1359,7 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) struct qla_hw_data *ha = tgt->ha; scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); struct se_session *se_sess; - struct se_node_acl *se_nacl; struct tcm_qla2xxx_lport *lport; - struct tcm_qla2xxx_nacl *nacl; BUG_ON(in_interrupt()); @@ -1371,8 +1369,6 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) dump_stack(); return; } - se_nacl = se_sess->se_node_acl; - nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); lport = vha->vha_tgt.target_lport_ptr; if (!lport) { @@ -1680,7 +1676,6 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha, (struct tcm_qla2xxx_lport *)target_lport_ptr; struct tcm_qla2xxx_lport *base_lport = (struct tcm_qla2xxx_lport *)base_vha->vha_tgt.target_lport_ptr; - struct tcm_qla2xxx_tpg *base_tpg; struct fc_vport_identifiers vport_id; if (!qla_tgt_mode_enabled(base_vha)) { @@ -1693,7 +1688,6 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha, pr_err("qla2xxx base_lport or tpg_1 not available\n"); return -EPERM; } - base_tpg = base_lport->tpg_1; memset(&vport_id, 0, sizeof(vport_id)); vport_id.port_name = npiv_wwpn; @@ -1958,7 +1952,7 @@ static void __exit tcm_qla2xxx_exit(void) tcm_qla2xxx_deregister_configfs(); } -MODULE_DESCRIPTION("TCM QLA2XXX series NPIV enabled fabric driver"); +MODULE_DESCRIPTION("TCM QLA24XX+ series NPIV enabled fabric driver"); MODULE_LICENSE("GPL"); module_init(tcm_qla2xxx_init); module_exit(tcm_qla2xxx_exit); diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c index 2ff092252b76..c126966130ab 100644 --- a/drivers/scsi/scsi_common.c +++ b/drivers/scsi/scsi_common.c @@ -5,6 +5,8 @@ #include <linux/bug.h> #include <linux/kernel.h> #include <linux/string.h> +#include <linux/errno.h> +#include <asm/unaligned.h> #include <scsi/scsi_common.h> /* NB: These are exposed through /proc/scsi/scsi and form part of the ABI. @@ -176,3 +178,110 @@ bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len, return true; } EXPORT_SYMBOL(scsi_normalize_sense); + +/** + * scsi_sense_desc_find - search for a given descriptor type in descriptor sense data format. + * @sense_buffer: byte array of descriptor format sense data + * @sb_len: number of valid bytes in sense_buffer + * @desc_type: value of descriptor type to find + * (e.g. 0 -> information) + * + * Notes: + * only valid when sense data is in descriptor format + * + * Return value: + * pointer to start of (first) descriptor if found else NULL + */ +const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, + int desc_type) +{ + int add_sen_len, add_len, desc_len, k; + const u8 * descp; + + if ((sb_len < 8) || (0 == (add_sen_len = sense_buffer[7]))) + return NULL; + if ((sense_buffer[0] < 0x72) || (sense_buffer[0] > 0x73)) + return NULL; + add_sen_len = (add_sen_len < (sb_len - 8)) ? + add_sen_len : (sb_len - 8); + descp = &sense_buffer[8]; + for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) { + descp += desc_len; + add_len = (k < (add_sen_len - 1)) ? descp[1]: -1; + desc_len = add_len + 2; + if (descp[0] == desc_type) + return descp; + if (add_len < 0) // short descriptor ?? + break; + } + return NULL; +} +EXPORT_SYMBOL(scsi_sense_desc_find); + +/** + * scsi_build_sense_buffer - build sense data in a buffer + * @desc: Sense format (non zero == descriptor format, + * 0 == fixed format) + * @buf: Where to build sense data + * @key: Sense key + * @asc: Additional sense code + * @ascq: Additional sense code qualifier + * + **/ +void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq) +{ + if (desc) { + buf[0] = 0x72; /* descriptor, current */ + buf[1] = key; + buf[2] = asc; + buf[3] = ascq; + buf[7] = 0; + } else { + buf[0] = 0x70; /* fixed, current */ + buf[2] = key; + buf[7] = 0xa; + buf[12] = asc; + buf[13] = ascq; + } +} +EXPORT_SYMBOL(scsi_build_sense_buffer); + +/** + * scsi_set_sense_information - set the information field in a + * formatted sense data buffer + * @buf: Where to build sense data + * @buf_len: buffer length + * @info: 64-bit information value to be set + * + * Return value: + * 0 on success or EINVAL for invalid sense buffer length + **/ +int scsi_set_sense_information(u8 *buf, int buf_len, u64 info) +{ + if ((buf[0] & 0x7f) == 0x72) { + u8 *ucp, len; + + len = buf[7]; + ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0); + if (!ucp) { + buf[7] = len + 0xc; + ucp = buf + 8 + len; + } + + if (buf_len < len + 0xc) + /* Not enough room for info */ + return -EINVAL; + + ucp[0] = 0; + ucp[1] = 0xa; + ucp[2] = 0x80; /* Valid bit */ + ucp[3] = 0; + put_unaligned_be64(info, &ucp[4]); + } else if ((buf[0] & 0x7f) == 0x70) { + buf[0] |= 0x80; + put_unaligned_be64(info, &buf[3]); + } + + return 0; +} +EXPORT_SYMBOL(scsi_set_sense_information); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index afd34a608fe7..dc4ee1479ceb 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -33,6 +33,7 @@ #include <scsi/scsi_device.h> #include <scsi/scsi_driver.h> #include <scsi/scsi_eh.h> +#include <scsi/scsi_common.h> #include <scsi/scsi_transport.h> #include <scsi/scsi_host.h> #include <scsi/scsi_ioctl.h> @@ -2416,45 +2417,6 @@ bool scsi_command_normalize_sense(const struct scsi_cmnd *cmd, EXPORT_SYMBOL(scsi_command_normalize_sense); /** - * scsi_sense_desc_find - search for a given descriptor type in descriptor sense data format. - * @sense_buffer: byte array of descriptor format sense data - * @sb_len: number of valid bytes in sense_buffer - * @desc_type: value of descriptor type to find - * (e.g. 0 -> information) - * - * Notes: - * only valid when sense data is in descriptor format - * - * Return value: - * pointer to start of (first) descriptor if found else NULL - */ -const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, - int desc_type) -{ - int add_sen_len, add_len, desc_len, k; - const u8 * descp; - - if ((sb_len < 8) || (0 == (add_sen_len = sense_buffer[7]))) - return NULL; - if ((sense_buffer[0] < 0x72) || (sense_buffer[0] > 0x73)) - return NULL; - add_sen_len = (add_sen_len < (sb_len - 8)) ? - add_sen_len : (sb_len - 8); - descp = &sense_buffer[8]; - for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) { - descp += desc_len; - add_len = (k < (add_sen_len - 1)) ? descp[1]: -1; - desc_len = add_len + 2; - if (descp[0] == desc_type) - return descp; - if (add_len < 0) // short descriptor ?? - break; - } - return NULL; -} -EXPORT_SYMBOL(scsi_sense_desc_find); - -/** * scsi_get_sense_info_fld - get information field from sense data (either fixed or descriptor format) * @sense_buffer: byte array of sense data * @sb_len: number of valid bytes in sense_buffer @@ -2503,31 +2465,3 @@ int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len, } } EXPORT_SYMBOL(scsi_get_sense_info_fld); - -/** - * scsi_build_sense_buffer - build sense data in a buffer - * @desc: Sense format (non zero == descriptor format, - * 0 == fixed format) - * @buf: Where to build sense data - * @key: Sense key - * @asc: Additional sense code - * @ascq: Additional sense code qualifier - * - **/ -void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq) -{ - if (desc) { - buf[0] = 0x72; /* descriptor, current */ - buf[1] = key; - buf[2] = asc; - buf[3] = ascq; - buf[7] = 0; - } else { - buf[0] = 0x70; /* fixed, current */ - buf[2] = key; - buf[7] = 0xa; - buf[12] = asc; - buf[13] = ascq; - } -} -EXPORT_SYMBOL(scsi_build_sense_buffer); diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index fd092909a457..13f59b79ecb3 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1209,7 +1209,6 @@ static u32 iscsit_do_crypto_hash_sg( u8 *pad_bytes) { u32 data_crc; - u32 i; struct scatterlist *sg; unsigned int page_off; @@ -1218,15 +1217,15 @@ static u32 iscsit_do_crypto_hash_sg( sg = cmd->first_data_sg; page_off = cmd->first_data_sg_off; - i = 0; while (data_length) { - u32 cur_len = min_t(u32, data_length, (sg[i].length - page_off)); + u32 cur_len = min_t(u32, data_length, (sg->length - page_off)); - crypto_hash_update(hash, &sg[i], cur_len); + crypto_hash_update(hash, sg, cur_len); data_length -= cur_len; page_off = 0; - i++; + /* iscsit_map_iovec has already checked for invalid sg pointers */ + sg = sg_next(sg); } if (padding) { @@ -2556,7 +2555,7 @@ static int iscsit_send_conn_drop_async_message( cmd->stat_sn = conn->stat_sn++; hdr->statsn = cpu_to_be32(cmd->stat_sn); hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); - hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); + hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn)); hdr->async_event = ISCSI_ASYNC_MSG_DROPPING_CONNECTION; hdr->param1 = cpu_to_be16(cmd->logout_cid); hdr->param2 = cpu_to_be16(conn->sess->sess_ops->DefaultTime2Wait); @@ -2628,7 +2627,7 @@ iscsit_build_datain_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn, hdr->statsn = cpu_to_be32(0xFFFFFFFF); hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); - hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); + hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn)); hdr->datasn = cpu_to_be32(datain->data_sn); hdr->offset = cpu_to_be32(datain->offset); @@ -2839,7 +2838,7 @@ iscsit_build_logout_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, iscsit_increment_maxcmdsn(cmd, conn->sess); hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); - hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); + hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn)); pr_debug("Built Logout Response ITT: 0x%08x StatSN:" " 0x%08x Response: 0x%02x CID: %hu on CID: %hu\n", @@ -2902,7 +2901,7 @@ iscsit_build_nopin_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, iscsit_increment_maxcmdsn(cmd, conn->sess); hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); - hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); + hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn)); pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x," " StatSN: 0x%08x, Length %u\n", (nopout_response) ? @@ -3049,7 +3048,7 @@ static int iscsit_send_r2t( hdr->ttt = cpu_to_be32(r2t->targ_xfer_tag); hdr->statsn = cpu_to_be32(conn->stat_sn); hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); - hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); + hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn)); hdr->r2tsn = cpu_to_be32(r2t->r2t_sn); hdr->data_offset = cpu_to_be32(r2t->offset); hdr->data_length = cpu_to_be32(r2t->xfer_len); @@ -3202,7 +3201,7 @@ void iscsit_build_rsp_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn, iscsit_increment_maxcmdsn(cmd, conn->sess); hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); - hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); + hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn)); pr_debug("Built SCSI Response, ITT: 0x%08x, StatSN: 0x%08x," " Response: 0x%02x, SAM Status: 0x%02x, CID: %hu\n", @@ -3321,7 +3320,7 @@ iscsit_build_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, iscsit_increment_maxcmdsn(cmd, conn->sess); hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); - hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); + hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn)); pr_debug("Built Task Management Response ITT: 0x%08x," " StatSN: 0x%08x, Response: 0x%02x, CID: %hu\n", @@ -3399,6 +3398,7 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd, int target_name_printed; unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */ unsigned char *text_in = cmd->text_in_ptr, *text_ptr = NULL; + bool active; buffer_len = min(conn->conn_ops->MaxRecvDataSegmentLength, SENDTARGETS_BUF_LIMIT); @@ -3452,13 +3452,12 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd, } spin_lock(&tpg->tpg_state_lock); - if ((tpg->tpg_state == TPG_STATE_FREE) || - (tpg->tpg_state == TPG_STATE_INACTIVE)) { - spin_unlock(&tpg->tpg_state_lock); - continue; - } + active = (tpg->tpg_state == TPG_STATE_ACTIVE); spin_unlock(&tpg->tpg_state_lock); + if (!active && tpg->tpg_attrib.tpg_enabled_sendtargets) + continue; + spin_lock(&tpg->tpg_np_lock); list_for_each_entry(tpg_np, &tpg->tpg_gnp_list, tpg_np_list) { @@ -3576,7 +3575,7 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, */ cmd->maxcmdsn_inc = 0; hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); - hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); + hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn)); pr_debug("Built Text Response: ITT: 0x%08x, TTT: 0x%08x, StatSN: 0x%08x," " Length: %u, CID: %hu F: %d C: %d\n", cmd->init_task_tag, @@ -3654,7 +3653,7 @@ iscsit_build_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn, cmd->stat_sn = conn->stat_sn++; hdr->statsn = cpu_to_be32(cmd->stat_sn); hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); - hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); + hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn)); } EXPORT_SYMBOL(iscsit_build_reject); diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index c1898c84b3d2..48f708bc101d 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -656,6 +656,7 @@ static ssize_t lio_target_nacl_show_info( struct iscsi_conn *conn; struct se_session *se_sess; ssize_t rb = 0; + u32 max_cmd_sn; spin_lock_bh(&se_nacl->nacl_sess_lock); se_sess = se_nacl->nacl_sess; @@ -703,11 +704,12 @@ static ssize_t lio_target_nacl_show_info( " Values]-----------------------\n"); rb += sprintf(page+rb, " CmdSN/WR : CmdSN/WC : ExpCmdSN" " : MaxCmdSN : ITT : TTT\n"); + max_cmd_sn = (u32) atomic_read(&sess->max_cmd_sn); rb += sprintf(page+rb, " 0x%08x 0x%08x 0x%08x 0x%08x" " 0x%08x 0x%08x\n", sess->cmdsn_window, - (sess->max_cmd_sn - sess->exp_cmd_sn) + 1, - sess->exp_cmd_sn, sess->max_cmd_sn, + (max_cmd_sn - sess->exp_cmd_sn) + 1, + sess->exp_cmd_sn, max_cmd_sn, sess->init_task_tag, sess->targ_xfer_tag); rb += sprintf(page+rb, "----------------------[iSCSI" " Connections]-------------------------\n"); @@ -1010,6 +1012,11 @@ TPG_ATTR(t10_pi, S_IRUGO | S_IWUSR); */ DEF_TPG_ATTRIB(fabric_prot_type); TPG_ATTR(fabric_prot_type, S_IRUGO | S_IWUSR); +/* + * Define iscsi_tpg_attrib_s_tpg_enabled_sendtargets + */ +DEF_TPG_ATTRIB(tpg_enabled_sendtargets); +TPG_ATTR(tpg_enabled_sendtargets, S_IRUGO | S_IWUSR); static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = { &iscsi_tpg_attrib_authentication.attr, @@ -1024,6 +1031,7 @@ static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = { &iscsi_tpg_attrib_default_erl.attr, &iscsi_tpg_attrib_t10_pi.attr, &iscsi_tpg_attrib_fabric_prot_type.attr, + &iscsi_tpg_attrib_tpg_enabled_sendtargets.attr, NULL, }; diff --git a/drivers/target/iscsi/iscsi_target_device.c b/drivers/target/iscsi/iscsi_target_device.c index 5fabcd3d623f..07d2ef67dba6 100644 --- a/drivers/target/iscsi/iscsi_target_device.c +++ b/drivers/target/iscsi/iscsi_target_device.c @@ -47,7 +47,7 @@ void iscsit_determine_maxcmdsn(struct iscsi_session *sess) * core_set_queue_depth_for_node(). */ sess->cmdsn_window = se_nacl->queue_depth; - sess->max_cmd_sn = (sess->max_cmd_sn + se_nacl->queue_depth) - 1; + atomic_set(&sess->max_cmd_sn, (u32) atomic_read(&sess->max_cmd_sn) + se_nacl->queue_depth - 1); } void iscsit_increment_maxcmdsn(struct iscsi_cmd *cmd, struct iscsi_session *sess) @@ -57,9 +57,6 @@ void iscsit_increment_maxcmdsn(struct iscsi_cmd *cmd, struct iscsi_session *sess cmd->maxcmdsn_inc = 1; - mutex_lock(&sess->cmdsn_mutex); - sess->max_cmd_sn += 1; - pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn); - mutex_unlock(&sess->cmdsn_mutex); + pr_debug("Updated MaxCmdSN to 0x%08x\n", atomic_inc_return(&sess->max_cmd_sn)); } EXPORT_SYMBOL(iscsit_increment_maxcmdsn); diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 7e8f65e5448f..7a62dfddff01 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -331,7 +331,7 @@ static int iscsi_login_zero_tsih_s1( * The FFP CmdSN window values will be allocated from the TPG's * Initiator Node's ACL once the login has been successfully completed. */ - sess->max_cmd_sn = be32_to_cpu(pdu->cmdsn); + atomic_set(&sess->max_cmd_sn, be32_to_cpu(pdu->cmdsn)); sess->sess_ops = kzalloc(sizeof(struct iscsi_sess_ops), GFP_KERNEL); if (!sess->sess_ops) { diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index f9cde9141836..ee830581204a 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -341,7 +341,6 @@ static int iscsi_target_check_first_request( static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_login *login) { u32 padding = 0; - struct iscsi_session *sess = conn->sess; struct iscsi_login_rsp *login_rsp; login_rsp = (struct iscsi_login_rsp *) login->rsp; @@ -353,7 +352,7 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log login_rsp->itt = login->init_task_tag; login_rsp->statsn = cpu_to_be32(conn->stat_sn++); login_rsp->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); - login_rsp->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); + login_rsp->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn)); pr_debug("Sending Login Response, Flags: 0x%02x, ITT: 0x%08x," " ExpCmdSN; 0x%08x, MaxCmdSN: 0x%08x, StatSN: 0x%08x, Length:" @@ -382,10 +381,8 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log goto err; login->rsp_length = 0; - mutex_lock(&sess->cmdsn_mutex); - login_rsp->exp_cmdsn = cpu_to_be32(sess->exp_cmd_sn); - login_rsp->max_cmdsn = cpu_to_be32(sess->max_cmd_sn); - mutex_unlock(&sess->cmdsn_mutex); + login_rsp->exp_cmdsn = cpu_to_be32(login_rsp->exp_cmdsn); + login_rsp->max_cmdsn = cpu_to_be32(login_rsp->max_cmdsn); return 0; diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c index cf59c397007b..11320df939f7 100644 --- a/drivers/target/iscsi/iscsi_target_tmr.c +++ b/drivers/target/iscsi/iscsi_target_tmr.c @@ -50,7 +50,7 @@ u8 iscsit_tmr_abort_task( pr_err("Unable to locate RefTaskTag: 0x%08x on CID:" " %hu.\n", hdr->rtt, conn->cid); return (iscsi_sna_gte(be32_to_cpu(hdr->refcmdsn), conn->sess->exp_cmd_sn) && - iscsi_sna_lte(be32_to_cpu(hdr->refcmdsn), conn->sess->max_cmd_sn)) ? + iscsi_sna_lte(be32_to_cpu(hdr->refcmdsn), (u32) atomic_read(&conn->sess->max_cmd_sn))) ? ISCSI_TMF_RSP_COMPLETE : ISCSI_TMF_RSP_NO_TASK; } if (ref_cmd->cmd_sn != be32_to_cpu(hdr->refcmdsn)) { diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index 968068ffcb1c..8262a853e888 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -226,6 +226,7 @@ static void iscsit_set_default_tpg_attribs(struct iscsi_portal_group *tpg) a->default_erl = TA_DEFAULT_ERL; a->t10_pi = TA_DEFAULT_T10_PI; a->fabric_prot_type = TA_DEFAULT_FABRIC_PROT_TYPE; + a->tpg_enabled_sendtargets = TA_DEFAULT_TPG_ENABLED_SENDTARGETS; } int iscsit_tpg_add_portal_group(struct iscsi_tiqn *tiqn, struct iscsi_portal_group *tpg) @@ -892,3 +893,21 @@ int iscsit_ta_fabric_prot_type( return 0; } + +int iscsit_ta_tpg_enabled_sendtargets( + struct iscsi_portal_group *tpg, + u32 flag) +{ + struct iscsi_tpg_attrib *a = &tpg->tpg_attrib; + + if ((flag != 0) && (flag != 1)) { + pr_err("Illegal value %d\n", flag); + return -EINVAL; + } + + a->tpg_enabled_sendtargets = flag; + pr_debug("iSCSI_TPG[%hu] - TPG enabled bit required for SendTargets:" + " %s\n", tpg->tpgt, (a->tpg_enabled_sendtargets) ? "ON" : "OFF"); + + return 0; +} diff --git a/drivers/target/iscsi/iscsi_target_tpg.h b/drivers/target/iscsi/iscsi_target_tpg.h index 95ff5bdecd71..a2790fd8f7da 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.h +++ b/drivers/target/iscsi/iscsi_target_tpg.h @@ -40,5 +40,6 @@ extern int iscsit_ta_demo_mode_discovery(struct iscsi_portal_group *, u32); extern int iscsit_ta_default_erl(struct iscsi_portal_group *, u32); extern int iscsit_ta_t10_pi(struct iscsi_portal_group *, u32); extern int iscsit_ta_fabric_prot_type(struct iscsi_portal_group *, u32); +extern int iscsit_ta_tpg_enabled_sendtargets(struct iscsi_portal_group *, u32); #endif /* ISCSI_TARGET_TPG_H */ diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index a2bff0702eb2..7df4fac69f39 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -233,6 +233,7 @@ struct iscsi_r2t *iscsit_get_holder_for_r2tsn( static inline int iscsit_check_received_cmdsn(struct iscsi_session *sess, u32 cmdsn) { + u32 max_cmdsn; int ret; /* @@ -241,10 +242,10 @@ static inline int iscsit_check_received_cmdsn(struct iscsi_session *sess, u32 cm * or order CmdSNs due to multiple connection sessions and/or * CRC failures. */ - if (iscsi_sna_gt(cmdsn, sess->max_cmd_sn)) { + max_cmdsn = atomic_read(&sess->max_cmd_sn); + if (iscsi_sna_gt(cmdsn, max_cmdsn)) { pr_err("Received CmdSN: 0x%08x is greater than" - " MaxCmdSN: 0x%08x, ignoring.\n", cmdsn, - sess->max_cmd_sn); + " MaxCmdSN: 0x%08x, ignoring.\n", cmdsn, max_cmdsn); ret = CMDSN_MAXCMDSN_OVERRUN; } else if (cmdsn == sess->exp_cmd_sn) { diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index a556bdebd775..5bc85ffed720 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -526,7 +526,7 @@ static inline struct tcm_loop_tpg *tl_tpg(struct se_portal_group *se_tpg) static char *tcm_loop_get_endpoint_wwn(struct se_portal_group *se_tpg) { /* - * Return the passed NAA identifier for the SAS Target Port + * Return the passed NAA identifier for the Target Port */ return &tl_tpg(se_tpg)->tl_hba->tl_wwn_address[0]; } @@ -845,7 +845,7 @@ static int tcm_loop_make_nexus( transport_free_session(tl_nexus->se_sess); goto out; } - /* Now, register the SAS I_T Nexus as active. */ + /* Now, register the I_T Nexus as active. */ transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl, tl_nexus->se_sess, tl_nexus); tl_tpg->tl_nexus = tl_nexus; @@ -884,7 +884,7 @@ static int tcm_loop_drop_nexus( " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tpg->tl_hba), tl_nexus->se_sess->se_node_acl->initiatorname); /* - * Release the SCSI I_T Nexus to the emulated SAS Target Port + * Release the SCSI I_T Nexus to the emulated Target Port */ transport_deregister_session(tl_nexus->se_sess); tpg->tl_nexus = NULL; @@ -1034,6 +1034,11 @@ static ssize_t tcm_loop_tpg_store_transport_status( } if (!strncmp(page, "offline", 7)) { tl_tpg->tl_transport_status = TCM_TRANSPORT_OFFLINE; + if (tl_tpg->tl_nexus) { + struct se_session *tl_sess = tl_tpg->tl_nexus->se_sess; + + core_allocate_nexus_loss_ua(tl_sess->se_node_acl); + } return count; } return -EINVAL; @@ -1077,7 +1082,7 @@ static struct se_portal_group *tcm_loop_make_naa_tpg( tl_tpg->tl_hba = tl_hba; tl_tpg->tl_tpgt = tpgt; /* - * Register the tl_tpg as a emulated SAS TCM Target Endpoint + * Register the tl_tpg as a emulated TCM Target Endpoint */ ret = core_tpg_register(wwn, &tl_tpg->tl_se_tpg, tl_hba->tl_proto_id); if (ret < 0) @@ -1102,11 +1107,11 @@ static void tcm_loop_drop_naa_tpg( tl_hba = tl_tpg->tl_hba; tpgt = tl_tpg->tl_tpgt; /* - * Release the I_T Nexus for the Virtual SAS link if present + * Release the I_T Nexus for the Virtual target link if present */ tcm_loop_drop_nexus(tl_tpg); /* - * Deregister the tl_tpg as a emulated SAS TCM Target Endpoint + * Deregister the tl_tpg as a emulated TCM Target Endpoint */ core_tpg_deregister(se_tpg); @@ -1199,8 +1204,9 @@ static void tcm_loop_drop_scsi_hba( struct tcm_loop_hba, tl_hba_wwn); pr_debug("TCM_Loop_ConfigFS: Deallocating emulated Target" - " SAS Address: %s at Linux/SCSI Host ID: %d\n", - tl_hba->tl_wwn_address, tl_hba->sh->host_no); + " %s Address: %s at Linux/SCSI Host ID: %d\n", + tcm_loop_dump_proto_id(tl_hba), tl_hba->tl_wwn_address, + tl_hba->sh->host_no); /* * Call device_unregister() on the original tl_hba->dev. * tcm_loop_fabric_scsi.c:tcm_loop_release_adapter() will diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 09e682b1c549..dcc424ac35d4 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -620,8 +620,6 @@ struct se_lun_acl *core_dev_init_initiator_node_lun_acl( lacl->mapped_lun = mapped_lun; lacl->se_lun_nacl = nacl; - snprintf(lacl->initiatorname, TRANSPORT_IQN_LEN, "%s", - nacl->initiatorname); return lacl; } @@ -656,7 +654,7 @@ int core_dev_add_initiator_node_lun_acl( " InitiatorNode: %s\n", tpg->se_tpg_tfo->get_fabric_name(), tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun, lacl->mapped_lun, (lun_access & TRANSPORT_LUNFLAGS_READ_WRITE) ? "RW" : "RO", - lacl->initiatorname); + nacl->initiatorname); /* * Check to see if there are any existing persistent reservation APTPL * pre-registrations that need to be enabled for this LUN ACL.. @@ -688,7 +686,7 @@ int core_dev_del_initiator_node_lun_acl( " InitiatorNode: %s Mapped LUN: %llu\n", tpg->se_tpg_tfo->get_fabric_name(), tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun, - lacl->initiatorname, lacl->mapped_lun); + nacl->initiatorname, lacl->mapped_lun); return 0; } @@ -701,7 +699,7 @@ void core_dev_free_initiator_node_lun_acl( " Mapped LUN: %llu\n", tpg->se_tpg_tfo->get_fabric_name(), tpg->se_tpg_tfo->tpg_get_tag(tpg), tpg->se_tpg_tfo->get_fabric_name(), - lacl->initiatorname, lacl->mapped_lun); + lacl->se_lun_nacl->initiatorname, lacl->mapped_lun); kfree(lacl); } @@ -754,7 +752,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->dev_link_magic = SE_DEV_LINK_MAGIC; dev->se_hba = hba; dev->transport = hba->backend->ops; - dev->prot_length = sizeof(struct se_dif_v1_tuple); + dev->prot_length = sizeof(struct t10_pi_tuple); dev->hba_index = hba->hba_index; INIT_LIST_HEAD(&dev->dev_list); @@ -771,7 +769,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) spin_lock_init(&dev->se_tmr_lock); spin_lock_init(&dev->qf_cmd_lock); sema_init(&dev->caw_sem, 1); - atomic_set(&dev->dev_ordered_id, 0); INIT_LIST_HEAD(&dev->t10_wwn.t10_vpd_list); spin_lock_init(&dev->t10_wwn.t10_vpd_lock); INIT_LIST_HEAD(&dev->t10_pr.registration_list); diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 48a36989c1a6..be42429468e2 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -203,7 +203,7 @@ static ssize_t target_fabric_mappedlun_store_write_protect( pr_debug("%s_ConfigFS: Changed Initiator ACL: %s" " Mapped LUN: %llu Write Protect bit to %s\n", se_tpg->se_tpg_tfo->get_fabric_name(), - lacl->initiatorname, lacl->mapped_lun, (op) ? "ON" : "OFF"); + se_nacl->initiatorname, lacl->mapped_lun, (op) ? "ON" : "OFF"); return count; diff --git a/drivers/target/target_core_hba.c b/drivers/target/target_core_hba.c index be9cefc07407..9522960c7fdd 100644 --- a/drivers/target/target_core_hba.c +++ b/drivers/target/target_core_hba.c @@ -184,3 +184,8 @@ core_delete_hba(struct se_hba *hba) kfree(hba); return 0; } + +bool target_sense_desc_format(struct se_device *dev) +{ + return dev->transport->get_blocks(dev) > U32_MAX; +} diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index e318ddbe15da..0b4b2a67d9f9 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -154,6 +154,38 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd) return 0; } +static sense_reason_t +sbc_emulate_startstop(struct se_cmd *cmd) +{ + unsigned char *cdb = cmd->t_task_cdb; + + /* + * See sbc3r36 section 5.25 + * Immediate bit should be set since there is nothing to complete + * POWER CONDITION MODIFIER 0h + */ + if (!(cdb[1] & 1) || cdb[2] || cdb[3]) + return TCM_INVALID_CDB_FIELD; + + /* + * See sbc3r36 section 5.25 + * POWER CONDITION 0h START_VALID - process START and LOEJ + */ + if (cdb[4] >> 4 & 0xf) + return TCM_INVALID_CDB_FIELD; + + /* + * See sbc3r36 section 5.25 + * LOEJ 0h - nothing to load or unload + * START 1h - we are ready + */ + if (!(cdb[4] & 1) || (cdb[4] & 2) || (cdb[4] & 4)) + return TCM_INVALID_CDB_FIELD; + + target_complete_cmd(cmd, SAM_STAT_GOOD); + return 0; +} + sector_t sbc_get_write_same_sectors(struct se_cmd *cmd) { u32 num_blocks; @@ -960,6 +992,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) " than 1\n", sectors); return TCM_INVALID_CDB_FIELD; } + if (sbc_check_dpofua(dev, cmd, cdb)) + return TCM_INVALID_CDB_FIELD; + /* * Double size because we have two buffers, note that * zero is not an error.. @@ -1069,6 +1104,10 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) size = 0; cmd->execute_cmd = sbc_emulate_noop; break; + case START_STOP: + size = 0; + cmd->execute_cmd = sbc_emulate_startstop; + break; default: ret = spc_parse_cdb(cmd, &size); if (ret) @@ -1191,7 +1230,7 @@ void sbc_dif_generate(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - struct se_dif_v1_tuple *sdt; + struct t10_pi_tuple *sdt; struct scatterlist *dsg = cmd->t_data_sg, *psg; sector_t sector = cmd->t_task_lba; void *daddr, *paddr; @@ -1203,7 +1242,7 @@ sbc_dif_generate(struct se_cmd *cmd) daddr = kmap_atomic(sg_page(dsg)) + dsg->offset; for (j = 0; j < psg->length; - j += sizeof(struct se_dif_v1_tuple)) { + j += sizeof(*sdt)) { __u16 crc; unsigned int avail; @@ -1256,7 +1295,7 @@ sbc_dif_generate(struct se_cmd *cmd) } static sense_reason_t -sbc_dif_v1_verify(struct se_cmd *cmd, struct se_dif_v1_tuple *sdt, +sbc_dif_v1_verify(struct se_cmd *cmd, struct t10_pi_tuple *sdt, __u16 crc, sector_t sector, unsigned int ei_lba) { __be16 csum; @@ -1346,7 +1385,7 @@ sbc_dif_verify(struct se_cmd *cmd, sector_t start, unsigned int sectors, unsigned int ei_lba, struct scatterlist *psg, int psg_off) { struct se_device *dev = cmd->se_dev; - struct se_dif_v1_tuple *sdt; + struct t10_pi_tuple *sdt; struct scatterlist *dsg = cmd->t_data_sg; sector_t sector = start; void *daddr, *paddr; @@ -1361,7 +1400,7 @@ sbc_dif_verify(struct se_cmd *cmd, sector_t start, unsigned int sectors, for (i = psg_off; i < psg->length && sector < start + sectors; - i += sizeof(struct se_dif_v1_tuple)) { + i += sizeof(*sdt)) { __u16 crc; unsigned int avail; diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index f87d4cef6d39..3295eba7313b 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -768,7 +768,12 @@ static int spc_modesense_control(struct se_cmd *cmd, u8 pc, u8 *p) if (pc == 1) goto out; - p[2] = 2; + /* GLTSD: No implicit save of log parameters */ + p[2] = (1 << 1); + if (target_sense_desc_format(dev)) + /* D_SENSE: Descriptor format sense data for 64bit sectors */ + p[2] |= (1 << 2); + /* * From spc4r23, 7.4.7 Control mode page * @@ -1151,6 +1156,7 @@ static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd) unsigned char *rbuf; u8 ua_asc = 0, ua_ascq = 0; unsigned char buf[SE_SENSE_BUF]; + bool desc_format = target_sense_desc_format(cmd->se_dev); memset(buf, 0, SE_SENSE_BUF); @@ -1164,32 +1170,11 @@ static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd) if (!rbuf) return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { - /* - * CURRENT ERROR, UNIT ATTENTION - */ - buf[0] = 0x70; - buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION; - - /* - * The Additional Sense Code (ASC) from the UNIT ATTENTION - */ - buf[SPC_ASC_KEY_OFFSET] = ua_asc; - buf[SPC_ASCQ_KEY_OFFSET] = ua_ascq; - buf[7] = 0x0A; - } else { - /* - * CURRENT ERROR, NO SENSE - */ - buf[0] = 0x70; - buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE; - - /* - * NO ADDITIONAL SENSE INFORMATION - */ - buf[SPC_ASC_KEY_OFFSET] = 0x00; - buf[7] = 0x0A; - } + if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) + scsi_build_sense_buffer(desc_format, buf, UNIT_ATTENTION, + ua_asc, ua_ascq); + else + scsi_build_sense_buffer(desc_format, buf, NO_SENSE, 0x0, 0x0); memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); transport_kunmap_data_sg(cmd); @@ -1418,9 +1403,6 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) } break; default: - pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode" - " 0x%02x, sending CHECK_CONDITION.\n", - cmd->se_tfo->get_fabric_name(), cdb[0]); return TCM_UNSUPPORTED_SCSI_OPCODE; } diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index babde4ad841f..2d0381dd105c 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -41,6 +41,7 @@ #include "target_core_internal.h" #include "target_core_alua.h" #include "target_core_pr.h" +#include "target_core_ua.h" extern struct se_device *g_lun0_dev; @@ -83,6 +84,22 @@ struct se_node_acl *core_tpg_get_initiator_node_acl( } EXPORT_SYMBOL(core_tpg_get_initiator_node_acl); +void core_allocate_nexus_loss_ua( + struct se_node_acl *nacl) +{ + struct se_dev_entry *deve; + + if (!nacl) + return; + + rcu_read_lock(); + hlist_for_each_entry_rcu(deve, &nacl->lun_entry_hlist, link) + core_scsi3_ua_allocate(deve, 0x29, + ASCQ_29H_NEXUS_LOSS_OCCURRED); + rcu_read_unlock(); +} +EXPORT_SYMBOL(core_allocate_nexus_loss_ua); + /* core_tpg_add_node_to_devs(): * * diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index ce8574b7220c..3f0b50082de4 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -39,6 +39,7 @@ #include <net/sock.h> #include <net/tcp.h> #include <scsi/scsi_proto.h> +#include <scsi/scsi_common.h> #include <target/target_core_base.h> #include <target/target_core_backend.h> @@ -1087,9 +1088,9 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size) " 0x%02x\n", cmd->se_tfo->get_fabric_name(), cmd->data_length, size, cmd->t_task_cdb[0]); - if (cmd->data_direction == DMA_TO_DEVICE) { - pr_err("Rejecting underflow/overflow" - " WRITE data\n"); + if (cmd->data_direction == DMA_TO_DEVICE && + cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { + pr_err("Rejecting underflow/overflow WRITE data\n"); return TCM_INVALID_CDB_FIELD; } /* @@ -1177,14 +1178,7 @@ transport_check_alloc_task_attr(struct se_cmd *cmd) " emulation is not supported\n"); return TCM_INVALID_CDB_FIELD; } - /* - * Used to determine when ORDERED commands should go from - * Dormant to Active status. - */ - cmd->se_ordered_id = atomic_inc_return(&dev->dev_ordered_id); - pr_debug("Allocated se_ordered_id: %u for Task Attr: 0x%02x on %s\n", - cmd->se_ordered_id, cmd->sam_task_attr, - dev->transport->name); + return 0; } @@ -1246,6 +1240,11 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb) } ret = dev->transport->parse_cdb(cmd); + if (ret == TCM_UNSUPPORTED_SCSI_OPCODE) + pr_warn_ratelimited("%s/%s: Unsupported SCSI Opcode 0x%02x, sending CHECK_CONDITION.\n", + cmd->se_tfo->get_fabric_name(), + cmd->se_sess->se_node_acl->initiatorname, + cmd->t_task_cdb[0]); if (ret) return ret; @@ -1767,16 +1766,14 @@ static bool target_handle_task_attr(struct se_cmd *cmd) */ switch (cmd->sam_task_attr) { case TCM_HEAD_TAG: - pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x, " - "se_ordered_id: %u\n", - cmd->t_task_cdb[0], cmd->se_ordered_id); + pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x\n", + cmd->t_task_cdb[0]); return false; case TCM_ORDERED_TAG: atomic_inc_mb(&dev->dev_ordered_sync); - pr_debug("Added ORDERED for CDB: 0x%02x to ordered list, " - " se_ordered_id: %u\n", - cmd->t_task_cdb[0], cmd->se_ordered_id); + pr_debug("Added ORDERED for CDB: 0x%02x to ordered list\n", + cmd->t_task_cdb[0]); /* * Execute an ORDERED command if no other older commands @@ -1800,10 +1797,8 @@ static bool target_handle_task_attr(struct se_cmd *cmd) list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list); spin_unlock(&dev->delayed_cmd_lock); - pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to" - " delayed CMD list, se_ordered_id: %u\n", - cmd->t_task_cdb[0], cmd->sam_task_attr, - cmd->se_ordered_id); + pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to delayed CMD listn", + cmd->t_task_cdb[0], cmd->sam_task_attr); return true; } @@ -1888,20 +1883,18 @@ static void transport_complete_task_attr(struct se_cmd *cmd) if (cmd->sam_task_attr == TCM_SIMPLE_TAG) { atomic_dec_mb(&dev->simple_cmds); dev->dev_cur_ordered_id++; - pr_debug("Incremented dev->dev_cur_ordered_id: %u for" - " SIMPLE: %u\n", dev->dev_cur_ordered_id, - cmd->se_ordered_id); + pr_debug("Incremented dev->dev_cur_ordered_id: %u for SIMPLE\n", + dev->dev_cur_ordered_id); } else if (cmd->sam_task_attr == TCM_HEAD_TAG) { dev->dev_cur_ordered_id++; - pr_debug("Incremented dev_cur_ordered_id: %u for" - " HEAD_OF_QUEUE: %u\n", dev->dev_cur_ordered_id, - cmd->se_ordered_id); + pr_debug("Incremented dev_cur_ordered_id: %u for HEAD_OF_QUEUE\n", + dev->dev_cur_ordered_id); } else if (cmd->sam_task_attr == TCM_ORDERED_TAG) { atomic_dec_mb(&dev->dev_ordered_sync); dev->dev_cur_ordered_id++; - pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED:" - " %u\n", dev->dev_cur_ordered_id, cmd->se_ordered_id); + pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED\n", + dev->dev_cur_ordered_id); } target_restart_delayed_cmds(dev); @@ -2615,37 +2608,159 @@ bool transport_wait_for_tasks(struct se_cmd *cmd) } EXPORT_SYMBOL(transport_wait_for_tasks); -static int transport_get_sense_codes( - struct se_cmd *cmd, - u8 *asc, - u8 *ascq) +struct sense_info { + u8 key; + u8 asc; + u8 ascq; + bool add_sector_info; +}; + +static const struct sense_info sense_info_table[] = { + [TCM_NO_SENSE] = { + .key = NOT_READY + }, + [TCM_NON_EXISTENT_LUN] = { + .key = ILLEGAL_REQUEST, + .asc = 0x25 /* LOGICAL UNIT NOT SUPPORTED */ + }, + [TCM_UNSUPPORTED_SCSI_OPCODE] = { + .key = ILLEGAL_REQUEST, + .asc = 0x20, /* INVALID COMMAND OPERATION CODE */ + }, + [TCM_SECTOR_COUNT_TOO_MANY] = { + .key = ILLEGAL_REQUEST, + .asc = 0x20, /* INVALID COMMAND OPERATION CODE */ + }, + [TCM_UNKNOWN_MODE_PAGE] = { + .key = ILLEGAL_REQUEST, + .asc = 0x24, /* INVALID FIELD IN CDB */ + }, + [TCM_CHECK_CONDITION_ABORT_CMD] = { + .key = ABORTED_COMMAND, + .asc = 0x29, /* BUS DEVICE RESET FUNCTION OCCURRED */ + .ascq = 0x03, + }, + [TCM_INCORRECT_AMOUNT_OF_DATA] = { + .key = ABORTED_COMMAND, + .asc = 0x0c, /* WRITE ERROR */ + .ascq = 0x0d, /* NOT ENOUGH UNSOLICITED DATA */ + }, + [TCM_INVALID_CDB_FIELD] = { + .key = ILLEGAL_REQUEST, + .asc = 0x24, /* INVALID FIELD IN CDB */ + }, + [TCM_INVALID_PARAMETER_LIST] = { + .key = ILLEGAL_REQUEST, + .asc = 0x26, /* INVALID FIELD IN PARAMETER LIST */ + }, + [TCM_PARAMETER_LIST_LENGTH_ERROR] = { + .key = ILLEGAL_REQUEST, + .asc = 0x1a, /* PARAMETER LIST LENGTH ERROR */ + }, + [TCM_UNEXPECTED_UNSOLICITED_DATA] = { + .key = ILLEGAL_REQUEST, + .asc = 0x0c, /* WRITE ERROR */ + .ascq = 0x0c, /* UNEXPECTED_UNSOLICITED_DATA */ + }, + [TCM_SERVICE_CRC_ERROR] = { + .key = ABORTED_COMMAND, + .asc = 0x47, /* PROTOCOL SERVICE CRC ERROR */ + .ascq = 0x05, /* N/A */ + }, + [TCM_SNACK_REJECTED] = { + .key = ABORTED_COMMAND, + .asc = 0x11, /* READ ERROR */ + .ascq = 0x13, /* FAILED RETRANSMISSION REQUEST */ + }, + [TCM_WRITE_PROTECTED] = { + .key = DATA_PROTECT, + .asc = 0x27, /* WRITE PROTECTED */ + }, + [TCM_ADDRESS_OUT_OF_RANGE] = { + .key = ILLEGAL_REQUEST, + .asc = 0x21, /* LOGICAL BLOCK ADDRESS OUT OF RANGE */ + }, + [TCM_CHECK_CONDITION_UNIT_ATTENTION] = { + .key = UNIT_ATTENTION, + }, + [TCM_CHECK_CONDITION_NOT_READY] = { + .key = NOT_READY, + }, + [TCM_MISCOMPARE_VERIFY] = { + .key = MISCOMPARE, + .asc = 0x1d, /* MISCOMPARE DURING VERIFY OPERATION */ + .ascq = 0x00, + }, + [TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED] = { + .key = ABORTED_COMMAND, + .asc = 0x10, + .ascq = 0x01, /* LOGICAL BLOCK GUARD CHECK FAILED */ + .add_sector_info = true, + }, + [TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED] = { + .key = ABORTED_COMMAND, + .asc = 0x10, + .ascq = 0x02, /* LOGICAL BLOCK APPLICATION TAG CHECK FAILED */ + .add_sector_info = true, + }, + [TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED] = { + .key = ABORTED_COMMAND, + .asc = 0x10, + .ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */ + .add_sector_info = true, + }, + [TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = { + /* + * Returning ILLEGAL REQUEST would cause immediate IO errors on + * Solaris initiators. Returning NOT READY instead means the + * operations will be retried a finite number of times and we + * can survive intermittent errors. + */ + .key = NOT_READY, + .asc = 0x08, /* LOGICAL UNIT COMMUNICATION FAILURE */ + }, +}; + +static int translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason) { - *asc = cmd->scsi_asc; - *ascq = cmd->scsi_ascq; + const struct sense_info *si; + u8 *buffer = cmd->sense_buffer; + int r = (__force int)reason; + u8 asc, ascq; + bool desc_format = target_sense_desc_format(cmd->se_dev); - return 0; -} + if (r < ARRAY_SIZE(sense_info_table) && sense_info_table[r].key) + si = &sense_info_table[r]; + else + si = &sense_info_table[(__force int) + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE]; -static -void transport_err_sector_info(unsigned char *buffer, sector_t bad_sector) -{ - /* Place failed LBA in sense data information descriptor 0. */ - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 0xc; - buffer[SPC_DESC_TYPE_OFFSET] = 0; /* Information */ - buffer[SPC_ADDITIONAL_DESC_LEN_OFFSET] = 0xa; - buffer[SPC_VALIDITY_OFFSET] = 0x80; + if (reason == TCM_CHECK_CONDITION_UNIT_ATTENTION) { + core_scsi3_ua_for_check_condition(cmd, &asc, &ascq); + WARN_ON_ONCE(asc == 0); + } else if (si->asc == 0) { + WARN_ON_ONCE(cmd->scsi_asc == 0); + asc = cmd->scsi_asc; + ascq = cmd->scsi_ascq; + } else { + asc = si->asc; + ascq = si->ascq; + } - /* Descriptor Information: failing sector */ - put_unaligned_be64(bad_sector, &buffer[12]); + scsi_build_sense_buffer(desc_format, buffer, si->key, asc, ascq); + if (si->add_sector_info) + return scsi_set_sense_information(buffer, + cmd->scsi_sense_length, + cmd->bad_sector); + + return 0; } int transport_send_check_condition_and_sense(struct se_cmd *cmd, sense_reason_t reason, int from_transport) { - unsigned char *buffer = cmd->sense_buffer; unsigned long flags; - u8 asc = 0, ascq = 0; spin_lock_irqsave(&cmd->t_state_lock, flags); if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { @@ -2655,243 +2770,17 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd, cmd->se_cmd_flags |= SCF_SENT_CHECK_CONDITION; spin_unlock_irqrestore(&cmd->t_state_lock, flags); - if (!reason && from_transport) - goto after_reason; + if (!from_transport) { + int rc; - if (!from_transport) cmd->se_cmd_flags |= SCF_EMULATED_TASK_SENSE; - - /* - * Actual SENSE DATA, see SPC-3 7.23.2 SPC_SENSE_KEY_OFFSET uses - * SENSE KEY values from include/scsi/scsi.h - */ - switch (reason) { - case TCM_NO_SENSE: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* Not Ready */ - buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY; - /* NO ADDITIONAL SENSE INFORMATION */ - buffer[SPC_ASC_KEY_OFFSET] = 0; - buffer[SPC_ASCQ_KEY_OFFSET] = 0; - break; - case TCM_NON_EXISTENT_LUN: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ILLEGAL REQUEST */ - buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; - /* LOGICAL UNIT NOT SUPPORTED */ - buffer[SPC_ASC_KEY_OFFSET] = 0x25; - break; - case TCM_UNSUPPORTED_SCSI_OPCODE: - case TCM_SECTOR_COUNT_TOO_MANY: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ILLEGAL REQUEST */ - buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; - /* INVALID COMMAND OPERATION CODE */ - buffer[SPC_ASC_KEY_OFFSET] = 0x20; - break; - case TCM_UNKNOWN_MODE_PAGE: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ILLEGAL REQUEST */ - buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; - /* INVALID FIELD IN CDB */ - buffer[SPC_ASC_KEY_OFFSET] = 0x24; - break; - case TCM_CHECK_CONDITION_ABORT_CMD: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ABORTED COMMAND */ - buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND; - /* BUS DEVICE RESET FUNCTION OCCURRED */ - buffer[SPC_ASC_KEY_OFFSET] = 0x29; - buffer[SPC_ASCQ_KEY_OFFSET] = 0x03; - break; - case TCM_INCORRECT_AMOUNT_OF_DATA: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ABORTED COMMAND */ - buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND; - /* WRITE ERROR */ - buffer[SPC_ASC_KEY_OFFSET] = 0x0c; - /* NOT ENOUGH UNSOLICITED DATA */ - buffer[SPC_ASCQ_KEY_OFFSET] = 0x0d; - break; - case TCM_INVALID_CDB_FIELD: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ILLEGAL REQUEST */ - buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; - /* INVALID FIELD IN CDB */ - buffer[SPC_ASC_KEY_OFFSET] = 0x24; - break; - case TCM_INVALID_PARAMETER_LIST: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ILLEGAL REQUEST */ - buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; - /* INVALID FIELD IN PARAMETER LIST */ - buffer[SPC_ASC_KEY_OFFSET] = 0x26; - break; - case TCM_PARAMETER_LIST_LENGTH_ERROR: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ILLEGAL REQUEST */ - buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; - /* PARAMETER LIST LENGTH ERROR */ - buffer[SPC_ASC_KEY_OFFSET] = 0x1a; - break; - case TCM_UNEXPECTED_UNSOLICITED_DATA: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ABORTED COMMAND */ - buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND; - /* WRITE ERROR */ - buffer[SPC_ASC_KEY_OFFSET] = 0x0c; - /* UNEXPECTED_UNSOLICITED_DATA */ - buffer[SPC_ASCQ_KEY_OFFSET] = 0x0c; - break; - case TCM_SERVICE_CRC_ERROR: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ABORTED COMMAND */ - buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND; - /* PROTOCOL SERVICE CRC ERROR */ - buffer[SPC_ASC_KEY_OFFSET] = 0x47; - /* N/A */ - buffer[SPC_ASCQ_KEY_OFFSET] = 0x05; - break; - case TCM_SNACK_REJECTED: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ABORTED COMMAND */ - buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND; - /* READ ERROR */ - buffer[SPC_ASC_KEY_OFFSET] = 0x11; - /* FAILED RETRANSMISSION REQUEST */ - buffer[SPC_ASCQ_KEY_OFFSET] = 0x13; - break; - case TCM_WRITE_PROTECTED: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* DATA PROTECT */ - buffer[SPC_SENSE_KEY_OFFSET] = DATA_PROTECT; - /* WRITE PROTECTED */ - buffer[SPC_ASC_KEY_OFFSET] = 0x27; - break; - case TCM_ADDRESS_OUT_OF_RANGE: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ILLEGAL REQUEST */ - buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; - /* LOGICAL BLOCK ADDRESS OUT OF RANGE */ - buffer[SPC_ASC_KEY_OFFSET] = 0x21; - break; - case TCM_CHECK_CONDITION_UNIT_ATTENTION: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* UNIT ATTENTION */ - buffer[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION; - core_scsi3_ua_for_check_condition(cmd, &asc, &ascq); - buffer[SPC_ASC_KEY_OFFSET] = asc; - buffer[SPC_ASCQ_KEY_OFFSET] = ascq; - break; - case TCM_CHECK_CONDITION_NOT_READY: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* Not Ready */ - buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY; - transport_get_sense_codes(cmd, &asc, &ascq); - buffer[SPC_ASC_KEY_OFFSET] = asc; - buffer[SPC_ASCQ_KEY_OFFSET] = ascq; - break; - case TCM_MISCOMPARE_VERIFY: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - buffer[SPC_SENSE_KEY_OFFSET] = MISCOMPARE; - /* MISCOMPARE DURING VERIFY OPERATION */ - buffer[SPC_ASC_KEY_OFFSET] = 0x1d; - buffer[SPC_ASCQ_KEY_OFFSET] = 0x00; - break; - case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ILLEGAL REQUEST */ - buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; - /* LOGICAL BLOCK GUARD CHECK FAILED */ - buffer[SPC_ASC_KEY_OFFSET] = 0x10; - buffer[SPC_ASCQ_KEY_OFFSET] = 0x01; - transport_err_sector_info(buffer, cmd->bad_sector); - break; - case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ILLEGAL REQUEST */ - buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; - /* LOGICAL BLOCK APPLICATION TAG CHECK FAILED */ - buffer[SPC_ASC_KEY_OFFSET] = 0x10; - buffer[SPC_ASCQ_KEY_OFFSET] = 0x02; - transport_err_sector_info(buffer, cmd->bad_sector); - break; - case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ILLEGAL REQUEST */ - buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; - /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */ - buffer[SPC_ASC_KEY_OFFSET] = 0x10; - buffer[SPC_ASCQ_KEY_OFFSET] = 0x03; - transport_err_sector_info(buffer, cmd->bad_sector); - break; - case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE: - default: - /* CURRENT ERROR */ - buffer[0] = 0x70; - buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* - * Returning ILLEGAL REQUEST would cause immediate IO errors on - * Solaris initiators. Returning NOT READY instead means the - * operations will be retried a finite number of times and we - * can survive intermittent errors. - */ - buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY; - /* LOGICAL UNIT COMMUNICATION FAILURE */ - buffer[SPC_ASC_KEY_OFFSET] = 0x08; - break; + cmd->scsi_status = SAM_STAT_CHECK_CONDITION; + cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER; + rc = translate_sense_reason(cmd, reason); + if (rc) + return rc; } - /* - * This code uses linux/include/scsi/scsi.h SAM status codes! - */ - cmd->scsi_status = SAM_STAT_CHECK_CONDITION; - /* - * Automatically padded, this value is encoded in the fabric's - * data_length response PDU containing the SCSI defined sense data. - */ - cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER; -after_reason: trace_target_cmd_complete(cmd); return cmd->se_tfo->queue_status(cmd); } diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 68031723e5be..aa3caca8bace 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -255,7 +255,7 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg) struct ft_cmd *cmd = arg; struct fc_frame_header *fh; - if (unlikely(IS_ERR(fp))) { + if (IS_ERR(fp)) { /* XXX need to find cmd if queued */ cmd->seq = NULL; cmd->aborted = true; diff --git a/include/scsi/scsi_common.h b/include/scsi/scsi_common.h index 676b03b78e57..11571b2a831e 100644 --- a/include/scsi/scsi_common.h +++ b/include/scsi/scsi_common.h @@ -61,4 +61,9 @@ static inline bool scsi_sense_valid(const struct scsi_sense_hdr *sshdr) extern bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len, struct scsi_sense_hdr *sshdr); +extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq); +int scsi_set_sense_information(u8 *buf, int buf_len, u64 info); +extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, + int desc_type); + #endif /* _SCSI_COMMON_H_ */ diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 8d1d7fa67ec4..dbb8c640e26f 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -4,6 +4,7 @@ #include <linux/scatterlist.h> #include <scsi/scsi_cmnd.h> +#include <scsi/scsi_common.h> struct scsi_device; struct Scsi_Host; @@ -21,14 +22,9 @@ static inline bool scsi_sense_is_deferred(const struct scsi_sense_hdr *sshdr) return ((sshdr->response_code >= 0x70) && (sshdr->response_code & 1)); } -extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, - int desc_type); - extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len, u64 * info_out); -extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq); - extern int scsi_ioctl_reset(struct scsi_device *, int __user *); struct scsi_eh_save { diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index 0aedbb2c10e0..bd44013ae482 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -62,6 +62,8 @@ /* T10 protection information disabled by default */ #define TA_DEFAULT_T10_PI 0 #define TA_DEFAULT_FABRIC_PROT_TYPE 0 +/* TPG status needs to be enabled to return sendtargets discovery endpoint info */ +#define TA_DEFAULT_TPG_ENABLED_SENDTARGETS 1 #define ISCSI_IOV_DATA_BUFFER 5 @@ -636,7 +638,7 @@ struct iscsi_session { /* session wide counter: expected command sequence number */ u32 exp_cmd_sn; /* session wide counter: maximum allowed command sequence number */ - u32 max_cmd_sn; + atomic_t max_cmd_sn; struct list_head sess_ooo_cmdsn_list; /* LIO specific session ID */ @@ -764,6 +766,7 @@ struct iscsi_tpg_attrib { u32 default_erl; u8 t10_pi; u32 fabric_prot_type; + u32 tpg_enabled_sendtargets; struct iscsi_portal_group *tpg; }; diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 1e5c8f949bae..56cf8e485ef2 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -93,4 +93,6 @@ bool target_lun_is_rdonly(struct se_cmd *); sense_reason_t passthrough_parse_cdb(struct se_cmd *cmd, sense_reason_t (*exec_cmd)(struct se_cmd *cmd)); +bool target_sense_desc_format(struct se_device *dev); + #endif /* TARGET_CORE_BACKEND_H */ diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 17ae2d6a4891..ac9bf1c0e42d 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -6,6 +6,7 @@ #include <linux/dma-mapping.h> #include <linux/blkdev.h> #include <linux/percpu_ida.h> +#include <linux/t10-pi.h> #include <net/sock.h> #include <net/tcp.h> @@ -426,12 +427,6 @@ enum target_core_dif_check { TARGET_DIF_CHECK_REFTAG = 0x1 << 2, }; -struct se_dif_v1_tuple { - __be16 guard_tag; - __be16 app_tag; - __be32 ref_tag; -}; - /* for sam_task_attr */ #define TCM_SIMPLE_TAG 0x20 #define TCM_HEAD_TAG 0x21 @@ -444,6 +439,9 @@ struct se_cmd { u8 scsi_asc; u8 scsi_ascq; u16 scsi_sense_length; + unsigned cmd_wait_set:1; + unsigned unknown_data_length:1; + bool state_active:1; u64 tag; /* SAM command identifier aka task tag */ /* Delay for ALUA Active/NonOptimized state access in milliseconds */ int alua_nonop_delay; @@ -455,11 +453,8 @@ struct se_cmd { unsigned int map_tag; /* Transport protocol dependent state, see transport_state_table */ enum transport_state_table t_state; - unsigned cmd_wait_set:1; - unsigned unknown_data_length:1; /* See se_cmd_flags_table */ u32 se_cmd_flags; - u32 se_ordered_id; /* Total size in bytes associated with command */ u32 data_length; u32 residual_count; @@ -477,7 +472,6 @@ struct se_cmd { struct se_tmr_req *se_tmr_req; struct list_head se_cmd_list; struct completion cmd_wait_comp; - struct kref cmd_kref; const struct target_core_fabric_ops *se_tfo; sense_reason_t (*execute_cmd)(struct se_cmd *); sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool); @@ -497,6 +491,7 @@ struct se_cmd { #define CMD_T_REQUEST_STOP (1 << 8) #define CMD_T_BUSY (1 << 9) spinlock_t t_state_lock; + struct kref cmd_kref; struct completion t_transport_stop_comp; struct work_struct work; @@ -509,8 +504,10 @@ struct se_cmd { struct scatterlist *t_bidi_data_sg; unsigned int t_bidi_data_nents; + /* Used for lun->lun_ref counting */ + int lun_ref_active; + struct list_head state_list; - bool state_active; /* old task stop completion, consider merging with some of the above */ struct completion task_stop_comp; @@ -518,20 +515,17 @@ struct se_cmd { /* backend private data */ void *priv; - /* Used for lun->lun_ref counting */ - int lun_ref_active; - /* DIF related members */ enum target_prot_op prot_op; enum target_prot_type prot_type; u8 prot_checks; + bool prot_pto; u32 prot_length; u32 reftag_seed; struct scatterlist *t_prot_sg; unsigned int t_prot_nents; sense_reason_t pi_err; sector_t bad_sector; - bool prot_pto; }; struct se_ua { @@ -598,7 +592,6 @@ struct se_ml_stat_grps { }; struct se_lun_acl { - char initiatorname[TRANSPORT_IQN_LEN]; u64 mapped_lun; struct se_node_acl *se_lun_nacl; struct se_lun *se_lun; @@ -685,7 +678,6 @@ struct se_lun { #define SE_LUN_LINK_MAGIC 0xffff7771 u32 lun_link_magic; u32 lun_access; - u32 lun_flags; u32 lun_index; /* RELATIVE TARGET PORT IDENTIFER */ @@ -751,7 +743,6 @@ struct se_device { atomic_long_t write_bytes; /* Active commands on this virtual SE device */ atomic_t simple_cmds; - atomic_t dev_ordered_id; atomic_t dev_ordered_sync; atomic_t dev_qf_count; u32 export_count; diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 18afef91b447..69355feabd1d 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h @@ -152,6 +152,7 @@ int transport_generic_handle_tmr(struct se_cmd *); void transport_generic_request_failure(struct se_cmd *, sense_reason_t); void __target_execute_cmd(struct se_cmd *); int transport_lookup_tmr_lun(struct se_cmd *, u64); +void core_allocate_nexus_loss_ua(struct se_node_acl *acl); struct se_node_acl *core_tpg_get_initiator_node_acl(struct se_portal_group *tpg, unsigned char *); |