Commit 3e082a910d217b2e7b186077ebf5a1126a68c62f

Authored by Matthew Wilcox
Committed by James Bottomley
1 parent 53a5fbdc2d

[SCSI] Add ability to scan scsi busses asynchronously

Since it often takes around 20-30 seconds to scan a scsi bus, it's
highly advantageous to do this in parallel with other things.  The bulk
of this patch is ensuring that devices don't change numbering, and that
all devices are discovered prior to trying to start init.  For those
who build SCSI as modules, there's a new scsi_wait_scan module that will
ensure all bus scans are finished.

This patch only handles drivers which call scsi_scan_host.  Fibre Channel,
SAS, SATA, USB and Firewire all need additional work.

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>

Showing 7 changed files with 256 additions and 21 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -1410,6 +1410,11 @@
1410 1410  
1411 1411 scsi_logging= [SCSI]
1412 1412  
  1413 + scsi_mod.scan= [SCSI] sync (default) scans SCSI busses as they are
  1414 + discovered. async scans them in kernel threads,
  1415 + allowing boot to proceed. none ignores them, expecting
  1416 + user space to do the scan.
  1417 +
1413 1418 selinux [SELINUX] Disable or enable SELinux at boot time.
1414 1419 Format: { "0" | "1" }
1415 1420 See security/selinux/Kconfig help text.
drivers/scsi/Makefile
... ... @@ -141,6 +141,8 @@
141 141 # This goes last, so that "real" scsi devices probe earlier
142 142 obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o
143 143  
  144 +obj-$(CONFIG_SCSI) += scsi_wait_scan.o
  145 +
144 146 scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \
145 147 scsicam.o scsi_error.o scsi_lib.o \
146 148 scsi_scan.o scsi_sysfs.o \
drivers/scsi/scsi_priv.h
... ... @@ -39,6 +39,9 @@
39 39 { };
40 40 #endif
41 41  
  42 +/* scsi_scan.c */
  43 +int scsi_complete_async_scans(void);
  44 +
42 45 /* scsi_devinfo.c */
43 46 extern int scsi_get_device_flags(struct scsi_device *sdev,
44 47 const unsigned char *vendor,
drivers/scsi/scsi_scan.c
... ... @@ -29,7 +29,9 @@
29 29 #include <linux/moduleparam.h>
30 30 #include <linux/init.h>
31 31 #include <linux/blkdev.h>
32   -#include <asm/semaphore.h>
  32 +#include <linux/delay.h>
  33 +#include <linux/kthread.h>
  34 +#include <linux/spinlock.h>
33 35  
34 36 #include <scsi/scsi.h>
35 37 #include <scsi/scsi_cmnd.h>
... ... @@ -87,6 +89,11 @@
87 89 MODULE_PARM_DESC(max_luns,
88 90 "last scsi LUN (should be between 1 and 2^32-1)");
89 91  
  92 +static char scsi_scan_type[6] = "sync";
  93 +
  94 +module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO);
  95 +MODULE_PARM_DESC(scan, "sync, async or none");
  96 +
90 97 /*
91 98 * max_scsi_report_luns: the maximum number of LUNS that will be
92 99 * returned from the REPORT LUNS command. 8 times this value must
93 100  
... ... @@ -108,7 +115,69 @@
108 115 "Timeout (in seconds) waiting for devices to answer INQUIRY."
109 116 " Default is 5. Some non-compliant devices need more.");
110 117  
  118 +static DEFINE_SPINLOCK(async_scan_lock);
  119 +static LIST_HEAD(scanning_hosts);
  120 +
  121 +struct async_scan_data {
  122 + struct list_head list;
  123 + struct Scsi_Host *shost;
  124 + struct completion prev_finished;
  125 +};
  126 +
111 127 /**
  128 + * scsi_complete_async_scans - Wait for asynchronous scans to complete
  129 + *
  130 + * Asynchronous scans add themselves to the scanning_hosts list. Once
  131 + * that list is empty, we know that the scans are complete. Rather than
  132 + * waking up periodically to check the state of the list, we pretend to be
  133 + * a scanning task by adding ourselves at the end of the list and going to
  134 + * sleep. When the task before us wakes us up, we take ourselves off the
  135 + * list and return.
  136 + */
  137 +int scsi_complete_async_scans(void)
  138 +{
  139 + struct async_scan_data *data;
  140 +
  141 + do {
  142 + if (list_empty(&scanning_hosts))
  143 + return 0;
  144 + /* If we can't get memory immediately, that's OK. Just
  145 + * sleep a little. Even if we never get memory, the async
  146 + * scans will finish eventually.
  147 + */
  148 + data = kmalloc(sizeof(*data), GFP_KERNEL);
  149 + if (!data)
  150 + msleep(1);
  151 + } while (!data);
  152 +
  153 + data->shost = NULL;
  154 + init_completion(&data->prev_finished);
  155 +
  156 + spin_lock(&async_scan_lock);
  157 + /* Check that there's still somebody else on the list */
  158 + if (list_empty(&scanning_hosts))
  159 + goto done;
  160 + list_add_tail(&data->list, &scanning_hosts);
  161 + spin_unlock(&async_scan_lock);
  162 +
  163 + printk(KERN_INFO "scsi: waiting for bus probes to complete ...\n");
  164 + wait_for_completion(&data->prev_finished);
  165 +
  166 + spin_lock(&async_scan_lock);
  167 + list_del(&data->list);
  168 + done:
  169 + spin_unlock(&async_scan_lock);
  170 +
  171 + kfree(data);
  172 + return 0;
  173 +}
  174 +
  175 +#ifdef MODULE
  176 +/* Only exported for the benefit of scsi_wait_scan */
  177 +EXPORT_SYMBOL_GPL(scsi_complete_async_scans);
  178 +#endif
  179 +
  180 +/**
112 181 * scsi_unlock_floptical - unlock device via a special MODE SENSE command
113 182 * @sdev: scsi device to send command to
114 183 * @result: area to store the result of the MODE SENSE
... ... @@ -619,7 +688,7 @@
619 688 * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized
620 689 **/
621 690 static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
622   - int *bflags)
  691 + int *bflags, int async)
623 692 {
624 693 /*
625 694 * XXX do not save the inquiry, since it can change underneath us,
... ... @@ -795,7 +864,7 @@
795 864 * register it and tell the rest of the kernel
796 865 * about it.
797 866 */
798   - if (scsi_sysfs_add_sdev(sdev) != 0)
  867 + if (!async && scsi_sysfs_add_sdev(sdev) != 0)
799 868 return SCSI_SCAN_NO_RESPONSE;
800 869  
801 870 return SCSI_SCAN_LUN_PRESENT;
... ... @@ -964,7 +1033,7 @@
964 1033 goto out_free_result;
965 1034 }
966 1035  
967   - res = scsi_add_lun(sdev, result, &bflags);
  1036 + res = scsi_add_lun(sdev, result, &bflags, shost->async_scan);
968 1037 if (res == SCSI_SCAN_LUN_PRESENT) {
969 1038 if (bflags & BLIST_KEY) {
970 1039 sdev->lockable = 0;
... ... @@ -1464,6 +1533,9 @@
1464 1533 {
1465 1534 struct Scsi_Host *shost = dev_to_shost(parent);
1466 1535  
  1536 + if (!shost->async_scan)
  1537 + scsi_complete_async_scans();
  1538 +
1467 1539 mutex_lock(&shost->scan_mutex);
1468 1540 if (scsi_host_scan_allowed(shost))
1469 1541 __scsi_scan_target(parent, channel, id, lun, rescan);
... ... @@ -1509,6 +1581,9 @@
1509 1581 "%s: <%u:%u:%u>\n",
1510 1582 __FUNCTION__, channel, id, lun));
1511 1583  
  1584 + if (!shost->async_scan)
  1585 + scsi_complete_async_scans();
  1586 +
1512 1587 if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
1513 1588 ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||
1514 1589 ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
1515 1590  
1516 1591  
... ... @@ -1529,14 +1604,130 @@
1529 1604 return 0;
1530 1605 }
1531 1606  
  1607 +static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
  1608 +{
  1609 + struct scsi_device *sdev;
  1610 + shost_for_each_device(sdev, shost) {
  1611 + if (scsi_sysfs_add_sdev(sdev) != 0)
  1612 + scsi_destroy_sdev(sdev);
  1613 + }
  1614 +}
  1615 +
1532 1616 /**
  1617 + * scsi_prep_async_scan - prepare for an async scan
  1618 + * @shost: the host which will be scanned
  1619 + * Returns: a cookie to be passed to scsi_finish_async_scan()
  1620 + *
  1621 + * Tells the midlayer this host is going to do an asynchronous scan.
  1622 + * It reserves the host's position in the scanning list and ensures
  1623 + * that other asynchronous scans started after this one won't affect the
  1624 + * ordering of the discovered devices.
  1625 + */
  1626 +struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
  1627 +{
  1628 + struct async_scan_data *data;
  1629 +
  1630 + if (strncmp(scsi_scan_type, "sync", 4) == 0)
  1631 + return NULL;
  1632 +
  1633 + if (shost->async_scan) {
  1634 + printk("%s called twice for host %d", __FUNCTION__,
  1635 + shost->host_no);
  1636 + dump_stack();
  1637 + return NULL;
  1638 + }
  1639 +
  1640 + data = kmalloc(sizeof(*data), GFP_KERNEL);
  1641 + if (!data)
  1642 + goto err;
  1643 + data->shost = scsi_host_get(shost);
  1644 + if (!data->shost)
  1645 + goto err;
  1646 + init_completion(&data->prev_finished);
  1647 +
  1648 + spin_lock(&async_scan_lock);
  1649 + shost->async_scan = 1;
  1650 + if (list_empty(&scanning_hosts))
  1651 + complete(&data->prev_finished);
  1652 + list_add_tail(&data->list, &scanning_hosts);
  1653 + spin_unlock(&async_scan_lock);
  1654 +
  1655 + return data;
  1656 +
  1657 + err:
  1658 + kfree(data);
  1659 + return NULL;
  1660 +}
  1661 +
  1662 +/**
  1663 + * scsi_finish_async_scan - asynchronous scan has finished
  1664 + * @data: cookie returned from earlier call to scsi_prep_async_scan()
  1665 + *
  1666 + * All the devices currently attached to this host have been found.
  1667 + * This function announces all the devices it has found to the rest
  1668 + * of the system.
  1669 + */
  1670 +void scsi_finish_async_scan(struct async_scan_data *data)
  1671 +{
  1672 + struct Scsi_Host *shost;
  1673 +
  1674 + if (!data)
  1675 + return;
  1676 +
  1677 + shost = data->shost;
  1678 + if (!shost->async_scan) {
  1679 + printk("%s called twice for host %d", __FUNCTION__,
  1680 + shost->host_no);
  1681 + dump_stack();
  1682 + return;
  1683 + }
  1684 +
  1685 + wait_for_completion(&data->prev_finished);
  1686 +
  1687 + scsi_sysfs_add_devices(shost);
  1688 +
  1689 + spin_lock(&async_scan_lock);
  1690 + shost->async_scan = 0;
  1691 + list_del(&data->list);
  1692 + if (!list_empty(&scanning_hosts)) {
  1693 + struct async_scan_data *next = list_entry(scanning_hosts.next,
  1694 + struct async_scan_data, list);
  1695 + complete(&next->prev_finished);
  1696 + }
  1697 + spin_unlock(&async_scan_lock);
  1698 +
  1699 + scsi_host_put(shost);
  1700 + kfree(data);
  1701 +}
  1702 +
  1703 +static int do_scan_async(void *_data)
  1704 +{
  1705 + struct async_scan_data *data = _data;
  1706 + scsi_scan_host_selected(data->shost, SCAN_WILD_CARD, SCAN_WILD_CARD,
  1707 + SCAN_WILD_CARD, 0);
  1708 +
  1709 + scsi_finish_async_scan(data);
  1710 + return 0;
  1711 +}
  1712 +
  1713 +/**
1533 1714 * scsi_scan_host - scan the given adapter
1534 1715 * @shost: adapter to scan
1535 1716 **/
1536 1717 void scsi_scan_host(struct Scsi_Host *shost)
1537 1718 {
1538   - scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD,
1539   - SCAN_WILD_CARD, 0);
  1719 + struct async_scan_data *data;
  1720 +
  1721 + if (strncmp(scsi_scan_type, "none", 4) == 0)
  1722 + return;
  1723 +
  1724 + data = scsi_prep_async_scan(shost);
  1725 + if (!data) {
  1726 + scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD,
  1727 + SCAN_WILD_CARD, 0);
  1728 + return;
  1729 + }
  1730 + kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
1540 1731 }
1541 1732 EXPORT_SYMBOL(scsi_scan_host);
1542 1733  
drivers/scsi/scsi_wait_scan.c
  1 +/*
  2 + * scsi_wait_scan.c
  3 + *
  4 + * Copyright (C) 2006 James Bottomley <James.Bottomley@SteelEye.com>
  5 + *
  6 + * This is a simple module to wait until all the async scans are
  7 + * complete. The idea is to use it in initrd/initramfs scripts. You
  8 + * modprobe it after all the modprobes of the root SCSI drivers and it
  9 + * will wait until they have all finished scanning their busses before
  10 + * allowing the boot to proceed
  11 + */
  12 +
  13 +#include <linux/module.h>
  14 +#include "scsi_priv.h"
  15 +
  16 +static int __init wait_scan_init(void)
  17 +{
  18 + scsi_complete_async_scans();
  19 + return 0;
  20 +}
  21 +
  22 +static void __exit wait_scan_exit(void)
  23 +{
  24 +}
  25 +
  26 +MODULE_DESCRIPTION("SCSI wait for scans");
  27 +MODULE_AUTHOR("James Bottomley");
  28 +MODULE_LICENSE("GPL");
  29 +
  30 +late_initcall(wait_scan_init);
  31 +module_exit(wait_scan_exit);
include/scsi/scsi_device.h
... ... @@ -223,13 +223,13 @@
223 223 struct scsi_device *);
224 224  
225 225 /**
226   - * shost_for_each_device - iterate over all devices of a host
227   - * @sdev: iterator
228   - * @host: host whiches devices we want to iterate over
  226 + * shost_for_each_device - iterate over all devices of a host
  227 + * @sdev: the &struct scsi_device to use as a cursor
  228 + * @shost: the &struct scsi_host to iterate over
229 229 *
230   - * This traverses over each devices of @shost. The devices have
231   - * a reference that must be released by scsi_host_put when breaking
232   - * out of the loop.
  230 + * Iterator that returns each device attached to @shost. This loop
  231 + * takes a reference on each device and releases it at the end. If
  232 + * you break out of the loop, you must call scsi_device_put(sdev).
233 233 */
234 234 #define shost_for_each_device(sdev, shost) \
235 235 for ((sdev) = __scsi_iterate_devices((shost), NULL); \
236 236  
237 237  
... ... @@ -237,17 +237,17 @@
237 237 (sdev) = __scsi_iterate_devices((shost), (sdev)))
238 238  
239 239 /**
240   - * __shost_for_each_device - iterate over all devices of a host (UNLOCKED)
241   - * @sdev: iterator
242   - * @host: host whiches devices we want to iterate over
  240 + * __shost_for_each_device - iterate over all devices of a host (UNLOCKED)
  241 + * @sdev: the &struct scsi_device to use as a cursor
  242 + * @shost: the &struct scsi_host to iterate over
243 243 *
244   - * This traverses over each devices of @shost. It does _not_ take a
245   - * reference on the scsi_device, thus it the whole loop must be protected
246   - * by shost->host_lock.
  244 + * Iterator that returns each device attached to @shost. It does _not_
  245 + * take a reference on the scsi_device, so the whole loop must be
  246 + * protected by shost->host_lock.
247 247 *
248   - * Note: The only reason why drivers would want to use this is because
249   - * they're need to access the device list in irq context. Otherwise you
250   - * really want to use shost_for_each_device instead.
  248 + * Note: The only reason to use this is because you need to access the
  249 + * device list in interrupt context. Otherwise you really want to use
  250 + * shost_for_each_device instead.
251 251 */
252 252 #define __shost_for_each_device(sdev, shost) \
253 253 list_for_each_entry((sdev), &((shost)->__devices), siblings)
include/scsi/scsi_host.h
... ... @@ -552,6 +552,9 @@
552 552 /* task mgmt function in progress */
553 553 unsigned tmf_in_progress:1;
554 554  
  555 + /* Asynchronous scan in progress */
  556 + unsigned async_scan:1;
  557 +
555 558 /*
556 559 * Optional work queue to be utilized by the transport
557 560 */