Skip to content

Commit 794d98e

Browse files
Joe EykholtJames Bottomley
authored andcommitted
[SCSI] libfcoe: retry rejected FLOGI to another FCF if possible
Switches using multiple-FCFs may reject FLOGI in order to balance the load between multiple FCFs. Even though the FCF was available, it may have more load at the point we actually send the FLOGI. If the FLOGI fails, select a different FCF if possible, among those with the same priority. If no other FCF is available, just deliver the reject to libfc for retry. Signed-off-by: Joe Eykholt <[email protected]> Signed-off-by: Robert Love <[email protected]> Signed-off-by: James Bottomley <[email protected]>
1 parent b69ae0a commit 794d98e

File tree

2 files changed

+185
-30
lines changed

2 files changed

+185
-30
lines changed

drivers/scsi/fcoe/libfcoe.c

Lines changed: 177 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ MODULE_LICENSE("GPL v2");
5454
static void fcoe_ctlr_timeout(unsigned long);
5555
static void fcoe_ctlr_timer_work(struct work_struct *);
5656
static void fcoe_ctlr_recv_work(struct work_struct *);
57+
static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *);
58+
static void fcoe_ctlr_select(struct fcoe_ctlr *);
5759

5860
static void fcoe_ctlr_vn_start(struct fcoe_ctlr *);
5961
static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *);
@@ -176,6 +178,7 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode)
176178
fip->mode = mode;
177179
INIT_LIST_HEAD(&fip->fcfs);
178180
mutex_init(&fip->ctlr_mutex);
181+
spin_lock_init(&fip->ctlr_lock);
179182
fip->flogi_oxid = FC_XID_UNKNOWN;
180183
setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip);
181184
INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work);
@@ -231,17 +234,31 @@ void fcoe_ctlr_destroy(struct fcoe_ctlr *fip)
231234
EXPORT_SYMBOL(fcoe_ctlr_destroy);
232235

233236
/**
234-
* fcoe_ctlr_announce() - announce new selection
237+
* fcoe_ctlr_announce() - announce new FCF selection
235238
* @fip: The FCoE controller
236239
*
237240
* Also sets the destination MAC for FCoE and control packets
241+
*
242+
* Called with neither ctlr_mutex nor ctlr_lock held.
238243
*/
239244
static void fcoe_ctlr_announce(struct fcoe_ctlr *fip)
240245
{
241-
struct fcoe_fcf *sel = fip->sel_fcf;
246+
struct fcoe_fcf *sel;
247+
struct fcoe_fcf *fcf;
248+
249+
mutex_lock(&fip->ctlr_mutex);
250+
spin_lock_bh(&fip->ctlr_lock);
251+
252+
kfree_skb(fip->flogi_req);
253+
fip->flogi_req = NULL;
254+
list_for_each_entry(fcf, &fip->fcfs, list)
255+
fcf->flogi_sent = 0;
256+
257+
spin_unlock_bh(&fip->ctlr_lock);
258+
sel = fip->sel_fcf;
242259

243260
if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr))
244-
return;
261+
goto unlock;
245262
if (!is_zero_ether_addr(fip->dest_addr)) {
246263
printk(KERN_NOTICE "libfcoe: host%d: "
247264
"FIP Fibre-Channel Forwarder MAC %pM deselected\n",
@@ -255,6 +272,8 @@ static void fcoe_ctlr_announce(struct fcoe_ctlr *fip)
255272
memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN);
256273
fip->map_dest = 0;
257274
}
275+
unlock:
276+
mutex_unlock(&fip->ctlr_mutex);
258277
}
259278

260279
/**
@@ -591,6 +610,9 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport,
591610
* The caller must check that the length is a multiple of 4.
592611
* The SKB must have enough headroom (28 bytes) and tailroom (8 bytes).
593612
* The the skb must also be an fc_frame.
613+
*
614+
* This is called from the lower-level driver with spinlocks held,
615+
* so we must not take a mutex here.
594616
*/
595617
int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
596618
struct sk_buff *skb)
@@ -628,7 +650,15 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
628650
switch (op) {
629651
case ELS_FLOGI:
630652
op = FIP_DT_FLOGI;
631-
break;
653+
if (fip->mode == FIP_MODE_VN2VN)
654+
break;
655+
spin_lock_bh(&fip->ctlr_lock);
656+
kfree_skb(fip->flogi_req);
657+
fip->flogi_req = skb;
658+
fip->flogi_req_send = 1;
659+
spin_unlock_bh(&fip->ctlr_lock);
660+
schedule_work(&fip->timer_work);
661+
return -EINPROGRESS;
632662
case ELS_FDISC:
633663
if (ntoh24(fh->fh_s_id))
634664
return 0;
@@ -1088,18 +1118,24 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
10881118
els_op = *(u8 *)(fh + 1);
10891119

10901120
if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) &&
1091-
sub == FIP_SC_REP && els_op == ELS_LS_ACC &&
1092-
fip->mode != FIP_MODE_VN2VN) {
1093-
if (!is_valid_ether_addr(granted_mac)) {
1094-
LIBFCOE_FIP_DBG(fip,
1095-
"Invalid MAC address %pM in FIP ELS\n",
1096-
granted_mac);
1097-
goto drop;
1098-
}
1099-
memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN);
1121+
sub == FIP_SC_REP && fip->mode != FIP_MODE_VN2VN) {
1122+
if (els_op == ELS_LS_ACC) {
1123+
if (!is_valid_ether_addr(granted_mac)) {
1124+
LIBFCOE_FIP_DBG(fip,
1125+
"Invalid MAC address %pM in FIP ELS\n",
1126+
granted_mac);
1127+
goto drop;
1128+
}
1129+
memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN);
11001130

1101-
if (fip->flogi_oxid == ntohs(fh->fh_ox_id))
1102-
fip->flogi_oxid = FC_XID_UNKNOWN;
1131+
if (fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
1132+
fip->flogi_oxid = FC_XID_UNKNOWN;
1133+
if (els_dtype == FIP_DT_FLOGI)
1134+
fcoe_ctlr_announce(fip);
1135+
}
1136+
} else if (els_dtype == FIP_DT_FLOGI &&
1137+
!fcoe_ctlr_flogi_retry(fip))
1138+
goto drop; /* retrying FLOGI so drop reject */
11031139
}
11041140

11051141
if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) &&
@@ -1355,12 +1391,15 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb)
13551391
*
13561392
* If there are conflicting advertisements, no FCF can be chosen.
13571393
*
1394+
* If there is already a selected FCF, this will choose a better one or
1395+
* an equivalent one that hasn't already been sent a FLOGI.
1396+
*
13581397
* Called with lock held.
13591398
*/
13601399
static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
13611400
{
13621401
struct fcoe_fcf *fcf;
1363-
struct fcoe_fcf *best = NULL;
1402+
struct fcoe_fcf *best = fip->sel_fcf;
13641403
struct fcoe_fcf *first;
13651404

13661405
first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list);
@@ -1377,6 +1416,8 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
13771416
"or FC-MAP\n");
13781417
return NULL;
13791418
}
1419+
if (fcf->flogi_sent)
1420+
continue;
13801421
if (!fcoe_ctlr_fcf_usable(fcf)) {
13811422
LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx "
13821423
"map %x %svalid %savailable\n",
@@ -1386,11 +1427,7 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
13861427
"" : "un");
13871428
continue;
13881429
}
1389-
if (!best) {
1390-
best = fcf;
1391-
continue;
1392-
}
1393-
if (fcf->pri < best->pri)
1430+
if (!best || fcf->pri < best->pri || best->flogi_sent)
13941431
best = fcf;
13951432
}
13961433
fip->sel_fcf = best;
@@ -1403,6 +1440,121 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
14031440
}
14041441
}
14051442

1443+
/**
1444+
* fcoe_ctlr_flogi_send_locked() - send FIP-encapsulated FLOGI to current FCF
1445+
* @fip: The FCoE controller
1446+
*
1447+
* Returns non-zero error if it could not be sent.
1448+
*
1449+
* Called with ctlr_mutex and ctlr_lock held.
1450+
* Caller must verify that fip->sel_fcf is not NULL.
1451+
*/
1452+
static int fcoe_ctlr_flogi_send_locked(struct fcoe_ctlr *fip)
1453+
{
1454+
struct sk_buff *skb;
1455+
struct sk_buff *skb_orig;
1456+
struct fc_frame_header *fh;
1457+
int error;
1458+
1459+
skb_orig = fip->flogi_req;
1460+
if (!skb_orig)
1461+
return -EINVAL;
1462+
1463+
/*
1464+
* Clone and send the FLOGI request. If clone fails, use original.
1465+
*/
1466+
skb = skb_clone(skb_orig, GFP_ATOMIC);
1467+
if (!skb) {
1468+
skb = skb_orig;
1469+
fip->flogi_req = NULL;
1470+
}
1471+
fh = (struct fc_frame_header *)skb->data;
1472+
error = fcoe_ctlr_encaps(fip, fip->lp, FIP_DT_FLOGI, skb,
1473+
ntoh24(fh->fh_d_id));
1474+
if (error) {
1475+
kfree_skb(skb);
1476+
return error;
1477+
}
1478+
fip->send(fip, skb);
1479+
fip->sel_fcf->flogi_sent = 1;
1480+
return 0;
1481+
}
1482+
1483+
/**
1484+
* fcoe_ctlr_flogi_retry() - resend FLOGI request to a new FCF if possible
1485+
* @fip: The FCoE controller
1486+
*
1487+
* Returns non-zero error code if there's no FLOGI request to retry or
1488+
* no alternate FCF available.
1489+
*/
1490+
static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
1491+
{
1492+
struct fcoe_fcf *fcf;
1493+
int error;
1494+
1495+
mutex_lock(&fip->ctlr_mutex);
1496+
spin_lock_bh(&fip->ctlr_lock);
1497+
LIBFCOE_FIP_DBG(fip, "re-sending FLOGI - reselect\n");
1498+
fcoe_ctlr_select(fip);
1499+
fcf = fip->sel_fcf;
1500+
if (!fcf || fcf->flogi_sent) {
1501+
kfree_skb(fip->flogi_req);
1502+
fip->flogi_req = NULL;
1503+
error = -ENOENT;
1504+
} else {
1505+
fcoe_ctlr_solicit(fip, NULL);
1506+
error = fcoe_ctlr_flogi_send_locked(fip);
1507+
}
1508+
spin_unlock_bh(&fip->ctlr_lock);
1509+
mutex_unlock(&fip->ctlr_mutex);
1510+
return error;
1511+
}
1512+
1513+
1514+
/**
1515+
* fcoe_ctlr_flogi_send() - Handle sending of FIP FLOGI.
1516+
* @fip: The FCoE controller that timed out
1517+
*
1518+
* Done here because fcoe_ctlr_els_send() can't get mutex.
1519+
*
1520+
* Called with ctlr_mutex held. The caller must not hold ctlr_lock.
1521+
*/
1522+
static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip)
1523+
{
1524+
struct fcoe_fcf *fcf;
1525+
1526+
spin_lock_bh(&fip->ctlr_lock);
1527+
fcf = fip->sel_fcf;
1528+
if (!fcf || !fip->flogi_req_send)
1529+
goto unlock;
1530+
1531+
LIBFCOE_FIP_DBG(fip, "sending FLOGI\n");
1532+
1533+
/*
1534+
* If this FLOGI is being sent due to a timeout retry
1535+
* to the same FCF as before, select a different FCF if possible.
1536+
*/
1537+
if (fcf->flogi_sent) {
1538+
LIBFCOE_FIP_DBG(fip, "sending FLOGI - reselect\n");
1539+
fcoe_ctlr_select(fip);
1540+
fcf = fip->sel_fcf;
1541+
if (!fcf || fcf->flogi_sent) {
1542+
LIBFCOE_FIP_DBG(fip, "sending FLOGI - clearing\n");
1543+
list_for_each_entry(fcf, &fip->fcfs, list)
1544+
fcf->flogi_sent = 0;
1545+
fcoe_ctlr_select(fip);
1546+
fcf = fip->sel_fcf;
1547+
}
1548+
}
1549+
if (fcf) {
1550+
fcoe_ctlr_flogi_send_locked(fip);
1551+
fip->flogi_req_send = 0;
1552+
} else /* XXX */
1553+
LIBFCOE_FIP_DBG(fip, "No FCF selected - defer send\n");
1554+
unlock:
1555+
spin_unlock_bh(&fip->ctlr_lock);
1556+
}
1557+
14061558
/**
14071559
* fcoe_ctlr_timeout() - FIP timeout handler
14081560
* @arg: The FCoE controller that timed out
@@ -1455,15 +1607,10 @@ static void fcoe_ctlr_timer_work(struct work_struct *work)
14551607
next_timer = fip->sel_time;
14561608
}
14571609

1458-
if (sel != fcf) {
1459-
fcf = sel; /* the old FCF may have been freed */
1460-
fcoe_ctlr_announce(fip);
1461-
if (sel) {
1462-
if (time_after(next_timer, fip->ctlr_ka_time))
1463-
next_timer = fip->ctlr_ka_time;
1464-
} else
1465-
reset = 1;
1466-
}
1610+
if (sel && fip->flogi_req_send)
1611+
fcoe_ctlr_flogi_send(fip);
1612+
else if (!sel && fcf)
1613+
reset = 1;
14671614

14681615
if (sel && !sel->fd_flags) {
14691616
if (time_after_eq(jiffies, fip->ctlr_ka_time)) {

include/scsi/libfcoe.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,12 @@ enum fip_state {
9292
* @timer_work: &work_struct for doing keep-alives and resets.
9393
* @recv_work: &work_struct for receiving FIP frames.
9494
* @fip_recv_list: list of received FIP frames.
95+
* @flogi_req: clone of FLOGI request sent
9596
* @rnd_state: state for pseudo-random number generator.
9697
* @port_id: proposed or selected local-port ID.
9798
* @user_mfs: configured maximum FC frame size, including FC header.
9899
* @flogi_oxid: exchange ID of most recent fabric login.
100+
* @flogi_req_send: send of FLOGI requested
99101
* @flogi_count: number of FLOGI attempts in AUTO mode.
100102
* @map_dest: use the FC_MAP mode for destination MAC addresses.
101103
* @spma: supports SPMA server-provided MACs mode
@@ -106,6 +108,7 @@ enum fip_state {
106108
* @update_mac: LLD-supplied function to handle changes to MAC addresses.
107109
* @get_src_addr: LLD-supplied function to supply a source MAC address.
108110
* @ctlr_mutex: lock protecting this structure.
111+
* @ctlr_lock: spinlock covering flogi_req
109112
*
110113
* This structure is used by all FCoE drivers. It contains information
111114
* needed by all FCoE low-level drivers (LLDs) as well as internal state
@@ -126,12 +129,14 @@ struct fcoe_ctlr {
126129
struct work_struct timer_work;
127130
struct work_struct recv_work;
128131
struct sk_buff_head fip_recv_list;
132+
struct sk_buff *flogi_req;
129133

130134
struct rnd_state rnd_state;
131135
u32 port_id;
132136

133137
u16 user_mfs;
134138
u16 flogi_oxid;
139+
u8 flogi_req_send;
135140
u8 flogi_count;
136141
u8 map_dest;
137142
u8 spma;
@@ -143,6 +148,7 @@ struct fcoe_ctlr {
143148
void (*update_mac)(struct fc_lport *, u8 *addr);
144149
u8 * (*get_src_addr)(struct fc_lport *);
145150
struct mutex ctlr_mutex;
151+
spinlock_t ctlr_lock;
146152
};
147153

148154
/**
@@ -155,6 +161,7 @@ struct fcoe_ctlr {
155161
* @fcf_mac: Ethernet address of the FCF
156162
* @vfid: virtual fabric ID
157163
* @pri: selection priority, smaller values are better
164+
* @flogi_sent: current FLOGI sent to this FCF
158165
* @flags: flags received from advertisement
159166
* @fka_period: keep-alive period, in jiffies
160167
*
@@ -176,6 +183,7 @@ struct fcoe_fcf {
176183
u8 fcf_mac[ETH_ALEN];
177184

178185
u8 pri;
186+
u8 flogi_sent;
179187
u16 flags;
180188
u32 fka_period;
181189
u8 fd_flags:1;

0 commit comments

Comments
 (0)