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

Reply via email to