mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-07 22:42:04 +00:00
tcm_fc: Fix ft_send_tm LUN lookup OOPs
This patch fixes a bug in ft_send_tm() that was incorrectly calling ft_get_lun_for_cmd() -> transport_get_lun_for_cmd(), instead of using transport_get_lun_for_tmr() for the proper struct se_lun lookup that was triggering an OOPs in the se_cmd->tmr_req failure path. This patch fixes the issue by re-arranging the codepath where transport_get_lun_for_tmr() is called after tmr request is allocated and made it available as part of se_cmd. It also drops the now unnecessary ft_get_lun_for_cmd() unpacking code, and uses scsilun_to_int() directly ahead of transport_get_lun_for_cmd() and transport_get_lun_for_tmr() usage. Signed-off-by: Patil, Kiran <kiran.patil@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
60d645a4e9
commit
61db952713
@ -144,7 +144,7 @@ enum ft_cmd_state {
|
|||||||
*/
|
*/
|
||||||
struct ft_cmd {
|
struct ft_cmd {
|
||||||
enum ft_cmd_state state;
|
enum ft_cmd_state state;
|
||||||
u16 lun; /* LUN from request */
|
u32 lun; /* LUN from request */
|
||||||
struct ft_sess *sess; /* session held for cmd */
|
struct ft_sess *sess; /* session held for cmd */
|
||||||
struct fc_seq *seq; /* sequence in exchange mgr */
|
struct fc_seq *seq; /* sequence in exchange mgr */
|
||||||
struct se_cmd se_cmd; /* Local TCM I/O descriptor */
|
struct se_cmd se_cmd; /* Local TCM I/O descriptor */
|
||||||
|
@ -94,29 +94,6 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
|
|||||||
16, 4, cmd->cdb, MAX_COMMAND_SIZE, 0);
|
16, 4, cmd->cdb, MAX_COMMAND_SIZE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Get LUN from CDB.
|
|
||||||
*/
|
|
||||||
static int ft_get_lun_for_cmd(struct ft_cmd *cmd, u8 *lunp)
|
|
||||||
{
|
|
||||||
u64 lun;
|
|
||||||
|
|
||||||
lun = lunp[1];
|
|
||||||
switch (lunp[0] >> 6) {
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
lun |= (lunp[0] & 0x3f) << 8;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (lun >= TRANSPORT_MAX_LUNS_PER_TPG)
|
|
||||||
return -1;
|
|
||||||
cmd->lun = lun;
|
|
||||||
return transport_get_lun_for_cmd(&cmd->se_cmd, NULL, lun);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ft_queue_cmd(struct ft_sess *sess, struct ft_cmd *cmd)
|
static void ft_queue_cmd(struct ft_sess *sess, struct ft_cmd *cmd)
|
||||||
{
|
{
|
||||||
struct se_queue_obj *qobj;
|
struct se_queue_obj *qobj;
|
||||||
@ -418,6 +395,7 @@ static void ft_send_tm(struct ft_cmd *cmd)
|
|||||||
{
|
{
|
||||||
struct se_tmr_req *tmr;
|
struct se_tmr_req *tmr;
|
||||||
struct fcp_cmnd *fcp;
|
struct fcp_cmnd *fcp;
|
||||||
|
struct ft_sess *sess;
|
||||||
u8 tm_func;
|
u8 tm_func;
|
||||||
|
|
||||||
fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
|
fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
|
||||||
@ -425,13 +403,6 @@ static void ft_send_tm(struct ft_cmd *cmd)
|
|||||||
switch (fcp->fc_tm_flags) {
|
switch (fcp->fc_tm_flags) {
|
||||||
case FCP_TMF_LUN_RESET:
|
case FCP_TMF_LUN_RESET:
|
||||||
tm_func = TMR_LUN_RESET;
|
tm_func = TMR_LUN_RESET;
|
||||||
if (ft_get_lun_for_cmd(cmd, fcp->fc_lun) < 0) {
|
|
||||||
ft_dump_cmd(cmd, __func__);
|
|
||||||
transport_send_check_condition_and_sense(&cmd->se_cmd,
|
|
||||||
cmd->se_cmd.scsi_sense_reason, 0);
|
|
||||||
ft_sess_put(cmd->sess);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case FCP_TMF_TGT_RESET:
|
case FCP_TMF_TGT_RESET:
|
||||||
tm_func = TMR_TARGET_WARM_RESET;
|
tm_func = TMR_TARGET_WARM_RESET;
|
||||||
@ -463,6 +434,36 @@ static void ft_send_tm(struct ft_cmd *cmd)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cmd->se_cmd.se_tmr_req = tmr;
|
cmd->se_cmd.se_tmr_req = tmr;
|
||||||
|
|
||||||
|
switch (fcp->fc_tm_flags) {
|
||||||
|
case FCP_TMF_LUN_RESET:
|
||||||
|
cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
|
||||||
|
if (transport_get_lun_for_tmr(&cmd->se_cmd, cmd->lun) < 0) {
|
||||||
|
/*
|
||||||
|
* Make sure to clean up newly allocated TMR request
|
||||||
|
* since "unable to handle TMR request because failed
|
||||||
|
* to get to LUN"
|
||||||
|
*/
|
||||||
|
FT_TM_DBG("Failed to get LUN for TMR func %d, "
|
||||||
|
"se_cmd %p, unpacked_lun %d\n",
|
||||||
|
tm_func, &cmd->se_cmd, cmd->lun);
|
||||||
|
ft_dump_cmd(cmd, __func__);
|
||||||
|
sess = cmd->sess;
|
||||||
|
transport_send_check_condition_and_sense(&cmd->se_cmd,
|
||||||
|
cmd->se_cmd.scsi_sense_reason, 0);
|
||||||
|
transport_generic_free_cmd(&cmd->se_cmd, 0, 1, 0);
|
||||||
|
ft_sess_put(sess);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FCP_TMF_TGT_RESET:
|
||||||
|
case FCP_TMF_CLR_TASK_SET:
|
||||||
|
case FCP_TMF_ABT_TASK_SET:
|
||||||
|
case FCP_TMF_CLR_ACA:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
transport_generic_handle_tmr(&cmd->se_cmd);
|
transport_generic_handle_tmr(&cmd->se_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -635,7 +636,8 @@ static void ft_send_cmd(struct ft_cmd *cmd)
|
|||||||
|
|
||||||
fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd);
|
fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd);
|
||||||
|
|
||||||
ret = ft_get_lun_for_cmd(cmd, fcp->fc_lun);
|
cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
|
||||||
|
ret = transport_get_lun_for_cmd(&cmd->se_cmd, NULL, cmd->lun);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ft_dump_cmd(cmd, __func__);
|
ft_dump_cmd(cmd, __func__);
|
||||||
transport_send_check_condition_and_sense(&cmd->se_cmd,
|
transport_send_check_condition_and_sense(&cmd->se_cmd,
|
||||||
|
Loading…
Reference in New Issue
Block a user