From: Joe Carnuccio Date: Wed, 15 Mar 2017 16:48:43 +0000 (-0700) Subject: qla2xxx: Allow vref count to timeout on vport delete. X-Git-Tag: v4.1.12-102.0.20170601_1400~233 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=45972ab4994b2834e8460ec42e6777790469fb10;p=users%2Fjedix%2Flinux-maple.git qla2xxx: Allow vref count to timeout on vport delete. This commit fixed a panic could be triggered with following steps: 1.create vhba #virsh nodedev-create vhba.xml 2.destroy vhba #virsh nodedev-destroy scsi_host9 Content of file vhba.xml: scsi_host7 Call trace of panic: [ 207.683754] BUG: unable to handle kernel NULL pointer dereference at 0000000000000410 [ 207.683805] IP: [] qla24xx_vport_delete+0xdf/0x180 [qla2xxx] [ 207.683850] PGD 0 [ 207.683863] Oops: 0000 [#1] SMP [ 207.684391] CPU: 0 PID: 2029 Comm: libvirtd Not tainted 4.1.12-94.2.1.el7uek.x86_64 #2 [ 207.684418] Hardware name: Oracle Corporation ORACLE SERVER X5-2/ASM,MOTHERBOARD,1U, BIOS 30100400 12/26/2016 [ 207.684454] task: ffff88026fc31c00 ti: ffff88007278c000 task.ti: ffff88007278c000 [ 207.684491] RIP: 0010:[] [] qla24xx_vport_delete+0xdf/0x180 [qla2xxx] [ 207.684535] RSP: 0018:ffff88007278fcf8 EFLAGS: 00010202 [ 207.684555] RAX: 0000000000000001 RBX: ffff8802729c17f8 RCX: ffffffffa0258e80 [ 207.684578] RDX: 0000000000007086 RSI: 0000000000000000 RDI: ffff88026fef0360 [ 207.684601] RBP: ffff88007278fd18 R08: 0000000000000001 R09: ffff88027741ad80 [ 207.684625] R10: ffffea0009bbbc00 R11: 0000000000000000 R12: ffff88026fef0000 [ 207.684649] R13: 0000000000000001 R14: ffff88026fef0360 R15: 0000000000000021 [ 207.684673] FS: 00007f24f538d700(0000) GS:ffff880277400000(0000) knlGS:0000000000000000 [ 207.684699] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 207.684719] CR2: 0000000000000410 CR3: 00000002731e7000 CR4: 00000000001406f0 [ 207.684744] Stack: [ 207.684755] ffff8802733dd800 ffff8802728fd000 ffff880474d3f000 ffff880474d3f648 [ 207.684785] ffff88007278fd58 ffffffffa000d344 ffff8804714f4000 ffff8802728fd000 [ 207.684814] ffff8802728fd000 ffff8802733dd800 0000000000000021 ffff880474d3f648 [ 207.684861] Call Trace: [ 207.684897] [] fc_vport_terminate+0x44/0x150 [scsi_transport_fc] [ 207.684927] [] store_fc_host_vport_delete+0x144/0x180 [scsi_transport_fc] [ 207.684959] [] dev_attr_store+0x18/0x30 [ 207.684996] [] sysfs_kf_write+0x3d/0x50 [ 207.685017] [] kernfs_fop_write+0x12a/0x180 [ 207.685040] [] __vfs_write+0x37/0x120 [ 207.685061] [] ? __sb_start_write+0x58/0x110 [ 207.685084] [] ? security_file_permission+0x23/0xa0 [ 207.685107] [] vfs_write+0xa9/0x1b0 [ 207.685128] [] ? mutex_lock+0x16/0x37 [ 207.685147] [] SyS_write+0x55/0xd0 [ 207.685179] [] system_call_fastpath+0x12/0x71 [ 207.685200] Code: 07 00 00 01 0f b7 83 b0 01 00 00 f0 49 0f b3 84 24 30 07 00 00 4c 89 f7 e8 5f 4d 51 e1 48 8b b3 b8 01 00 00 0f b7 83 b0 01 00 00 <66> 39 86 10 04 00 00 74 68 45 0f b7 c5 48 89 de 31 c0 48 c7 c1 [ 207.686827] RIP [] qla24xx_vport_delete+0xdf/0x180 [qla2xxx] [ 207.687634] RSP [ 207.688391] CR2: 0000000000000410 Cc: Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Nicholas Bellinger (cherry picked from commit c4a9b538ab2a109c5f9798bea1f8f4bf93aadfb9) Orabug: 26021151 Signed-off-by: Ethan Zhao Conflicts: drivers/scsi/qla2xxx/qla_attr.c drivers/scsi/qla2xxx/qla_def.h drivers/scsi/qla2xxx/qla_os.c --- diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index ce28f6c2c60bd..6c6acc8fa40fc 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -2119,8 +2119,6 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) "Timer for the VP[%d] has stopped\n", vha->vp_idx); } - BUG_ON(atomic_read(&vha->vref_count)); - qla2x00_free_fcports(vha); mutex_lock(&ha->vport_lock); @@ -2128,7 +2126,7 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) clear_bit(vha->vp_idx, ha->vp_idx_map); mutex_unlock(&ha->vport_lock); - if (vha->qpair->vp_idx == vha->vp_idx) { + if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) { if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS) ql_log(ql_log_warn, vha, 0x7087, "Queue Pair delete failed.\n"); diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 2362215d5a4b1..972c0ff6abf0c 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3729,6 +3729,8 @@ typedef struct scsi_qla_host { atomic_t vref_count; struct qla8044_reset_template reset_tmplt; uint16_t bbcr; + + wait_queue_head_t vref_waitq; } scsi_qla_host_t; struct qla27xx_image_status { @@ -3784,14 +3786,17 @@ struct qla2_sgx { mb(); \ if (__vha->flags.delete_progress) { \ atomic_dec(&__vha->vref_count); \ + wake_up(&__vha->vref_waitq); \ __bail = 1; \ } else { \ __bail = 0; \ } \ } while (0) -#define QLA_VHA_MARK_NOT_BUSY(__vha) \ +#define QLA_VHA_MARK_NOT_BUSY(__vha) do { \ atomic_dec(&__vha->vref_count); \ + wake_up(&__vha->vref_waitq); \ +} while (0) \ #define QLA_QPAIR_MARK_BUSY(__qpair, __bail) do { \ atomic_inc(&__qpair->ref_count); \ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index aab3c9707886d..37d4cbcd3b90e 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -4300,6 +4300,7 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha) } } atomic_dec(&vha->vref_count); + wake_up(&vha->vref_waitq); } spin_unlock_irqrestore(&ha->vport_slock, flags); } diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 55307928d4351..e8fb4d809d33b 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -74,13 +74,14 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha) * ensures no active vp_list traversal while the vport is removed * from the queue) */ - spin_lock_irqsave(&ha->vport_slock, flags); - while (atomic_read(&vha->vref_count)) { - spin_unlock_irqrestore(&ha->vport_slock, flags); - - msleep(500); + wait_event_timeout(vha->vref_waitq, atomic_read(&vha->vref_count), + 10*HZ); - spin_lock_irqsave(&ha->vport_slock, flags); + spin_lock_irqsave(&ha->vport_slock, flags); + if (atomic_read(&vha->vref_count)) { + ql_dbg(ql_dbg_vport, vha, 0xfffa, + "vha->vref_count=%u timeout\n", vha->vref_count.counter); + vha->vref_count = (atomic_t)ATOMIC_INIT(0); } list_del(&vha->list); qlt_update_vp_map(vha, RESET_VP_IDX); @@ -269,6 +270,7 @@ qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) spin_lock_irqsave(&ha->vport_slock, flags); atomic_dec(&vha->vref_count); + wake_up(&vha->vref_waitq); } i++; } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3d1788f6796cb..6c3cf1b1b2bdc 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -4019,6 +4019,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, INIT_LIST_HEAD(&vha->qp_list); spin_lock_init(&vha->work_lock); + init_waitqueue_head(&vha->vref_waitq); sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no); ql_dbg(ql_dbg_init, vha, 0x0041,