aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc
diff options
context:
space:
mode:
authorBart Van Assche <bvanassche@acm.org>2013-08-17 16:34:43 -0400
committerRobert Love <robert.w.love@intel.com>2013-09-04 16:45:22 -0400
commit7030fd626129ec4d616784516a462d317c251d39 (patch)
treecd9a65fa2d45e6397ba1620846dc4c9359638df4 /drivers/scsi/libfc
parentf95b35cfcacadac16dbc5477fd22b0786256a3d1 (diff)
libfc: Do not invoke the response handler after fc_exch_done()
While the FCoE initiator driver invokes fc_exch_done() from inside the libfc response handler, FCoE target drivers typically invoke fc_exch_done() from outside the libfc response handler. The object fc_exch.arg points at may disappear as soon as fc_exch_done() has finished. So it's important not to invoke the response handler function after fc_exch_done() has finished. Modify libfc such that this guarantee is provided if fc_exch_done() is invoked from outside a response handler. This patch fixes a sporadic crash in FCoE target implementations after a command has been aborted. 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>
Diffstat (limited to 'drivers/scsi/libfc')
-rw-r--r--drivers/scsi/libfc/fc_exch.c131
1 files changed, 92 insertions, 39 deletions
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 47ebc7b1e143..1b3a09473452 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -381,6 +381,8 @@ static void fc_exch_timer_set(struct fc_exch *ep, unsigned int timer_msec)
381/** 381/**
382 * fc_exch_done_locked() - Complete an exchange with the exchange lock held 382 * fc_exch_done_locked() - Complete an exchange with the exchange lock held
383 * @ep: The exchange that is complete 383 * @ep: The exchange that is complete
384 *
385 * Note: May sleep if invoked from outside a response handler.
384 */ 386 */
385static int fc_exch_done_locked(struct fc_exch *ep) 387static 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 * ep, and in that case we only clear the resp and set it as 394 * ep, and in that case we only clear the resp and set it as
393 * complete, so it can be reused by the timer to send the rrq. 395 * complete, so it can be reused by the timer to send the rrq.
394 */ 396 */
395 ep->resp = NULL;
396 if (ep->state & FC_EX_DONE) 397 if (ep->state & FC_EX_DONE)
397 return rc; 398 return rc;
398 ep->esb_stat |= ESB_ST_COMPLETE; 399 ep->esb_stat |= ESB_ST_COMPLETE;
@@ -589,6 +590,8 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp)
589 590
590/* 591/*
591 * Set the response handler for the exchange associated with a sequence. 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 */
593static void fc_seq_set_resp(struct fc_seq *sp, 596static void fc_seq_set_resp(struct fc_seq *sp,
594 void (*resp)(struct fc_seq *, struct fc_frame *, 597 void (*resp)(struct fc_seq *, struct fc_frame *,
@@ -596,8 +599,18 @@ static void fc_seq_set_resp(struct fc_seq *sp,
596 void *arg) 599 void *arg)
597{ 600{
598 struct fc_exch *ep = fc_seq_exch(sp); 601 struct fc_exch *ep = fc_seq_exch(sp);
602 DEFINE_WAIT(wait);
599 603
600 spin_lock_bh(&ep->ex_lock); 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 ep->resp = resp; 614 ep->resp = resp;
602 ep->arg = arg; 615 ep->arg = arg;
603 spin_unlock_bh(&ep->ex_lock); 616 spin_unlock_bh(&ep->ex_lock);
@@ -681,6 +694,61 @@ static int fc_seq_exch_abort(const struct fc_seq *req_sp,
681} 694}
682 695
683/** 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 */
718static 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
751/**
684 * fc_exch_timeout() - Handle exchange timer expiration 752 * fc_exch_timeout() - Handle exchange timer expiration
685 * @work: The work_struct identifying the exchange that timed out 753 * @work: The work_struct identifying the exchange that timed out
686 */ 754 */
@@ -689,8 +757,6 @@ static void fc_exch_timeout(struct work_struct *work)
689 struct fc_exch *ep = container_of(work, struct fc_exch, 757 struct fc_exch *ep = container_of(work, struct fc_exch,
690 timeout_work.work); 758 timeout_work.work);
691 struct fc_seq *sp = &ep->seq; 759 struct fc_seq *sp = &ep->seq;
692 void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg);
693 void *arg;
694 u32 e_stat; 760 u32 e_stat;
695 int rc = 1; 761 int rc = 1;
696 762
@@ -708,16 +774,13 @@ static void fc_exch_timeout(struct work_struct *work)
708 fc_exch_rrq(ep); 774 fc_exch_rrq(ep);
709 goto done; 775 goto done;
710 } else { 776 } else {
711 resp = ep->resp;
712 arg = ep->arg;
713 ep->resp = NULL;
714 if (e_stat & ESB_ST_ABNORMAL) 777 if (e_stat & ESB_ST_ABNORMAL)
715 rc = fc_exch_done_locked(ep); 778 rc = fc_exch_done_locked(ep);
716 spin_unlock_bh(&ep->ex_lock); 779 spin_unlock_bh(&ep->ex_lock);
717 if (!rc) 780 if (!rc)
718 fc_exch_delete(ep); 781 fc_exch_delete(ep);
719 if (resp) 782 fc_invoke_resp(ep, sp, ERR_PTR(-FC_EX_TIMEOUT));
720 resp(sp, ERR_PTR(-FC_EX_TIMEOUT), arg); 783 fc_seq_set_resp(sp, NULL, ep->arg);
721 fc_seq_exch_abort(sp, 2 * ep->r_a_tov); 784 fc_seq_exch_abort(sp, 2 * ep->r_a_tov);
722 goto done; 785 goto done;
723 } 786 }
@@ -804,6 +867,8 @@ hit:
804 ep->f_ctl = FC_FC_FIRST_SEQ; /* next seq is first seq */ 867 ep->f_ctl = FC_FC_FIRST_SEQ; /* next seq is first seq */
805 ep->rxid = FC_XID_UNKNOWN; 868 ep->rxid = FC_XID_UNKNOWN;
806 ep->class = mp->class; 869 ep->class = mp->class;
870 ep->resp_active = 0;
871 init_waitqueue_head(&ep->resp_wq);
807 INIT_DELAYED_WORK(&ep->timeout_work, fc_exch_timeout); 872 INIT_DELAYED_WORK(&ep->timeout_work, fc_exch_timeout);
808out: 873out:
809 return ep; 874 return ep;
@@ -864,6 +929,8 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
864 * fc_exch_done() - Indicate that an exchange/sequence tuple is complete and 929 * fc_exch_done() - Indicate that an exchange/sequence tuple is complete and
865 * the memory allocated for the related objects may be freed. 930 * the memory allocated for the related objects may be freed.
866 * @sp: The sequence that has completed 931 * @sp: The sequence that has completed
932 *
933 * Note: May sleep if invoked from outside a response handler.
867 */ 934 */
868static void fc_exch_done(struct fc_seq *sp) 935static void fc_exch_done(struct fc_seq *sp)
869{ 936{
@@ -873,6 +940,8 @@ static void fc_exch_done(struct fc_seq *sp)
873 spin_lock_bh(&ep->ex_lock); 940 spin_lock_bh(&ep->ex_lock);
874 rc = fc_exch_done_locked(ep); 941 rc = fc_exch_done_locked(ep);
875 spin_unlock_bh(&ep->ex_lock); 942 spin_unlock_bh(&ep->ex_lock);
943
944 fc_seq_set_resp(sp, NULL, ep->arg);
876 if (!rc) 945 if (!rc)
877 fc_exch_delete(ep); 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 * If new exch resp handler is valid then call that 1505 * If new exch resp handler is valid then call that
1437 * first. 1506 * first.
1438 */ 1507 */
1439 if (ep->resp) 1508 if (!fc_invoke_resp(ep, sp, fp))
1440 ep->resp(sp, fp, ep->arg);
1441 else
1442 lport->tt.lport_recv(lport, fp); 1509 lport->tt.lport_recv(lport, fp);
1443 fc_exch_release(ep); /* release from lookup */ 1510 fc_exch_release(ep); /* release from lookup */
1444 } else { 1511 } else {
@@ -1462,8 +1529,6 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
1462 struct fc_exch *ep; 1529 struct fc_exch *ep;
1463 enum fc_sof sof; 1530 enum fc_sof sof;
1464 u32 f_ctl; 1531 u32 f_ctl;
1465 void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg);
1466 void *ex_resp_arg;
1467 int rc; 1532 int rc;
1468 1533
1469 ep = fc_exch_find(mp, ntohs(fh->fh_ox_id)); 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 if (fc_sof_needs_ack(sof)) 1572 if (fc_sof_needs_ack(sof))
1508 fc_seq_send_ack(sp, fp); 1573 fc_seq_send_ack(sp, fp);
1509 resp = ep->resp;
1510 ex_resp_arg = ep->arg;
1511 1574
1512 if (fh->fh_type != FC_TYPE_FCP && fr_eof(fp) == FC_EOF_T && 1575 if (fh->fh_type != FC_TYPE_FCP && fr_eof(fp) == FC_EOF_T &&
1513 (f_ctl & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) == 1576 (f_ctl & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) ==
1514 (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) { 1577 (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) {
1515 spin_lock_bh(&ep->ex_lock); 1578 spin_lock_bh(&ep->ex_lock);
1516 resp = ep->resp;
1517 rc = fc_exch_done_locked(ep); 1579 rc = fc_exch_done_locked(ep);
1518 WARN_ON(fc_seq_exch(sp) != ep); 1580 WARN_ON(fc_seq_exch(sp) != ep);
1519 spin_unlock_bh(&ep->ex_lock); 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 * If new exch resp handler is valid then call that 1596 * If new exch resp handler is valid then call that
1535 * first. 1597 * first.
1536 */ 1598 */
1537 if (resp) 1599 fc_invoke_resp(ep, sp, fp);
1538 resp(sp, fp, ex_resp_arg); 1600
1539 else
1540 fc_frame_free(fp);
1541 fc_exch_release(ep); 1601 fc_exch_release(ep);
1542 return; 1602 return;
1543rel: 1603rel:
@@ -1576,8 +1636,6 @@ static void fc_exch_recv_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
1576 */ 1636 */
1577static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) 1637static 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 struct fc_frame_header *fh; 1639 struct fc_frame_header *fh;
1582 struct fc_ba_acc *ap; 1640 struct fc_ba_acc *ap;
1583 struct fc_seq *sp; 1641 struct fc_seq *sp;
@@ -1622,9 +1680,6 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
1622 break; 1680 break;
1623 } 1681 }
1624 1682
1625 resp = ep->resp;
1626 ex_resp_arg = ep->arg;
1627
1628 /* do we need to do some other checks here. Can we reuse more of 1683 /* do we need to do some other checks here. Can we reuse more of
1629 * fc_exch_recv_seq_resp 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 ntoh24(fh->fh_f_ctl) & FC_FC_LAST_SEQ) 1691 ntoh24(fh->fh_f_ctl) & FC_FC_LAST_SEQ)
1637 rc = fc_exch_done_locked(ep); 1692 rc = fc_exch_done_locked(ep);
1638 spin_unlock_bh(&ep->ex_lock); 1693 spin_unlock_bh(&ep->ex_lock);
1694
1695 fc_exch_hold(ep);
1639 if (!rc) 1696 if (!rc)
1640 fc_exch_delete(ep); 1697 fc_exch_delete(ep);
1641 1698 fc_invoke_resp(ep, sp, fp);
1642 if (resp)
1643 resp(sp, fp, ex_resp_arg);
1644 else
1645 fc_frame_free(fp);
1646
1647 if (has_rec) 1699 if (has_rec)
1648 fc_exch_timer_set(ep, ep->r_a_tov); 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 * fc_exch_reset() - Reset an exchange 1821 * fc_exch_reset() - Reset an exchange
1770 * @ep: The exchange to be reset 1822 * @ep: The exchange to be reset
1823 *
1824 * Note: May sleep if invoked from outside a response handler.
1771 */ 1825 */
1772static void fc_exch_reset(struct fc_exch *ep) 1826static void fc_exch_reset(struct fc_exch *ep)
1773{ 1827{
1774 struct fc_seq *sp; 1828 struct fc_seq *sp;
1775 void (*resp)(struct fc_seq *, struct fc_frame *, void *);
1776 void *arg;
1777 int rc = 1; 1829 int rc = 1;
1778 1830
1779 spin_lock_bh(&ep->ex_lock); 1831 spin_lock_bh(&ep->ex_lock);
1780 fc_exch_abort_locked(ep, 0); 1832 fc_exch_abort_locked(ep, 0);
1781 ep->state |= FC_EX_RST_CLEANUP; 1833 ep->state |= FC_EX_RST_CLEANUP;
1782 fc_exch_timer_cancel(ep); 1834 fc_exch_timer_cancel(ep);
1783 resp = ep->resp;
1784 ep->resp = NULL;
1785 if (ep->esb_stat & ESB_ST_REC_QUAL) 1835 if (ep->esb_stat & ESB_ST_REC_QUAL)
1786 atomic_dec(&ep->ex_refcnt); /* drop hold for rec_qual */ 1836 atomic_dec(&ep->ex_refcnt); /* drop hold for rec_qual */
1787 ep->esb_stat &= ~ESB_ST_REC_QUAL; 1837 ep->esb_stat &= ~ESB_ST_REC_QUAL;
1788 arg = ep->arg;
1789 sp = &ep->seq; 1838 sp = &ep->seq;
1790 rc = fc_exch_done_locked(ep); 1839 rc = fc_exch_done_locked(ep);
1791 spin_unlock_bh(&ep->ex_lock); 1840 spin_unlock_bh(&ep->ex_lock);
1841
1842 fc_exch_hold(ep);
1843
1792 if (!rc) 1844 if (!rc)
1793 fc_exch_delete(ep); 1845 fc_exch_delete(ep);
1794 1846
1795 if (resp) 1847 fc_invoke_resp(ep, sp, ERR_PTR(-FC_EX_CLOSED));
1796 resp(sp, ERR_PTR(-FC_EX_CLOSED), arg); 1848 fc_seq_set_resp(sp, NULL, ep->arg);
1849 fc_exch_release(ep);
1797} 1850}
1798 1851
1799/** 1852/**