diff --git a/nightly/conf/nightly.conf b/nightly/conf/nightly.conf index 1bcb50c0e..d775a3ff2 100644 --- a/nightly/conf/nightly.conf +++ b/nightly/conf/nightly.conf @@ -3,11 +3,11 @@ ABT_DETAILS="x86_64" ABT_JOBS=5 ABT_KERNELS=" \ -5.2 \ -5.1.17-nc \ +5.2.1 \ +5.1.18-nc \ 5.0.21-nc \ 4.20.17-nc \ -4.19.58-nc \ +4.19.59-nc \ 4.18.20-nc \ 4.17.19-nc \ 4.16.18-nc \ diff --git a/qla2x00t-32gbit/qla2x00-target/README b/qla2x00t-32gbit/qla2x00-target/README index fb1b717e8..c410467f2 100644 --- a/qla2x00t-32gbit/qla2x00-target/README +++ b/qla2x00t-32gbit/qla2x00-target/README @@ -73,3 +73,32 @@ Call Trace: [] ? retint_restore_args+0x13/0x43 [] ? kthread+0x0/0xc0 [] ? child_rip+0x0/0x30 + +When using RHEL 6 unloading this driver triggers a deadlock: + +INFO: task events/0:35 blocked for more than 120 seconds. + Not tainted 2.6.32-754.11.1.el6.x86_64.debug #1 +"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +events/0 D ffff880077e24408 12408 35 2 0x00000000 + ffff88007e02fa60 0000000000000046 0000000000000000 7fffffffffffffff + 7fffffffffffffff 00000365a5588f80 ffff88007e028a80 ffff88000d7d93d8 + 0000000100346a5e 00000000000003c8 ffff88007e029040 ffff88007e02ffd8 +Call Trace: + [] schedule_timeout+0x265/0x330 + [] ? wait_for_common+0x4f/0x180 + [] ? wait_for_common+0x4f/0x180 + [] ? default_wake_function+0x0/0x20 + [] wait_for_common+0x12b/0x180 + [] ? default_wake_function+0x0/0x20 + [] wait_for_completion+0x1d/0x20 + [] ? qlt_free_session_done+0x1d6/0x930 [qla2xxx_scst] + [] ? qlt_free_session_done+0x0/0x930 [qla2xxx_scst] + [] ? worker_thread+0x21e/0x3f0 + [] ? worker_thread+0x1cb/0x3f0 + [] ? autoremove_wake_function+0x0/0x40 + [] ? worker_thread+0x0/0x3f0 + [] ? kthread+0xa0/0xc0 + [] ? child_rip+0x20/0x30 + [] ? retint_restore_args+0x13/0x43 + [] ? kthread+0x0/0xc0 + [] ? child_rip+0x0/0x30 diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 5c793e41c..7801cc785 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -2428,6 +2428,7 @@ typedef struct fc_port { #define NVME_FLAG_RESETTING 1 struct fc_port *conflict; + unsigned char logout_completed; int generation; struct se_session *se_sess; @@ -2435,9 +2436,8 @@ typedef struct fc_port { struct qla_tgt *tgt; unsigned long expires; struct list_head del_list_entry; + struct work_struct free_work; struct work_struct reg_work; - struct work_struct post_logout_work; - struct work_struct finish_logout_work; uint64_t jiffies_at_registration; struct qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX]; struct completion *unreg_done; diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 12f91ccd6..a4ebff52c 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -293,6 +293,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, goto done; fcport->flags |= FCF_ASYNC_SENT; + fcport->logout_completed = 0; fcport->disc_state = DSC_LOGIN_PEND; sp->type = SRB_LOGIN_CMD; @@ -465,7 +466,7 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea) fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2, fcport->rscn_gen, ea->sp->gen1, fcport->loop_id); - if (ea->rc != QLA_SUCCESS) { + if (ea->data[0] != MBS_COMMAND_COMPLETE) { ql_dbg(ql_dbg_disc, vha, 0x2066, "%s %s: adisc fail: post delete\n", __func__, wwn_to_str(ea->fcport->port_name)); @@ -1199,6 +1200,7 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport) return rval; fcport->flags |= FCF_ASYNC_SENT; + fcport->logout_completed = 0; sp->type = SRB_PRLI_CMD; sp->name = "prli"; @@ -1884,8 +1886,8 @@ qla24xx_async_abort_command(srb_t *sp) static void qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea) { - switch (ea->rc) { - case QLA_SUCCESS: + switch (ea->data[0]) { + case MBS_COMMAND_COMPLETE: ql_dbg(ql_dbg_disc, vha, 0x2118, "%s %d %s post gpdb\n", __func__, __LINE__, wwn_to_str(ea->fcport->port_name)); @@ -1965,8 +1967,8 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea) return; } - switch (ea->rc) { - case QLA_SUCCESS: + switch (ea->data[0]) { + case MBS_COMMAND_COMPLETE: /* * Driver must validate login state - If PRLI not complete, * force a relogin attempt via implicit LOGO, PLOGI, and PRLI @@ -1994,7 +1996,7 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea) qla24xx_post_gpdb_work(vha, ea->fcport, 0); } break; - case QLA_COMMAND_ERROR: + case MBS_COMMAND_ERROR: ql_dbg(ql_dbg_disc, vha, 0x20eb, "%s %d %s cmd error %x\n", __func__, __LINE__, wwn_to_str(ea->fcport->port_name), ea->data[1]); @@ -2005,7 +2007,7 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea) else qla2x00_mark_device_lost(vha, ea->fcport, 1, 0); break; - case QLA_LOOP_ID_USED: + case MBS_LOOP_ID_USED: /* data[1] = IO PARAM 1 = nport ID */ cid.b.domain = (ea->iop[1] >> 16) & 0xff; cid.b.area = (ea->iop[1] >> 8) & 0xff; @@ -2021,7 +2023,7 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea) ea->fcport->loop_id = FC_NO_LOOP_ID; qla24xx_post_gnl_work(vha, ea->fcport); break; - case QLA_PORT_ID_USED: + case MBS_PORT_ID_USED: lid = ea->iop[1] & 0xffff; qlt_find_sess_invalidate_other(vha, wwn_to_u64(ea->fcport->port_name), @@ -4877,8 +4879,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn); INIT_WORK(&fcport->reg_work, qla_register_fcport_fn); - INIT_WORK(&fcport->post_logout_work, qlt_post_logout); - INIT_WORK(&fcport->finish_logout_work, qlt_finish_logout); INIT_LIST_HEAD(&fcport->gnl_entry); INIT_LIST_HEAD(&fcport->list); diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index 65d8be906..7518a35c6 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -568,8 +568,10 @@ static void qla_nvme_remoteport_delete(struct nvme_fc_remote_port *rport) } complete(&fcport->nvme_del_done); - if (!test_bit(UNLOADING, &fcport->vha->dpc_flags)) - schedule_work(&fcport->post_logout_work); + if (!test_bit(UNLOADING, &fcport->vha->dpc_flags)) { + INIT_WORK(&fcport->free_work, qlt_free_session_done); + schedule_work(&fcport->free_work); + } fcport->nvme_flag &= ~NVME_FLAG_DELETING; ql_log(ql_log_info, fcport->vha, 0x2110, diff --git a/qla2x00t-32gbit/qla_target.c b/qla2x00t-32gbit/qla_target.c index 69ec184a0..a307301e7 100644 --- a/qla2x00t-32gbit/qla_target.c +++ b/qla2x00t-32gbit/qla_target.c @@ -698,8 +698,7 @@ void qla24xx_do_nack_work(struct scsi_qla_host *vha, struct qla_work_evt *e) case SRB_NACK_PRLI: t = e->u.nack.fcport; flush_work(&t->del_work); - flush_work(&t->post_logout_work); - flush_work(&t->finish_logout_work); + flush_work(&t->free_work); mutex_lock(&vha->vha_tgt.tgt_mutex); t = qlt_create_sess(vha, e->u.nack.fcport, 0); mutex_unlock(&vha->vha_tgt.tgt_mutex); @@ -967,13 +966,16 @@ qlt_send_first_logo(struct scsi_qla_host *vha, qlt_port_logo_t *logo) logo->cmd_count, res); } -void qlt_post_logout(struct work_struct *work) +void qlt_free_session_done(struct work_struct *work) { struct fc_port *sess = container_of(work, struct fc_port, - post_logout_work); + free_work); + struct qla_tgt *tgt = sess->tgt; struct scsi_qla_host *vha = sess->vha; struct qla_hw_data *ha = vha->hw; + unsigned long flags; bool logout_started = false; + scsi_qla_host_t *base_vha; struct qlt_plogi_ack_t *own = sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN]; @@ -1033,19 +1035,22 @@ void qlt_post_logout(struct work_struct *work) if (sess->se_sess != NULL) ha->tgt.tgt_ops->free_session(sess); - if (!logout_started) - qlt_finish_logout(&sess->finish_logout_work); -} + if (logout_started) { + bool traced = false; -void qlt_finish_logout(struct work_struct *work) -{ - struct fc_port *sess = container_of(work, struct fc_port, - finish_logout_work); - struct qla_tgt *tgt = sess->tgt; - struct scsi_qla_host *vha = sess->vha; - struct qla_hw_data *ha = vha->hw; - scsi_qla_host_t *base_vha; - unsigned long flags; + while (!READ_ONCE(sess->logout_completed)) { + if (!traced) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf086, + "%s: waiting for sess %p logout\n", + __func__, sess); + traced = true; + } + msleep(100); + } + + ql_dbg(ql_dbg_disc, vha, 0xf087, + "%s: sess %p logout completed\n", __func__, sess); + } if (sess->logo_ack_needed) { sess->logo_ack_needed = 0; @@ -1082,8 +1087,7 @@ void qlt_finish_logout(struct work_struct *work) struct qlt_plogi_ack_t *con = sess->plogi_link[QLT_PLOGI_LINK_CONFLICT]; struct imm_ntfy_from_isp *iocb; - struct qlt_plogi_ack_t *own = - sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN]; + own = sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN]; if (con) { iocb = &con->iocb; @@ -1179,7 +1183,8 @@ void qlt_unreg_sess(struct fc_port *sess) sess->nvme_flag |= NVME_FLAG_DELETING; schedule_work(&sess->nvme_del_work); } else { - schedule_work(&sess->post_logout_work); + INIT_WORK(&sess->free_work, qlt_free_session_done); + schedule_work(&sess->free_work); } } EXPORT_SYMBOL(qlt_unreg_sess); @@ -1385,6 +1390,7 @@ static struct fc_port *qlt_create_sess( */ sess->logout_on_delete = 1; sess->keep_nport_handle = 0; + sess->logout_completed = 0; if (ha->tgt.tgt_ops->check_initiator_node_acl(vha, &fcport->port_name[0], sess) < 0) { @@ -4612,7 +4618,7 @@ void qlt_logo_completion_handler(fc_port_t *fcport, int rc) fcport->d_id.b.al_pa, rc); } - schedule_work(&fcport->finish_logout_work); + fcport->logout_completed = 1; } /* diff --git a/qla2x00t-32gbit/qla_target.h b/qla2x00t-32gbit/qla_target.h index 17bde2b5d..586c980db 100644 --- a/qla2x00t-32gbit/qla_target.h +++ b/qla2x00t-32gbit/qla_target.h @@ -1065,9 +1065,7 @@ extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *, int); extern int __init qlt_init(void); extern void qlt_exit(void); extern void qlt_update_vp_map(struct scsi_qla_host *, int); -extern void qlt_post_logout(struct work_struct *); -extern void qlt_finish_logout(struct work_struct *work); - +extern void qlt_free_session_done(struct work_struct *); /* * This macro is used during early initializations when host->active_mode * is not set. Right now, ha value is ignored.