Commit d6dfc868 authored by Roland Dreier's avatar Roland Dreier Committed by Nicholas Bellinger

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 <chad.dupuis@qlogic.com>
Cc: Arun Easi <arun.easi@qlogic.com>
Cc: Chris Boot <bootc@bootc.net>
Cc: Stefan Richter <stefanr@s5r6.in-berlin.de>
Cc: Mark Rustad <mark.d.rustad@intel.com>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Andy Grover <agrover@redhat.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 7409a665
...@@ -597,10 +597,9 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, ...@@ -597,10 +597,9 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
return -EINVAL; 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, cmd->unpacked_lun, data_length, fcp_task_attr,
data_dir, flags); data_dir, flags);
return 0;
} }
static void tcm_qla2xxx_handle_data_work(struct work_struct *work) static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
......
...@@ -1235,9 +1235,11 @@ static void sbp_handle_command(struct sbp_target_request *req) ...@@ -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", 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); req->orb_pointer, unpacked_lun, data_length, data_dir);
target_submit_cmd(&req->se_cmd, sess->se_sess, req->cmd_buf, if (target_submit_cmd(&req->se_cmd, sess->se_sess, req->cmd_buf,
req->sense_buf, unpacked_lun, data_length, req->sense_buf, unpacked_lun, data_length,
MSG_SIMPLE_TAG, data_dir, 0); MSG_SIMPLE_TAG, data_dir, 0))
goto err;
return; return;
err: err:
......
...@@ -1447,10 +1447,14 @@ EXPORT_SYMBOL(transport_handle_cdb_direct); ...@@ -1447,10 +1447,14 @@ EXPORT_SYMBOL(transport_handle_cdb_direct);
* @data_dir: DMA data direction * @data_dir: DMA data direction
* @flags: flags for command submission from target_sc_flags_tables * @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 * This may only be called from process context, and also currently
* assumes internal allocation of fabric payload buffer by target-core. * 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, unsigned char *cdb, unsigned char *sense, u32 unpacked_lun,
u32 data_length, int task_attr, int data_dir, int flags) 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, ...@@ -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)); rc = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
if (rc) if (rc)
return; return rc;
/* /*
* Signal bidirectional data payloads to target-core * 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, ...@@ -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, transport_send_check_condition_and_sense(se_cmd,
se_cmd->scsi_sense_reason, 0); se_cmd->scsi_sense_reason, 0);
target_put_sess_cmd(se_sess, se_cmd); target_put_sess_cmd(se_sess, se_cmd);
return; return 0;
} }
rc = target_setup_cmd_from_cdb(se_cmd, cdb); rc = target_setup_cmd_from_cdb(se_cmd, cdb);
if (rc != 0) { if (rc != 0) {
transport_generic_request_failure(se_cmd); 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, ...@@ -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); core_alua_check_nonop_delay(se_cmd);
transport_handle_cdb_direct(se_cmd); transport_handle_cdb_direct(se_cmd);
return; return 0;
} }
EXPORT_SYMBOL(target_submit_cmd); EXPORT_SYMBOL(target_submit_cmd);
......
...@@ -543,9 +543,11 @@ static void ft_send_work(struct work_struct *work) ...@@ -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 * Use a single se_cmd->cmd_kref as we expect to release se_cmd
* directly from ft_check_stop_free callback in response path. * directly from ft_check_stop_free callback in response path.
*/ */
target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb, 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), &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun),
ntohl(fcp->fc_dl), task_attr, data_dir, 0); 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); pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl);
return; return;
......
...@@ -1065,16 +1065,20 @@ static void usbg_cmd_work(struct work_struct *work) ...@@ -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->se_tpg->se_tpg_tfo,
tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE, tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
cmd->prio_attr, cmd->sense_iu.sense); cmd->prio_attr, cmd->sense_iu.sense);
goto out;
}
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)
goto out;
return;
out:
transport_send_check_condition_and_sense(se_cmd, transport_send_check_condition_and_sense(se_cmd,
TCM_UNSUPPORTED_SCSI_OPCODE, 1); TCM_UNSUPPORTED_SCSI_OPCODE, 1);
usbg_cleanup_cmd(cmd); usbg_cleanup_cmd(cmd);
return;
}
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);
} }
static int usbg_submit_command(struct f_uas *fu, static int usbg_submit_command(struct f_uas *fu,
...@@ -1177,16 +1181,20 @@ static void bot_cmd_work(struct work_struct *work) ...@@ -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->se_tpg->se_tpg_tfo,
tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE, tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
cmd->prio_attr, cmd->sense_iu.sense); cmd->prio_attr, cmd->sense_iu.sense);
goto out;
}
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) < 0)
goto out;
return;
out:
transport_send_check_condition_and_sense(se_cmd, transport_send_check_condition_and_sense(se_cmd,
TCM_UNSUPPORTED_SCSI_OPCODE, 1); TCM_UNSUPPORTED_SCSI_OPCODE, 1);
usbg_cleanup_cmd(cmd); usbg_cleanup_cmd(cmd);
return;
}
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);
} }
static int bot_submit_command(struct f_uas *fu, static int bot_submit_command(struct f_uas *fu,
......
...@@ -102,7 +102,7 @@ void transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *, ...@@ -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 *); struct se_session *, u32, int, int, unsigned char *);
int transport_lookup_cmd_lun(struct se_cmd *, u32); int transport_lookup_cmd_lun(struct se_cmd *, u32);
int target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *); 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); unsigned char *, u32, u32, int, int, int);
int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
unsigned char *sense, u32 unpacked_lun, unsigned char *sense, u32 unpacked_lun,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment