@@ -381,6 +381,8 @@ static void fc_exch_timer_set(struct fc_exch *ep, unsigned int timer_msec)
381
381
/**
382
382
* fc_exch_done_locked() - Complete an exchange with the exchange lock held
383
383
* @ep: The exchange that is complete
384
+ *
385
+ * Note: May sleep if invoked from outside a response handler.
384
386
*/
385
387
static int fc_exch_done_locked (struct fc_exch * ep )
386
388
{
@@ -392,7 +394,6 @@ static int fc_exch_done_locked(struct fc_exch *ep)
392
394
* ep, and in that case we only clear the resp and set it as
393
395
* complete, so it can be reused by the timer to send the rrq.
394
396
*/
395
- ep -> resp = NULL ;
396
397
if (ep -> state & FC_EX_DONE )
397
398
return rc ;
398
399
ep -> esb_stat |= ESB_ST_COMPLETE ;
@@ -589,15 +590,27 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp)
589
590
590
591
/*
591
592
* Set the response handler for the exchange associated with a sequence.
593
+ *
594
+ * Note: May sleep if invoked from outside a response handler.
592
595
*/
593
596
static void fc_seq_set_resp (struct fc_seq * sp ,
594
597
void (* resp )(struct fc_seq * , struct fc_frame * ,
595
598
void * ),
596
599
void * arg )
597
600
{
598
601
struct fc_exch * ep = fc_seq_exch (sp );
602
+ DEFINE_WAIT (wait );
599
603
600
604
spin_lock_bh (& ep -> ex_lock );
605
+ while (ep -> resp_active && ep -> resp_task != current ) {
606
+ prepare_to_wait (& ep -> resp_wq , & wait , TASK_UNINTERRUPTIBLE );
607
+ spin_unlock_bh (& ep -> ex_lock );
608
+
609
+ schedule ();
610
+
611
+ spin_lock_bh (& ep -> ex_lock );
612
+ }
613
+ finish_wait (& ep -> resp_wq , & wait );
601
614
ep -> resp = resp ;
602
615
ep -> arg = arg ;
603
616
spin_unlock_bh (& ep -> ex_lock );
@@ -680,6 +693,61 @@ static int fc_seq_exch_abort(const struct fc_seq *req_sp,
680
693
return error ;
681
694
}
682
695
696
+ /**
697
+ * fc_invoke_resp() - invoke ep->resp()
698
+ *
699
+ * Notes:
700
+ * It is assumed that after initialization finished (this means the
701
+ * first unlock of ex_lock after fc_exch_alloc()) ep->resp and ep->arg are
702
+ * modified only via fc_seq_set_resp(). This guarantees that none of these
703
+ * two variables changes if ep->resp_active > 0.
704
+ *
705
+ * If an fc_seq_set_resp() call is busy modifying ep->resp and ep->arg when
706
+ * this function is invoked, the first spin_lock_bh() call in this function
707
+ * will wait until fc_seq_set_resp() has finished modifying these variables.
708
+ *
709
+ * Since fc_exch_done() invokes fc_seq_set_resp() it is guaranteed that that
710
+ * ep->resp() won't be invoked after fc_exch_done() has returned.
711
+ *
712
+ * The response handler itself may invoke fc_exch_done(), which will clear the
713
+ * ep->resp pointer.
714
+ *
715
+ * Return value:
716
+ * Returns true if and only if ep->resp has been invoked.
717
+ */
718
+ static bool fc_invoke_resp (struct fc_exch * ep , struct fc_seq * sp ,
719
+ struct fc_frame * fp )
720
+ {
721
+ void (* resp )(struct fc_seq * , struct fc_frame * fp , void * arg );
722
+ void * arg ;
723
+ bool res = false;
724
+
725
+ spin_lock_bh (& ep -> ex_lock );
726
+ ep -> resp_active ++ ;
727
+ if (ep -> resp_task != current )
728
+ ep -> resp_task = !ep -> resp_task ? current : NULL ;
729
+ resp = ep -> resp ;
730
+ arg = ep -> arg ;
731
+ spin_unlock_bh (& ep -> ex_lock );
732
+
733
+ if (resp ) {
734
+ resp (sp , fp , arg );
735
+ res = true;
736
+ } else if (!IS_ERR (fp )) {
737
+ fc_frame_free (fp );
738
+ }
739
+
740
+ spin_lock_bh (& ep -> ex_lock );
741
+ if (-- ep -> resp_active == 0 )
742
+ ep -> resp_task = NULL ;
743
+ spin_unlock_bh (& ep -> ex_lock );
744
+
745
+ if (ep -> resp_active == 0 )
746
+ wake_up (& ep -> resp_wq );
747
+
748
+ return res ;
749
+ }
750
+
683
751
/**
684
752
* fc_exch_timeout() - Handle exchange timer expiration
685
753
* @work: The work_struct identifying the exchange that timed out
@@ -689,8 +757,6 @@ static void fc_exch_timeout(struct work_struct *work)
689
757
struct fc_exch * ep = container_of (work , struct fc_exch ,
690
758
timeout_work .work );
691
759
struct fc_seq * sp = & ep -> seq ;
692
- void (* resp )(struct fc_seq * , struct fc_frame * fp , void * arg );
693
- void * arg ;
694
760
u32 e_stat ;
695
761
int rc = 1 ;
696
762
@@ -708,16 +774,13 @@ static void fc_exch_timeout(struct work_struct *work)
708
774
fc_exch_rrq (ep );
709
775
goto done ;
710
776
} else {
711
- resp = ep -> resp ;
712
- arg = ep -> arg ;
713
- ep -> resp = NULL ;
714
777
if (e_stat & ESB_ST_ABNORMAL )
715
778
rc = fc_exch_done_locked (ep );
716
779
spin_unlock_bh (& ep -> ex_lock );
717
780
if (!rc )
718
781
fc_exch_delete (ep );
719
- if ( resp )
720
- resp (sp , ERR_PTR ( - FC_EX_TIMEOUT ), arg );
782
+ fc_invoke_resp ( ep , sp , ERR_PTR ( - FC_EX_TIMEOUT ));
783
+ fc_seq_set_resp (sp , NULL , ep -> arg );
721
784
fc_seq_exch_abort (sp , 2 * ep -> r_a_tov );
722
785
goto done ;
723
786
}
@@ -804,6 +867,8 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
804
867
ep -> f_ctl = FC_FC_FIRST_SEQ ; /* next seq is first seq */
805
868
ep -> rxid = FC_XID_UNKNOWN ;
806
869
ep -> class = mp -> class ;
870
+ ep -> resp_active = 0 ;
871
+ init_waitqueue_head (& ep -> resp_wq );
807
872
INIT_DELAYED_WORK (& ep -> timeout_work , fc_exch_timeout );
808
873
out :
809
874
return ep ;
@@ -864,6 +929,8 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
864
929
* fc_exch_done() - Indicate that an exchange/sequence tuple is complete and
865
930
* the memory allocated for the related objects may be freed.
866
931
* @sp: The sequence that has completed
932
+ *
933
+ * Note: May sleep if invoked from outside a response handler.
867
934
*/
868
935
static void fc_exch_done (struct fc_seq * sp )
869
936
{
@@ -873,6 +940,8 @@ static void fc_exch_done(struct fc_seq *sp)
873
940
spin_lock_bh (& ep -> ex_lock );
874
941
rc = fc_exch_done_locked (ep );
875
942
spin_unlock_bh (& ep -> ex_lock );
943
+
944
+ fc_seq_set_resp (sp , NULL , ep -> arg );
876
945
if (!rc )
877
946
fc_exch_delete (ep );
878
947
}
@@ -1436,9 +1505,7 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp,
1436
1505
* If new exch resp handler is valid then call that
1437
1506
* first.
1438
1507
*/
1439
- if (ep -> resp )
1440
- ep -> resp (sp , fp , ep -> arg );
1441
- else
1508
+ if (!fc_invoke_resp (ep , sp , fp ))
1442
1509
lport -> tt .lport_recv (lport , fp );
1443
1510
fc_exch_release (ep ); /* release from lookup */
1444
1511
} else {
@@ -1462,8 +1529,6 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
1462
1529
struct fc_exch * ep ;
1463
1530
enum fc_sof sof ;
1464
1531
u32 f_ctl ;
1465
- void (* resp )(struct fc_seq * , struct fc_frame * fp , void * arg );
1466
- void * ex_resp_arg ;
1467
1532
int rc ;
1468
1533
1469
1534
ep = fc_exch_find (mp , ntohs (fh -> fh_ox_id ));
@@ -1506,14 +1571,11 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
1506
1571
1507
1572
if (fc_sof_needs_ack (sof ))
1508
1573
fc_seq_send_ack (sp , fp );
1509
- resp = ep -> resp ;
1510
- ex_resp_arg = ep -> arg ;
1511
1574
1512
1575
if (fh -> fh_type != FC_TYPE_FCP && fr_eof (fp ) == FC_EOF_T &&
1513
1576
(f_ctl & (FC_FC_LAST_SEQ | FC_FC_END_SEQ )) ==
1514
1577
(FC_FC_LAST_SEQ | FC_FC_END_SEQ )) {
1515
1578
spin_lock_bh (& ep -> ex_lock );
1516
- resp = ep -> resp ;
1517
1579
rc = fc_exch_done_locked (ep );
1518
1580
WARN_ON (fc_seq_exch (sp ) != ep );
1519
1581
spin_unlock_bh (& ep -> ex_lock );
@@ -1534,10 +1596,8 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
1534
1596
* If new exch resp handler is valid then call that
1535
1597
* first.
1536
1598
*/
1537
- if (resp )
1538
- resp (sp , fp , ex_resp_arg );
1539
- else
1540
- fc_frame_free (fp );
1599
+ fc_invoke_resp (ep , sp , fp );
1600
+
1541
1601
fc_exch_release (ep );
1542
1602
return ;
1543
1603
rel :
@@ -1576,8 +1636,6 @@ static void fc_exch_recv_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
1576
1636
*/
1577
1637
static void fc_exch_abts_resp (struct fc_exch * ep , struct fc_frame * fp )
1578
1638
{
1579
- void (* resp )(struct fc_seq * , struct fc_frame * fp , void * arg );
1580
- void * ex_resp_arg ;
1581
1639
struct fc_frame_header * fh ;
1582
1640
struct fc_ba_acc * ap ;
1583
1641
struct fc_seq * sp ;
@@ -1622,9 +1680,6 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
1622
1680
break ;
1623
1681
}
1624
1682
1625
- resp = ep -> resp ;
1626
- ex_resp_arg = ep -> arg ;
1627
-
1628
1683
/* do we need to do some other checks here. Can we reuse more of
1629
1684
* fc_exch_recv_seq_resp
1630
1685
*/
@@ -1636,17 +1691,14 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
1636
1691
ntoh24 (fh -> fh_f_ctl ) & FC_FC_LAST_SEQ )
1637
1692
rc = fc_exch_done_locked (ep );
1638
1693
spin_unlock_bh (& ep -> ex_lock );
1694
+
1695
+ fc_exch_hold (ep );
1639
1696
if (!rc )
1640
1697
fc_exch_delete (ep );
1641
-
1642
- if (resp )
1643
- resp (sp , fp , ex_resp_arg );
1644
- else
1645
- fc_frame_free (fp );
1646
-
1698
+ fc_invoke_resp (ep , sp , fp );
1647
1699
if (has_rec )
1648
1700
fc_exch_timer_set (ep , ep -> r_a_tov );
1649
-
1701
+ fc_exch_release ( ep );
1650
1702
}
1651
1703
1652
1704
/**
@@ -1768,32 +1820,33 @@ static void fc_seq_ls_rjt(struct fc_frame *rx_fp, enum fc_els_rjt_reason reason,
1768
1820
/**
1769
1821
* fc_exch_reset() - Reset an exchange
1770
1822
* @ep: The exchange to be reset
1823
+ *
1824
+ * Note: May sleep if invoked from outside a response handler.
1771
1825
*/
1772
1826
static void fc_exch_reset (struct fc_exch * ep )
1773
1827
{
1774
1828
struct fc_seq * sp ;
1775
- void (* resp )(struct fc_seq * , struct fc_frame * , void * );
1776
- void * arg ;
1777
1829
int rc = 1 ;
1778
1830
1779
1831
spin_lock_bh (& ep -> ex_lock );
1780
1832
fc_exch_abort_locked (ep , 0 );
1781
1833
ep -> state |= FC_EX_RST_CLEANUP ;
1782
1834
fc_exch_timer_cancel (ep );
1783
- resp = ep -> resp ;
1784
- ep -> resp = NULL ;
1785
1835
if (ep -> esb_stat & ESB_ST_REC_QUAL )
1786
1836
atomic_dec (& ep -> ex_refcnt ); /* drop hold for rec_qual */
1787
1837
ep -> esb_stat &= ~ESB_ST_REC_QUAL ;
1788
- arg = ep -> arg ;
1789
1838
sp = & ep -> seq ;
1790
1839
rc = fc_exch_done_locked (ep );
1791
1840
spin_unlock_bh (& ep -> ex_lock );
1841
+
1842
+ fc_exch_hold (ep );
1843
+
1792
1844
if (!rc )
1793
1845
fc_exch_delete (ep );
1794
1846
1795
- if (resp )
1796
- resp (sp , ERR_PTR (- FC_EX_CLOSED ), arg );
1847
+ fc_invoke_resp (ep , sp , ERR_PTR (- FC_EX_CLOSED ));
1848
+ fc_seq_set_resp (sp , NULL , ep -> arg );
1849
+ fc_exch_release (ep );
1797
1850
}
1798
1851
1799
1852
/**
0 commit comments