When number of NPIV ports created are greater than the xids allocated per pool -- for eg., creating 255 NPIV ports on a system with nr_cpu_ids of 32, with each pool containing 128 xids -- and then generating a link event - for eg., shutdown/no shutdown -- on the switch port causes the hang with the following stack trace.
Call Trace: schedule_timeout+0x19d/0x230 wait_for_common+0xc0/0x170 __cancel_work_timer+0xcf/0x1b0 fc_disc_stop+0x16/0x30 [libfc] fc_lport_reset_locked+0x47/0x90 [libfc] fc_lport_enter_reset+0x67/0xe0 [libfc] fc_lport_disc_callback+0xbc/0xe0 [libfc] fc_disc_done+0xa8/0xf0 [libfc] fc_disc_timeout+0x29/0x40 [libfc] run_workqueue+0xb8/0x140 worker_thread+0x96/0x110 kthread+0x96/0xa0 child_rip+0xa/0x20 Fix is to not cancel the disc_work if discovery is already stopped. Signed-off-by: Bhanu Prakash Gollapudi <[email protected]> --- drivers/scsi/libfc/fc_disc.c | 8 ++++++-- include/scsi/libfc.h | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 32f67c4..cd1dfc9 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -223,6 +223,7 @@ static void fc_disc_restart(struct fc_disc *disc) FC_DISC_DBG(disc, "Restarting discovery\n"); + disc->disc_stopped = 0; disc->requested = 1; if (disc->pending) return; @@ -333,8 +334,10 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp) } disc->retry_count++; schedule_delayed_work(&disc->disc_work, delay); - } else + } else { + disc->disc_stopped = 1; fc_disc_done(disc, DISC_EV_FAILED); + } } } @@ -685,7 +688,8 @@ void fc_disc_stop(struct fc_lport *lport) struct fc_disc *disc = &lport->disc; if (disc) { - cancel_delayed_work_sync(&disc->disc_work); + if (!disc->disc_stopped) + cancel_delayed_work_sync(&disc->disc_work); fc_disc_stop_rports(disc); } } diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 74e0985..36edda1 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -736,7 +736,8 @@ struct libfc_function_template { * struct fc_disc - Discovery context * @retry_count: Number of retries * @pending: 1 if discovery is pending, 0 if not - * @requesting: 1 if discovery has been requested, 0 if not + * @requested: 1 if discovery has been requested, 0 if not + * @disc_stopped: 1 if discovery is stopped, 0 if not * @seq_count: Number of sequences used for discovery * @buf_len: Length of the discovery buffer * @disc_id: Discovery ID @@ -752,6 +753,7 @@ struct fc_disc { unsigned char retry_count; unsigned char pending; unsigned char requested; + unsigned char disc_stopped; unsigned short seq_count; unsigned char buf_len; u16 disc_id; -- 1.7.0.6 _______________________________________________ devel mailing list [email protected] http://www.open-fcoe.org/mailman/listinfo/devel
