Skip to content

Commit

Permalink
[SCSI] libfcoe: fix lenient aging of FCF advertisements
Browse files Browse the repository at this point in the history
[This patch has several improvements to the code in
the fip timers.  It hasn't been tested yet.
I'm sending it out for review.  Vasu, perhaps you can
merge this with your patch and test it together.]

The current code allows an advertisement to be used
even if it has been 3 times the FCF keep-alive
advertisement period (FKA) since one was received from
that FCF.  The spec. calls for 2.5 times FKA.

Fix this and make sure we detect missed keep-alives promptly.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Joe Eykholt authored and James Bottomley committed Jul 27, 2010
1 parent f8fc6c2 commit 8690cb8
Showing 1 changed file with 42 additions and 34 deletions.
76 changes: 42 additions & 34 deletions drivers/scsi/fcoe/libfcoe.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,38 +557,44 @@ EXPORT_SYMBOL(fcoe_ctlr_els_send);
*
* Called with lock held and preemption disabled.
*
* An FCF is considered old if we have missed three advertisements.
* That is, there have been no valid advertisement from it for three
* times its keep-alive period including fuzz.
* An FCF is considered old if we have missed two advertisements.
* That is, there have been no valid advertisement from it for 2.5
* times its keep-alive period.
*
* In addition, determine the time when an FCF selection can occur.
*
* Also, increment the MissDiscAdvCount when no advertisement is received
* for the corresponding FCF for 1.5 * FKA_ADV_PERIOD (FC-BB-5 LESB).
*
* Returns the time in jiffies for the next call.
*/
static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
{
struct fcoe_fcf *fcf;
struct fcoe_fcf *next;
unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
unsigned long deadline;
unsigned long sel_time = 0;
unsigned long mda_time = 0;
struct fcoe_dev_stats *stats;

list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
mda_time = fcf->fka_period + (fcf->fka_period >> 1);
if ((fip->sel_fcf == fcf) &&
(time_after(jiffies, fcf->time + mda_time))) {
mod_timer(&fip->timer, jiffies + mda_time);
stats = per_cpu_ptr(fip->lp->dev_stats,
smp_processor_id());
stats->MissDiscAdvCount++;
printk(KERN_INFO "libfcoe: host%d: Missing Discovery "
"Advertisement for fab %16.16llx count %lld\n",
fip->lp->host->host_no, fcf->fabric_name,
stats->MissDiscAdvCount);
deadline = fcf->time + fcf->fka_period + fcf->fka_period / 2;
if (fip->sel_fcf == fcf) {
if (time_after(jiffies, deadline)) {
stats = per_cpu_ptr(fip->lp->dev_stats,
smp_processor_id());
stats->MissDiscAdvCount++;
printk(KERN_INFO "libfcoe: host%d: "
"Missing Discovery Advertisement "
"for fab %16.16llx count %lld\n",
fip->lp->host->host_no, fcf->fabric_name,
stats->MissDiscAdvCount);
} else if (time_after(next_timer, deadline))
next_timer = deadline;
}
if (time_after(jiffies, fcf->time + fcf->fka_period * 3 +
msecs_to_jiffies(FIP_FCF_FUZZ * 3))) {

deadline += fcf->fka_period;
if (time_after(jiffies, deadline)) {
if (fip->sel_fcf == fcf)
fip->sel_fcf = NULL;
list_del(&fcf->list);
Expand All @@ -598,19 +604,21 @@ static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
stats = per_cpu_ptr(fip->lp->dev_stats,
smp_processor_id());
stats->VLinkFailureCount++;
} else if (fcoe_ctlr_mtu_valid(fcf) &&
(!sel_time || time_before(sel_time, fcf->time))) {
sel_time = fcf->time;
} else {
if (time_after(next_timer, deadline))
next_timer = deadline;
if (fcoe_ctlr_mtu_valid(fcf) &&
(!sel_time || time_before(sel_time, fcf->time)))
sel_time = fcf->time;
}
}
if (sel_time) {
sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY);
fip->sel_time = sel_time;
if (time_before(sel_time, fip->timer.expires))
mod_timer(&fip->timer, sel_time);
} else {
fip->sel_time = 0;
}
return next_timer;
}

/**
Expand Down Expand Up @@ -1148,7 +1156,7 @@ static void fcoe_ctlr_timeout(unsigned long arg)
struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg;
struct fcoe_fcf *sel;
struct fcoe_fcf *fcf;
unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
unsigned long next_timer;

spin_lock_bh(&fip->lock);
if (fip->state == FIP_ST_DISABLED) {
Expand All @@ -1157,13 +1165,16 @@ static void fcoe_ctlr_timeout(unsigned long arg)
}

fcf = fip->sel_fcf;
fcoe_ctlr_age_fcfs(fip);
next_timer = fcoe_ctlr_age_fcfs(fip);

sel = fip->sel_fcf;
if (!sel && fip->sel_time && time_after_eq(jiffies, fip->sel_time)) {
fcoe_ctlr_select(fip);
sel = fip->sel_fcf;
fip->sel_time = 0;
if (!sel && fip->sel_time) {
if (time_after_eq(jiffies, fip->sel_time)) {
fcoe_ctlr_select(fip);
sel = fip->sel_fcf;
fip->sel_time = 0;
} else if (time_after(next_timer, fip->sel_time))
next_timer = fip->sel_time;
}

if (sel != fcf) {
Expand Down Expand Up @@ -1201,12 +1212,9 @@ static void fcoe_ctlr_timeout(unsigned long arg)
}
if (time_after(next_timer, fip->port_ka_time))
next_timer = fip->port_ka_time;
mod_timer(&fip->timer, next_timer);
} else if (fip->sel_time) {
next_timer = fip->sel_time +
msecs_to_jiffies(FCOE_CTLR_START_DELAY);
mod_timer(&fip->timer, next_timer);
}
if (!list_empty(&fip->fcfs))
mod_timer(&fip->timer, next_timer);
if (fip->send_ctlr_ka || fip->send_port_ka)
schedule_work(&fip->timer_work);
spin_unlock_bh(&fip->lock);
Expand Down

0 comments on commit 8690cb8

Please sign in to comment.