Commit a0421da4 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch '3.4-rc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

Pull target fixes from Nicholas Bellinger:
 "Pull two tcm_fc fabric related fixes for -rc2:

  Note that both have been CC'ed to stable, and patch #1 is the
  important one that addresses a memory corruption bug related to FC
  exchange timeouts + command abort.

  Thanks again to MDR for tracking down this issue!"

* '3.4-rc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  tcm_fc: Do not free tpg structure during wq allocation failure
  tcm_fc: Add abort flag for gracefully handling exchange timeout
parents 4157368e 06383f10
...@@ -122,6 +122,7 @@ struct ft_cmd { ...@@ -122,6 +122,7 @@ struct ft_cmd {
/* Local sense buffer */ /* Local sense buffer */
unsigned char ft_sense_buffer[TRANSPORT_SENSE_BUFFER]; unsigned char ft_sense_buffer[TRANSPORT_SENSE_BUFFER];
u32 was_ddp_setup:1; /* Set only if ddp is setup */ u32 was_ddp_setup:1; /* Set only if ddp is setup */
u32 aborted:1; /* Set if aborted by reset or timeout */
struct scatterlist *sg; /* Set only if DDP is setup */ struct scatterlist *sg; /* Set only if DDP is setup */
u32 sg_cnt; /* No. of item in scatterlist */ u32 sg_cnt; /* No. of item in scatterlist */
}; };
......
...@@ -121,6 +121,8 @@ int ft_queue_status(struct se_cmd *se_cmd) ...@@ -121,6 +121,8 @@ int ft_queue_status(struct se_cmd *se_cmd)
struct fc_exch *ep; struct fc_exch *ep;
size_t len; size_t len;
if (cmd->aborted)
return 0;
ft_dump_cmd(cmd, __func__); ft_dump_cmd(cmd, __func__);
ep = fc_seq_exch(cmd->seq); ep = fc_seq_exch(cmd->seq);
lport = ep->lp; lport = ep->lp;
...@@ -187,6 +189,8 @@ int ft_write_pending(struct se_cmd *se_cmd) ...@@ -187,6 +189,8 @@ int ft_write_pending(struct se_cmd *se_cmd)
ft_dump_cmd(cmd, __func__); ft_dump_cmd(cmd, __func__);
if (cmd->aborted)
return 0;
ep = fc_seq_exch(cmd->seq); ep = fc_seq_exch(cmd->seq);
lport = ep->lp; lport = ep->lp;
fp = fc_frame_alloc(lport, sizeof(*txrdy)); fp = fc_frame_alloc(lport, sizeof(*txrdy));
...@@ -252,10 +256,10 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg) ...@@ -252,10 +256,10 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
struct ft_cmd *cmd = arg; struct ft_cmd *cmd = arg;
struct fc_frame_header *fh; struct fc_frame_header *fh;
if (IS_ERR(fp)) { if (unlikely(IS_ERR(fp))) {
/* XXX need to find cmd if queued */ /* XXX need to find cmd if queued */
cmd->seq = NULL; cmd->seq = NULL;
transport_generic_free_cmd(&cmd->se_cmd, 0); cmd->aborted = true;
return; return;
} }
...@@ -399,6 +403,8 @@ int ft_queue_tm_resp(struct se_cmd *se_cmd) ...@@ -399,6 +403,8 @@ int ft_queue_tm_resp(struct se_cmd *se_cmd)
struct se_tmr_req *tmr = se_cmd->se_tmr_req; struct se_tmr_req *tmr = se_cmd->se_tmr_req;
enum fcp_resp_rsp_codes code; enum fcp_resp_rsp_codes code;
if (cmd->aborted)
return 0;
switch (tmr->response) { switch (tmr->response) {
case TMR_FUNCTION_COMPLETE: case TMR_FUNCTION_COMPLETE:
code = FCP_TMF_CMPL; code = FCP_TMF_CMPL;
......
...@@ -300,6 +300,7 @@ static struct se_portal_group *ft_add_tpg( ...@@ -300,6 +300,7 @@ static struct se_portal_group *ft_add_tpg(
{ {
struct ft_lport_acl *lacl; struct ft_lport_acl *lacl;
struct ft_tpg *tpg; struct ft_tpg *tpg;
struct workqueue_struct *wq;
unsigned long index; unsigned long index;
int ret; int ret;
...@@ -321,18 +322,20 @@ static struct se_portal_group *ft_add_tpg( ...@@ -321,18 +322,20 @@ static struct se_portal_group *ft_add_tpg(
tpg->lport_acl = lacl; tpg->lport_acl = lacl;
INIT_LIST_HEAD(&tpg->lun_list); INIT_LIST_HEAD(&tpg->lun_list);
ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg, wq = alloc_workqueue("tcm_fc", 0, 1);
tpg, TRANSPORT_TPG_TYPE_NORMAL); if (!wq) {
if (ret < 0) {
kfree(tpg); kfree(tpg);
return NULL; return NULL;
} }
tpg->workqueue = alloc_workqueue("tcm_fc", 0, 1); ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
if (!tpg->workqueue) { tpg, TRANSPORT_TPG_TYPE_NORMAL);
if (ret < 0) {
destroy_workqueue(wq);
kfree(tpg); kfree(tpg);
return NULL; return NULL;
} }
tpg->workqueue = wq;
mutex_lock(&ft_lport_lock); mutex_lock(&ft_lport_lock);
list_add_tail(&tpg->list, &lacl->tpg_list); list_add_tail(&tpg->list, &lacl->tpg_list);
......
...@@ -81,6 +81,8 @@ int ft_queue_data_in(struct se_cmd *se_cmd) ...@@ -81,6 +81,8 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
void *from; void *from;
void *to = NULL; void *to = NULL;
if (cmd->aborted)
return 0;
ep = fc_seq_exch(cmd->seq); ep = fc_seq_exch(cmd->seq);
lport = ep->lp; lport = ep->lp;
cmd->seq = lport->tt.seq_start_next(cmd->seq); cmd->seq = lport->tt.seq_start_next(cmd->seq);
......
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