mirror of
https://github.com/torvalds/linux.git
synced 2024-10-31 01:01:52 +00:00
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
This commit is contained in:
commit
a0421da44f
@ -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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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(
|
|||||||
{
|
{
|
||||||
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(
|
|||||||
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)
|
|||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user