Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f6c6149 authored by Joe Eykholt's avatar Joe Eykholt Committed by James Bottomley
Browse files

[SCSI] libfc: do not log off rports before or after discovery



When receiving an RSCN, do not log off all rports.  This is
extremely disruptive.  If, after the GPN_FT response, some
rports haven't been listed, delete them.

Add field disc_id to structs fc_rport_priv and fc_disc.
disc_id is an arbitrary serial number used to identify the
rports found by the latest discovery.  This eliminates the need
to go through the rport list when restarting discovery.

Signed-off-by: default avatarJoe Eykholt <jeykholt@cisco.com>
Signed-off-by: default avatarRobert Love <robert.w.love@intel.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 8025b5db
Loading
Loading
Loading
Loading
+34 −13
Original line number Diff line number Diff line
@@ -221,16 +221,18 @@ 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)
	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;
	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);
	}
+3 −0
Original line number Diff line number Diff line
@@ -202,6 +202,7 @@ struct fc_rport_libfc_priv {
 * @ids: remote port identifiers and roles
 * @flags: REC and RETRY supported flags
 * @max_seq: maximum number of concurrent sequences
 * @disc_id: discovery identifier
 * @maxframe_size: maximum frame size
 * @retries: retry count in current state
 * @e_d_tov: error detect timeout value (in msec)
@@ -218,6 +219,7 @@ struct fc_rport_priv {
	struct fc_rport_identifiers ids;
	u16			   flags;
	u16		           max_seq;
	u16			   disc_id;
	u16			   maxframe_size;
	unsigned int	           retries;
	unsigned int	           e_d_tov;
@@ -678,6 +680,7 @@ struct fc_disc {
	unsigned char		requested;
	unsigned short		seq_count;
	unsigned char		buf_len;
	u16			disc_id;

	void (*disc_callback)(struct fc_lport *,
			      enum fc_disc_event);