From: Quinn Tran <quinn.tran@xxxxxxxxxx> In Some instance following stack trace is seen for slow memory allocation with lock held Call Trace: [<ffffffff81341687>] dump_stack+0x6b/0xa4 [<ffffffff810c3e30>] ? print_irqtrace_events+0xd0/0xe0 [<ffffffff8109e3c3>] ___might_sleep+0x183/0x240 [<ffffffff8109e4d2>] __might_sleep+0x52/0x90 [<ffffffff811fe17b>] kmem_cache_alloc_trace+0x5b/0x300 [<ffffffff810c666b>] ? __lock_acquired+0x30b/0x420 [<ffffffffa0733c28>] qla2x00_alloc_fcport+0x38/0x2a0 [qla2xxx] [<ffffffffa07217f4>] ? qla2x00_do_work+0x34/0x2b0 [qla2xxx] [<ffffffff816cc82b>] ? _raw_spin_lock_irqsave+0x7b/0x90 [<ffffffffa072169a>] ? qla24xx_create_new_sess+0x3a/0x160 [qla2xxx] [<ffffffffa0721723>] qla24xx_create_new_sess+0xc3/0x160 [qla2xxx] [<ffffffff810c91ed>] ? trace_hardirqs_on+0xd/0x10 [<ffffffffa07218f8>] qla2x00_do_work+0x138/0x2b0 [qla2xxx] Signed-off-by: Quinn Tran <quinn.tran@xxxxxxxxxx> Signed-off-by: Himanshu Madhani <himanshu.madhani@xxxxxxxxxx> --- drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_os.c | 35 ++++++++++++++++++++++++++++++++++- drivers/scsi/qla2xxx/qla_target.c | 11 +++++------ 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 2e28b3f..9489a1c 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -143,6 +143,7 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, extern int ql_dm_tgt_ex_pct; extern struct workqueue_struct *qla_wq; extern int ql2xmvasynctoatio; +extern struct kmem_cache *qla_tgt_plogi_cachep; extern int qla2x00_loop_reset(scsi_qla_host_t *); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 87dc64a..8137238 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -4486,8 +4486,9 @@ int qla24xx_post_upd_fcport_work(struct scsi_qla_host *vha, fc_port_t *fcport) void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) { unsigned long flags; - fc_port_t *fcport = NULL; + fc_port_t *fcport = NULL, *tfcp; qlt_plogi_ack_t *pla = (qlt_plogi_ack_t *)e->u.new_sess.pla; + uint8_t free_fcport = 0; spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); fcport = qla2x00_find_fcport_by_wwpn(vha, e->u.new_sess.port_name, 1); @@ -4502,6 +4503,8 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) pla->ref_count--; } } else { + spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); if (fcport) { fcport->d_id = e->u.new_sess.id; @@ -4511,6 +4514,30 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) memcpy(&fcport->port_name, e->u.new_sess.port_name, WWN_SIZE); + } else { + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s %8phC mem alloc fail.\n", + __func__, e->u.new_sess.port_name); + + if (pla) + kmem_cache_free(qla_tgt_plogi_cachep, pla); + return; + } + + spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); + /* search again to make sure one else got ahead */ + tfcp = qla2x00_find_fcport_by_wwpn(vha, + e->u.new_sess.port_name, 1); + if (tfcp) { + /* should rarily happen */ + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s %8phC found existing fcport b4 add. DS %d LS %d\n", + __func__, tfcp->port_name, tfcp->disc_state, + tfcp->fw_login_state); + + free_fcport = 1; + } else { + list_add_tail(&fcport->list, &vha->vp_fcports); if (pla) { @@ -4527,6 +4554,12 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) else qla24xx_async_gnl(vha, fcport); } + + if (free_fcport) { + qla2x00_free_fcport(fcport); + if (pla) + kmem_cache_free(qla_tgt_plogi_cachep, pla); + } } void diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 54a5337..8a4b506 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -49,13 +49,12 @@ module_param(qlop_mode, charp, S_IRUGO); MODULE_PARM_DESC(qlop_mode, "Determines operating mode. Possible values: " - "\"exclusive\" - initiator mode will be enabled on load, " - "disabled on enabling target mode and then on disabling target mode " - "enabled back; " + "\"exclusive\" - Initiator Mode will be enabled on load. " + " Target Mode can be activated when ready. Only one mode can be active at a time; " "\"tgt_mode\" - Target mode only. Initiator mode will never be enabled; " - "\"dual_mode\" - Initiator Modes will be enabled. Target Mode can be " + "\"dual_mode\" - Initiator Modes will be enabled on load. Target Mode can be " "activated when ready; " - "\"ini_mode\" (default) - initiator mode will always stay enabled."); + "\"ini_mode\" (default) - Initiator mode will always stay enabled."); int ql_dm_tgt_ex_pct = 50; module_param(ql_dm_tgt_ex_pct, int, S_IRUGO|S_IWUSR); @@ -133,7 +132,7 @@ static struct fc_port *qlt_create_sess(struct scsi_qla_host *vha, /* * Global Variables */ -static struct kmem_cache *qla_tgt_plogi_cachep; +struct kmem_cache *qla_tgt_plogi_cachep; static struct workqueue_struct *qla_tgt_wq; static DEFINE_MUTEX(qla_tgt_mutex); LIST_HEAD(qla_tgt_glist); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html