|
@@ -221,17 +221,19 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp,
|
|
|
*/
|
|
|
static void fc_disc_restart(struct fc_disc *disc)
|
|
|
{
|
|
|
- struct fc_rport_priv *rdata, *next;
|
|
|
- struct fc_lport *lport = disc->lport;
|
|
|
-
|
|
|
FC_DISC_DBG(disc, "Restarting discovery\n");
|
|
|
|
|
|
- list_for_each_entry_safe(rdata, next, &disc->rports, peers)
|
|
|
- lport->tt.rport_logoff(rdata);
|
|
|
-
|
|
|
disc->requested = 1;
|
|
|
- if (!disc->pending)
|
|
|
- fc_disc_gpn_ft_req(disc);
|
|
|
+ if (disc->pending)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Advance disc_id. This is an arbitrary non-zero number that will
|
|
|
+ * match the value in the fc_rport_priv after discovery for all
|
|
|
+ * freshly-discovered remote ports. Avoid wrapping to zero.
|
|
|
+ */
|
|
|
+ disc->disc_id = (disc->disc_id + 2) | 1;
|
|
|
+ fc_disc_gpn_ft_req(disc);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -278,6 +280,7 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
|
|
|
}
|
|
|
kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
|
|
|
} else {
|
|
|
+ disc->disc_id = (disc->disc_id + 2) | 1;
|
|
|
fc_disc_gpn_ft_req(disc); /* get ports by FC-4 type */
|
|
|
}
|
|
|
|
|
@@ -345,13 +348,30 @@ static int fc_disc_new_target(struct fc_disc *disc,
|
|
|
static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event)
|
|
|
{
|
|
|
struct fc_lport *lport = disc->lport;
|
|
|
+ struct fc_rport_priv *rdata;
|
|
|
|
|
|
FC_DISC_DBG(disc, "Discovery complete\n");
|
|
|
|
|
|
- if (disc->requested)
|
|
|
- fc_disc_gpn_ft_req(disc);
|
|
|
- else
|
|
|
- disc->pending = 0;
|
|
|
+ disc->pending = 0;
|
|
|
+ if (disc->requested) {
|
|
|
+ fc_disc_restart(disc);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Go through all remote ports. If they were found in the latest
|
|
|
+ * discovery, reverify or log them in. Otherwise, log them out.
|
|
|
+ * Skip ports which were never discovered. These are the dNS port
|
|
|
+ * and ports which were created by PLOGI.
|
|
|
+ */
|
|
|
+ list_for_each_entry(rdata, &disc->rports, peers) {
|
|
|
+ if (!rdata->disc_id)
|
|
|
+ continue;
|
|
|
+ if (rdata->disc_id == disc->disc_id)
|
|
|
+ lport->tt.rport_login(rdata);
|
|
|
+ else
|
|
|
+ lport->tt.rport_logoff(rdata);
|
|
|
+ }
|
|
|
|
|
|
mutex_unlock(&disc->disc_mutex);
|
|
|
disc->disc_callback(lport, event);
|
|
@@ -496,7 +516,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
|
|
|
ids.port_name != lport->wwpn) {
|
|
|
rdata = lport->tt.rport_create(lport, &ids);
|
|
|
if (rdata)
|
|
|
- lport->tt.rport_login(rdata);
|
|
|
+ rdata->disc_id = disc->disc_id;
|
|
|
else
|
|
|
printk(KERN_WARNING "libfc: Failed to allocate "
|
|
|
"memory for the newly discovered port "
|
|
@@ -640,6 +660,7 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
|
|
|
|
|
|
rdata = lport->tt.rport_create(lport, &dp->ids);
|
|
|
if (rdata) {
|
|
|
+ rdata->disc_id = disc->disc_id;
|
|
|
kfree(dp);
|
|
|
lport->tt.rport_login(rdata);
|
|
|
}
|