]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
scsi: qla2xxx: Fix slow mem alloc behind lock
authorQuinn Tran <quinn.tran@qlogic.com>
Wed, 30 Aug 2017 17:16:49 +0000 (10:16 -0700)
committerShan Hai <shan.hai@oracle.com>
Fri, 17 Nov 2017 06:38:10 +0000 (14:38 +0800)
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@qlogic.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
(cherry picked from commit b5d1531260b9e5819edcaed8b549859e582e4ca4)

Orabug: 27134422

Signed-off-by: Shan Hai <shan.hai@oracle.com>
Reviewed-by: Ethan Zhao <ethan.zhao@oracle.com>
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_target.c

index 05e75cbd3b41f4dd6e682fd0f9ed7475291fb436..ca85bdd9c7972327f7aa3f52e34ddf5e2b269488 100644 (file)
@@ -112,6 +112,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
 extern char qla2x00_version_str[];
 
 extern struct kmem_cache *srb_cachep;
+extern struct kmem_cache *qla_tgt_plogi_cachep;
 
 extern int ql2xlogintimeout;
 extern int qlport_down_retry;
index a1422c7034232a0d035d7a2ffd01a2020abfc04d..f5dd1ec00308e9eb5de9b086a93b505ce08c20a3 100644 (file)
@@ -4280,9 +4280,10 @@ static
 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;
        struct qlt_plogi_ack_t *pla =
            (struct 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);
@@ -4297,6 +4298,7 @@ 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;
@@ -4306,6 +4308,29 @@ 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) {
@@ -4323,6 +4348,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
index 74200614299a5ce905a1b8f064a61bb3e7bf2d6c..a19cea1f209ec61699490944c78949d985317ed3 100644 (file)
@@ -128,7 +128,7 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *,
  * Global Variables
  */
 static struct kmem_cache *qla_tgt_mgmt_cmd_cachep;
-static struct kmem_cache *qla_tgt_plogi_cachep;
+struct kmem_cache *qla_tgt_plogi_cachep;
 static mempool_t *qla_tgt_mgmt_cmd_mempool;
 static struct workqueue_struct *qla_tgt_wq;
 static DEFINE_MUTEX(qla_tgt_mutex);