From: Robert Love <robert.w.love@intel.com>
To: James.Bottomley@HansenPartnership.com, linux-scsi@vger.kernel.org
Cc: Joe Eykholt <jeykholt@cisco.com>, Robert Love <robert.w.love@intel.com>
Subject: [PATCH 62/64] libfc: send GPN_ID in reaction to single-port RSCNs.
Date: Tue, 25 Aug 2009 14:03:58 -0700 [thread overview]
Message-ID: <20090825210357.1553.1237.stgit@localhost.localdomain> (raw)
In-Reply-To: <20090825205826.1553.94414.stgit@localhost.localdomain>
From: Joe Eykholt <jeykholt@cisco.com>
When an RSCN indicates changes to individual remote ports,
don't blindly log them out and then back in. Instead, determine
whether they're still in the directory, by doing GPN_ID.
If that is successful, call login, which will send ADISC and reverify,
otherwise, call logoff. Perhaps we should just delete the rport,
not send LOGO, but it seems safer.
Also, fix a possible issue where if a mix of records in the RSCN
cause us to queue disc_ports for disc_single and then we decide
to do full rediscovery, we leak memory for those disc_ports queued.
So, go through the list of disc_ports even if doing full discovery.
Free the disc_ports in any case. If any of the disc_single() calls
return error, do a full discovery.
The ability to fill in GPN_ID requests was added to fc_ct_fill().
For this, it needs the FC_ID to be passed in as an arg.
The did parameter for fc_elsct_send() is used for that, since the
actual D_DID will always be 0xfffffc for all CT requests so far.
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/libfc/fc_disc.c | 137 ++++++++++++++++++++++++++++++++++-------
drivers/scsi/libfc/fc_elsct.c | 2 -
include/scsi/fc_encode.h | 16 ++++-
3 files changed, 128 insertions(+), 27 deletions(-)
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 4242894..c48799e 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -47,7 +47,7 @@ static void fc_disc_gpn_ft_req(struct fc_disc *);
static void fc_disc_gpn_ft_resp(struct fc_seq *, struct fc_frame *, void *);
static void fc_disc_done(struct fc_disc *, enum fc_disc_event);
static void fc_disc_timeout(struct work_struct *);
-static void fc_disc_single(struct fc_disc *, struct fc_disc_port *);
+static int fc_disc_single(struct fc_lport *, struct fc_disc_port *);
static void fc_disc_restart(struct fc_disc *);
/**
@@ -83,7 +83,6 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
struct fc_disc *disc)
{
struct fc_lport *lport;
- struct fc_rport_priv *rdata;
struct fc_els_rscn *rp;
struct fc_els_rscn_page *pp;
struct fc_seq_els_data rjt_data;
@@ -150,6 +149,19 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
}
}
lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
+
+ /*
+ * If not doing a complete rediscovery, do GPN_ID on
+ * the individual ports mentioned in the list.
+ * If any of these get an error, do a full rediscovery.
+ * In any case, go through the list and free the entries.
+ */
+ list_for_each_entry_safe(dp, next, &disc_ports, peers) {
+ list_del(&dp->peers);
+ if (!redisc)
+ redisc = fc_disc_single(lport, dp);
+ kfree(dp);
+ }
if (redisc) {
FC_DISC_DBG(disc, "RSCN received: rediscovering\n");
fc_disc_restart(disc);
@@ -157,14 +169,6 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
FC_DISC_DBG(disc, "RSCN received: not rediscovering. "
"redisc %d state %d in_prog %d\n",
redisc, lport->state, disc->pending);
- list_for_each_entry_safe(dp, next, &disc_ports, peers) {
- list_del(&dp->peers);
- rdata = lport->tt.rport_lookup(lport, dp->port_id);
- if (rdata) {
- lport->tt.rport_logoff(rdata);
- }
- fc_disc_single(disc, dp);
- }
}
fc_frame_free(fp);
return;
@@ -562,32 +566,117 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
}
/**
- * fc_disc_single() - Discover the directory information for a single target
- * @lport: FC local port
- * @dp: The port to rediscover
+ * fc_disc_gpn_id_resp() - Handle a response frame from Get Port Names (GPN_ID)
+ * @sp: exchange sequence
+ * @fp: response frame
+ * @rdata_arg: remote port private data
*
- * Locking Note: This function expects that the disc_mutex is locked
- * before it is called.
+ * Locking Note: This function is called without disc mutex held.
*/
-static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
+static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
+ void *rdata_arg)
{
+ struct fc_rport_priv *rdata = rdata_arg;
+ struct fc_rport_priv *new_rdata;
struct fc_lport *lport;
- struct fc_rport_priv *rdata;
+ struct fc_disc *disc;
+ struct fc_ct_hdr *cp;
+ struct fc_ns_gid_pn *pn;
+ u64 port_name;
- lport = disc->lport;
+ lport = rdata->local_port;
+ disc = &lport->disc;
- if (dp->port_id == fc_host_port_id(lport->host))
+ mutex_lock(&disc->disc_mutex);
+ if (PTR_ERR(fp) == -FC_EX_CLOSED)
goto out;
+ if (IS_ERR(fp))
+ goto redisc;
+
+ cp = fc_frame_payload_get(fp, sizeof(*cp));
+ if (!cp)
+ goto redisc;
+ if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
+ if (fr_len(fp) < sizeof(struct fc_frame_header) +
+ sizeof(*cp) + sizeof(*pn))
+ goto redisc;
+ pn = (struct fc_ns_gid_pn *)(cp + 1);
+ port_name = get_unaligned_be64(&pn->fn_wwpn);
+ if (rdata->ids.port_name == -1)
+ rdata->ids.port_name = port_name;
+ else if (rdata->ids.port_name != port_name) {
+ FC_DISC_DBG(disc, "GPN_ID accepted. WWPN changed. "
+ "Port-id %x wwpn %llx\n",
+ rdata->ids.port_id, port_name);
+ lport->tt.rport_logoff(rdata);
- rdata = lport->tt.rport_create(lport, dp->port_id);
- if (rdata) {
+ new_rdata = lport->tt.rport_create(lport,
+ rdata->ids.port_id);
+ if (new_rdata) {
+ new_rdata->disc_id = disc->disc_id;
+ lport->tt.rport_login(new_rdata);
+ }
+ goto out;
+ }
rdata->disc_id = disc->disc_id;
- kfree(dp);
lport->tt.rport_login(rdata);
+ } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) {
+ FC_DISC_DBG(disc, "GPN_ID rejected reason %x exp %x\n",
+ cp->ct_reason, cp->ct_explan);
+ lport->tt.rport_logoff(rdata);
+ } else {
+ FC_DISC_DBG(disc, "GPN_ID unexpected response code %x\n",
+ ntohs(cp->ct_cmd));
+redisc:
+ fc_disc_restart(disc);
}
- return;
out:
- kfree(dp);
+ mutex_unlock(&disc->disc_mutex);
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
+}
+
+/**
+ * fc_disc_gpn_id_req() - Send Get Port Names by ID (GPN_ID) request
+ * @lport: local port
+ * @rdata: remote port private data
+ *
+ * Locking Note: This function expects that the disc_mutex is locked
+ * before it is called.
+ * On failure, an error code is returned.
+ */
+static int fc_disc_gpn_id_req(struct fc_lport *lport,
+ struct fc_rport_priv *rdata)
+{
+ struct fc_frame *fp;
+
+ fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) +
+ sizeof(struct fc_ns_fid));
+ if (!fp)
+ return -ENOMEM;
+ if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, FC_NS_GPN_ID,
+ fc_disc_gpn_id_resp, rdata, lport->e_d_tov))
+ return -ENOMEM;
+ kref_get(&rdata->kref);
+ return 0;
+}
+
+/**
+ * fc_disc_single() - Discover the directory information for a single target
+ * @lport: local port
+ * @dp: The port to rediscover
+ *
+ * Locking Note: This function expects that the disc_mutex is locked
+ * before it is called.
+ */
+static int fc_disc_single(struct fc_lport *lport, struct fc_disc_port *dp)
+{
+ struct fc_rport_priv *rdata;
+
+ rdata = lport->tt.rport_create(lport, dp->port_id);
+ if (!rdata)
+ return -ENOMEM;
+ rdata->disc_id = 0;
+ return fc_disc_gpn_id_req(lport, rdata);
}
/**
diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c
index d655924..5cfa687 100644
--- a/drivers/scsi/libfc/fc_elsct.c
+++ b/drivers/scsi/libfc/fc_elsct.c
@@ -49,7 +49,7 @@ static struct fc_seq *fc_elsct_send(struct fc_lport *lport,
rc = fc_els_fill(lport, did, fp, op, &r_ctl, &fh_type);
else {
/* CT requests */
- rc = fc_ct_fill(lport, fp, op, &r_ctl, &fh_type);
+ rc = fc_ct_fill(lport, did, fp, op, &r_ctl, &fh_type);
did = FC_FID_DIR_SERV;
}
diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h
index c5ee6bb..27dad70 100644
--- a/include/scsi/fc_encode.h
+++ b/include/scsi/fc_encode.h
@@ -32,6 +32,7 @@ struct fc_ct_req {
struct fc_ns_gid_ft gid;
struct fc_ns_rn_id rn;
struct fc_ns_rft rft;
+ struct fc_ns_fid fid;
} payload;
};
@@ -94,10 +95,16 @@ static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp,
}
/**
- * fc_ct_fill - Fill in a name service request frame
+ * fc_ct_fill() - Fill in a name service request frame
+ * @lport: local port.
+ * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
+ * @fp: frame to contain payload.
+ * @op: CT opcode.
+ * @r_ctl: pointer to FC header R_CTL.
+ * @fh_type: pointer to FC-4 type.
*/
static inline int fc_ct_fill(struct fc_lport *lport,
- struct fc_frame *fp,
+ u32 fc_id, struct fc_frame *fp,
unsigned int op, enum fc_rctl *r_ctl,
enum fc_fh_type *fh_type)
{
@@ -109,6 +116,11 @@ static inline int fc_ct_fill(struct fc_lport *lport,
ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
break;
+ case FC_NS_GPN_ID:
+ ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_fid));
+ hton24(ct->payload.fid.fp_fid, fc_id);
+ break;
+
case FC_NS_RFT_ID:
ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rft));
hton24(ct->payload.rft.fid.fp_fid,
next prev parent reply other threads:[~2009-08-25 21:03 UTC|newest]
Thread overview: 69+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
2009-08-25 20:58 ` [PATCH 01/64] fcoe: Add format spacing to FCOE_NETDEV_DBG debug macro Robert Love
2009-08-25 20:58 ` [PATCH 02/64] libfc: Fix misleading debug statement Robert Love
2009-08-25 20:58 ` [PATCH 03/64] fcoe: libfcoe: extra semicolon in CHECK_LOGGING macros causes compile error Robert Love
2009-08-25 20:58 ` [PATCH 04/64] fcoe, libfc: adds per cpu exch pool within exchange manager(EM) Robert Love
2009-08-25 20:58 ` [PATCH 05/64] fcoe, libfc: fully makes use of per cpu exch pool and then removes em_lock Robert Love
2009-08-25 20:58 ` [PATCH 06/64] libfc: Export FC headers Robert Love
2009-08-27 10:27 ` Christof Schmitt
2009-08-27 17:42 ` Robert Love
2009-08-28 8:32 ` Swen Schillig
2009-08-28 16:58 ` Robert Love
2009-08-25 20:59 ` [PATCH 07/64] fcoe: Add sysfs parameter to fcoe for minimum DDP read I/O size Robert Love
2009-08-25 20:59 ` [PATCH 08/64] libfcoe: fcoe_ctlr_destroy use cancel_work_sync instead of flush_work Robert Love
2009-08-25 20:59 ` [PATCH 09/64] fcoe: fix missing error check in call to fcoe_if_init Robert Love
2009-08-25 20:59 ` [PATCH 10/64] fcoe: remove unnecessary list and lock initializations Robert Love
2009-08-25 20:59 ` [PATCH 11/64] fcoe: interface changes to fcoe_if_create and fcoe_if_destroy Robert Love
2009-08-25 20:59 ` [PATCH 12/64] fcoe: Introduce and allocate fcoe_interface structure, 1:1 with net_device Robert Love
2009-08-25 20:59 ` [PATCH 13/64] fcoe: move netdev to fcoe_interface Robert Love
2009-08-25 20:59 ` [PATCH 14/64] fcoe: move packet handlers from fcoe_port " Robert Love
2009-08-25 20:59 ` [PATCH 15/64] fcoe: move FIP controller " Robert Love
2009-08-25 20:59 ` [PATCH 16/64] fcoe: move offload exchange manager pointer " Robert Love
2009-08-25 20:59 ` [PATCH 17/64] fcoe: remove fcoe_interface->priv pointer Robert Love
2009-08-25 21:00 ` [PATCH 18/64] fcoe: fcoe_interface create, destroy and refcounting Robert Love
2009-08-25 21:00 ` [PATCH 19/64] fcoe: split out per interface setup Robert Love
2009-08-25 21:00 ` [PATCH 20/64] fcoe: add mutex to protect create and destroy Robert Love
2009-08-25 21:00 ` [PATCH 21/64] fcoe: move the host-list add/remove to keep out VN_Ports Robert Love
2009-08-25 21:00 ` [PATCH 22/64] fcoe: Fix module ref count bug by adding NETDEV UNREGISTER handling Robert Love
2009-08-25 21:00 ` [PATCH 23/64] fcoe: use rtnl mutex in place of hostlist lock Robert Love
2009-08-25 21:00 ` [PATCH 24/64] libfc: prepare to split off struct fc_rport_priv from fc_rport_libfc_priv Robert Love
2009-08-25 21:00 ` [PATCH 25/64] libfc: change interface for rport_create Robert Love
2009-08-25 21:00 ` [PATCH 26/64] libfc: fix RPORT_TO_PRIV and PRIV_TO_RPORT() macros Robert Love
2009-08-25 21:00 ` [PATCH 27/64] libfc: make fc_rport_priv the primary rport interface Robert Love
2009-08-25 21:00 ` [PATCH 28/64] libfc: change elsct to use FC_ID instead of rdata Robert Love
2009-08-25 21:01 ` [PATCH 29/64] libfc: make rport structure optional Robert Love
2009-08-25 21:01 ` [PATCH 30/64] libfc: rearrange code in fc_rport_work Robert Love
2009-08-25 21:01 ` [PATCH 31/64] libfc: rename rport event CREATED to READY Robert Love
2009-08-25 21:01 ` [PATCH 32/64] libfc: don't create dummy (rogue) remote ports Robert Love
2009-08-25 21:01 ` [PATCH 33/64] libfc: fix rport event race between READY and LOGO Robert Love
2009-08-25 21:01 ` [PATCH 34/64] libfc: eliminate disc->event Robert Love
2009-08-25 21:01 ` [PATCH 35/64] libfc: remove unused disc->delay element Robert Love
2009-08-25 21:01 ` [PATCH 36/64] libfc: rport debug messages were printing pointer values Robert Love
2009-08-25 21:01 ` [PATCH 37/64] libfc: simplify fc_lport_rport_callback Robert Love
2009-08-25 21:01 ` [PATCH 38/64] libfc: make rport module maintain the rport list Robert Love
2009-08-25 21:01 ` [PATCH 39/64] libfc: have rport_create do a lookup for pre-existing rports first Robert Love
2009-08-25 21:02 ` [PATCH 40/64] libfc: change to make remote port callback optional Robert Love
2009-08-25 21:02 ` [PATCH 41/64] libfc: move rport_lookup into fc_rport.c Robert Love
2009-08-25 21:02 ` [PATCH 42/64] libfc: do not log off rports before or after discovery Robert Love
2009-08-25 21:02 ` [PATCH 43/64] libfc: discovery restart sequence error fix Robert Love
2009-08-25 21:02 ` [PATCH 44/64] libfc: rearrange code in fc_disc_gpn_ft_resp() Robert Love
2009-08-25 21:02 ` [PATCH 45/64] libfc: handle discovery failure more correctly Robert Love
2009-08-25 21:02 ` [PATCH 46/64] libfc: fix: empty zone causes endless discovery retries Robert Love
2009-08-25 21:02 ` [PATCH 47/64] libfc: discovery retry should clear pending first Robert Love
2009-08-25 21:02 ` [PATCH 48/64] libfc: discovery gpn_ft parse bug Robert Love
2009-08-25 21:02 ` [PATCH 49/64] libfc: clean up point-to-point discovery code Robert Love
2009-08-25 21:02 ` [PATCH 50/64] libfc: don't do discovery before callback is set Robert Love
2009-08-25 21:02 ` [PATCH 51/64] libfc: Initialize fc_rport_identifiers inside fc_rport_create Robert Love
2009-08-25 21:03 ` [PATCH 52/64] libfc: Always reset remote port roles when receiving PRLI Robert Love
2009-08-25 21:03 ` [PATCH 53/64] libfc: move remote port lookup for ELS requests into fc_rport.c Robert Love
2009-08-25 21:03 ` [PATCH 54/64] libfc: fix: rport_recv_req needs disc_mutex when calling rport_lookup Robert Love
2009-08-25 21:03 ` [PATCH 55/64] libfc: improve debug messages for ELS response handlers Robert Love
2009-08-25 21:03 ` [PATCH 56/64] libfc: correctly handle incoming PLOGI request Robert Love
2009-08-25 21:03 ` [PATCH 57/64] libfc: fix rport error handling for login-required and invalid ops Robert Love
2009-08-25 21:03 ` [PATCH 58/64] libfc: re-login to remote ports that send us LOGO Robert Love
2009-08-25 21:03 ` [PATCH 59/64] libfc: LOGO response code had extraeous enter_rtv Robert Love
2009-08-25 21:03 ` [PATCH 60/64] libfc: use ADISC to verify rport login state Robert Love
2009-08-25 21:03 ` [PATCH 61/64] libfc: fix handling of incoming Discover Address (ADISC) requests Robert Love
2009-08-25 21:03 ` Robert Love [this message]
2009-08-25 21:04 ` [PATCH 63/64] libfc: don't swap OX_ID and RX_ID when sending BA_RJT Robert Love
2009-08-25 21:04 ` [PATCH 64/64] fcoe: flush per-cpu thread work when destroying interface Robert Love
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090825210357.1553.1237.stgit@localhost.localdomain \
--to=robert.w.love@intel.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=jeykholt@cisco.com \
--cc=linux-scsi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.