diff options
author | Kiran Patil <kiran.patil@intel.com> | 2011-06-22 19:30:22 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-06-23 20:09:15 -0400 |
commit | 61db952713a8bc1b18515db3f2eac354ec8990bd (patch) | |
tree | 94495bc24648a2990b39baf8c865fe0c36ccc9bf /drivers/target | |
parent | 60d645a4e9e7e7ddc20e534fea82aa4e6947f911 (diff) |
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>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/tcm_fc/tcm_fc.h | 2 | ||||
-rw-r--r-- | drivers/target/tcm_fc/tfc_cmd.c | 64 |
2 files changed, 34 insertions, 32 deletions
diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h index defff32b7880..7b82f1b7fef8 100644 --- a/drivers/target/tcm_fc/tcm_fc.h +++ b/drivers/target/tcm_fc/tcm_fc.h | |||
@@ -144,7 +144,7 @@ enum ft_cmd_state { | |||
144 | */ | 144 | */ |
145 | struct ft_cmd { | 145 | struct ft_cmd { |
146 | enum ft_cmd_state state; | 146 | enum ft_cmd_state state; |
147 | u16 lun; /* LUN from request */ | 147 | u32 lun; /* LUN from request */ |
148 | struct ft_sess *sess; /* session held for cmd */ | 148 | struct ft_sess *sess; /* session held for cmd */ |
149 | struct fc_seq *seq; /* sequence in exchange mgr */ | 149 | struct fc_seq *seq; /* sequence in exchange mgr */ |
150 | struct se_cmd se_cmd; /* Local TCM I/O descriptor */ | 150 | struct se_cmd se_cmd; /* Local TCM I/O descriptor */ |
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index c056a1132ae1..b2a106729d49 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c | |||
@@ -94,29 +94,6 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) | |||
94 | 16, 4, cmd->cdb, MAX_COMMAND_SIZE, 0); | 94 | 16, 4, cmd->cdb, MAX_COMMAND_SIZE, 0); |
95 | } | 95 | } |
96 | 96 | ||
97 | /* | ||
98 | * Get LUN from CDB. | ||
99 | */ | ||
100 | static int ft_get_lun_for_cmd(struct ft_cmd *cmd, u8 *lunp) | ||
101 | { | ||
102 | u64 lun; | ||
103 | |||
104 | lun = lunp[1]; | ||
105 | switch (lunp[0] >> 6) { | ||
106 | case 0: | ||
107 | break; | ||
108 | case 1: | ||
109 | lun |= (lunp[0] & 0x3f) << 8; | ||
110 | break; | ||
111 | default: | ||
112 | return -1; | ||
113 | } | ||
114 | if (lun >= TRANSPORT_MAX_LUNS_PER_TPG) | ||
115 | return -1; | ||
116 | cmd->lun = lun; | ||
117 | return transport_get_lun_for_cmd(&cmd->se_cmd, NULL, lun); | ||
118 | } | ||
119 | |||
120 | static void ft_queue_cmd(struct ft_sess *sess, struct ft_cmd *cmd) | 97 | static void ft_queue_cmd(struct ft_sess *sess, struct ft_cmd *cmd) |
121 | { | 98 | { |
122 | struct se_queue_obj *qobj; | 99 | struct se_queue_obj *qobj; |
@@ -418,6 +395,7 @@ static void ft_send_tm(struct ft_cmd *cmd) | |||
418 | { | 395 | { |
419 | struct se_tmr_req *tmr; | 396 | struct se_tmr_req *tmr; |
420 | struct fcp_cmnd *fcp; | 397 | struct fcp_cmnd *fcp; |
398 | struct ft_sess *sess; | ||
421 | u8 tm_func; | 399 | u8 tm_func; |
422 | 400 | ||
423 | fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp)); | 401 | fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp)); |
@@ -425,13 +403,6 @@ static void ft_send_tm(struct ft_cmd *cmd) | |||
425 | switch (fcp->fc_tm_flags) { | 403 | switch (fcp->fc_tm_flags) { |
426 | case FCP_TMF_LUN_RESET: | 404 | case FCP_TMF_LUN_RESET: |
427 | tm_func = TMR_LUN_RESET; | 405 | tm_func = TMR_LUN_RESET; |
428 | if (ft_get_lun_for_cmd(cmd, fcp->fc_lun) < 0) { | ||
429 | ft_dump_cmd(cmd, __func__); | ||
430 | transport_send_check_condition_and_sense(&cmd->se_cmd, | ||
431 | cmd->se_cmd.scsi_sense_reason, 0); | ||
432 | ft_sess_put(cmd->sess); | ||
433 | return; | ||
434 | } | ||
435 | break; | 406 | break; |
436 | case FCP_TMF_TGT_RESET: | 407 | case FCP_TMF_TGT_RESET: |
437 | tm_func = TMR_TARGET_WARM_RESET; | 408 | tm_func = TMR_TARGET_WARM_RESET; |
@@ -463,6 +434,36 @@ static void ft_send_tm(struct ft_cmd *cmd) | |||
463 | return; | 434 | return; |
464 | } | 435 | } |
465 | cmd->se_cmd.se_tmr_req = tmr; | 436 | cmd->se_cmd.se_tmr_req = tmr; |
437 | |||
438 | switch (fcp->fc_tm_flags) { | ||
439 | case FCP_TMF_LUN_RESET: | ||
440 | cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun); | ||
441 | if (transport_get_lun_for_tmr(&cmd->se_cmd, cmd->lun) < 0) { | ||
442 | /* | ||
443 | * Make sure to clean up newly allocated TMR request | ||
444 | * since "unable to handle TMR request because failed | ||
445 | * to get to LUN" | ||
446 | */ | ||
447 | FT_TM_DBG("Failed to get LUN for TMR func %d, " | ||
448 | "se_cmd %p, unpacked_lun %d\n", | ||
449 | tm_func, &cmd->se_cmd, cmd->lun); | ||
450 | ft_dump_cmd(cmd, __func__); | ||
451 | sess = cmd->sess; | ||
452 | transport_send_check_condition_and_sense(&cmd->se_cmd, | ||
453 | cmd->se_cmd.scsi_sense_reason, 0); | ||
454 | transport_generic_free_cmd(&cmd->se_cmd, 0, 1, 0); | ||
455 | ft_sess_put(sess); | ||
456 | return; | ||
457 | } | ||
458 | break; | ||
459 | case FCP_TMF_TGT_RESET: | ||
460 | case FCP_TMF_CLR_TASK_SET: | ||
461 | case FCP_TMF_ABT_TASK_SET: | ||
462 | case FCP_TMF_CLR_ACA: | ||
463 | break; | ||
464 | default: | ||
465 | return; | ||
466 | } | ||
466 | transport_generic_handle_tmr(&cmd->se_cmd); | 467 | transport_generic_handle_tmr(&cmd->se_cmd); |
467 | } | 468 | } |
468 | 469 | ||
@@ -635,7 +636,8 @@ static void ft_send_cmd(struct ft_cmd *cmd) | |||
635 | 636 | ||
636 | fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd); | 637 | fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd); |
637 | 638 | ||
638 | ret = ft_get_lun_for_cmd(cmd, fcp->fc_lun); | 639 | cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun); |
640 | ret = transport_get_lun_for_cmd(&cmd->se_cmd, NULL, cmd->lun); | ||
639 | if (ret < 0) { | 641 | if (ret < 0) { |
640 | ft_dump_cmd(cmd, __func__); | 642 | ft_dump_cmd(cmd, __func__); |
641 | transport_send_check_condition_and_sense(&cmd->se_cmd, | 643 | transport_send_check_condition_and_sense(&cmd->se_cmd, |