aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2006-08-18 17:33:29 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-09-04 22:22:05 -0400
commit0f29b966d60e9a4f5ecff9f3832257b38aea4f13 (patch)
tree0b14cbcdf74aee4676c49353f816ae5f98c504ee
parentae36764a230ff6a278ed93735acf5fcda08f2786 (diff)
[SCSI] FC transport: Add dev_loss_tmo callbacks, and new fast_io_fail_tmo w/ callback
This patch adds the following functionality to the FC transport: - dev_loss_tmo LLDD callback : Called to essentially confirm the deletion of an rport. Thus, it is called whenever the dev_loss_tmo fires, or when the rport is deleted due to other circumstances (module unload, etc). It is expected that the callback will initiate the termination of any outstanding i/o on the rport. - fast_io_fail_tmo and LLD callback: There are some cases where it may take a long while to truly determine device loss, but the system is in a multipathing configuration that if the i/o was failed quickly (faster than dev_loss_tmo), it could be redirected to a different path and completed sooner. Many thanks to Mike Reed who cleaned up the initial RFC in support of this post. The original RFC is at: http://marc.theaimsgroup.com/?l=linux-scsi&m=115505981027246&w=2 Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/scsi_transport_fc.c134
-rw-r--r--include/scsi/scsi_transport_fc.h5
2 files changed, 128 insertions, 11 deletions
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 293188cbff8c..4ab176ed480d 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -242,6 +242,7 @@ fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
242 242
243 243
244static void fc_timeout_deleted_rport(void *data); 244static void fc_timeout_deleted_rport(void *data);
245static void fc_timeout_fail_rport_io(void *data);
245static void fc_scsi_scan_rport(void *data); 246static void fc_scsi_scan_rport(void *data);
246 247
247/* 248/*
@@ -249,7 +250,7 @@ static void fc_scsi_scan_rport(void *data);
249 * Increase these values if you add attributes 250 * Increase these values if you add attributes
250 */ 251 */
251#define FC_STARGET_NUM_ATTRS 3 252#define FC_STARGET_NUM_ATTRS 3
252#define FC_RPORT_NUM_ATTRS 9 253#define FC_RPORT_NUM_ATTRS 10
253#define FC_HOST_NUM_ATTRS 17 254#define FC_HOST_NUM_ATTRS 17
254 255
255struct fc_internal { 256struct fc_internal {
@@ -622,11 +623,14 @@ store_fc_rport_##field(struct class_device *cdev, const char *buf, \
622 struct fc_rport *rport = transport_class_to_rport(cdev); \ 623 struct fc_rport *rport = transport_class_to_rport(cdev); \
623 struct Scsi_Host *shost = rport_to_shost(rport); \ 624 struct Scsi_Host *shost = rport_to_shost(rport); \
624 struct fc_internal *i = to_fc_internal(shost->transportt); \ 625 struct fc_internal *i = to_fc_internal(shost->transportt); \
626 char *cp; \
625 if ((rport->port_state == FC_PORTSTATE_BLOCKED) || \ 627 if ((rport->port_state == FC_PORTSTATE_BLOCKED) || \
626 (rport->port_state == FC_PORTSTATE_DELETED) || \ 628 (rport->port_state == FC_PORTSTATE_DELETED) || \
627 (rport->port_state == FC_PORTSTATE_NOTPRESENT)) \ 629 (rport->port_state == FC_PORTSTATE_NOTPRESENT)) \
628 return -EBUSY; \ 630 return -EBUSY; \
629 val = simple_strtoul(buf, NULL, 0); \ 631 val = simple_strtoul(buf, &cp, 0); \
632 if (*cp && (*cp != '\n')) \
633 return -EINVAL; \
630 i->f->set_rport_##field(rport, val); \ 634 i->f->set_rport_##field(rport, val); \
631 return count; \ 635 return count; \
632} 636}
@@ -708,6 +712,13 @@ static FC_CLASS_DEVICE_ATTR(rport, title, S_IRUGO, \
708 if (i->f->show_rport_##field) \ 712 if (i->f->show_rport_##field) \
709 count++ 713 count++
710 714
715#define SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(field) \
716{ \
717 i->private_rport_attrs[count] = class_device_attr_rport_##field; \
718 i->rport_attrs[count] = &i->private_rport_attrs[count]; \
719 count++; \
720}
721
711 722
712/* The FC Transport Remote Port Attributes: */ 723/* The FC Transport Remote Port Attributes: */
713 724
@@ -740,12 +751,14 @@ store_fc_rport_dev_loss_tmo(struct class_device *cdev, const char *buf,
740 struct fc_rport *rport = transport_class_to_rport(cdev); 751 struct fc_rport *rport = transport_class_to_rport(cdev);
741 struct Scsi_Host *shost = rport_to_shost(rport); 752 struct Scsi_Host *shost = rport_to_shost(rport);
742 struct fc_internal *i = to_fc_internal(shost->transportt); 753 struct fc_internal *i = to_fc_internal(shost->transportt);
754 char *cp;
743 if ((rport->port_state == FC_PORTSTATE_BLOCKED) || 755 if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
744 (rport->port_state == FC_PORTSTATE_DELETED) || 756 (rport->port_state == FC_PORTSTATE_DELETED) ||
745 (rport->port_state == FC_PORTSTATE_NOTPRESENT)) 757 (rport->port_state == FC_PORTSTATE_NOTPRESENT))
746 return -EBUSY; 758 return -EBUSY;
747 val = simple_strtoul(buf, NULL, 0); 759 val = simple_strtoul(buf, &cp, 0);
748 if ((val < 0) || (val > SCSI_DEVICE_BLOCK_MAX_TIMEOUT)) 760 if ((*cp && (*cp != '\n')) ||
761 (val < 0) || (val > SCSI_DEVICE_BLOCK_MAX_TIMEOUT))
749 return -EINVAL; 762 return -EINVAL;
750 i->f->set_rport_dev_loss_tmo(rport, val); 763 i->f->set_rport_dev_loss_tmo(rport, val);
751 return count; 764 return count;
@@ -795,6 +808,44 @@ static FC_CLASS_DEVICE_ATTR(rport, roles, S_IRUGO,
795fc_private_rport_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN); 808fc_private_rport_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN);
796fc_private_rport_rd_attr(scsi_target_id, "%d\n", 20); 809fc_private_rport_rd_attr(scsi_target_id, "%d\n", 20);
797 810
811/*
812 * fast_io_fail_tmo attribute
813 */
814static ssize_t
815show_fc_rport_fast_io_fail_tmo (struct class_device *cdev, char *buf)
816{
817 struct fc_rport *rport = transport_class_to_rport(cdev);
818
819 if (rport->fast_io_fail_tmo == -1)
820 return snprintf(buf, 5, "off\n");
821 return snprintf(buf, 20, "%d\n", rport->fast_io_fail_tmo);
822}
823
824static ssize_t
825store_fc_rport_fast_io_fail_tmo(struct class_device *cdev, const char *buf,
826 size_t count)
827{
828 int val;
829 char *cp;
830 struct fc_rport *rport = transport_class_to_rport(cdev);
831
832 if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
833 (rport->port_state == FC_PORTSTATE_DELETED) ||
834 (rport->port_state == FC_PORTSTATE_NOTPRESENT))
835 return -EBUSY;
836 if (strncmp(buf, "off", 3) == 0)
837 rport->fast_io_fail_tmo = -1;
838 else {
839 val = simple_strtoul(buf, &cp, 0);
840 if ((*cp && (*cp != '\n')) ||
841 (val < 0) || (val >= rport->dev_loss_tmo))
842 return -EINVAL;
843 rport->fast_io_fail_tmo = val;
844 }
845 return count;
846}
847static FC_CLASS_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
848 show_fc_rport_fast_io_fail_tmo, store_fc_rport_fast_io_fail_tmo);
798 849
799 850
800/* 851/*
@@ -880,8 +931,11 @@ store_fc_host_##field(struct class_device *cdev, const char *buf, \
880 int val; \ 931 int val; \
881 struct Scsi_Host *shost = transport_class_to_shost(cdev); \ 932 struct Scsi_Host *shost = transport_class_to_shost(cdev); \
882 struct fc_internal *i = to_fc_internal(shost->transportt); \ 933 struct fc_internal *i = to_fc_internal(shost->transportt); \
934 char *cp; \
883 \ 935 \
884 val = simple_strtoul(buf, NULL, 0); \ 936 val = simple_strtoul(buf, &cp, 0); \
937 if (*cp && (*cp != '\n')) \
938 return -EINVAL; \
885 i->f->set_host_##field(shost, val); \ 939 i->f->set_host_##field(shost, val); \
886 return count; \ 940 return count; \
887} 941}
@@ -1481,6 +1535,8 @@ fc_attach_transport(struct fc_function_template *ft)
1481 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(roles); 1535 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(roles);
1482 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_state); 1536 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_state);
1483 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(scsi_target_id); 1537 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(scsi_target_id);
1538 if (ft->terminate_rport_io)
1539 SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(fast_io_fail_tmo);
1484 1540
1485 BUG_ON(count > FC_RPORT_NUM_ATTRS); 1541 BUG_ON(count > FC_RPORT_NUM_ATTRS);
1486 1542
@@ -1552,7 +1608,7 @@ fc_flush_work(struct Scsi_Host *shost)
1552 * @delay: jiffies to delay the work queuing 1608 * @delay: jiffies to delay the work queuing
1553 * 1609 *
1554 * Return value: 1610 * Return value:
1555 * 0 on success / != 0 for error 1611 * 1 on success / 0 already queued / < 0 for error
1556 **/ 1612 **/
1557static int 1613static int
1558fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work, 1614fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work,
@@ -1567,6 +1623,9 @@ fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work,
1567 return -EINVAL; 1623 return -EINVAL;
1568 } 1624 }
1569 1625
1626 if (delay == 0)
1627 return queue_work(fc_host_devloss_work_q(shost), work);
1628
1570 return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay); 1629 return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay);
1571} 1630}
1572 1631
@@ -1659,10 +1718,23 @@ fc_starget_delete(void *data)
1659 struct fc_rport *rport = (struct fc_rport *)data; 1718 struct fc_rport *rport = (struct fc_rport *)data;
1660 struct Scsi_Host *shost = rport_to_shost(rport); 1719 struct Scsi_Host *shost = rport_to_shost(rport);
1661 unsigned long flags; 1720 unsigned long flags;
1721 struct fc_internal *i = to_fc_internal(shost->transportt);
1722
1723 /*
1724 * Involve the LLDD if possible. All io on the rport is to
1725 * be terminated, either as part of the dev_loss_tmo callback
1726 * processing, or via the terminate_rport_io function.
1727 */
1728 if (i->f->dev_loss_tmo_callbk)
1729 i->f->dev_loss_tmo_callbk(rport);
1730 else if (i->f->terminate_rport_io)
1731 i->f->terminate_rport_io(rport);
1662 1732
1663 spin_lock_irqsave(shost->host_lock, flags); 1733 spin_lock_irqsave(shost->host_lock, flags);
1664 if (rport->flags & FC_RPORT_DEVLOSS_PENDING) { 1734 if (rport->flags & FC_RPORT_DEVLOSS_PENDING) {
1665 spin_unlock_irqrestore(shost->host_lock, flags); 1735 spin_unlock_irqrestore(shost->host_lock, flags);
1736 if (!cancel_delayed_work(&rport->fail_io_work))
1737 fc_flush_devloss(shost);
1666 if (!cancel_delayed_work(&rport->dev_loss_work)) 1738 if (!cancel_delayed_work(&rport->dev_loss_work))
1667 fc_flush_devloss(shost); 1739 fc_flush_devloss(shost);
1668 spin_lock_irqsave(shost->host_lock, flags); 1740 spin_lock_irqsave(shost->host_lock, flags);
@@ -1685,10 +1757,7 @@ fc_rport_final_delete(void *data)
1685 struct fc_rport *rport = (struct fc_rport *)data; 1757 struct fc_rport *rport = (struct fc_rport *)data;
1686 struct device *dev = &rport->dev; 1758 struct device *dev = &rport->dev;
1687 struct Scsi_Host *shost = rport_to_shost(rport); 1759 struct Scsi_Host *shost = rport_to_shost(rport);
1688 1760 struct fc_internal *i = to_fc_internal(shost->transportt);
1689 /* Delete SCSI target and sdevs */
1690 if (rport->scsi_target_id != -1)
1691 fc_starget_delete(data);
1692 1761
1693 /* 1762 /*
1694 * if a scan is pending, flush the SCSI Host work_q so that 1763 * if a scan is pending, flush the SCSI Host work_q so that
@@ -1697,6 +1766,14 @@ fc_rport_final_delete(void *data)
1697 if (rport->flags & FC_RPORT_SCAN_PENDING) 1766 if (rport->flags & FC_RPORT_SCAN_PENDING)
1698 scsi_flush_work(shost); 1767 scsi_flush_work(shost);
1699 1768
1769 /* Delete SCSI target and sdevs */
1770 if (rport->scsi_target_id != -1)
1771 fc_starget_delete(data);
1772 else if (i->f->dev_loss_tmo_callbk)
1773 i->f->dev_loss_tmo_callbk(rport);
1774 else if (i->f->terminate_rport_io)
1775 i->f->terminate_rport_io(rport);
1776
1700 transport_remove_device(dev); 1777 transport_remove_device(dev);
1701 device_del(dev); 1778 device_del(dev);
1702 transport_destroy_device(dev); 1779 transport_destroy_device(dev);
@@ -1748,8 +1825,10 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
1748 if (fci->f->dd_fcrport_size) 1825 if (fci->f->dd_fcrport_size)
1749 rport->dd_data = &rport[1]; 1826 rport->dd_data = &rport[1];
1750 rport->channel = channel; 1827 rport->channel = channel;
1828 rport->fast_io_fail_tmo = -1;
1751 1829
1752 INIT_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport, rport); 1830 INIT_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport, rport);
1831 INIT_WORK(&rport->fail_io_work, fc_timeout_fail_rport_io, rport);
1753 INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport); 1832 INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport);
1754 INIT_WORK(&rport->stgt_delete_work, fc_starget_delete, rport); 1833 INIT_WORK(&rport->stgt_delete_work, fc_starget_delete, rport);
1755 INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete, rport); 1834 INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete, rport);
@@ -1913,11 +1992,13 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
1913 /* restart the target */ 1992 /* restart the target */
1914 1993
1915 /* 1994 /*
1916 * Stop the target timer first. Take no action 1995 * Stop the target timers first. Take no action
1917 * on the del_timer failure as the state 1996 * on the del_timer failure as the state
1918 * machine state change will validate the 1997 * machine state change will validate the
1919 * transaction. 1998 * transaction.
1920 */ 1999 */
2000 if (!cancel_delayed_work(&rport->fail_io_work))
2001 fc_flush_devloss(shost);
1921 if (!cancel_delayed_work(work)) 2002 if (!cancel_delayed_work(work))
1922 fc_flush_devloss(shost); 2003 fc_flush_devloss(shost);
1923 2004
@@ -2061,6 +2142,7 @@ void
2061fc_remote_port_delete(struct fc_rport *rport) 2142fc_remote_port_delete(struct fc_rport *rport)
2062{ 2143{
2063 struct Scsi_Host *shost = rport_to_shost(rport); 2144 struct Scsi_Host *shost = rport_to_shost(rport);
2145 struct fc_internal *i = to_fc_internal(shost->transportt);
2064 int timeout = rport->dev_loss_tmo; 2146 int timeout = rport->dev_loss_tmo;
2065 unsigned long flags; 2147 unsigned long flags;
2066 2148
@@ -2091,6 +2173,12 @@ fc_remote_port_delete(struct fc_rport *rport)
2091 2173
2092 scsi_target_block(&rport->dev); 2174 scsi_target_block(&rport->dev);
2093 2175
2176 /* see if we need to kill io faster than waiting for device loss */
2177 if ((rport->fast_io_fail_tmo != -1) &&
2178 (rport->fast_io_fail_tmo < timeout) && (i->f->terminate_rport_io))
2179 fc_queue_devloss_work(shost, &rport->fail_io_work,
2180 rport->fast_io_fail_tmo * HZ);
2181
2094 /* cap the length the devices can be blocked until they are deleted */ 2182 /* cap the length the devices can be blocked until they are deleted */
2095 fc_queue_devloss_work(shost, &rport->dev_loss_work, timeout * HZ); 2183 fc_queue_devloss_work(shost, &rport->dev_loss_work, timeout * HZ);
2096} 2184}
@@ -2150,6 +2238,8 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
2150 * machine state change will validate the 2238 * machine state change will validate the
2151 * transaction. 2239 * transaction.
2152 */ 2240 */
2241 if (!cancel_delayed_work(&rport->fail_io_work))
2242 fc_flush_devloss(shost);
2153 if (!cancel_delayed_work(&rport->dev_loss_work)) 2243 if (!cancel_delayed_work(&rport->dev_loss_work))
2154 fc_flush_devloss(shost); 2244 fc_flush_devloss(shost);
2155 2245
@@ -2271,6 +2361,28 @@ fc_timeout_deleted_rport(void *data)
2271} 2361}
2272 2362
2273/** 2363/**
2364 * fc_timeout_fail_rport_io - Timeout handler for a fast io failing on a
2365 * disconnected SCSI target.
2366 *
2367 * @data: rport to terminate io on.
2368 *
2369 * Notes: Only requests the failure of the io, not that all are flushed
2370 * prior to returning.
2371 **/
2372static void
2373fc_timeout_fail_rport_io(void *data)
2374{
2375 struct fc_rport *rport = (struct fc_rport *)data;
2376 struct Scsi_Host *shost = rport_to_shost(rport);
2377 struct fc_internal *i = to_fc_internal(shost->transportt);
2378
2379 if (rport->port_state != FC_PORTSTATE_BLOCKED)
2380 return;
2381
2382 i->f->terminate_rport_io(rport);
2383}
2384
2385/**
2274 * fc_scsi_scan_rport - called to perform a scsi scan on a remote port. 2386 * fc_scsi_scan_rport - called to perform a scsi scan on a remote port.
2275 * 2387 *
2276 * @data: remote port to be scanned. 2388 * @data: remote port to be scanned.
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 0b11eff989e0..fd352323378b 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -195,6 +195,7 @@ struct fc_rport { /* aka fc_starget_attrs */
195 u32 roles; 195 u32 roles;
196 enum fc_port_state port_state; /* Will only be ONLINE or UNKNOWN */ 196 enum fc_port_state port_state; /* Will only be ONLINE or UNKNOWN */
197 u32 scsi_target_id; 197 u32 scsi_target_id;
198 u32 fast_io_fail_tmo;
198 199
199 /* exported data */ 200 /* exported data */
200 void *dd_data; /* Used for driver-specific storage */ 201 void *dd_data; /* Used for driver-specific storage */
@@ -207,6 +208,7 @@ struct fc_rport { /* aka fc_starget_attrs */
207 struct device dev; 208 struct device dev;
208 struct work_struct dev_loss_work; 209 struct work_struct dev_loss_work;
209 struct work_struct scan_work; 210 struct work_struct scan_work;
211 struct work_struct fail_io_work;
210 struct work_struct stgt_delete_work; 212 struct work_struct stgt_delete_work;
211 struct work_struct rport_delete_work; 213 struct work_struct rport_delete_work;
212} __attribute__((aligned(sizeof(unsigned long)))); 214} __attribute__((aligned(sizeof(unsigned long))));
@@ -445,6 +447,9 @@ struct fc_function_template {
445 447
446 int (*issue_fc_host_lip)(struct Scsi_Host *); 448 int (*issue_fc_host_lip)(struct Scsi_Host *);
447 449
450 void (*dev_loss_tmo_callbk)(struct fc_rport *);
451 void (*terminate_rport_io)(struct fc_rport *);
452
448 /* allocation lengths for host-specific data */ 453 /* allocation lengths for host-specific data */
449 u32 dd_fcrport_size; 454 u32 dd_fcrport_size;
450 455