From eceb4459df4a5b6127ae479280168847b9780b25 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 1 Jun 2017 20:21:33 -0700 Subject: iscsi-target: Avoid holding ->tpg_state_lock during param update As originally reported by Jia-Ju, iscsit_tpg_enable_portal_group() holds iscsi_portal_group->tpg_state_lock while updating AUTHMETHOD via iscsi_update_param_value(), which performs a GFP_KERNEL allocation. However, since iscsit_tpg_enable_portal_group() is already protected by iscsit_get_tpg() -> iscsi_portal_group->tpg_access_lock in it's parent caller, ->tpg_state_lock only needs to be held when setting TPG_STATE_ACTIVE. Reported-by: Jia-Ju Bai Reviewed-by: Jia-Ju Bai Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_tpg.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/target/iscsi') diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index 2e7e08dbda48..abaabbaebd88 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -311,11 +311,9 @@ int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *tpg) struct iscsi_tiqn *tiqn = tpg->tpg_tiqn; int ret; - spin_lock(&tpg->tpg_state_lock); if (tpg->tpg_state == TPG_STATE_ACTIVE) { pr_err("iSCSI target portal group: %hu is already" " active, ignoring request.\n", tpg->tpgt); - spin_unlock(&tpg->tpg_state_lock); return -EINVAL; } /* @@ -324,10 +322,8 @@ int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *tpg) * is enforced (as per default), and remove the NONE option. */ param = iscsi_find_param_from_key(AUTHMETHOD, tpg->param_list); - if (!param) { - spin_unlock(&tpg->tpg_state_lock); + if (!param) return -EINVAL; - } if (tpg->tpg_attrib.authentication) { if (!strcmp(param->value, NONE)) { @@ -341,6 +337,7 @@ int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *tpg) goto err; } + spin_lock(&tpg->tpg_state_lock); tpg->tpg_state = TPG_STATE_ACTIVE; spin_unlock(&tpg->tpg_state_lock); @@ -353,7 +350,6 @@ int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *tpg) return 0; err: - spin_unlock(&tpg->tpg_state_lock); return ret; } -- cgit v1.2.3-55-g7522 From 03db016a1bf2d35f41c08aad2ca4f4f18eeda4be Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 2 Jun 2017 23:33:56 -0700 Subject: iscsi-target: Kill left-over iscsi_target_do_cleanup With commit 25cdda95fda7 in place to address the initial login PDU asynchronous socket close OOPs, go ahead and kill off the left-over iscsi_target_do_cleanup() and ->login_cleanup_work. Reported-by: Mike Christie Cc: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_nego.c | 24 ------------------------ include/target/iscsi/iscsi_target_core.h | 1 - 2 files changed, 25 deletions(-) (limited to 'drivers/target/iscsi') diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 6f88b31242b0..96df63f1f795 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -655,28 +655,6 @@ err: iscsit_deaccess_np(np, tpg, tpg_np); } -static void iscsi_target_do_cleanup(struct work_struct *work) -{ - struct iscsi_conn *conn = container_of(work, - struct iscsi_conn, login_cleanup_work.work); - struct sock *sk = conn->sock->sk; - struct iscsi_login *login = conn->login; - struct iscsi_np *np = login->np; - struct iscsi_portal_group *tpg = conn->tpg; - struct iscsi_tpg_np *tpg_np = conn->tpg_np; - - pr_debug("Entering iscsi_target_do_cleanup\n"); - - cancel_delayed_work_sync(&conn->login_work); - conn->orig_state_change(sk); - - iscsi_target_restore_sock_callbacks(conn); - iscsi_target_login_drop(conn, login); - iscsit_deaccess_np(np, tpg, tpg_np); - - pr_debug("iscsi_target_do_cleanup done()\n"); -} - static void iscsi_target_sk_state_change(struct sock *sk) { struct iscsi_conn *conn; @@ -1082,7 +1060,6 @@ int iscsi_target_locate_portal( int sessiontype = 0, ret = 0, tag_num, tag_size; INIT_DELAYED_WORK(&conn->login_work, iscsi_target_do_login_rx); - INIT_DELAYED_WORK(&conn->login_cleanup_work, iscsi_target_do_cleanup); iscsi_target_set_sock_callbacks(conn); login->np = np; @@ -1331,7 +1308,6 @@ int iscsi_target_start_negotiation( if (ret < 0) { cancel_delayed_work_sync(&conn->login_work); - cancel_delayed_work_sync(&conn->login_cleanup_work); iscsi_target_restore_sock_callbacks(conn); iscsi_remove_failed_auth_entry(conn); } diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index 5f17fb770477..7948fc68286b 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -560,7 +560,6 @@ struct iscsi_conn { #define LOGIN_FLAGS_INITIAL_PDU 8 unsigned long login_flags; struct delayed_work login_work; - struct delayed_work login_cleanup_work; struct iscsi_login *login; struct timer_list nopin_timer; struct timer_list nopin_response_timer; -- cgit v1.2.3-55-g7522 From 4412a67131a037fa1d032bcd50270e9d336a775d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 23 May 2017 16:48:43 -0700 Subject: target/iscsi: Remove second argument of __iscsit_free_cmd() Initialize .data_direction to DMA_NONE in iscsit_allocate_cmd() such that the second argument of __iscsit_free_cmd() can be left out. Note: this patch causes the first part of __iscsit_free_cmd() no longer to be skipped for TMFs. That's fine since no data segments are associated with TMFs. Signed-off-by: Bart Van Assche Reviewed-by: Hannes Reinecke Cc: Christoph Hellwig Cc: Andy Grover Cc: David Disseldorp Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 4 +--- drivers/target/iscsi/iscsi_target_util.c | 29 +++++++++++++---------------- drivers/target/iscsi/iscsi_target_util.h | 2 +- 3 files changed, 15 insertions(+), 20 deletions(-) (limited to 'drivers/target/iscsi') diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 3fdca2cdd8da..735d4ff2d0ce 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -488,15 +488,13 @@ EXPORT_SYMBOL(iscsit_queue_rsp); void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd) { - bool scsi_cmd = (cmd->iscsi_opcode == ISCSI_OP_SCSI_CMD); - spin_lock_bh(&conn->cmd_lock); if (!list_empty(&cmd->i_conn_node) && !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP)) list_del_init(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); - __iscsit_free_cmd(cmd, scsi_cmd, true); + __iscsit_free_cmd(cmd, true); } EXPORT_SYMBOL(iscsit_aborted_task); diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 7d3e2fcc26a0..41b9e7cc08b8 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -167,6 +167,7 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, int state) cmd->se_cmd.map_tag = tag; cmd->conn = conn; + cmd->data_direction = DMA_NONE; INIT_LIST_HEAD(&cmd->i_conn_node); INIT_LIST_HEAD(&cmd->datain_list); INIT_LIST_HEAD(&cmd->cmd_r2t_list); @@ -711,19 +712,16 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd) } EXPORT_SYMBOL(iscsit_release_cmd); -void __iscsit_free_cmd(struct iscsi_cmd *cmd, bool scsi_cmd, - bool check_queues) +void __iscsit_free_cmd(struct iscsi_cmd *cmd, bool check_queues) { struct iscsi_conn *conn = cmd->conn; - if (scsi_cmd) { - if (cmd->data_direction == DMA_TO_DEVICE) { - iscsit_stop_dataout_timer(cmd); - iscsit_free_r2ts_from_list(cmd); - } - if (cmd->data_direction == DMA_FROM_DEVICE) - iscsit_free_all_datain_reqs(cmd); + if (cmd->data_direction == DMA_TO_DEVICE) { + iscsit_stop_dataout_timer(cmd); + iscsit_free_r2ts_from_list(cmd); } + if (cmd->data_direction == DMA_FROM_DEVICE) + iscsit_free_all_datain_reqs(cmd); if (conn && check_queues) { iscsit_remove_cmd_from_immediate_queue(cmd, conn); @@ -738,23 +736,22 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown) { struct se_cmd *se_cmd = NULL; int rc; - bool op_scsi = false; + /* * Determine if a struct se_cmd is associated with * this struct iscsi_cmd. */ switch (cmd->iscsi_opcode) { case ISCSI_OP_SCSI_CMD: - op_scsi = true; /* * Fallthrough */ case ISCSI_OP_SCSI_TMFUNC: se_cmd = &cmd->se_cmd; - __iscsit_free_cmd(cmd, op_scsi, shutdown); + __iscsit_free_cmd(cmd, shutdown); rc = transport_generic_free_cmd(se_cmd, shutdown); if (!rc && shutdown && se_cmd->se_sess) { - __iscsit_free_cmd(cmd, op_scsi, shutdown); + __iscsit_free_cmd(cmd, shutdown); target_put_sess_cmd(se_cmd); } break; @@ -766,18 +763,18 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown) */ if (cmd->se_cmd.se_tfo != NULL) { se_cmd = &cmd->se_cmd; - __iscsit_free_cmd(cmd, true, shutdown); + __iscsit_free_cmd(cmd, shutdown); rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown); if (!rc && shutdown && se_cmd->se_sess) { - __iscsit_free_cmd(cmd, true, shutdown); + __iscsit_free_cmd(cmd, shutdown); target_put_sess_cmd(se_cmd); } break; } /* Fall-through */ default: - __iscsit_free_cmd(cmd, false, shutdown); + __iscsit_free_cmd(cmd, shutdown); iscsit_release_cmd(cmd); break; } diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index 9e4197af8708..425160565d0c 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h @@ -37,7 +37,7 @@ extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_co extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *); extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *); extern void iscsit_release_cmd(struct iscsi_cmd *); -extern void __iscsit_free_cmd(struct iscsi_cmd *, bool, bool); +extern void __iscsit_free_cmd(struct iscsi_cmd *, bool); extern void iscsit_free_cmd(struct iscsi_cmd *, bool); extern int iscsit_check_session_usage_count(struct iscsi_session *); extern void iscsit_dec_session_usage_count(struct iscsi_session *); -- cgit v1.2.3-55-g7522 From d1c26857cdec3e3bdb5cf7179411f6ce8cc0834c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 23 May 2017 16:48:44 -0700 Subject: target/iscsi: Simplify iscsit_free_cmd() Since .se_tfo is only set if a command has been submitted to the LIO core, check .se_tfo instead of .iscsi_opcode. Since __iscsit_free_cmd() only affects SCSI commands but not TMFs, calling that function for TMFs does not change behavior. This patch does not change the behavior of iscsit_free_cmd(). Signed-off-by: Bart Van Assche Cc: Hannes Reinecke Cc: Christoph Hellwig Cc: Andy Grover Cc: David Disseldorp Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_util.c | 39 ++++---------------------------- 1 file changed, 4 insertions(+), 35 deletions(-) (limited to 'drivers/target/iscsi') diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 41b9e7cc08b8..1e36f83b5961 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -734,49 +734,18 @@ void __iscsit_free_cmd(struct iscsi_cmd *cmd, bool check_queues) void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown) { - struct se_cmd *se_cmd = NULL; + struct se_cmd *se_cmd = cmd->se_cmd.se_tfo ? &cmd->se_cmd : NULL; int rc; - /* - * Determine if a struct se_cmd is associated with - * this struct iscsi_cmd. - */ - switch (cmd->iscsi_opcode) { - case ISCSI_OP_SCSI_CMD: - /* - * Fallthrough - */ - case ISCSI_OP_SCSI_TMFUNC: - se_cmd = &cmd->se_cmd; - __iscsit_free_cmd(cmd, shutdown); + __iscsit_free_cmd(cmd, shutdown); + if (se_cmd) { rc = transport_generic_free_cmd(se_cmd, shutdown); if (!rc && shutdown && se_cmd->se_sess) { __iscsit_free_cmd(cmd, shutdown); target_put_sess_cmd(se_cmd); } - break; - case ISCSI_OP_REJECT: - /* - * Handle special case for REJECT when iscsi_add_reject*() has - * overwritten the original iscsi_opcode assignment, and the - * associated cmd->se_cmd needs to be released. - */ - if (cmd->se_cmd.se_tfo != NULL) { - se_cmd = &cmd->se_cmd; - __iscsit_free_cmd(cmd, shutdown); - - rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown); - if (!rc && shutdown && se_cmd->se_sess) { - __iscsit_free_cmd(cmd, shutdown); - target_put_sess_cmd(se_cmd); - } - break; - } - /* Fall-through */ - default: - __iscsit_free_cmd(cmd, shutdown); + } else { iscsit_release_cmd(cmd); - break; } } EXPORT_SYMBOL(iscsit_free_cmd); -- cgit v1.2.3-55-g7522 From 8fa4011e0dd9423f1226f2f9769a1cf25c264468 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 23 May 2017 16:48:45 -0700 Subject: target/iscsi: Remove dead code from iscsit_process_scsi_cmd() If an iSCSI command is rejected before iscsit_process_scsi_cmd() is called, .reject_reason is set but iscsit_process_scsi_cmd() is not called. This means that the "if (cmd->reject_reason) ..." code in this function can be removed without changing the behavior of this function. Signed-off-by: Bart Van Assche Cc: Hannes Reinecke Cc: Christoph Hellwig Cc: Andy Grover Cc: David Disseldorp Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/target/iscsi') diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 735d4ff2d0ce..74e4975dd1b1 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1249,12 +1249,8 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, * execution. These exceptions are processed in CmdSN order using * iscsit_check_received_cmdsn() in iscsit_get_immediate_data() below. */ - if (cmd->sense_reason) { - if (cmd->reject_reason) - return 0; - + if (cmd->sense_reason) return 1; - } /* * Call directly into transport_generic_new_cmd() to perform * the backend memory allocation. -- cgit v1.2.3-55-g7522 From 138d351eefb727ab9e41a3dc5f112ceb4f6e59f2 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 7 Jul 2017 14:45:49 -0700 Subject: iscsi-target: Add login_keys_workaround attribute for non RFC initiators This patch re-introduces part of a long standing login workaround that was recently dropped by: commit 1c99de981f30b3e7868b8d20ce5479fa1c0fea46 Author: Nicholas Bellinger Date: Sun Apr 2 13:36:44 2017 -0700 iscsi-target: Drop work-around for legacy GlobalSAN initiator Namely, the workaround for FirstBurstLength ended up being required by Mellanox Flexboot PXE boot ROMs as reported by Robert. So this patch re-adds the work-around for FirstBurstLength within iscsi_check_proposer_for_optional_reply(), and makes the key optional to respond when the initiator does not propose, nor respond to it. Also as requested by Arun, this patch introduces a new TPG attribute named 'login_keys_workaround' that controls the use of both the FirstBurstLength workaround, as well as the two other existing workarounds for gPXE iSCSI boot client. By default, the workaround is enabled with login_keys_workaround=1, since Mellanox FlexBoot requires it, and Arun has verified the Qlogic MSFT initiator already proposes FirstBurstLength, so it's uneffected by this re-adding this part of the original work-around. Reported-by: Robert LeBlanc Cc: Robert LeBlanc Reviewed-by: Arun Easi Cc: # 3.1+ Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_configfs.c | 2 ++ drivers/target/iscsi/iscsi_target_nego.c | 6 ++-- drivers/target/iscsi/iscsi_target_parameters.c | 41 ++++++++++++++++++-------- drivers/target/iscsi/iscsi_target_parameters.h | 2 +- drivers/target/iscsi/iscsi_target_tpg.c | 19 ++++++++++++ drivers/target/iscsi/iscsi_target_tpg.h | 1 + include/target/iscsi/iscsi_target_core.h | 9 ++++++ 7 files changed, 64 insertions(+), 16 deletions(-) (limited to 'drivers/target/iscsi') diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 535a8e06a401..0dd4c45f7575 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -781,6 +781,7 @@ DEF_TPG_ATTRIB(default_erl); DEF_TPG_ATTRIB(t10_pi); DEF_TPG_ATTRIB(fabric_prot_type); DEF_TPG_ATTRIB(tpg_enabled_sendtargets); +DEF_TPG_ATTRIB(login_keys_workaround); static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = { &iscsi_tpg_attrib_attr_authentication, @@ -796,6 +797,7 @@ static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = { &iscsi_tpg_attrib_attr_t10_pi, &iscsi_tpg_attrib_attr_fabric_prot_type, &iscsi_tpg_attrib_attr_tpg_enabled_sendtargets, + &iscsi_tpg_attrib_attr_login_keys_workaround, NULL, }; diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 96df63f1f795..7a6751fecd32 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -864,7 +864,8 @@ static int iscsi_target_handle_csg_zero( SENDER_TARGET, login->rsp_buf, &login->rsp_length, - conn->param_list); + conn->param_list, + conn->tpg->tpg_attrib.login_keys_workaround); if (ret < 0) return -1; @@ -934,7 +935,8 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log SENDER_TARGET, login->rsp_buf, &login->rsp_length, - conn->param_list); + conn->param_list, + conn->tpg->tpg_attrib.login_keys_workaround); if (ret < 0) { iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, ISCSI_LOGIN_STATUS_INIT_ERR); diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index fce627628200..caab1045742d 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c @@ -765,7 +765,8 @@ static int iscsi_check_for_auth_key(char *key) return 0; } -static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param) +static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param, + bool keys_workaround) { if (IS_TYPE_BOOL_AND(param)) { if (!strcmp(param->value, NO)) @@ -773,19 +774,31 @@ static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param) } else if (IS_TYPE_BOOL_OR(param)) { if (!strcmp(param->value, YES)) SET_PSTATE_REPLY_OPTIONAL(param); - /* - * Required for gPXE iSCSI boot client - */ - if (!strcmp(param->name, IMMEDIATEDATA)) - SET_PSTATE_REPLY_OPTIONAL(param); + + if (keys_workaround) { + /* + * Required for gPXE iSCSI boot client + */ + if (!strcmp(param->name, IMMEDIATEDATA)) + SET_PSTATE_REPLY_OPTIONAL(param); + } } else if (IS_TYPE_NUMBER(param)) { if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) SET_PSTATE_REPLY_OPTIONAL(param); - /* - * Required for gPXE iSCSI boot client - */ - if (!strcmp(param->name, MAXCONNECTIONS)) - SET_PSTATE_REPLY_OPTIONAL(param); + + if (keys_workaround) { + /* + * Required for Mellanox Flexboot PXE boot ROM + */ + if (!strcmp(param->name, FIRSTBURSTLENGTH)) + SET_PSTATE_REPLY_OPTIONAL(param); + + /* + * Required for gPXE iSCSI boot client + */ + if (!strcmp(param->name, MAXCONNECTIONS)) + SET_PSTATE_REPLY_OPTIONAL(param); + } } else if (IS_PHASE_DECLARATIVE(param)) SET_PSTATE_REPLY_OPTIONAL(param); } @@ -1422,7 +1435,8 @@ int iscsi_encode_text_output( u8 sender, char *textbuf, u32 *length, - struct iscsi_param_list *param_list) + struct iscsi_param_list *param_list, + bool keys_workaround) { char *output_buf = NULL; struct iscsi_extra_response *er; @@ -1458,7 +1472,8 @@ int iscsi_encode_text_output( *length += 1; output_buf = textbuf + *length; SET_PSTATE_PROPOSER(param); - iscsi_check_proposer_for_optional_reply(param); + iscsi_check_proposer_for_optional_reply(param, + keys_workaround); pr_debug("Sending key: %s=%s\n", param->name, param->value); } diff --git a/drivers/target/iscsi/iscsi_target_parameters.h b/drivers/target/iscsi/iscsi_target_parameters.h index 9962ccf0ccd7..c47b73f57528 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.h +++ b/drivers/target/iscsi/iscsi_target_parameters.h @@ -46,7 +46,7 @@ extern int iscsi_extract_key_value(char *, char **, char **); extern int iscsi_update_param_value(struct iscsi_param *, char *); extern int iscsi_decode_text_input(u8, u8, char *, u32, struct iscsi_conn *); extern int iscsi_encode_text_output(u8, u8, char *, u32 *, - struct iscsi_param_list *); + struct iscsi_param_list *, bool); extern int iscsi_check_negotiated_keys(struct iscsi_param_list *); extern void iscsi_set_connection_parameters(struct iscsi_conn_ops *, struct iscsi_param_list *); diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index abaabbaebd88..594d07a1e995 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -227,6 +227,7 @@ static void iscsit_set_default_tpg_attribs(struct iscsi_portal_group *tpg) 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; + a->login_keys_workaround = TA_DEFAULT_LOGIN_KEYS_WORKAROUND; } int iscsit_tpg_add_portal_group(struct iscsi_tiqn *tiqn, struct iscsi_portal_group *tpg) @@ -895,3 +896,21 @@ int iscsit_ta_tpg_enabled_sendtargets( return 0; } + +int iscsit_ta_login_keys_workaround( + 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->login_keys_workaround = flag; + pr_debug("iSCSI_TPG[%hu] - TPG enabled bit for login keys workaround: %s ", + tpg->tpgt, (a->login_keys_workaround) ? "ON" : "OFF"); + + return 0; +} diff --git a/drivers/target/iscsi/iscsi_target_tpg.h b/drivers/target/iscsi/iscsi_target_tpg.h index ceba29851167..59fd3cabe89d 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.h +++ b/drivers/target/iscsi/iscsi_target_tpg.h @@ -48,5 +48,6 @@ 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); +extern int iscsit_ta_login_keys_workaround(struct iscsi_portal_group *, u32); #endif /* ISCSI_TARGET_TPG_H */ diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index 7948fc68286b..0ca1fb08805b 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -66,6 +66,14 @@ struct sock; #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 +/* + * Used to control the sending of keys with optional to respond state bit, + * as a workaround for non RFC compliant initiators,that do not propose, + * nor respond to specific keys required for login to complete. + * + * See iscsi_check_proposer_for_optional_reply() for more details. + */ +#define TA_DEFAULT_LOGIN_KEYS_WORKAROUND 1 #define ISCSI_IOV_DATA_BUFFER 5 @@ -768,6 +776,7 @@ struct iscsi_tpg_attrib { u8 t10_pi; u32 fabric_prot_type; u32 tpg_enabled_sendtargets; + u32 login_keys_workaround; struct iscsi_portal_group *tpg; }; -- cgit v1.2.3-55-g7522