Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libfc: Reduce exchange lock contention in fc_exch_recv_abts()

Reduce the time during which the exchange lock is held by allocating
a frame before obtaining the exchange lock.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>

authored by

Bart Van Assche and committed by
Robert Love
f95b35cf cae7b6dd

+10 -8
+10 -8
drivers/scsi/libfc/fc_exch.c
··· 1307 1307 1308 1308 if (!ep) 1309 1309 goto reject; 1310 + 1311 + fp = fc_frame_alloc(ep->lp, sizeof(*ap)); 1312 + if (!fp) 1313 + goto free; 1314 + 1310 1315 spin_lock_bh(&ep->ex_lock); 1311 1316 if (ep->esb_stat & ESB_ST_COMPLETE) { 1312 1317 spin_unlock_bh(&ep->ex_lock); 1318 + 1319 + fc_frame_free(fp); 1313 1320 goto reject; 1314 1321 } 1315 1322 if (!(ep->esb_stat & ESB_ST_REC_QUAL)) { ··· 1324 1317 fc_exch_hold(ep); /* hold for REC_QUAL */ 1325 1318 } 1326 1319 fc_exch_timer_set_locked(ep, ep->r_a_tov); 1327 - 1328 - fp = fc_frame_alloc(ep->lp, sizeof(*ap)); 1329 - if (!fp) { 1330 - spin_unlock_bh(&ep->ex_lock); 1331 - goto free; 1332 - } 1333 1320 fh = fc_frame_header_get(fp); 1334 1321 ap = fc_frame_payload_get(fp, sizeof(*ap)); 1335 1322 memset(ap, 0, sizeof(*ap)); ··· 1339 1338 fc_seq_send_last(sp, fp, FC_RCTL_BA_ACC, FC_TYPE_BLS); 1340 1339 ep->esb_stat |= ESB_ST_ABNORMAL; 1341 1340 spin_unlock_bh(&ep->ex_lock); 1341 + 1342 + free: 1342 1343 fc_frame_free(rx_fp); 1343 1344 return; 1344 1345 1345 1346 reject: 1346 1347 fc_exch_send_ba_rjt(rx_fp, FC_BA_RJT_UNABLE, FC_BA_RJT_INV_XID); 1347 - free: 1348 - fc_frame_free(rx_fp); 1348 + goto free; 1349 1349 } 1350 1350 1351 1351 /**