* [PATCH 00/30] FCoE VN2VN fixes
@ 2016-08-26 12:01 Hannes Reinecke
2016-08-26 12:01 ` [PATCH 01/30] libfc: Revisit kref handling Hannes Reinecke
` (30 more replies)
0 siblings, 31 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke
Hi all,
here's a patchset to get VN2VN running on non-DCB fabrics.
With it it's possible to run FCoE VN2VN over virtio, allowing
for a fully virtualized FC testbed. Which would make it ideal
to integrate into Mike's mptest test suite.
It also irons out some generic issues with the libfc stack,
like another round for kref handling updates and handling PRLI correctly.
(The PRLI problems even have a workaround in iPXE, so it's time to do
something about it ...)
As usual, comments and reviews are welcome.
Hannes Reinecke (29):
libfc: Revisit kref handling
libfc: additional debugging messages
libfc: spurious I/O error under high load
libfc: Do not login if the port is already started
libfc: use configured lport R_A_TOV when sending
libfc: use configured e_d_tov for remote port state
libfc: do not overwrite DID_TIME_OUT status
libfc: use error code for fc_rport_error()
libfc: Send LS_RJT responses on frame allocation
libfc: don't advance state machine for incoming FLOGI
libfc: Fixup disc_mutex handling
libfc: Do not drop down to FLOGI for fc_rport_login()
libfc: Implement RTV responder
libfc: Rework PRLI handling
libfc: Return LS_RJT_BUSY for PRLI in status PLOGI
libfc: Clarify ramp-down messages
libfc: sanitize E_D_TOV and R_A_TOV setting
libfc: safeguard against invalid exchange index
libfc: quarantine timed out xids
libfc: don't fail sequence abort for completed
libfc: Do not drop out-of-order frames
libfc: reset timeout on queue full
libfc: wait for E_D_TOV when out-of-order sequence is received
fcoe: set default TC priority
fcoe: inhibit writing invalid values into the 'enabled'
fcoe: correct sending FIP VLAN packets on VLAN 0
fcoe: FIP debugging
fcoe: filter out frames from invalid vlans
fcoe: make R_A_TOV and E_D_TOV configurable
Wei Yongjun (1):
fcoe: Use kfree_skb() instead of kfree()
drivers/scsi/fcoe/fcoe.c | 23 ++-
drivers/scsi/fcoe/fcoe_ctlr.c | 93 +++++++--
drivers/scsi/fcoe/fcoe_sysfs.c | 83 +++++++-
drivers/scsi/libfc/fc_disc.c | 30 +--
drivers/scsi/libfc/fc_exch.c | 118 +++++++----
drivers/scsi/libfc/fc_fcp.c | 195 ++++++++++++------
drivers/scsi/libfc/fc_lport.c | 8 +-
drivers/scsi/libfc/fc_rport.c | 436 ++++++++++++++++++++++++++++++-----------
include/scsi/libfc.h | 9 +-
9 files changed, 760 insertions(+), 235 deletions(-)
--
1.8.5.6
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 01/30] libfc: Revisit kref handling
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 13:37 ` Johannes Thumshirn
2016-08-26 12:01 ` [PATCH 02/30] libfc: additional debugging messages Hannes Reinecke
` (29 subsequent siblings)
30 siblings, 1 reply; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
The kref handling in fc_rport is a mess. This patch updates
the kref handling according to the following rules:
- Take a reference whenever scheduling a workqueue
- Take a reference whenever an ELS command is send
- Drop the reference at the end of the workqueue function
- Drop the reference at the end of handling ELS replies
- Take a reference when allocating an rport
- Drop the reference when removing an rport
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_rport.c | 136 ++++++++++++++++++++++++++++++++----------
1 file changed, 105 insertions(+), 31 deletions(-)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 97aeadd..8909280 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -44,6 +44,19 @@
* path this potential over-use of the mutex is acceptable.
*/
+/*
+ * RPORT REFERENCE COUNTING
+ *
+ * A rport reference should be taken when:
+ * - an rport is allocated
+ * - a workqueue item is scheduled
+ * - an ELS request is send
+ * The reference should be dropped when:
+ * - the workqueue function has finished
+ * - the ELS response is handled
+ * - an rport is removed
+ */
+
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
@@ -242,6 +255,8 @@ static void fc_rport_state_enter(struct fc_rport_priv *rdata,
/**
* fc_rport_work() - Handler for remote port events in the rport_event_queue
* @work: Handle to the remote port being dequeued
+ *
+ * Reference counting: drops kref on return
*/
static void fc_rport_work(struct work_struct *work)
{
@@ -272,8 +287,10 @@ static void fc_rport_work(struct work_struct *work)
kref_get(&rdata->kref);
mutex_unlock(&rdata->rp_mutex);
- if (!rport)
+ if (!rport) {
+ FC_RPORT_DBG(rdata, "No rport!\n");
rport = fc_remote_port_add(lport->host, 0, &ids);
+ }
if (!rport) {
FC_RPORT_DBG(rdata, "Failed to add the rport\n");
lport->tt.rport_logoff(rdata);
@@ -329,7 +346,8 @@ static void fc_rport_work(struct work_struct *work)
FC_RPORT_DBG(rdata, "lld callback ev %d\n", event);
rdata->lld_event_callback(lport, rdata, event);
}
- cancel_delayed_work_sync(&rdata->retry_work);
+ if (cancel_delayed_work_sync(&rdata->retry_work))
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
/*
* Reset any outstanding exchanges before freeing rport.
@@ -381,6 +399,7 @@ static void fc_rport_work(struct work_struct *work)
mutex_unlock(&rdata->rp_mutex);
break;
}
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
}
/**
@@ -431,10 +450,14 @@ static int fc_rport_login(struct fc_rport_priv *rdata)
* Set the new event so that the old pending event will not occur.
* Since we have the mutex, even if fc_rport_work() is already started,
* it'll see the new event.
+ *
+ * Reference counting: does not modify kref
*/
static void fc_rport_enter_delete(struct fc_rport_priv *rdata,
enum fc_rport_event event)
{
+ struct fc_lport *lport = rdata->local_port;
+
if (rdata->rp_state == RPORT_ST_DELETE)
return;
@@ -442,8 +465,11 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata,
fc_rport_state_enter(rdata, RPORT_ST_DELETE);
- if (rdata->event == RPORT_EV_NONE)
- queue_work(rport_event_queue, &rdata->event_work);
+ kref_get(&rdata->kref);
+ if (rdata->event == RPORT_EV_NONE &&
+ !queue_work(rport_event_queue, &rdata->event_work))
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
+
rdata->event = event;
}
@@ -496,15 +522,22 @@ out:
*
* Locking Note: The rport lock is expected to be held before calling
* this routine.
+ *
+ * Reference counting: schedules workqueue, does not modify kref
*/
static void fc_rport_enter_ready(struct fc_rport_priv *rdata)
{
+ struct fc_lport *lport = rdata->local_port;
+
fc_rport_state_enter(rdata, RPORT_ST_READY);
FC_RPORT_DBG(rdata, "Port is Ready\n");
- if (rdata->event == RPORT_EV_NONE)
- queue_work(rport_event_queue, &rdata->event_work);
+ kref_get(&rdata->kref);
+ if (rdata->event == RPORT_EV_NONE &&
+ !queue_work(rport_event_queue, &rdata->event_work))
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
+
rdata->event = RPORT_EV_READY;
}
@@ -515,13 +548,17 @@ static void fc_rport_enter_ready(struct fc_rport_priv *rdata)
* Locking Note: Called without the rport lock held. This
* function will hold the rport lock, call an _enter_*
* function and then unlock the rport.
+ *
+ * Reference counting: Drops kref on return.
*/
static void fc_rport_timeout(struct work_struct *work)
{
struct fc_rport_priv *rdata =
container_of(work, struct fc_rport_priv, retry_work.work);
+ struct fc_lport *lport = rdata->local_port;
mutex_lock(&rdata->rp_mutex);
+ FC_RPORT_DBG(rdata, "Port timeout, state %s\n", fc_rport_state(rdata));
switch (rdata->rp_state) {
case RPORT_ST_FLOGI:
@@ -547,6 +584,7 @@ static void fc_rport_timeout(struct work_struct *work)
}
mutex_unlock(&rdata->rp_mutex);
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
}
/**
@@ -556,6 +594,8 @@ static void fc_rport_timeout(struct work_struct *work)
*
* Locking Note: The rport lock is expected to be held before
* calling this routine
+ *
+ * Reference counting: does not modify kref
*/
static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
{
@@ -602,11 +642,14 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
*
* Locking Note: The rport lock is expected to be held before
* calling this routine
+ *
+ * Reference counting: increments kref when scheduling retry_work
*/
static void fc_rport_error_retry(struct fc_rport_priv *rdata,
struct fc_frame *fp)
{
unsigned long delay = msecs_to_jiffies(FC_DEF_E_D_TOV);
+ struct fc_lport *lport = rdata->local_port;
/* make sure this isn't an FC_EX_CLOSED error, never retry those */
if (PTR_ERR(fp) == -FC_EX_CLOSED)
@@ -619,7 +662,9 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata,
/* no additional delay on exchange timeouts */
if (PTR_ERR(fp) == -FC_EX_TIMEOUT)
delay = 0;
- schedule_delayed_work(&rdata->retry_work, delay);
+ kref_get(&rdata->kref);
+ if (!schedule_delayed_work(&rdata->retry_work, delay))
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
return;
}
@@ -740,6 +785,8 @@ bad:
*
* Locking Note: The rport lock is expected to be held before calling
* this routine.
+ *
+ * Reference counting: increments kref when sending ELS
*/
static void fc_rport_enter_flogi(struct fc_rport_priv *rdata)
{
@@ -758,18 +805,21 @@ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata)
if (!fp)
return fc_rport_error_retry(rdata, fp);
+ kref_get(&rdata->kref);
if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_FLOGI,
fc_rport_flogi_resp, rdata,
- 2 * lport->r_a_tov))
+ 2 * lport->r_a_tov)) {
fc_rport_error_retry(rdata, NULL);
- else
- kref_get(&rdata->kref);
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
+ }
}
/**
* fc_rport_recv_flogi_req() - Handle Fabric Login (FLOGI) request in p-mp mode
* @lport: The local port that received the PLOGI request
* @rx_fp: The PLOGI request frame
+ *
+ * Reference counting: drops kref on return
*/
static void fc_rport_recv_flogi_req(struct fc_lport *lport,
struct fc_frame *rx_fp)
@@ -824,8 +874,7 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
* RPORT wouldn;t have created and 'rport_lookup' would have
* failed anyway in that case.
*/
- if (lport->point_to_multipoint)
- break;
+ break;
case RPORT_ST_DELETE:
mutex_unlock(&rdata->rp_mutex);
rjt_data.reason = ELS_RJT_FIP;
@@ -969,6 +1018,8 @@ fc_rport_compatible_roles(struct fc_lport *lport, struct fc_rport_priv *rdata)
*
* Locking Note: The rport lock is expected to be held before calling
* this routine.
+ *
+ * Reference counting: increments kref when sending ELS
*/
static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
{
@@ -995,12 +1046,13 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
}
rdata->e_d_tov = lport->e_d_tov;
+ kref_get(&rdata->kref);
if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI,
fc_rport_plogi_resp, rdata,
- 2 * lport->r_a_tov))
+ 2 * lport->r_a_tov)) {
fc_rport_error_retry(rdata, NULL);
- else
- kref_get(&rdata->kref);
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
+ }
}
/**
@@ -1108,6 +1160,8 @@ err:
*
* Locking Note: The rport lock is expected to be held before calling
* this routine.
+ *
+ * Reference counting: increments kref when sending ELS
*/
static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
{
@@ -1151,11 +1205,12 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
fc_host_port_id(lport->host), FC_TYPE_ELS,
FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
+ kref_get(&rdata->kref);
if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp,
- NULL, rdata, 2 * lport->r_a_tov))
+ NULL, rdata, 2 * lport->r_a_tov)) {
fc_rport_error_retry(rdata, NULL);
- else
- kref_get(&rdata->kref);
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
+ }
}
/**
@@ -1230,6 +1285,8 @@ err:
*
* Locking Note: The rport lock is expected to be held before calling
* this routine.
+ *
+ * Reference counting: increments kref when sending ELS
*/
static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
{
@@ -1247,12 +1304,13 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
return;
}
+ kref_get(&rdata->kref);
if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV,
fc_rport_rtv_resp, rdata,
- 2 * lport->r_a_tov))
+ 2 * lport->r_a_tov)) {
fc_rport_error_retry(rdata, NULL);
- else
- kref_get(&rdata->kref);
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
+ }
}
/**
@@ -1262,15 +1320,16 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
* @lport_arg: The local port
*/
static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
- void *lport_arg)
+ void *rdata_arg)
{
- struct fc_lport *lport = lport_arg;
+ struct fc_rport_priv *rdata = rdata_arg;
+ struct fc_lport *lport = rdata->local_port;
FC_RPORT_ID_DBG(lport, fc_seq_exch(sp)->did,
"Received a LOGO %s\n", fc_els_resp_type(fp));
- if (IS_ERR(fp))
- return;
- fc_frame_free(fp);
+ if (!IS_ERR(fp))
+ fc_frame_free(fp);
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
}
/**
@@ -1279,6 +1338,8 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
*
* Locking Note: The rport lock is expected to be held before calling
* this routine.
+ *
+ * Reference counting: increments kref when sending ELS
*/
static void fc_rport_enter_logo(struct fc_rport_priv *rdata)
{
@@ -1291,8 +1352,10 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata)
fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo));
if (!fp)
return;
- (void)lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO,
- fc_rport_logo_resp, lport, 0);
+ kref_get(&rdata->kref);
+ if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO,
+ fc_rport_logo_resp, rdata, 0))
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
}
/**
@@ -1359,6 +1422,8 @@ err:
*
* Locking Note: The rport lock is expected to be held before calling
* this routine.
+ *
+ * Reference counting: increments kref when sending ELS
*/
static void fc_rport_enter_adisc(struct fc_rport_priv *rdata)
{
@@ -1375,12 +1440,13 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata)
fc_rport_error_retry(rdata, fp);
return;
}
+ kref_get(&rdata->kref);
if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC,
fc_rport_adisc_resp, rdata,
- 2 * lport->r_a_tov))
+ 2 * lport->r_a_tov)) {
fc_rport_error_retry(rdata, NULL);
- else
- kref_get(&rdata->kref);
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
+ }
}
/**
@@ -1494,6 +1560,8 @@ out:
* The ELS opcode has already been validated by the caller.
*
* Locking Note: Called with the lport lock held.
+ *
+ * Reference counting: does not modify kref
*/
static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
{
@@ -1561,6 +1629,8 @@ reject:
* @fp: The request frame
*
* Locking Note: Called with the lport lock held.
+ *
+ * Reference counting: does not modify kref
*/
static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
{
@@ -1605,6 +1675,8 @@ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
* @rx_fp: The PLOGI request frame
*
* Locking Note: The rport lock is held before calling this function.
+ *
+ * Reference counting: increments kref on return
*/
static void fc_rport_recv_plogi_req(struct fc_lport *lport,
struct fc_frame *rx_fp)
@@ -1919,6 +1991,8 @@ drop:
*
* Locking Note: The rport lock is expected to be held before calling
* this function.
+ *
+ * Reference counting: drops kref on return
*/
static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp)
{
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 02/30] libfc: additional debugging messages
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
2016-08-26 12:01 ` [PATCH 01/30] libfc: Revisit kref handling Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 03/30] libfc: spurious I/O error under high load Hannes Reinecke
` (28 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_exch.c | 59 +++++++++++++++++++++++++++++++++++--------
drivers/scsi/libfc/fc_fcp.c | 39 +++++++++++++++++++++++-----
drivers/scsi/libfc/fc_rport.c | 20 ++++++++++++---
3 files changed, 97 insertions(+), 21 deletions(-)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 16ca31a..f178084 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -362,8 +362,10 @@ static inline void fc_exch_timer_set_locked(struct fc_exch *ep,
fc_exch_hold(ep); /* hold for timer */
if (!queue_delayed_work(fc_exch_workqueue, &ep->timeout_work,
- msecs_to_jiffies(timer_msec)))
+ msecs_to_jiffies(timer_msec))) {
+ FC_EXCH_DBG(ep, "Exchange already queued\n");
fc_exch_release(ep);
+ }
}
/**
@@ -632,9 +634,13 @@ static int fc_exch_abort_locked(struct fc_exch *ep,
struct fc_frame *fp;
int error;
+ FC_EXCH_DBG(ep, "exch: abort, time %d msecs\n", timer_msec);
if (ep->esb_stat & (ESB_ST_COMPLETE | ESB_ST_ABNORMAL) ||
- ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP))
+ ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP)) {
+ FC_EXCH_DBG(ep, "exch: already completed esb %x state %x\n",
+ ep->esb_stat, ep->state);
return -ENXIO;
+ }
/*
* Send the abort on a new sequence if possible.
@@ -758,7 +764,7 @@ static void fc_exch_timeout(struct work_struct *work)
u32 e_stat;
int rc = 1;
- FC_EXCH_DBG(ep, "Exchange timed out\n");
+ FC_EXCH_DBG(ep, "Exchange timed out state %x\n", ep->state);
spin_lock_bh(&ep->ex_lock);
if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE))
@@ -1258,8 +1264,10 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp)
*/
if (fc_sof_needs_ack(fr_sof(rx_fp))) {
fp = fc_frame_alloc(lport, 0);
- if (!fp)
+ if (!fp) {
+ FC_EXCH_DBG(ep, "Drop ACK request, out of memory\n");
return;
+ }
fh = fc_frame_header_get(fp);
fh->fh_r_ctl = FC_RCTL_ACK_1;
@@ -1312,13 +1320,18 @@ static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp,
struct fc_frame_header *rx_fh;
struct fc_frame_header *fh;
struct fc_ba_rjt *rp;
+ struct fc_seq *sp;
struct fc_lport *lport;
unsigned int f_ctl;
lport = fr_dev(rx_fp);
+ sp = fr_seq(rx_fp);
fp = fc_frame_alloc(lport, sizeof(*rp));
- if (!fp)
+ if (!fp) {
+ FC_EXCH_DBG(fc_seq_exch(sp),
+ "Drop BA_RJT request, out of memory\n");
return;
+ }
fh = fc_frame_header_get(fp);
rx_fh = fc_frame_header_get(rx_fp);
@@ -1383,14 +1396,17 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp)
if (!ep)
goto reject;
+ FC_EXCH_DBG(ep, "exch: ABTS received\n");
fp = fc_frame_alloc(ep->lp, sizeof(*ap));
- if (!fp)
+ if (!fp) {
+ FC_EXCH_DBG(ep, "Drop ABTS request, out of memory\n");
goto free;
+ }
spin_lock_bh(&ep->ex_lock);
if (ep->esb_stat & ESB_ST_COMPLETE) {
spin_unlock_bh(&ep->ex_lock);
-
+ FC_EXCH_DBG(ep, "exch: ABTS rejected, exchange complete\n");
fc_frame_free(fp);
goto reject;
}
@@ -1784,11 +1800,16 @@ static void fc_seq_ls_acc(struct fc_frame *rx_fp)
struct fc_lport *lport;
struct fc_els_ls_acc *acc;
struct fc_frame *fp;
+ struct fc_seq *sp;
lport = fr_dev(rx_fp);
+ sp = fr_seq(rx_fp);
fp = fc_frame_alloc(lport, sizeof(*acc));
- if (!fp)
+ if (!fp) {
+ FC_EXCH_DBG(fc_seq_exch(sp),
+ "exch: drop LS_ACC, out of memory\n");
return;
+ }
acc = fc_frame_payload_get(fp, sizeof(*acc));
memset(acc, 0, sizeof(*acc));
acc->la_cmd = ELS_LS_ACC;
@@ -1811,11 +1832,16 @@ static void fc_seq_ls_rjt(struct fc_frame *rx_fp, enum fc_els_rjt_reason reason,
struct fc_lport *lport;
struct fc_els_ls_rjt *rjt;
struct fc_frame *fp;
+ struct fc_seq *sp;
lport = fr_dev(rx_fp);
+ sp = fr_seq(rx_fp);
fp = fc_frame_alloc(lport, sizeof(*rjt));
- if (!fp)
+ if (!fp) {
+ FC_EXCH_DBG(fc_seq_exch(sp),
+ "exch: drop LS_ACC, out of memory\n");
return;
+ }
rjt = fc_frame_payload_get(fp, sizeof(*rjt));
memset(rjt, 0, sizeof(*rjt));
rjt->er_cmd = ELS_LS_RJT;
@@ -1975,15 +2001,23 @@ static void fc_exch_els_rec(struct fc_frame *rfp)
ep = fc_exch_lookup(lport,
sid == fc_host_port_id(lport->host) ? oxid : rxid);
explan = ELS_EXPL_OXID_RXID;
- if (!ep)
+ if (!ep) {
+ FC_LPORT_DBG(lport, "REC request from %x: "
+ "xid %4.4x-%4.4x not found\n",
+ sid, rxid, oxid);
goto reject;
+ }
+ FC_EXCH_DBG(ep, "REC request from %x: rxid %x oxid %x\n",
+ sid, rxid, oxid);
if (ep->oid != sid || oxid != ep->oxid)
goto rel;
if (rxid != FC_XID_UNKNOWN && rxid != ep->rxid)
goto rel;
fp = fc_frame_alloc(lport, sizeof(*acc));
- if (!fp)
+ if (!fp) {
+ FC_EXCH_DBG(ep, "Drop REC request, out of memory\n");
goto out;
+ }
acc = fc_frame_payload_get(fp, sizeof(*acc));
memset(acc, 0, sizeof(*acc));
@@ -2176,6 +2210,7 @@ static void fc_exch_rrq(struct fc_exch *ep)
return;
retry:
+ FC_EXCH_DBG(ep, "exch: RRQ send failed\n");
spin_lock_bh(&ep->ex_lock);
if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE)) {
spin_unlock_bh(&ep->ex_lock);
@@ -2218,6 +2253,8 @@ static void fc_exch_els_rrq(struct fc_frame *fp)
if (!ep)
goto reject;
spin_lock_bh(&ep->ex_lock);
+ FC_EXCH_DBG(ep, "RRQ request from %x: xid %x rxid %x oxid %x\n",
+ sid, xid, ntohs(rp->rrq_rx_id), ntohs(rp->rrq_ox_id));
if (ep->oxid != ntohs(rp->rrq_ox_id))
goto unlock_reject;
if (ep->rxid != ntohs(rp->rrq_rx_id) &&
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 5121272..bd4bdbf 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -764,8 +764,11 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg)
fh = fc_frame_header_get(fp);
r_ctl = fh->fh_r_ctl;
- if (lport->state != LPORT_ST_READY)
+ if (lport->state != LPORT_ST_READY) {
+ FC_FCP_DBG(fsp, "lport state %d, ignoring r_ctl %x\n",
+ lport->state, r_ctl);
goto out;
+ }
if (fc_fcp_lock_pkt(fsp))
goto out;
@@ -774,8 +777,10 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg)
goto unlock;
}
- if (fsp->state & (FC_SRB_ABORTED | FC_SRB_ABORT_PENDING))
+ if (fsp->state & (FC_SRB_ABORTED | FC_SRB_ABORT_PENDING)) {
+ FC_FCP_DBG(fsp, "command aborted, ignoring r_ctl %x\n", r_ctl);
goto unlock;
+ }
if (r_ctl == FC_RCTL_DD_DATA_DESC) {
/*
@@ -910,6 +915,10 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
* Wait a at least one jiffy to see if it is delivered.
* If this expires without data, we may do SRR.
*/
+ FC_FCP_DBG(fsp, "tgt %6.6x xfer len %zx data underrun "
+ "len %x, data len %x\n",
+ fsp->rport->port_id,
+ fsp->xfer_len, expected_len, fsp->data_len);
fc_fcp_timer_set(fsp, 2);
return;
}
@@ -959,8 +968,12 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp)
if (fsp->cdb_status == SAM_STAT_GOOD &&
fsp->xfer_len < fsp->data_len && !fsp->io_status &&
(!(fsp->scsi_comp_flags & FCP_RESID_UNDER) ||
- fsp->xfer_len < fsp->data_len - fsp->scsi_resid))
+ fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) {
+ FC_FCP_DBG( fsp, "data underrun, "
+ "xfer_len %zx data_len %x\n",
+ fsp->xfer_len, fsp->data_len );
fsp->status_code = FC_DATA_UNDRUN;
+ }
}
seq = fsp->seq_ptr;
@@ -1222,8 +1235,11 @@ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp)
int rc = FAILED;
unsigned long ticks_left;
- if (fc_fcp_send_abort(fsp))
+ FC_FCP_DBG(fsp, "pkt abort state %x\n", fsp->state);
+ if (fc_fcp_send_abort(fsp)) {
+ FC_FCP_DBG(fsp, "failed to send abort\n");
return FAILED;
+ }
init_completion(&fsp->tm_done);
fsp->wait_for_comp = 1;
@@ -1394,6 +1410,8 @@ static void fc_fcp_timeout(unsigned long data)
if (fsp->cdb_cmd.fc_tm_flags)
goto unlock;
+ FC_FCP_DBG(fsp, "fcp timeout, flags %x state %x\n",
+ rpriv->flags, fsp->state);
fsp->state |= FC_SRB_FCP_PROCESSING_TMO;
if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
@@ -1503,6 +1521,10 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
break;
case ELS_RJT_LOGIC:
case ELS_RJT_UNAB:
+ FC_FCP_DBG(fsp, "device %x REC reject "
+ "reason %d expl %d\n",
+ fsp->rport->port_id, rjt->er_reason,
+ rjt->er_explan);
/*
* If no data transfer, the command frame got dropped
* so we just retry. If data was transferred, we
@@ -1608,6 +1630,8 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
switch (error) {
case -FC_EX_CLOSED:
+ FC_FCP_DBG(fsp, "REC %p fid %6.6x exchange closed\n",
+ fsp, fsp->rport->port_id);
fc_fcp_retry_cmd(fsp);
break;
@@ -1622,8 +1646,8 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
* Assume REC or LS_ACC was lost.
* The exchange manager will have aborted REC, so retry.
*/
- FC_FCP_DBG(fsp, "REC fid %6.6x error error %d retry %d/%d\n",
- fsp->rport->port_id, error, fsp->recov_retry,
+ FC_FCP_DBG(fsp, "REC %p fid %6.6x exchange timeout retry %d/%d\n",
+ fsp, fsp->rport->port_id, fsp->recov_retry,
FC_MAX_RECOV_RETRY);
if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
fc_fcp_rec(fsp);
@@ -1642,6 +1666,7 @@ out:
*/
static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code)
{
+ FC_FCP_DBG(fsp, "start recovery code %x\n", code);
fsp->status_code = code;
fsp->cdb_status = 0;
fsp->io_status = 0;
@@ -1768,12 +1793,14 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
goto out;
switch (PTR_ERR(fp)) {
case -FC_EX_TIMEOUT:
+ FC_FCP_DBG(fsp, "SRR timeout, retries %d\n", fsp->recov_retry);
if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
fc_fcp_rec(fsp);
else
fc_fcp_recovery(fsp, FC_TIMED_OUT);
break;
case -FC_EX_CLOSED: /* e.g., link failure */
+ FC_FCP_DBG(fsp, "SRR error, exchange closed\n");
/* fall through */
default:
fc_fcp_retry_cmd(fsp);
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 8909280..a37b37b 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -389,8 +389,10 @@ static void fc_rport_work(struct work_struct *work)
* Re-open for events. Reissue READY event if ready.
*/
rdata->event = RPORT_EV_NONE;
- if (rdata->rp_state == RPORT_ST_READY)
+ if (rdata->rp_state == RPORT_ST_READY) {
+ FC_RPORT_DBG(rdata, "work reopen\n");
fc_rport_enter_ready(rdata);
+ }
mutex_unlock(&rdata->rp_mutex);
}
break;
@@ -1074,6 +1076,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
struct fc_els_spp spp;
} *pp;
struct fc_els_spp temp_spp;
+ struct fc_els_ls_rjt *rjt;
struct fc4_prov *prov;
u32 roles = FC_RPORT_ROLE_UNKNOWN;
u32 fcp_parm = 0;
@@ -1143,8 +1146,10 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
fc_rport_enter_rtv(rdata);
} else {
- FC_RPORT_DBG(rdata, "Bad ELS response for PRLI command\n");
- fc_rport_error_retry(rdata, fp);
+ rjt = fc_frame_payload_get(fp, sizeof (*rjt));
+ FC_RPORT_DBG(rdata, "PRLI ELS rejected, reason %x expl %x\n",
+ rjt->er_reason, rjt->er_explan);
+ fc_rport_error_retry(rdata, NULL);
}
out:
@@ -1569,8 +1574,12 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
struct fc_seq_els_data els_data;
rdata = lport->tt.rport_lookup(lport, fc_frame_sid(fp));
- if (!rdata)
+ if (!rdata) {
+ FC_RPORT_ID_DBG(lport, fc_frame_sid(fp),
+ "Received ELS 0x%02x from non-logged-in port\n",
+ fc_frame_payload_op(fp));
goto reject;
+ }
mutex_lock(&rdata->rp_mutex);
@@ -1581,6 +1590,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
case RPORT_ST_ADISC:
break;
default:
+ FC_RPORT_DBG(rdata,
+ "Reject ELS 0x%02x while in state %s\n",
+ fc_frame_payload_op(fp), fc_rport_state(rdata));
mutex_unlock(&rdata->rp_mutex);
kref_put(&rdata->kref, lport->tt.rport_destroy);
goto reject;
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 03/30] libfc: spurious I/O error under high load
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
2016-08-26 12:01 ` [PATCH 01/30] libfc: Revisit kref handling Hannes Reinecke
2016-08-26 12:01 ` [PATCH 02/30] libfc: additional debugging messages Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 04/30] libfc: Do not login if the port is already started Hannes Reinecke
` (27 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke
If a command times out libfc is sending an REC, which also
might fail (due to frames being lost or something).
If no data has been transferred we can simply retry
the command, but the current code sets a state of FC_ERROR,
which then is being translated into DID_ERROR, resulting
in an I/O error.
So to handle this properly we need to set a separate
state FC_TRANS_RESET and mapping it onto DID_SOFT_RETRY.
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/libfc/fc_fcp.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index bd4bdbf..289c481 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -122,6 +122,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *);
#define FC_HRD_ERROR 9
#define FC_CRC_ERROR 10
#define FC_TIMED_OUT 11
+#define FC_TRANS_RESET 12
/*
* Error recovery timeout values.
@@ -283,7 +284,7 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
* fc_io_compl() will notify the SCSI-ml that the I/O is done.
* The SCSI-ml will retry the command.
*/
-static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp)
+static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp, int status_code)
{
if (fsp->seq_ptr) {
fsp->lp->tt.exch_done(fsp->seq_ptr);
@@ -292,7 +293,7 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp)
fsp->state &= ~FC_SRB_ABORT_PENDING;
fsp->io_status = 0;
- fsp->status_code = FC_ERROR;
+ fsp->status_code = status_code;
fc_fcp_complete_locked(fsp);
}
@@ -1209,7 +1210,7 @@ static void fc_fcp_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
return;
if (error == -FC_EX_CLOSED) {
- fc_fcp_retry_cmd(fsp);
+ fc_fcp_retry_cmd(fsp, FC_ERROR);
goto unlock;
}
@@ -1522,9 +1523,9 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
case ELS_RJT_LOGIC:
case ELS_RJT_UNAB:
FC_FCP_DBG(fsp, "device %x REC reject "
- "reason %d expl %d\n",
+ "reason %x expl %x xfer_len %zx\n",
fsp->rport->port_id, rjt->er_reason,
- rjt->er_explan);
+ rjt->er_explan, fsp->xfer_len);
/*
* If no data transfer, the command frame got dropped
* so we just retry. If data was transferred, we
@@ -1533,10 +1534,11 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
*/
if (rjt->er_explan == ELS_EXPL_OXID_RXID &&
fsp->xfer_len == 0) {
- fc_fcp_retry_cmd(fsp);
+ fsp->state |= FC_SRB_ABORTED;
+ fc_fcp_retry_cmd(fsp, FC_TRANS_RESET);
break;
}
- fc_fcp_recovery(fsp, FC_ERROR);
+ fc_fcp_recovery(fsp, FC_TRANS_RESET);
break;
}
} else if (opcode == ELS_LS_ACC) {
@@ -1632,7 +1634,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
case -FC_EX_CLOSED:
FC_FCP_DBG(fsp, "REC %p fid %6.6x exchange closed\n",
fsp, fsp->rport->port_id);
- fc_fcp_retry_cmd(fsp);
+ fc_fcp_retry_cmd(fsp, FC_ERROR);
break;
default:
@@ -1731,7 +1733,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
fc_fcp_pkt_hold(fsp); /* hold for outstanding SRR */
return;
retry:
- fc_fcp_retry_cmd(fsp);
+ fc_fcp_retry_cmd(fsp, FC_TRANS_RESET);
}
/**
@@ -1803,7 +1805,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
FC_FCP_DBG(fsp, "SRR error, exchange closed\n");
/* fall through */
default:
- fc_fcp_retry_cmd(fsp);
+ fc_fcp_retry_cmd(fsp, FC_ERROR);
break;
}
fc_fcp_unlock_pkt(fsp);
@@ -2016,6 +2018,11 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
"due to FC_CMD_RESET\n");
sc_cmd->result = (DID_RESET << 16);
break;
+ case FC_TRANS_RESET:
+ FC_FCP_DBG(fsp, "Returning DID_SOFT_ERROR to scsi-ml "
+ "due to FC_TRANS_RESET\n");
+ sc_cmd->result = (DID_SOFT_ERROR << 16);
+ break;
case FC_HRD_ERROR:
FC_FCP_DBG(fsp, "Returning DID_NO_CONNECT to scsi-ml "
"due to FC_HRD_ERROR\n");
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 04/30] libfc: Do not login if the port is already started
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (2 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 03/30] libfc: spurious I/O error under high load Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 05/30] libfc: use configured lport R_A_TOV when sending Hannes Reinecke
` (26 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
When the port is already started we don't need to login; that
will only confuse the state machine.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_rport.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index a37b37b..2406276 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -420,6 +420,12 @@ static int fc_rport_login(struct fc_rport_priv *rdata)
{
mutex_lock(&rdata->rp_mutex);
+ if (rdata->flags & FC_RP_STARTED) {
+ FC_RPORT_DBG(rdata, "port already started\n");
+ mutex_unlock(&rdata->rp_mutex);
+ return 0;
+ }
+
rdata->flags |= FC_RP_STARTED;
switch (rdata->rp_state) {
case RPORT_ST_READY:
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 05/30] libfc: use configured lport R_A_TOV when sending
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (3 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 04/30] libfc: Do not login if the port is already started Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 06/30] libfc: use configured e_d_tov for remote port state Hannes Reinecke
` (25 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
We should be using the configured R_A_TOV value when sending the
exchange.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_exch.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index f178084..7d0e7ca 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -2135,7 +2135,7 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport,
ep->resp = resp;
ep->destructor = destructor;
ep->arg = arg;
- ep->r_a_tov = FC_DEF_R_A_TOV;
+ ep->r_a_tov = lport->r_a_tov;
ep->lp = lport;
sp = &ep->seq;
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 06/30] libfc: use configured e_d_tov for remote port state
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (4 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 05/30] libfc: use configured lport R_A_TOV when sending Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 07/30] libfc: do not overwrite DID_TIME_OUT status Hannes Reinecke
` (24 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
If fc_rport_error_retry() is attempting to retry the remote
port state we should be waiting for the configured e_d_tov
value rather than the default.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_rport.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 2406276..4c13acc 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -656,7 +656,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
static void fc_rport_error_retry(struct fc_rport_priv *rdata,
struct fc_frame *fp)
{
- unsigned long delay = msecs_to_jiffies(FC_DEF_E_D_TOV);
+ unsigned long delay = msecs_to_jiffies(rdata->e_d_tov);
struct fc_lport *lport = rdata->local_port;
/* make sure this isn't an FC_EX_CLOSED error, never retry those */
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 07/30] libfc: do not overwrite DID_TIME_OUT status
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (5 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 06/30] libfc: use configured e_d_tov for remote port state Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 08/30] libfc: use error code for fc_rport_error() Hannes Reinecke
` (23 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
When a command is aborted it might already have the DID_TIME_OUT
status set, so we shouldn't be overwriting that.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_fcp.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 289c481..a667c8c 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -2009,9 +2009,15 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
sc_cmd->result = (DID_ERROR << 16) | fsp->cdb_status;
break;
case FC_CMD_ABORTED:
- FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
- "due to FC_CMD_ABORTED\n");
- sc_cmd->result = (DID_ERROR << 16) | fsp->io_status;
+ if (host_byte(sc_cmd->result) == DID_TIME_OUT)
+ FC_FCP_DBG(fsp, "Returning DID_TIME_OUT to scsi-ml "
+ "due to FC_CMD_ABORTED\n");
+ else {
+ FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
+ "due to FC_CMD_ABORTED\n");
+ set_host_byte(sc_cmd, DID_ERROR);
+ }
+ sc_cmd->result |= fsp->io_status;
break;
case FC_CMD_RESET:
FC_FCP_DBG(fsp, "Returning DID_RESET to scsi-ml "
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 08/30] libfc: use error code for fc_rport_error()
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (6 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 07/30] libfc: do not overwrite DID_TIME_OUT status Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 09/30] libfc: Send LS_RJT responses on frame allocation Hannes Reinecke
` (22 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
We only ever use the 'fp' argument for fc_rport_error() to
encapsulate the error code, so we can as well do away with that
and pass the error directly.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_rport.c | 97 +++++++++++++++++++++++++------------------
include/scsi/libfc.h | 5 +++
2 files changed, 62 insertions(+), 40 deletions(-)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 4c13acc..29a51c6 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -87,8 +87,8 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *, struct fc_frame *);
static void fc_rport_recv_prlo_req(struct fc_rport_priv *, struct fc_frame *);
static void fc_rport_recv_logo_req(struct fc_lport *, struct fc_frame *);
static void fc_rport_timeout(struct work_struct *);
-static void fc_rport_error(struct fc_rport_priv *, struct fc_frame *);
-static void fc_rport_error_retry(struct fc_rport_priv *, struct fc_frame *);
+static void fc_rport_error(struct fc_rport_priv *, int);
+static void fc_rport_error_retry(struct fc_rport_priv *, int);
static void fc_rport_work(struct work_struct *);
static const char *fc_rport_state_names[] = {
@@ -598,20 +598,19 @@ static void fc_rport_timeout(struct work_struct *work)
/**
* fc_rport_error() - Error handler, called once retries have been exhausted
* @rdata: The remote port the error is happened on
- * @fp: The error code encapsulated in a frame pointer
+ * @err: The error code
*
* Locking Note: The rport lock is expected to be held before
* calling this routine
*
* Reference counting: does not modify kref
*/
-static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
+static void fc_rport_error(struct fc_rport_priv *rdata, int err)
{
struct fc_lport *lport = rdata->local_port;
- FC_RPORT_DBG(rdata, "Error %ld in state %s, retries %d\n",
- IS_ERR(fp) ? -PTR_ERR(fp) : 0,
- fc_rport_state(rdata), rdata->retries);
+ FC_RPORT_DBG(rdata, "Error %d in state %s, retries %d\n",
+ -err, fc_rport_state(rdata), rdata->retries);
switch (rdata->rp_state) {
case RPORT_ST_FLOGI:
@@ -643,7 +642,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
/**
* fc_rport_error_retry() - Handler for remote port state retries
* @rdata: The remote port whose state is to be retried
- * @fp: The error code encapsulated in a frame pointer
+ * @err: The error code
*
* If the error was an exchange timeout retry immediately,
* otherwise wait for E_D_TOV.
@@ -653,22 +652,21 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
*
* Reference counting: increments kref when scheduling retry_work
*/
-static void fc_rport_error_retry(struct fc_rport_priv *rdata,
- struct fc_frame *fp)
+static void fc_rport_error_retry(struct fc_rport_priv *rdata, int err)
{
unsigned long delay = msecs_to_jiffies(rdata->e_d_tov);
struct fc_lport *lport = rdata->local_port;
/* make sure this isn't an FC_EX_CLOSED error, never retry those */
- if (PTR_ERR(fp) == -FC_EX_CLOSED)
+ if (err == -FC_EX_CLOSED)
goto out;
if (rdata->retries < rdata->local_port->max_rport_retry_count) {
- FC_RPORT_DBG(rdata, "Error %ld in state %s, retrying\n",
- PTR_ERR(fp), fc_rport_state(rdata));
+ FC_RPORT_DBG(rdata, "Error %d in state %s, retrying\n",
+ err, fc_rport_state(rdata));
rdata->retries++;
/* no additional delay on exchange timeouts */
- if (PTR_ERR(fp) == -FC_EX_TIMEOUT)
+ if (err == -FC_EX_TIMEOUT)
delay = 0;
kref_get(&rdata->kref);
if (!schedule_delayed_work(&rdata->retry_work, delay))
@@ -677,7 +675,7 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata,
}
out:
- fc_rport_error(rdata, fp);
+ fc_rport_error(rdata, err);
}
/**
@@ -737,8 +735,10 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
struct fc_lport *lport = rdata->local_port;
struct fc_els_flogi *flogi;
unsigned int r_a_tov;
+ int err = 0;
- FC_RPORT_DBG(rdata, "Received a FLOGI %s\n", fc_els_resp_type(fp));
+ FC_RPORT_DBG(rdata, "Received a FLOGI %s\n",
+ IS_ERR(fp)? "error" : fc_els_resp_type(fp));
if (fp == ERR_PTR(-FC_EX_CLOSED))
goto put;
@@ -754,18 +754,30 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
}
if (IS_ERR(fp)) {
- fc_rport_error(rdata, fp);
+ fc_rport_error(rdata, PTR_ERR(fp));
goto err;
}
- if (fc_frame_payload_op(fp) != ELS_LS_ACC)
+ if (fc_frame_payload_op(fp) != ELS_LS_ACC) {
+ struct fc_els_ls_rjt *rjt;
+
+ rjt = fc_frame_payload_get(fp, sizeof (*rjt));
+ FC_RPORT_DBG(rdata, "FLOGI ELS rejected, reason %x expl %x\n",
+ rjt->er_reason, rjt->er_explan);
+ err = -FC_EX_ELS_RJT;
goto bad;
- if (fc_rport_login_complete(rdata, fp))
+ }
+ if (fc_rport_login_complete(rdata, fp)) {
+ FC_RPORT_DBG(rdata, "FLOGI failed, no login\n");
+ err = -FC_EX_INV_LOGIN;
goto bad;
+ }
flogi = fc_frame_payload_get(fp, sizeof(*flogi));
- if (!flogi)
+ if (!flogi) {
+ err = -FC_EX_ALLOC_ERR;
goto bad;
+ }
r_a_tov = ntohl(flogi->fl_csp.sp_r_a_tov);
if (r_a_tov > rdata->r_a_tov)
rdata->r_a_tov = r_a_tov;
@@ -783,7 +795,7 @@ put:
return;
bad:
FC_RPORT_DBG(rdata, "Bad FLOGI response\n");
- fc_rport_error_retry(rdata, fp);
+ fc_rport_error_retry(rdata, err);
goto out;
}
@@ -811,13 +823,13 @@ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata)
fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
if (!fp)
- return fc_rport_error_retry(rdata, fp);
+ return fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);
kref_get(&rdata->kref);
if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_FLOGI,
fc_rport_flogi_resp, rdata,
2 * lport->r_a_tov)) {
- fc_rport_error_retry(rdata, NULL);
+ fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);
kref_put(&rdata->kref, lport->tt.rport_destroy);
}
}
@@ -974,7 +986,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
}
if (IS_ERR(fp)) {
- fc_rport_error_retry(rdata, fp);
+ fc_rport_error_retry(rdata, PTR_ERR(fp));
goto err;
}
@@ -996,9 +1008,14 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
rdata->max_seq = csp_seq;
rdata->maxframe_size = fc_plogi_get_maxframe(plp, lport->mfs);
fc_rport_enter_prli(rdata);
- } else
- fc_rport_error_retry(rdata, fp);
+ } else {
+ struct fc_els_ls_rjt *rjt;
+ rjt = fc_frame_payload_get(fp, sizeof (*rjt));
+ FC_RPORT_DBG(rdata, "PLOGI ELS rejected, reason %x expl %x\n",
+ rjt->er_reason, rjt->er_explan);
+ fc_rport_error_retry(rdata, -FC_EX_ELS_RJT);
+ }
out:
fc_frame_free(fp);
err:
@@ -1049,7 +1066,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
if (!fp) {
FC_RPORT_DBG(rdata, "%s frame alloc failed\n", __func__);
- fc_rport_error_retry(rdata, fp);
+ fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);
return;
}
rdata->e_d_tov = lport->e_d_tov;
@@ -1058,7 +1075,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI,
fc_rport_plogi_resp, rdata,
2 * lport->r_a_tov)) {
- fc_rport_error_retry(rdata, NULL);
+ fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);
kref_put(&rdata->kref, lport->tt.rport_destroy);
}
}
@@ -1102,7 +1119,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
}
if (IS_ERR(fp)) {
- fc_rport_error_retry(rdata, fp);
+ fc_rport_error_retry(rdata, PTR_ERR(fp));
goto err;
}
@@ -1121,9 +1138,9 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
rdata->spp_type = pp->spp.spp_type;
if (resp_code != FC_SPP_RESP_ACK) {
if (resp_code == FC_SPP_RESP_CONF)
- fc_rport_error(rdata, fp);
+ fc_rport_error(rdata, -FC_EX_SEQ_ERR);
else
- fc_rport_error_retry(rdata, fp);
+ fc_rport_error_retry(rdata, -FC_EX_SEQ_ERR);
goto out;
}
if (pp->prli.prli_spp_len < sizeof(pp->spp))
@@ -1155,7 +1172,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
rjt = fc_frame_payload_get(fp, sizeof (*rjt));
FC_RPORT_DBG(rdata, "PRLI ELS rejected, reason %x expl %x\n",
rjt->er_reason, rjt->er_explan);
- fc_rport_error_retry(rdata, NULL);
+ fc_rport_error_retry(rdata, FC_EX_ELS_RJT);
}
out:
@@ -1200,7 +1217,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
fp = fc_frame_alloc(lport, sizeof(*pp));
if (!fp) {
- fc_rport_error_retry(rdata, fp);
+ fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);
return;
}
@@ -1219,7 +1236,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
kref_get(&rdata->kref);
if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp,
NULL, rdata, 2 * lport->r_a_tov)) {
- fc_rport_error_retry(rdata, NULL);
+ fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);
kref_put(&rdata->kref, lport->tt.rport_destroy);
}
}
@@ -1255,7 +1272,7 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
}
if (IS_ERR(fp)) {
- fc_rport_error(rdata, fp);
+ fc_rport_error(rdata, PTR_ERR(fp));
goto err;
}
@@ -1311,7 +1328,7 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
fp = fc_frame_alloc(lport, sizeof(struct fc_els_rtv));
if (!fp) {
- fc_rport_error_retry(rdata, fp);
+ fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);
return;
}
@@ -1319,7 +1336,7 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV,
fc_rport_rtv_resp, rdata,
2 * lport->r_a_tov)) {
- fc_rport_error_retry(rdata, NULL);
+ fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);
kref_put(&rdata->kref, lport->tt.rport_destroy);
}
}
@@ -1399,7 +1416,7 @@ static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp,
}
if (IS_ERR(fp)) {
- fc_rport_error(rdata, fp);
+ fc_rport_error(rdata, PTR_ERR(fp));
goto err;
}
@@ -1448,14 +1465,14 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata)
fp = fc_frame_alloc(lport, sizeof(struct fc_els_adisc));
if (!fp) {
- fc_rport_error_retry(rdata, fp);
+ fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);
return;
}
kref_get(&rdata->kref);
if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC,
fc_rport_adisc_resp, rdata,
2 * lport->r_a_tov)) {
- fc_rport_error_retry(rdata, NULL);
+ fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);
kref_put(&rdata->kref, lport->tt.rport_destroy);
}
}
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 7428a53..dc42d80 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -44,6 +44,11 @@
#define FC_NO_ERR 0 /* no error */
#define FC_EX_TIMEOUT 1 /* Exchange timeout */
#define FC_EX_CLOSED 2 /* Exchange closed */
+#define FC_EX_ALLOC_ERR 3 /* Exchange allocation failed */
+#define FC_EX_XMIT_ERR 4 /* Exchange transmit failed */
+#define FC_EX_ELS_RJT 5 /* ELS rejected */
+#define FC_EX_INV_LOGIN 6 /* Login not completed */
+#define FC_EX_SEQ_ERR 6 /* Exchange sequence error */
/**
* enum fc_lport_state - Local port states
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 09/30] libfc: Send LS_RJT responses on frame allocation
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (7 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 08/30] libfc: use error code for fc_rport_error() Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 10/30] libfc: don't advance state machine for incoming FLOGI Hannes Reinecke
` (21 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
When we fail to allocate a frame we should be sending an LS_RJT
response and not just silently drop the frame altogether.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_rport.c | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 29a51c6..f9b6f59 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -926,8 +926,12 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
}
fp = fc_frame_alloc(lport, sizeof(*flp));
- if (!fp)
- goto out;
+ if (!fp) {
+ mutex_unlock(&rdata->rp_mutex);
+ rjt_data.reason = ELS_RJT_UNAB;
+ rjt_data.explan = ELS_EXPL_INSUF_RES;
+ goto reject_put;
+ }
fc_flogi_fill(lport, fp);
flp = fc_frame_payload_get(fp, sizeof(*flp));
@@ -940,7 +944,7 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
fc_rport_enter_plogi(rdata);
else
fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT);
-out:
+
mutex_unlock(&rdata->rp_mutex);
kref_put(&rdata->kref, lport->tt.rport_destroy);
fc_frame_free(rx_fp);
@@ -1503,8 +1507,12 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata,
}
fp = fc_frame_alloc(lport, sizeof(*adisc));
- if (!fp)
+ if (!fp) {
+ rjt_data.reason = ELS_RJT_UNAB;
+ rjt_data.explan = ELS_EXPL_INSUF_RES;
+ lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data);
goto drop;
+ }
fc_adisc_fill(lport, fp);
adisc = fc_frame_payload_get(fp, sizeof(*adisc));
adisc->adisc_cmd = ELS_LS_ACC;
@@ -1812,14 +1820,17 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport,
* Send LS_ACC. If this fails, the originator should retry.
*/
fp = fc_frame_alloc(lport, sizeof(*pl));
- if (!fp)
- goto out;
-
+ if (!fp) {
+ mutex_unlock(&rdata->rp_mutex);
+ rjt_data.reason = ELS_RJT_UNAB;
+ rjt_data.explan = ELS_EXPL_INSUF_RES;
+ goto reject;
+ }
fc_plogi_fill(lport, fp, ELS_LS_ACC);
fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);
lport->tt.frame_send(lport, fp);
fc_rport_enter_prli(rdata);
-out:
+
mutex_unlock(&rdata->rp_mutex);
fc_frame_free(rx_fp);
return;
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 10/30] libfc: don't advance state machine for incoming FLOGI
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (8 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 09/30] libfc: Send LS_RJT responses on frame allocation Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 11/30] libfc: Fixup disc_mutex handling Hannes Reinecke
` (20 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
When we receive an FLOGI but have already sent our own we should
not advance the state machine but rather wait for our FLOGI to
return before continuing with PLOGI.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_rport.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index f9b6f59..91866a5 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -775,6 +775,7 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
flogi = fc_frame_payload_get(fp, sizeof(*flogi));
if (!flogi) {
+ FC_RPORT_DBG(rdata, "Bad FLOGI response\n");
err = -FC_EX_ALLOC_ERR;
goto bad;
}
@@ -794,7 +795,6 @@ put:
kref_put(&rdata->kref, lport->tt.rport_destroy);
return;
bad:
- FC_RPORT_DBG(rdata, "Bad FLOGI response\n");
fc_rport_error_retry(rdata, err);
goto out;
}
@@ -940,11 +940,17 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);
lport->tt.frame_send(lport, fp);
- if (rdata->ids.port_name < lport->wwpn)
- fc_rport_enter_plogi(rdata);
- else
- fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT);
-
+ /*
+ * Do not proceed with the state machine if our
+ * FLOGI has crossed with an FLOGI from the
+ * remote port; wait for the FLOGI response instead.
+ */
+ if (rdata->rp_state != RPORT_ST_FLOGI) {
+ if (rdata->ids.port_name < lport->wwpn)
+ fc_rport_enter_plogi(rdata);
+ else
+ fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT);
+ }
mutex_unlock(&rdata->rp_mutex);
kref_put(&rdata->kref, lport->tt.rport_destroy);
fc_frame_free(rx_fp);
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 11/30] libfc: Fixup disc_mutex handling
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (9 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 10/30] libfc: don't advance state machine for incoming FLOGI Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 12/30] libfc: Do not drop down to FLOGI for fc_rport_login() Hannes Reinecke
` (19 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
The list of attached 'rdata' remote port structures is RCU
protected, so there is no need to take the 'disc_mutex' when
traversing it.
Rather we should be using rcu_read_lock() and kref_get_unless_zero()
to validate the entries.
We need, however, take the disc_mutex when deleting an entry;
otherwise we risk clashes with list_add.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/fcoe/fcoe_ctlr.c | 28 ++++++++++++++++++++++------
drivers/scsi/libfc/fc_disc.c | 30 +++++++++++++++++++-----------
drivers/scsi/libfc/fc_rport.c | 2 ++
3 files changed, 43 insertions(+), 17 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index a569c65..5eacd33 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -2145,9 +2145,15 @@ static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport)
{
struct fc_rport_priv *rdata;
+ rcu_read_lock();
+ list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) {
+ if (kref_get_unless_zero(&rdata->kref)) {
+ lport->tt.rport_logoff(rdata);
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
+ }
+ }
+ rcu_read_unlock();
mutex_lock(&lport->disc.disc_mutex);
- list_for_each_entry_rcu(rdata, &lport->disc.rports, peers)
- lport->tt.rport_logoff(rdata);
lport->disc.disc_callback = NULL;
mutex_unlock(&lport->disc.disc_mutex);
}
@@ -2638,11 +2644,15 @@ static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip)
unsigned long deadline;
next_time = jiffies + msecs_to_jiffies(FIP_VN_BEACON_INT * 10);
- mutex_lock(&lport->disc.disc_mutex);
+ rcu_read_lock();
list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) {
+ if (!kref_get_unless_zero(&rdata->kref))
+ continue;
frport = fcoe_ctlr_rport(rdata);
- if (!frport->time)
+ if (!frport->time) {
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
continue;
+ }
deadline = frport->time +
msecs_to_jiffies(FIP_VN_BEACON_INT * 25 / 10);
if (time_after_eq(jiffies, deadline)) {
@@ -2653,8 +2663,9 @@ static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip)
lport->tt.rport_logoff(rdata);
} else if (time_before(deadline, next_time))
next_time = deadline;
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
}
- mutex_unlock(&lport->disc.disc_mutex);
+ rcu_read_unlock();
return next_time;
}
@@ -2991,12 +3002,17 @@ static void fcoe_ctlr_vn_disc(struct fcoe_ctlr *fip)
mutex_lock(&disc->disc_mutex);
callback = disc->pending ? disc->disc_callback : NULL;
disc->pending = 0;
+ mutex_unlock(&disc->disc_mutex);
+ rcu_read_lock();
list_for_each_entry_rcu(rdata, &disc->rports, peers) {
+ if (!kref_get_unless_zero(&rdata->kref))
+ continue;
frport = fcoe_ctlr_rport(rdata);
if (frport->time)
lport->tt.rport_login(rdata);
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
}
- mutex_unlock(&disc->disc_mutex);
+ rcu_read_unlock();
if (callback)
callback(lport, DISC_EV_SUCCESS);
}
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 880a906..351022a 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -68,10 +68,14 @@ static void fc_disc_stop_rports(struct fc_disc *disc)
lport = fc_disc_lport(disc);
- mutex_lock(&disc->disc_mutex);
- list_for_each_entry_rcu(rdata, &disc->rports, peers)
- lport->tt.rport_logoff(rdata);
- mutex_unlock(&disc->disc_mutex);
+ rcu_read_lock();
+ list_for_each_entry_rcu(rdata, &disc->rports, peers) {
+ if (kref_get_unless_zero(&rdata->kref)) {
+ lport->tt.rport_logoff(rdata);
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
+ }
+ }
+ rcu_read_unlock();
}
/**
@@ -289,16 +293,20 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event)
* Skip ports which were never discovered. These are the dNS port
* and ports which were created by PLOGI.
*/
+ mutex_unlock(&disc->disc_mutex);
+ rcu_read_lock();
list_for_each_entry_rcu(rdata, &disc->rports, peers) {
- if (!rdata->disc_id)
+ if (!kref_get_unless_zero(&rdata->kref))
continue;
- if (rdata->disc_id == disc->disc_id)
- lport->tt.rport_login(rdata);
- else
- lport->tt.rport_logoff(rdata);
+ if (rdata->disc_id) {
+ if (rdata->disc_id == disc->disc_id)
+ lport->tt.rport_login(rdata);
+ else
+ lport->tt.rport_logoff(rdata);
+ }
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
}
-
- mutex_unlock(&disc->disc_mutex);
+ rcu_read_unlock();
disc->disc_callback(lport, event);
mutex_lock(&disc->disc_mutex);
}
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 91866a5..fa716f5 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -380,7 +380,9 @@ static void fc_rport_work(struct work_struct *work)
mutex_unlock(&rdata->rp_mutex);
} else {
FC_RPORT_DBG(rdata, "work delete\n");
+ mutex_lock(&lport->disc.disc_mutex);
list_del_rcu(&rdata->peers);
+ mutex_unlock(&lport->disc.disc_mutex);
mutex_unlock(&rdata->rp_mutex);
kref_put(&rdata->kref, lport->tt.rport_destroy);
}
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 12/30] libfc: Do not drop down to FLOGI for fc_rport_login()
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (10 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 11/30] libfc: Fixup disc_mutex handling Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 13/30] libfc: Implement RTV responder Hannes Reinecke
` (18 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
When fc_rport_login() is called while the rport is not
in RPORT_ST_INIT, RPORT_ST_READY, or RPORT_ST_DELETE
login is already in progress and there's no need to
drop down to FLOGI; doing so will only confuse the
other side.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_rport.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index fa716f5..d392d45 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -437,10 +437,14 @@ static int fc_rport_login(struct fc_rport_priv *rdata)
case RPORT_ST_DELETE:
FC_RPORT_DBG(rdata, "Restart deleted port\n");
break;
- default:
+ case RPORT_ST_INIT:
FC_RPORT_DBG(rdata, "Login to port\n");
fc_rport_enter_flogi(rdata);
break;
+ default:
+ FC_RPORT_DBG(rdata, "Login in progress, state %s\n",
+ fc_rport_state(rdata));
+ break;
}
mutex_unlock(&rdata->rp_mutex);
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 13/30] libfc: Implement RTV responder
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (11 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 12/30] libfc: Do not drop down to FLOGI for fc_rport_login() Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 14/30] libfc: Rework PRLI handling Hannes Reinecke
` (17 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
The libfc stack generates an RTV request, so we should be implementing
an RTV responder, too.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_rport.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index d392d45..a76f29d 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1258,7 +1258,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
}
/**
- * fc_rport_els_rtv_resp() - Handler for Request Timeout Value (RTV) responses
+ * fc_rport_rtv_resp() - Handler for Request Timeout Value (RTV) responses
* @sp: The sequence the RTV was on
* @fp: The RTV response frame
* @rdata_arg: The remote port that sent the RTV response
@@ -1358,6 +1358,41 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
}
/**
+ * fc_rport_recv_rtv_req() - Handler for Read Timeout Value (RTV) requests
+ * @rdata: The remote port that sent the RTV request
+ * @in_fp: The RTV request frame
+ *
+ * Locking Note: Called with the lport and rport locks held.
+ */
+static void fc_rport_recv_rtv_req(struct fc_rport_priv *rdata,
+ struct fc_frame *in_fp)
+{
+ struct fc_lport *lport = rdata->local_port;
+ struct fc_frame *fp;
+ struct fc_els_rtv_acc *rtv;
+ struct fc_seq_els_data rjt_data;
+
+ FC_RPORT_DBG(rdata, "Received RTV request\n");
+
+ fp = fc_frame_alloc(lport, sizeof(*rtv));
+ if (!fp) {
+ rjt_data.reason = ELS_RJT_UNAB;
+ rjt_data.reason = ELS_EXPL_INSUF_RES;
+ lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data);
+ goto drop;
+ }
+ rtv = fc_frame_payload_get(fp, sizeof(*rtv));
+ rtv->rtv_cmd = ELS_LS_ACC;
+ rtv->rtv_r_a_tov = htonl(lport->r_a_tov);
+ rtv->rtv_e_d_tov = htonl(lport->e_d_tov);
+ rtv->rtv_toq = 0;
+ fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0);
+ lport->tt.frame_send(lport, fp);
+drop:
+ fc_frame_free(in_fp);
+}
+
+/**
* fc_rport_logo_resp() - Handler for logout (LOGO) responses
* @sp: The sequence the LOGO was on
* @fp: The LOGO response frame
@@ -1662,6 +1697,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
case ELS_RLS:
fc_rport_recv_rls_req(rdata, fp);
break;
+ case ELS_RTV:
+ fc_rport_recv_rtv_req(rdata, fp);
+ break;
default:
fc_frame_free(fp); /* can't happen */
break;
@@ -1713,6 +1751,7 @@ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
case ELS_RRQ:
case ELS_REC:
case ELS_RLS:
+ case ELS_RTV:
fc_rport_recv_els_req(lport, fp);
break;
default:
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 14/30] libfc: Rework PRLI handling
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (12 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 13/30] libfc: Implement RTV responder Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 15/30] libfc: Return LS_RJT_BUSY for PRLI in status PLOGI Hannes Reinecke
` (16 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
PRLI is only required if the port is acting as an initiator; ports
which support target functionality only do not need to send PRLI.
At the same time the PRLI state is only used if the port initiated
a PRLI transfer; if we received a PRLI request we should _not_
change the state as this would cause our PRLI response to be dropped.
And when we receive a PRLI response we need to check if an image
pair has been established; if not the remote port cannot act as a
target for us and we need to disable target functionality.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_rport.c | 62 +++++++++++++++++++++++++++++--------------
1 file changed, 42 insertions(+), 20 deletions(-)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index a76f29d..69c93c7 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1120,7 +1120,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
u32 roles = FC_RPORT_ROLE_UNKNOWN;
u32 fcp_parm = 0;
u8 op;
- u8 resp_code = 0;
+ enum fc_els_spp_resp resp_code;
mutex_lock(&rdata->rp_mutex);
@@ -1149,8 +1149,8 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
goto out;
resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK);
- FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x\n",
- pp->spp.spp_flags);
+ FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x spp_type 0x%x\n",
+ pp->spp.spp_flags, pp->spp.spp_type);
rdata->spp_type = pp->spp.spp_type;
if (resp_code != FC_SPP_RESP_ACK) {
if (resp_code == FC_SPP_RESP_CONF)
@@ -1168,13 +1168,28 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
if (fcp_parm & FCP_SPPF_CONF_COMPL)
rdata->flags |= FC_RP_FLAGS_CONF_REQ;
- prov = fc_passive_prov[FC_TYPE_FCP];
+ /*
+ * Call prli provider if we should act as a target
+ */
+ prov = fc_passive_prov[rdata->spp_type];
if (prov) {
memset(&temp_spp, 0, sizeof(temp_spp));
- prov->prli(rdata, pp->prli.prli_spp_len,
- &pp->spp, &temp_spp);
+ resp_code = prov->prli(rdata, pp->prli.prli_spp_len,
+ &pp->spp, &temp_spp);
+ } else {
+ memcpy(&temp_spp, &pp->spp, sizeof(temp_spp));
+ }
+ /*
+ * Check if the image pair could be established
+ */
+ if (rdata->spp_type != FC_TYPE_FCP ||
+ resp_code != FC_SPP_RESP_ACK ||
+ !(temp_spp.spp_flags & FC_SPP_EST_IMG_PAIR)) {
+ /*
+ * Nope; we can't use this port as a target.
+ */
+ fcp_parm &= ~FCP_SPPF_TARG_FCN;
}
-
rdata->supported_classes = FC_COS_CLASS3;
if (fcp_parm & FCP_SPPF_INIT_FCN)
roles |= FC_RPORT_ROLE_FCP_INITIATOR;
@@ -1226,6 +1241,15 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
return;
}
+ /*
+ * And if the local port does not support the initiator function
+ * there's no need to send a PRLI, either.
+ */
+ if (!(lport->service_params & FCP_SPPF_INIT_FCN)) {
+ fc_rport_enter_ready(rdata);
+ return;
+ }
+
FC_RPORT_DBG(rdata, "Port entered PRLI state from %s state\n",
fc_rport_state(rdata));
@@ -1913,7 +1937,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
unsigned int len;
unsigned int plen;
enum fc_els_spp_resp resp;
- enum fc_els_spp_resp passive;
struct fc_seq_els_data rjt_data;
struct fc4_prov *prov;
@@ -1963,15 +1986,21 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
resp = 0;
if (rspp->spp_type < FC_FC4_PROV_SIZE) {
+ enum fc_els_spp_resp active = 0, passive = 0;
+
prov = fc_active_prov[rspp->spp_type];
if (prov)
- resp = prov->prli(rdata, plen, rspp, spp);
+ active = prov->prli(rdata, plen, rspp, spp);
prov = fc_passive_prov[rspp->spp_type];
- if (prov) {
+ if (prov)
passive = prov->prli(rdata, plen, rspp, spp);
- if (!resp || passive == FC_SPP_RESP_ACK)
- resp = passive;
- }
+ if (!active || passive == FC_SPP_RESP_ACK)
+ resp = passive;
+ else
+ resp = active;
+ FC_RPORT_DBG(rdata, "PRLI rspp type %x "
+ "active %x passive %x\n",
+ rspp->spp_type, active, passive);
}
if (!resp) {
if (spp->spp_flags & FC_SPP_EST_IMG_PAIR)
@@ -1992,13 +2021,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);
lport->tt.frame_send(lport, fp);
- switch (rdata->rp_state) {
- case RPORT_ST_PRLI:
- fc_rport_enter_ready(rdata);
- break;
- default:
- break;
- }
goto drop;
reject_len:
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 15/30] libfc: Return LS_RJT_BUSY for PRLI in status PLOGI
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (13 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 14/30] libfc: Rework PRLI handling Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 16/30] libfc: Clarify ramp-down messages Hannes Reinecke
` (15 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
Occasionally it might happen that we receive a PRLI while we're still
waiting for our PLOGI response. In that case we should return
'busy' LS status instead of 'plogi required' LS status.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_rport.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 69c93c7..68d4c92 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1691,6 +1691,15 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
case RPORT_ST_READY:
case RPORT_ST_ADISC:
break;
+ case RPORT_ST_PLOGI:
+ if (fc_frame_payload_op(fp) == ELS_PRLI) {
+ FC_RPORT_DBG(rdata, "Reject ELS PRLI "
+ "while in state %s\n",
+ fc_rport_state(rdata));
+ mutex_unlock(&rdata->rp_mutex);
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
+ goto busy;
+ }
default:
FC_RPORT_DBG(rdata,
"Reject ELS 0x%02x while in state %s\n",
@@ -1738,6 +1747,14 @@ reject:
els_data.explan = ELS_EXPL_PLOGI_REQD;
lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data);
fc_frame_free(fp);
+ return;
+
+busy:
+ els_data.reason = ELS_RJT_BUSY;
+ els_data.explan = ELS_EXPL_NONE;
+ lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data);
+ fc_frame_free(fp);
+ return;
}
/**
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 16/30] libfc: Clarify ramp-down messages
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (14 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 15/30] libfc: Return LS_RJT_BUSY for PRLI in status PLOGI Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 17/30] libfc: sanitize E_D_TOV and R_A_TOV setting Hannes Reinecke
` (14 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
When the queue depth is reduced we should print out the reason
for this; it might be due to a queue full condition.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_fcp.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index a667c8c..abddfe2 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -403,8 +403,6 @@ static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport)
if (!can_queue)
can_queue = 1;
lport->host->can_queue = can_queue;
- shost_printk(KERN_ERR, lport->host, "libfc: Could not allocate frame.\n"
- "Reducing can_queue to %d.\n", can_queue);
unlock:
spin_unlock_irqrestore(lport->host->host_lock, flags);
@@ -431,6 +429,9 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport,
put_cpu();
/* error case */
fc_fcp_can_queue_ramp_down(lport);
+ shost_printk(KERN_ERR, lport->host,
+ "libfc: Could not allocate frame, "
+ "reducing can_queue to %d.\n", lport->host->can_queue);
return NULL;
}
@@ -1861,8 +1862,13 @@ int fc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc_cmd)
rpriv = rport->dd_data;
if (!fc_fcp_lport_queue_ready(lport)) {
- if (lport->qfull)
+ if (lport->qfull) {
fc_fcp_can_queue_ramp_down(lport);
+ shost_printk(KERN_ERR, lport->host,
+ "libfc: queue full, "
+ "reducing can_queue to %d.\n",
+ lport->host->can_queue);
+ }
rc = SCSI_MLQUEUE_HOST_BUSY;
goto out;
}
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 17/30] libfc: sanitize E_D_TOV and R_A_TOV setting
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (15 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 16/30] libfc: Clarify ramp-down messages Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 18/30] libfc: safeguard against invalid exchange index Hannes Reinecke
` (13 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
When setting the FCP timeout we need to ensure a lower boundary
for E_D_TOV and R_A_TOV, otherwise we'd be getting spurious I/O
issues due to the fcp timer firing too early.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_fcp.c | 9 +++++----
drivers/scsi/libfc/fc_lport.c | 8 +++++---
drivers/scsi/libfc/fc_rport.c | 6 ++++--
3 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index abddfe2..1cb2c59 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1139,8 +1139,11 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
{
struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data;
+ unsigned int e_d_tov = FC_DEF_E_D_TOV;
- return msecs_to_jiffies(rpriv->e_d_tov) + HZ;
+ if (rpriv && rpriv->e_d_tov > e_d_tov)
+ e_d_tov = rpriv->e_d_tov;
+ return msecs_to_jiffies(e_d_tov) + HZ;
}
/**
@@ -1696,7 +1699,6 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
struct fc_seq *seq;
struct fcp_srr *srr;
struct fc_frame *fp;
- unsigned int rec_tov;
rport = fsp->rport;
rpriv = rport->dd_data;
@@ -1720,10 +1722,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
rpriv->local_port->port_id, FC_TYPE_FCP,
FC_FCTL_REQ, 0);
- rec_tov = get_fsp_rec_tov(fsp);
seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp,
fc_fcp_pkt_destroy,
- fsp, jiffies_to_msecs(rec_tov));
+ fsp, get_fsp_rec_tov(fsp));
if (!seq)
goto retry;
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 04ce7cf..ccf773a 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1772,7 +1772,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
if ((csp_flags & FC_SP_FT_FPORT) == 0) {
if (e_d_tov > lport->e_d_tov)
lport->e_d_tov = e_d_tov;
- lport->r_a_tov = 2 * e_d_tov;
+ lport->r_a_tov = 2 * lport->e_d_tov;
fc_lport_set_port_id(lport, did, fp);
printk(KERN_INFO "host%d: libfc: "
"Port (%6.6x) entered "
@@ -1784,8 +1784,10 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
get_unaligned_be64(
&flp->fl_wwnn));
} else {
- lport->e_d_tov = e_d_tov;
- lport->r_a_tov = r_a_tov;
+ if (e_d_tov > lport->e_d_tov)
+ lport->e_d_tov = e_d_tov;
+ if (r_a_tov > lport->r_a_tov)
+ lport->r_a_tov = r_a_tov;
fc_host_fabric_name(lport->host) =
get_unaligned_be64(&flp->fl_wwnn);
fc_lport_set_port_id(lport, did, fp);
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 68d4c92..5a9c871 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1328,13 +1328,15 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
tov = ntohl(rtv->rtv_r_a_tov);
if (tov == 0)
tov = 1;
- rdata->r_a_tov = tov;
+ if (tov > rdata->r_a_tov)
+ rdata->r_a_tov = tov;
tov = ntohl(rtv->rtv_e_d_tov);
if (toq & FC_ELS_RTV_EDRES)
tov /= 1000000;
if (tov == 0)
tov = 1;
- rdata->e_d_tov = tov;
+ if (tov > rdata->e_d_tov)
+ rdata->e_d_tov = tov;
}
}
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 18/30] libfc: safeguard against invalid exchange index
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (16 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 17/30] libfc: sanitize E_D_TOV and R_A_TOV setting Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 19/30] libfc: quarantine timed out xids Hannes Reinecke
` (12 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
The cached exchange index might be invalid, in which case
we should drop down to allocate a new one.
And we should not try to access an invalid exchange when
responding to a BA_ABTS.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_exch.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 7d0e7ca..da9c727 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -827,14 +827,18 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
/* peek cache of free slot */
if (pool->left != FC_XID_UNKNOWN) {
- index = pool->left;
- pool->left = FC_XID_UNKNOWN;
- goto hit;
+ if (!WARN_ON(fc_exch_ptr_get(pool, pool->left))) {
+ index = pool->left;
+ pool->left = FC_XID_UNKNOWN;
+ goto hit;
+ }
}
if (pool->right != FC_XID_UNKNOWN) {
- index = pool->right;
- pool->right = FC_XID_UNKNOWN;
- goto hit;
+ if (!WARN_ON(fc_exch_ptr_get(pool, pool->right))) {
+ index = pool->right;
+ pool->right = FC_XID_UNKNOWN;
+ goto hit;
+ }
}
index = pool->next_index;
@@ -1777,7 +1781,10 @@ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp)
fc_frame_free(fp);
break;
case FC_RCTL_BA_ABTS:
- fc_exch_recv_abts(ep, fp);
+ if (ep)
+ fc_exch_recv_abts(ep, fp);
+ else
+ fc_frame_free(fp);
break;
default: /* ignore junk */
fc_frame_free(fp);
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 19/30] libfc: quarantine timed out xids
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (17 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 18/30] libfc: safeguard against invalid exchange index Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 20/30] libfc: don't fail sequence abort for completed Hannes Reinecke
` (11 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
When a sequence times out we have no idea what happened to the
frame. And we do not know if we will ever receive the frame.
Hence we cannot re-use the xid as we would risk data corruption
if the xid had been re-used and the timed out frame would be
received after that.
So we need to quarantine the xid until the lport is reset.
Yes, I know this will (eventually) deplete the xid pool.
But for now it's the safest method.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_exch.c | 33 ++++++++++++++++++++++-----------
drivers/scsi/libfc/fc_fcp.c | 13 +++++++------
include/scsi/libfc.h | 1 +
3 files changed, 30 insertions(+), 17 deletions(-)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index da9c727..510f38c 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -94,6 +94,7 @@ struct fc_exch_pool {
struct fc_exch_mgr {
struct fc_exch_pool __percpu *pool;
mempool_t *ep_pool;
+ struct fc_lport *lport;
enum fc_class class;
struct kref kref;
u16 min_xid;
@@ -408,6 +409,8 @@ static int fc_exch_done_locked(struct fc_exch *ep)
return rc;
}
+static struct fc_exch fc_quarantine_exch;
+
/**
* fc_exch_ptr_get() - Return an exchange from an exchange pool
* @pool: Exchange Pool to get an exchange from
@@ -452,14 +455,17 @@ static void fc_exch_delete(struct fc_exch *ep)
/* update cache of free slot */
index = (ep->xid - ep->em->min_xid) >> fc_cpu_order;
- if (pool->left == FC_XID_UNKNOWN)
- pool->left = index;
- else if (pool->right == FC_XID_UNKNOWN)
- pool->right = index;
- else
- pool->next_index = index;
-
- fc_exch_ptr_set(pool, index, NULL);
+ if (!(ep->state & FC_EX_QUARANTINE)) {
+ if (pool->left == FC_XID_UNKNOWN)
+ pool->left = index;
+ else if (pool->right == FC_XID_UNKNOWN)
+ pool->right = index;
+ else
+ pool->next_index = index;
+ fc_exch_ptr_set(pool, index, NULL);
+ } else {
+ fc_exch_ptr_set(pool, index, &fc_quarantine_exch);
+ }
list_del(&ep->ex_list);
spin_unlock_bh(&pool->lock);
fc_exch_release(ep); /* drop hold for exch in mp */
@@ -916,14 +922,14 @@ static inline struct fc_exch *fc_exch_alloc(struct fc_lport *lport,
*/
static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
{
+ struct fc_lport *lport = mp->lport;
struct fc_exch_pool *pool;
struct fc_exch *ep = NULL;
u16 cpu = xid & fc_cpu_mask;
if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) {
- printk_ratelimited(KERN_ERR
- "libfc: lookup request for XID = %d, "
- "indicates invalid CPU %d\n", xid, cpu);
+ pr_err("host%u: lport %6.6x: xid %d invalid CPU %d\n:",
+ lport->host->host_no, lport->port_id, xid, cpu);
return NULL;
}
@@ -931,6 +937,10 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
pool = per_cpu_ptr(mp->pool, cpu);
spin_lock_bh(&pool->lock);
ep = fc_exch_ptr_get(pool, (xid - mp->min_xid) >> fc_cpu_order);
+ if (ep == &fc_quarantine_exch) {
+ FC_LPORT_DBG(lport, "xid %x quarantined\n", xid);
+ ep = NULL;
+ }
if (ep) {
WARN_ON(ep->xid != xid);
fc_exch_hold(ep);
@@ -2429,6 +2439,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport,
return NULL;
mp->class = class;
+ mp->lport = lport;
/* adjust em exch xid range for offload */
mp->min_xid = min_xid;
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 1cb2c59..8694e87 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1531,13 +1531,14 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
fsp->rport->port_id, rjt->er_reason,
rjt->er_explan, fsp->xfer_len);
/*
- * If no data transfer, the command frame got dropped
- * so we just retry. If data was transferred, we
- * lost the response but the target has no record,
- * so we abort and retry.
+ * If response got lost or is stuck in the
+ * queue somewhere we have no idea if and when
+ * the response will be received. So quarantine
+ * the xid and retry the command.
*/
- if (rjt->er_explan == ELS_EXPL_OXID_RXID &&
- fsp->xfer_len == 0) {
+ if (rjt->er_explan == ELS_EXPL_OXID_RXID) {
+ struct fc_exch *ep = fc_seq_exch(fsp->seq_ptr);
+ ep->state |= FC_EX_QUARANTINE;
fsp->state |= FC_SRB_ABORTED;
fc_fcp_retry_cmd(fsp, FC_TRANS_RESET);
break;
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index dc42d80..8cb752f 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -390,6 +390,7 @@ struct fc_seq {
#define FC_EX_DONE (1 << 0) /* ep is completed */
#define FC_EX_RST_CLEANUP (1 << 1) /* reset is forcing completion */
+#define FC_EX_QUARANTINE (1 << 2) /* exch is quarantined */
/**
* struct fc_exch - Fibre Channel Exchange
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 20/30] libfc: don't fail sequence abort for completed
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (18 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 19/30] libfc: quarantine timed out xids Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 21/30] libfc: Do not drop out-of-order frames Hannes Reinecke
` (10 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
If a sequence should be aborted the exchange might already
be completed (eg if the response is still queued in the rx
queue), so this shouldn't considered as an error.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_fcp.c | 40 ++++++++++++++++++++++++++++++----------
1 file changed, 30 insertions(+), 10 deletions(-)
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 8694e87..63c821b 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -258,6 +258,17 @@ static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay)
mod_timer(&fsp->timer, jiffies + delay);
}
+static void fc_fcp_abort_done(struct fc_fcp_pkt *fsp)
+{
+ fsp->state |= FC_SRB_ABORTED;
+ fsp->state &= ~FC_SRB_ABORT_PENDING;
+
+ if (fsp->wait_for_comp)
+ complete(&fsp->tm_done);
+ else
+ fc_fcp_complete_locked(fsp);
+}
+
/**
* fc_fcp_send_abort() - Send an abort for exchanges associated with a
* fcp_pkt
@@ -265,6 +276,8 @@ static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay)
*/
static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
{
+ int rc;
+
if (!fsp->seq_ptr)
return -EINVAL;
@@ -272,7 +285,16 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
put_cpu();
fsp->state |= FC_SRB_ABORT_PENDING;
- return fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0);
+ rc = fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0);
+ /*
+ * ->seq_exch_abort() might return -ENXIO if
+ * the sequence is already completed
+ */
+ if (rc == -ENXIO) {
+ fc_fcp_abort_done(fsp);
+ rc = 0;
+ }
+ return rc;
}
/**
@@ -729,15 +751,8 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
ba_done = 0;
}
- if (ba_done) {
- fsp->state |= FC_SRB_ABORTED;
- fsp->state &= ~FC_SRB_ABORT_PENDING;
-
- if (fsp->wait_for_comp)
- complete(&fsp->tm_done);
- else
- fc_fcp_complete_locked(fsp);
- }
+ if (ba_done)
+ fc_fcp_abort_done(fsp);
}
/**
@@ -1246,6 +1261,11 @@ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp)
return FAILED;
}
+ if (fsp->state & FC_SRB_ABORTED) {
+ FC_FCP_DBG(fsp, "target abort cmd completed\n");
+ return SUCCESS;
+ }
+
init_completion(&fsp->tm_done);
fsp->wait_for_comp = 1;
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 21/30] libfc: Do not drop out-of-order frames
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (19 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 20/30] libfc: don't fail sequence abort for completed Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 22/30] libfc: reset timeout on queue full Hannes Reinecke
` (9 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
When receiving packets from the network we cannot guarantee any
frame ordering, so we should be receiving all valid frames and
let the upper layers deal with it.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_exch.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 510f38c..b366bb5 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -1592,9 +1592,6 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
if (fc_sof_is_init(sof)) {
sp->ssb_stat |= SSB_ST_RESP;
sp->id = fh->fh_seq_id;
- } else if (sp->id != fh->fh_seq_id) {
- atomic_inc(&mp->stats.seq_not_found);
- goto rel;
}
f_ctl = ntoh24(fh->fh_f_ctl);
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 22/30] libfc: reset timeout on queue full
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (20 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 21/30] libfc: Do not drop out-of-order frames Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 23/30] libfc: wait for E_D_TOV when out-of-order sequence is received Hannes Reinecke
` (8 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
When we're receiving a timeout we should be checking for queue
full status; if there are still some packets pending we should
be resetting the counter to ensure we're not missing out any
packets which are still queued.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_fcp.c | 21 ++++++++++++++++++---
include/scsi/libfc.h | 3 ++-
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 63c821b..3e059e4 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -254,8 +254,10 @@ static inline void fc_fcp_unlock_pkt(struct fc_fcp_pkt *fsp)
*/
static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay)
{
- if (!(fsp->state & FC_SRB_COMPL))
+ if (!(fsp->state & FC_SRB_COMPL)) {
mod_timer(&fsp->timer, jiffies + delay);
+ fsp->timer_delay = delay;
+ }
}
static void fc_fcp_abort_done(struct fc_fcp_pkt *fsp)
@@ -932,6 +934,12 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
* Wait a at least one jiffy to see if it is delivered.
* If this expires without data, we may do SRR.
*/
+ if (fsp->lp->qfull) {
+ FC_FCP_DBG(fsp, "tgt %6.6x data underrun, "
+ "retry due to queue busy\n",
+ fsp->rport->port_id);
+ return;
+ }
FC_FCP_DBG(fsp, "tgt %6.6x xfer len %zx data underrun "
"len %x, data len %x\n",
fsp->rport->port_id,
@@ -1435,8 +1443,15 @@ static void fc_fcp_timeout(unsigned long data)
if (fsp->cdb_cmd.fc_tm_flags)
goto unlock;
- FC_FCP_DBG(fsp, "fcp timeout, flags %x state %x\n",
- rpriv->flags, fsp->state);
+ if (fsp->lp->qfull) {
+ FC_FCP_DBG(fsp, "fcp timeout, resetting timer delay %d\n",
+ fsp->timer_delay);
+ setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp);
+ fc_fcp_timer_set(fsp, fsp->timer_delay);
+ goto unlock;
+ }
+ FC_FCP_DBG(fsp, "fcp timeout, delay %d flags %x state %x\n",
+ fsp->timer_delay, rpriv->flags, fsp->state);
fsp->state |= FC_SRB_FCP_PROCESSING_TMO;
if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 8cb752f..f5aa54b 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -355,7 +355,8 @@ struct fc_fcp_pkt {
/* Timeout/error related information */
struct timer_list timer;
- int wait_for_comp;
+ int wait_for_comp;
+ int timer_delay;
u32 recov_retry;
struct fc_seq *recov_seq;
struct completion tm_done;
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 23/30] libfc: wait for E_D_TOV when out-of-order sequence is received
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (21 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 22/30] libfc: reset timeout on queue full Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 24/30] fcoe: Use kfree_skb() instead of kfree() Hannes Reinecke
` (7 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
When detecting an out-of-order sequence we should be waiting for
E_D_TOV before trying to abort the sequence.
The response might still be stuck in the queue somewhere.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/libfc/fc_fcp.c | 38 ++++++++++++++++++++------------------
1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 3e059e4..f087c6e 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -460,6 +460,22 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport,
}
/**
+ * get_fsp_rec_tov() - Helper function to get REC_TOV
+ * @fsp: the FCP packet
+ *
+ * Returns rec tov in jiffies as rpriv->e_d_tov + 1 second
+ */
+static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
+{
+ struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data;
+ unsigned int e_d_tov = FC_DEF_E_D_TOV;
+
+ if (rpriv && rpriv->e_d_tov > e_d_tov)
+ e_d_tov = rpriv->e_d_tov;
+ return msecs_to_jiffies(e_d_tov) + HZ;
+}
+
+/**
* fc_fcp_recv_data() - Handler for receiving SCSI-FCP data from a target
* @fsp: The FCP packet the data is on
* @fp: The data frame
@@ -562,8 +578,10 @@ crc_err:
* and completes the transfer, call the completion handler.
*/
if (unlikely(fsp->state & FC_SRB_RCV_STATUS) &&
- fsp->xfer_len == fsp->data_len - fsp->scsi_resid)
+ fsp->xfer_len == fsp->data_len - fsp->scsi_resid) {
+ FC_FCP_DBG( fsp, "complete out-of-order sequence\n" );
fc_fcp_complete_locked(fsp);
+ }
return;
err:
fc_fcp_recovery(fsp, host_bcode);
@@ -944,7 +962,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
"len %x, data len %x\n",
fsp->rport->port_id,
fsp->xfer_len, expected_len, fsp->data_len);
- fc_fcp_timer_set(fsp, 2);
+ fc_fcp_timer_set(fsp, get_fsp_rec_tov(fsp));
return;
}
fsp->status_code = FC_DATA_OVRRUN;
@@ -1154,22 +1172,6 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
}
/**
- * get_fsp_rec_tov() - Helper function to get REC_TOV
- * @fsp: the FCP packet
- *
- * Returns rec tov in jiffies as rpriv->e_d_tov + 1 second
- */
-static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
-{
- struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data;
- unsigned int e_d_tov = FC_DEF_E_D_TOV;
-
- if (rpriv && rpriv->e_d_tov > e_d_tov)
- e_d_tov = rpriv->e_d_tov;
- return msecs_to_jiffies(e_d_tov) + HZ;
-}
-
-/**
* fc_fcp_cmd_send() - Send a FCP command
* @lport: The local port to send the command on
* @fsp: The FCP packet the command is on
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 24/30] fcoe: Use kfree_skb() instead of kfree()
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (22 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 23/30] libfc: wait for E_D_TOV when out-of-order sequence is received Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 25/30] fcoe: set default TC priority Hannes Reinecke
` (6 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Wei Yongjun
From: Wei Yongjun <weiyj.lk@gmail.com>
Use kfree_skb() instead of kfree() to free sk_buff.
Signed-off-by: Wei Yongjun <weiyj.lk@gmail.com>
Reviewed-by: Johannes Thumshirn <jth@kernel.org>
---
drivers/scsi/fcoe/fcoe_ctlr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 5eacd33..1dd8a7c 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -2934,7 +2934,7 @@ static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
mutex_unlock(&fip->ctlr_mutex);
drop:
- kfree(skb);
+ kfree_skb(skb);
return rc;
}
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 25/30] fcoe: set default TC priority
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (23 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 24/30] fcoe: Use kfree_skb() instead of kfree() Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 26/30] fcoe: inhibit writing invalid values into the 'enabled' Hannes Reinecke
` (5 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
If DCB is not enabled or compiled in we still should be setting
a sane default priority. So put FCoE frames in priority class
'interactive' and FIP frames in priority class 'besteffort'.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/fcoe/fcoe.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 9bd41a3..81e7f99 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -2160,6 +2160,8 @@ static bool fcoe_match(struct net_device *netdev)
*/
static void fcoe_dcb_create(struct fcoe_interface *fcoe)
{
+ int ctlr_prio = TC_PRIO_BESTEFFORT;
+ int fcoe_prio = TC_PRIO_INTERACTIVE;
#ifdef CONFIG_DCB
int dcbx;
u8 fup, up;
@@ -2186,10 +2188,12 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe)
fup = dcb_getapp(netdev, &app);
}
- fcoe->priority = ffs(up) ? ffs(up) - 1 : 0;
- ctlr->priority = ffs(fup) ? ffs(fup) - 1 : fcoe->priority;
+ fcoe_prio = ffs(up) ? ffs(up) - 1 : 0;
+ ctlr_prio = ffs(fup) ? ffs(fup) - 1 : fcoe_prio;
}
#endif
+ fcoe->priority = fcoe_prio;
+ ctlr->priority = ctlr_prio;
}
enum fcoe_create_link_state {
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 26/30] fcoe: inhibit writing invalid values into the 'enabled'
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (24 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 25/30] fcoe: set default TC priority Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 27/30] fcoe: correct sending FIP VLAN packets on VLAN 0 Hannes Reinecke
` (4 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
The 'enabled' sysfs attribute only accepts the values '0' and '1',
so we should error out any other values.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/fcoe/fcoe_sysfs.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index 0675fd1..5bfa2b1 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -335,16 +335,24 @@ static ssize_t store_ctlr_enabled(struct device *dev,
const char *buf, size_t count)
{
struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
+ bool enabled;
int rc;
+ if (*buf == '1')
+ enabled = true;
+ else if (*buf == '0')
+ enabled = false;
+ else
+ return -EINVAL;
+
switch (ctlr->enabled) {
case FCOE_CTLR_ENABLED:
- if (*buf == '1')
+ if (enabled)
return count;
ctlr->enabled = FCOE_CTLR_DISABLED;
break;
case FCOE_CTLR_DISABLED:
- if (*buf == '0')
+ if (!enabled)
return count;
ctlr->enabled = FCOE_CTLR_ENABLED;
break;
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 27/30] fcoe: correct sending FIP VLAN packets on VLAN 0
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (25 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 26/30] fcoe: inhibit writing invalid values into the 'enabled' Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 28/30] fcoe: FIP debugging Hannes Reinecke
` (3 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
The FIP VLAN frame consists of an ethernet header followed
by the FIP VLAN frame, so we need to skip the ethernet header
if we want to check the FIP opcode.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/fcoe/fcoe.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 81e7f99..706de91 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -582,7 +582,8 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
* Use default VLAN for FIP VLAN discovery protocol
*/
frame = (struct fip_frame *)skb->data;
- if (frame->fip.fip_op == ntohs(FIP_OP_VLAN) &&
+ if (ntohs(frame->eth.h_proto) == ETH_P_FIP &&
+ ntohs(frame->fip.fip_op) == FIP_OP_VLAN &&
fcoe->realdev != fcoe->netdev)
skb->dev = fcoe->realdev;
else
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 28/30] fcoe: FIP debugging
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (26 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 27/30] fcoe: correct sending FIP VLAN packets on VLAN 0 Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 29/30] fcoe: filter out frames from invalid vlans Hannes Reinecke
` (2 subsequent siblings)
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
Add additional statements for debugging FIP frames.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/fcoe/fcoe_ctlr.c | 51 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 46 insertions(+), 5 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 1dd8a7c..8be27ea 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -801,6 +801,8 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
return -EINPROGRESS;
drop:
kfree_skb(skb);
+ LIBFCOE_FIP_DBG(fip, "drop els_send op %u d_id %x\n",
+ op, ntoh24(fh->fh_d_id));
return -EINVAL;
}
EXPORT_SYMBOL(fcoe_ctlr_els_send);
@@ -2399,6 +2401,8 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
switch (fip->state) {
case FIP_ST_VNMP_CLAIM:
case FIP_ST_VNMP_UP:
+ LIBFCOE_FIP_DBG(fip, "vn_probe_req: send reply, state %x\n",
+ fip->state);
fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
frport->enode_mac, 0);
break;
@@ -2413,15 +2417,21 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
*/
if (fip->lp->wwpn > rdata->ids.port_name &&
!(frport->flags & FIP_FL_REC_OR_P2P)) {
+ LIBFCOE_FIP_DBG(fip, "vn_probe_req: "
+ "port_id collision\n");
fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
frport->enode_mac, 0);
break;
}
/* fall through */
case FIP_ST_VNMP_START:
+ LIBFCOE_FIP_DBG(fip, "vn_probe_req: "
+ "restart VN2VN negotiation\n");
fcoe_ctlr_vn_restart(fip);
break;
default:
+ LIBFCOE_FIP_DBG(fip, "vn_probe_req: ignore state %x\n",
+ fip->state);
break;
}
}
@@ -2443,9 +2453,12 @@ static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip,
case FIP_ST_VNMP_PROBE1:
case FIP_ST_VNMP_PROBE2:
case FIP_ST_VNMP_CLAIM:
+ LIBFCOE_FIP_DBG(fip, "vn_probe_reply: restart state %x\n",
+ fip->state);
fcoe_ctlr_vn_restart(fip);
break;
case FIP_ST_VNMP_UP:
+ LIBFCOE_FIP_DBG(fip, "vn_probe_reply: send claim notify\n");
fcoe_ctlr_vn_send_claim(fip);
break;
default:
@@ -2484,15 +2497,18 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
ids = &rdata->ids;
if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) ||
- (ids->node_name != -1 && ids->node_name != new->ids.node_name))
+ (ids->node_name != -1 && ids->node_name != new->ids.node_name)) {
+ LIBFCOE_FIP_DBG(fip, "vn_add rport logoff %6.6x\n", port_id);
lport->tt.rport_logoff(rdata);
+ }
ids->port_name = new->ids.port_name;
ids->node_name = new->ids.node_name;
mutex_unlock(&lport->disc.disc_mutex);
frport = fcoe_ctlr_rport(rdata);
- LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s\n",
- port_id, frport->fcoe_len ? "old" : "new");
+ LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s state %d\n",
+ port_id, frport->fcoe_len ? "old" : "new",
+ rdata->rp_state);
*frport = *fcoe_ctlr_rport(new);
frport->time = 0;
}
@@ -2535,6 +2551,7 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
struct fcoe_rport *frport = fcoe_ctlr_rport(new);
if (frport->flags & FIP_FL_REC_OR_P2P) {
+ LIBFCOE_FIP_DBG(fip, "send probe req for P2P/REC\n");
fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
return;
}
@@ -2542,25 +2559,37 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
case FIP_ST_VNMP_START:
case FIP_ST_VNMP_PROBE1:
case FIP_ST_VNMP_PROBE2:
- if (new->ids.port_id == fip->port_id)
+ if (new->ids.port_id == fip->port_id) {
+ LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
+ "restart, state %d\n",
+ fip->state);
fcoe_ctlr_vn_restart(fip);
+ }
break;
case FIP_ST_VNMP_CLAIM:
case FIP_ST_VNMP_UP:
if (new->ids.port_id == fip->port_id) {
if (new->ids.port_name > fip->lp->wwpn) {
+ LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
+ "restart, port_id collision\n");
fcoe_ctlr_vn_restart(fip);
break;
}
+ LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
+ "send claim notify\n");
fcoe_ctlr_vn_send_claim(fip);
break;
}
+ LIBFCOE_FIP_DBG(fip, "vn_claim_notify: send reply to %x\n",
+ new->ids.port_id);
fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, frport->enode_mac,
min((u32)frport->fcoe_len,
fcoe_ctlr_fcoe_size(fip)));
fcoe_ctlr_vn_add(fip, new);
break;
default:
+ LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
+ "ignoring claim from %x\n", new->ids.port_id);
break;
}
}
@@ -2597,6 +2626,7 @@ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
frport = fcoe_ctlr_rport(new);
if (frport->flags & FIP_FL_REC_OR_P2P) {
+ LIBFCOE_FIP_DBG(fip, "p2p beacon while in vn2vn mode\n");
fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
return;
}
@@ -2605,8 +2635,14 @@ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
if (rdata->ids.node_name == new->ids.node_name &&
rdata->ids.port_name == new->ids.port_name) {
frport = fcoe_ctlr_rport(rdata);
- if (!frport->time && fip->state == FIP_ST_VNMP_UP)
+ LIBFCOE_FIP_DBG(fip, "beacon from rport %x\n",
+ rdata->ids.port_id);
+ if (!frport->time && fip->state == FIP_ST_VNMP_UP) {
+ LIBFCOE_FIP_DBG(fip, "beacon expired "
+ "for rport %x\n",
+ rdata->ids.port_id);
lport->tt.rport_login(rdata);
+ }
frport->time = jiffies;
}
kref_put(&rdata->kref, lport->tt.rport_destroy);
@@ -3031,11 +3067,13 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
switch (fip->state) {
case FIP_ST_VNMP_START:
fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE1);
+ LIBFCOE_FIP_DBG(fip, "vn_timeout: send 1st probe request\n");
fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
next_time = jiffies + msecs_to_jiffies(FIP_VN_PROBE_WAIT);
break;
case FIP_ST_VNMP_PROBE1:
fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE2);
+ LIBFCOE_FIP_DBG(fip, "vn_timeout: send 2nd probe request\n");
fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
break;
@@ -3046,6 +3084,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
hton24(mac + 3, new_port_id);
fcoe_ctlr_map_dest(fip);
fip->update_mac(fip->lp, mac);
+ LIBFCOE_FIP_DBG(fip, "vn_timeout: send claim notify\n");
fcoe_ctlr_vn_send_claim(fip);
next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
break;
@@ -3057,6 +3096,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
next_time = fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT);
if (time_after_eq(jiffies, next_time)) {
fcoe_ctlr_set_state(fip, FIP_ST_VNMP_UP);
+ LIBFCOE_FIP_DBG(fip, "vn_timeout: send vn2vn beacon\n");
fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
fcoe_all_vn2vn, 0);
next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
@@ -3067,6 +3107,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
case FIP_ST_VNMP_UP:
next_time = fcoe_ctlr_vn_age(fip);
if (time_after_eq(jiffies, fip->port_ka_time)) {
+ LIBFCOE_FIP_DBG(fip, "vn_timeout: send vn2vn beacon\n");
fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
fcoe_all_vn2vn, 0);
fip->port_ka_time = jiffies +
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 29/30] fcoe: filter out frames from invalid vlans
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (27 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 28/30] fcoe: FIP debugging Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 12:01 ` [PATCH 30/30] fcoe: make R_A_TOV and E_D_TOV configurable Hannes Reinecke
2016-08-26 13:48 ` [PATCH 00/30] FCoE VN2VN fixes Johannes Thumshirn
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke
Any multicase address is set on all interfaces, the base interface
and any VLAN interface on top of this. So we might receive frames
which are not destined for us but in fact on another VLAN.
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/fcoe/fcoe_ctlr.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 8be27ea..e6557ea 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -2721,11 +2721,21 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
struct fc_rport_priv rdata;
struct fcoe_rport frport;
} buf;
- int rc;
+ int rc, vlan_id = 0;
fiph = (struct fip_header *)skb->data;
sub = fiph->fip_subcode;
+ if (fip->lp->vlan)
+ vlan_id = skb_vlan_tag_get_id(skb);
+
+ if (vlan_id && vlan_id != fip->lp->vlan) {
+ LIBFCOE_FIP_DBG(fip, "vn_recv drop frame sub %x vlan %d\n",
+ sub, vlan_id);
+ rc = -EAGAIN;
+ goto drop;
+ }
+
rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata);
if (rc) {
LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc);
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 30/30] fcoe: make R_A_TOV and E_D_TOV configurable
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (28 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 29/30] fcoe: filter out frames from invalid vlans Hannes Reinecke
@ 2016-08-26 12:01 ` Hannes Reinecke
2016-08-26 13:48 ` [PATCH 00/30] FCoE VN2VN fixes Johannes Thumshirn
30 siblings, 0 replies; 35+ messages in thread
From: Hannes Reinecke @ 2016-08-26 12:01 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, Johannes Thumshirn,
linux-scsi, Mike Snitzer, Martin Wilck, Hannes Reinecke,
Hannes Reinecke
The user might want to modify the values for R_A_TOV and E_D_TOV,
so add new module parameters 'e_d_tov' and 'r_a_tov' for the
'fcoe' modules and allow to modify them via sysfs attributes.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/fcoe/fcoe.c | 12 +++++--
drivers/scsi/fcoe/fcoe_sysfs.c | 71 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 706de91..cf4adaa 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -63,6 +63,14 @@ unsigned int fcoe_debug_logging;
module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
+unsigned int fcoe_e_d_tov = 2 * 1000;
+module_param_named(e_d_tov, fcoe_e_d_tov, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(e_d_tov, "E_D_TOV in ms, default 2000");
+
+unsigned int fcoe_r_a_tov = 2 * 2 * 1000;
+module_param_named(r_a_tov, fcoe_r_a_tov, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(r_a_tov, "R_A_TOV in ms, default 4000");
+
static DEFINE_MUTEX(fcoe_config_mutex);
static struct workqueue_struct *fcoe_wq;
@@ -634,8 +642,8 @@ static int fcoe_lport_config(struct fc_lport *lport)
lport->qfull = 0;
lport->max_retry_count = 3;
lport->max_rport_retry_count = 3;
- lport->e_d_tov = 2 * 1000; /* FC-FS default */
- lport->r_a_tov = 2 * 2 * 1000;
+ lport->e_d_tov = fcoe_e_d_tov;
+ lport->r_a_tov = fcoe_r_a_tov;
lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
lport->does_npiv = 1;
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index 5bfa2b1..9cf3d56 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -432,6 +432,75 @@ static FCOE_DEVICE_ATTR(ctlr, fip_vlan_responder, S_IRUGO | S_IWUSR,
store_ctlr_fip_resp);
static ssize_t
+fcoe_ctlr_var_store(u32 *var, const char *buf, size_t count)
+{
+ int err;
+ unsigned long v;
+
+ err = kstrtoul(buf, 10, &v);
+ if (err || v > UINT_MAX)
+ return -EINVAL;
+
+ *var = v;
+
+ return count;
+}
+
+static ssize_t store_ctlr_r_a_tov(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
+ struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+
+ if (ctlr_dev->enabled == FCOE_CTLR_ENABLED)
+ return -EBUSY;
+ if (ctlr_dev->enabled == FCOE_CTLR_DISABLED)
+ return fcoe_ctlr_var_store(&ctlr->lp->r_a_tov, buf, count);
+ return -ENOTSUPP;
+}
+
+static ssize_t show_ctlr_r_a_tov(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
+ struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+
+ return sprintf(buf, "%d\n", ctlr->lp->r_a_tov);
+}
+
+static FCOE_DEVICE_ATTR(ctlr, r_a_tov, S_IRUGO | S_IWUSR,
+ show_ctlr_r_a_tov, store_ctlr_r_a_tov);
+
+static ssize_t store_ctlr_e_d_tov(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
+ struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+
+ if (ctlr_dev->enabled == FCOE_CTLR_ENABLED)
+ return -EBUSY;
+ if (ctlr_dev->enabled == FCOE_CTLR_DISABLED)
+ return fcoe_ctlr_var_store(&ctlr->lp->e_d_tov, buf, count);
+ return -ENOTSUPP;
+}
+
+static ssize_t show_ctlr_e_d_tov(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
+ struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+
+ return sprintf(buf, "%d\n", ctlr->lp->e_d_tov);
+}
+
+static FCOE_DEVICE_ATTR(ctlr, e_d_tov, S_IRUGO | S_IWUSR,
+ show_ctlr_e_d_tov, store_ctlr_e_d_tov);
+
+static ssize_t
store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
@@ -515,6 +584,8 @@ static struct attribute_group fcoe_ctlr_lesb_attr_group = {
static struct attribute *fcoe_ctlr_attrs[] = {
&device_attr_fcoe_ctlr_fip_vlan_responder.attr,
&device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr,
+ &device_attr_fcoe_ctlr_r_a_tov.attr,
+ &device_attr_fcoe_ctlr_e_d_tov.attr,
&device_attr_fcoe_ctlr_enabled.attr,
&device_attr_fcoe_ctlr_mode.attr,
NULL,
--
1.8.5.6
^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [PATCH 01/30] libfc: Revisit kref handling
2016-08-26 12:01 ` [PATCH 01/30] libfc: Revisit kref handling Hannes Reinecke
@ 2016-08-26 13:37 ` Johannes Thumshirn
0 siblings, 0 replies; 35+ messages in thread
From: Johannes Thumshirn @ 2016-08-26 13:37 UTC (permalink / raw)
To: Hannes Reinecke
Cc: Martin K. Petersen, James Bottomley, Christoph Hellwig,
Johannes Thumshirn, linux-scsi, Mike Snitzer, Martin Wilck,
Hannes Reinecke
On Fri, Aug 26, 2016 at 02:01:24PM +0200, Hannes Reinecke wrote:
> The kref handling in fc_rport is a mess. This patch updates
> the kref handling according to the following rules:
>
> - Take a reference whenever scheduling a workqueue
> - Take a reference whenever an ELS command is send
> - Drop the reference at the end of the workqueue function
> - Drop the reference at the end of handling ELS replies
> - Take a reference when allocating an rport
> - Drop the reference when removing an rport
>
> Signed-off-by: Hannes Reinecke <hare@suse.com>
> ---
Acked-by: Johannes Thumshirn <jth@kernel.org>
--
Johannes Thumshirn Storage
jthumshirn@suse.de +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 00/30] FCoE VN2VN fixes
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
` (29 preceding siblings ...)
2016-08-26 12:01 ` [PATCH 30/30] fcoe: make R_A_TOV and E_D_TOV configurable Hannes Reinecke
@ 2016-08-26 13:48 ` Johannes Thumshirn
2016-08-31 2:46 ` Martin K. Petersen
30 siblings, 1 reply; 35+ messages in thread
From: Johannes Thumshirn @ 2016-08-26 13:48 UTC (permalink / raw)
To: Hannes Reinecke
Cc: Martin K. Petersen, James Bottomley, Christoph Hellwig,
Johannes Thumshirn, linux-scsi, Mike Snitzer, Martin Wilck
On Fri, Aug 26, 2016 at 02:01:23PM +0200, Hannes Reinecke wrote:
> Hi all,
>
> here's a patchset to get VN2VN running on non-DCB fabrics.
> With it it's possible to run FCoE VN2VN over virtio, allowing
> for a fully virtualized FC testbed. Which would make it ideal
> to integrate into Mike's mptest test suite.
> It also irons out some generic issues with the libfc stack,
> like another round for kref handling updates and handling PRLI correctly.
> (The PRLI problems even have a workaround in iPXE, so it's time to do
> something about it ...)
>
> As usual, comments and reviews are welcome.
>
> Hannes Reinecke (29):
> libfc: Revisit kref handling
> libfc: additional debugging messages
> libfc: spurious I/O error under high load
> libfc: Do not login if the port is already started
> libfc: use configured lport R_A_TOV when sending
> libfc: use configured e_d_tov for remote port state
> libfc: do not overwrite DID_TIME_OUT status
> libfc: use error code for fc_rport_error()
> libfc: Send LS_RJT responses on frame allocation
> libfc: don't advance state machine for incoming FLOGI
> libfc: Fixup disc_mutex handling
> libfc: Do not drop down to FLOGI for fc_rport_login()
> libfc: Implement RTV responder
> libfc: Rework PRLI handling
> libfc: Return LS_RJT_BUSY for PRLI in status PLOGI
> libfc: Clarify ramp-down messages
> libfc: sanitize E_D_TOV and R_A_TOV setting
> libfc: safeguard against invalid exchange index
> libfc: quarantine timed out xids
> libfc: don't fail sequence abort for completed
> libfc: Do not drop out-of-order frames
> libfc: reset timeout on queue full
> libfc: wait for E_D_TOV when out-of-order sequence is received
> fcoe: set default TC priority
> fcoe: inhibit writing invalid values into the 'enabled'
> fcoe: correct sending FIP VLAN packets on VLAN 0
> fcoe: FIP debugging
> fcoe: filter out frames from invalid vlans
I _think_ I already reviewed them (at least I do have a deja-vu when I
read 'Revisit kref handling')
>
> Wei Yongjun (1):
> fcoe: Use kfree_skb() instead of kfree()
This one is already in Linus' tree as commit
ea0a95d7f162bfa1c9df74471f0064f71cdf80ea.
--
Johannes Thumshirn Storage
jthumshirn@suse.de +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 00/30] FCoE VN2VN fixes
2016-08-26 13:48 ` [PATCH 00/30] FCoE VN2VN fixes Johannes Thumshirn
@ 2016-08-31 2:46 ` Martin K. Petersen
2016-08-31 7:25 ` Johannes Thumshirn
0 siblings, 1 reply; 35+ messages in thread
From: Martin K. Petersen @ 2016-08-31 2:46 UTC (permalink / raw)
To: Hannes Reinecke
Cc: Johannes Thumshirn, Martin K. Petersen, James Bottomley,
Christoph Hellwig, Johannes Thumshirn, linux-scsi, Mike Snitzer,
Martin Wilck
>>>>> "Johannes" == Johannes Thumshirn <jthumshirn@suse.de> writes:
Hannes,
Johannes> I _think_ I already reviewed them (at least I do have a
Johannes> deja-vu when I read 'Revisit kref handling')
In v1 of the series patches 7, 11, 15 and 22 needed changes, everything
else had been reviewed. 15 appears to have been dropped ("libfc: frame
alloc failure messages"). Whereas 7, 11 and 15 have emerged as patches
25, 26 and 29 in the new series.
Anyway. You can't expect me, nor reviewers to keep track of all this
shuffling. Especially not in a series with 30 patches. Please maintain a
changelog when you repost and apply tags for patches you haven't
tweaked.
I am happy to apply a partial series as long as nothing breaks. I have
done a few where I have committed up to the first patch that had
comments.
--
Martin K. Petersen Oracle Linux Engineering
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 00/30] FCoE VN2VN fixes
2016-08-31 2:46 ` Martin K. Petersen
@ 2016-08-31 7:25 ` Johannes Thumshirn
0 siblings, 0 replies; 35+ messages in thread
From: Johannes Thumshirn @ 2016-08-31 7:25 UTC (permalink / raw)
To: Martin K. Petersen
Cc: Hannes Reinecke, James Bottomley, Christoph Hellwig,
Johannes Thumshirn, linux-scsi, Mike Snitzer, Martin Wilck
On Tue, Aug 30, 2016 at 10:46:17PM -0400, Martin K . Petersen wrote:
> >>>>> "Johannes" == Johannes Thumshirn <jthumshirn@suse.de> writes:
>
> Hannes,
>
> Johannes> I _think_ I already reviewed them (at least I do have a
> Johannes> deja-vu when I read 'Revisit kref handling')
>
> In v1 of the series patches 7, 11, 15 and 22 needed changes, everything
> else had been reviewed. 15 appears to have been dropped ("libfc: frame
> alloc failure messages"). Whereas 7, 11 and 15 have emerged as patches
> 25, 26 and 29 in the new series.
>
> Anyway. You can't expect me, nor reviewers to keep track of all this
> shuffling. Especially not in a series with 30 patches. Please maintain a
> changelog when you repost and apply tags for patches you haven't
> tweaked.
>
> I am happy to apply a partial series as long as nothing breaks. I have
> done a few where I have committed up to the first patch that had
> comments.
Hannes is currently on vacation. I think it's the save if we wait for
him to return so he can make a proper v2 (or v3) of this series.
Thanks,
Johannes
--
Johannes Thumshirn Storage
jthumshirn@suse.de +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
^ permalink raw reply [flat|nested] 35+ messages in thread
end of thread, other threads:[~2016-08-31 7:26 UTC | newest]
Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-26 12:01 [PATCH 00/30] FCoE VN2VN fixes Hannes Reinecke
2016-08-26 12:01 ` [PATCH 01/30] libfc: Revisit kref handling Hannes Reinecke
2016-08-26 13:37 ` Johannes Thumshirn
2016-08-26 12:01 ` [PATCH 02/30] libfc: additional debugging messages Hannes Reinecke
2016-08-26 12:01 ` [PATCH 03/30] libfc: spurious I/O error under high load Hannes Reinecke
2016-08-26 12:01 ` [PATCH 04/30] libfc: Do not login if the port is already started Hannes Reinecke
2016-08-26 12:01 ` [PATCH 05/30] libfc: use configured lport R_A_TOV when sending Hannes Reinecke
2016-08-26 12:01 ` [PATCH 06/30] libfc: use configured e_d_tov for remote port state Hannes Reinecke
2016-08-26 12:01 ` [PATCH 07/30] libfc: do not overwrite DID_TIME_OUT status Hannes Reinecke
2016-08-26 12:01 ` [PATCH 08/30] libfc: use error code for fc_rport_error() Hannes Reinecke
2016-08-26 12:01 ` [PATCH 09/30] libfc: Send LS_RJT responses on frame allocation Hannes Reinecke
2016-08-26 12:01 ` [PATCH 10/30] libfc: don't advance state machine for incoming FLOGI Hannes Reinecke
2016-08-26 12:01 ` [PATCH 11/30] libfc: Fixup disc_mutex handling Hannes Reinecke
2016-08-26 12:01 ` [PATCH 12/30] libfc: Do not drop down to FLOGI for fc_rport_login() Hannes Reinecke
2016-08-26 12:01 ` [PATCH 13/30] libfc: Implement RTV responder Hannes Reinecke
2016-08-26 12:01 ` [PATCH 14/30] libfc: Rework PRLI handling Hannes Reinecke
2016-08-26 12:01 ` [PATCH 15/30] libfc: Return LS_RJT_BUSY for PRLI in status PLOGI Hannes Reinecke
2016-08-26 12:01 ` [PATCH 16/30] libfc: Clarify ramp-down messages Hannes Reinecke
2016-08-26 12:01 ` [PATCH 17/30] libfc: sanitize E_D_TOV and R_A_TOV setting Hannes Reinecke
2016-08-26 12:01 ` [PATCH 18/30] libfc: safeguard against invalid exchange index Hannes Reinecke
2016-08-26 12:01 ` [PATCH 19/30] libfc: quarantine timed out xids Hannes Reinecke
2016-08-26 12:01 ` [PATCH 20/30] libfc: don't fail sequence abort for completed Hannes Reinecke
2016-08-26 12:01 ` [PATCH 21/30] libfc: Do not drop out-of-order frames Hannes Reinecke
2016-08-26 12:01 ` [PATCH 22/30] libfc: reset timeout on queue full Hannes Reinecke
2016-08-26 12:01 ` [PATCH 23/30] libfc: wait for E_D_TOV when out-of-order sequence is received Hannes Reinecke
2016-08-26 12:01 ` [PATCH 24/30] fcoe: Use kfree_skb() instead of kfree() Hannes Reinecke
2016-08-26 12:01 ` [PATCH 25/30] fcoe: set default TC priority Hannes Reinecke
2016-08-26 12:01 ` [PATCH 26/30] fcoe: inhibit writing invalid values into the 'enabled' Hannes Reinecke
2016-08-26 12:01 ` [PATCH 27/30] fcoe: correct sending FIP VLAN packets on VLAN 0 Hannes Reinecke
2016-08-26 12:01 ` [PATCH 28/30] fcoe: FIP debugging Hannes Reinecke
2016-08-26 12:01 ` [PATCH 29/30] fcoe: filter out frames from invalid vlans Hannes Reinecke
2016-08-26 12:01 ` [PATCH 30/30] fcoe: make R_A_TOV and E_D_TOV configurable Hannes Reinecke
2016-08-26 13:48 ` [PATCH 00/30] FCoE VN2VN fixes Johannes Thumshirn
2016-08-31 2:46 ` Martin K. Petersen
2016-08-31 7:25 ` Johannes Thumshirn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).