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

[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>

authored by

Matthew Wilcox and committed by
James Bottomley
3e082a91 53a5fbdc

+256 -21
+5
Documentation/kernel-parameters.txt
··· 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.
+2
drivers/scsi/Makefile
··· 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 \
+3
drivers/scsi/scsi_priv.h
··· 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,
+197 -6
drivers/scsi/scsi_scan.c
··· 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> ··· 89 87 MODULE_PARM_DESC(max_luns, 90 88 "last scsi LUN (should be between 1 and 2^32-1)"); 91 89 90 + static char scsi_scan_type[6] = "sync"; 91 + 92 + module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO); 93 + MODULE_PARM_DESC(scan, "sync, async or none"); 94 + 92 95 /* 93 96 * max_scsi_report_luns: the maximum number of LUNS that will be 94 97 * returned from the REPORT LUNS command. 8 times this value must ··· 114 107 MODULE_PARM_DESC(inq_timeout, 115 108 "Timeout (in seconds) waiting for devices to answer INQUIRY." 116 109 " Default is 5. Some non-compliant devices need more."); 110 + 111 + static DEFINE_SPINLOCK(async_scan_lock); 112 + static LIST_HEAD(scanning_hosts); 113 + 114 + struct async_scan_data { 115 + struct list_head list; 116 + struct Scsi_Host *shost; 117 + struct completion prev_finished; 118 + }; 119 + 120 + /** 121 + * scsi_complete_async_scans - Wait for asynchronous scans to complete 122 + * 123 + * Asynchronous scans add themselves to the scanning_hosts list. Once 124 + * that list is empty, we know that the scans are complete. Rather than 125 + * waking up periodically to check the state of the list, we pretend to be 126 + * a scanning task by adding ourselves at the end of the list and going to 127 + * sleep. When the task before us wakes us up, we take ourselves off the 128 + * list and return. 129 + */ 130 + int scsi_complete_async_scans(void) 131 + { 132 + struct async_scan_data *data; 133 + 134 + do { 135 + if (list_empty(&scanning_hosts)) 136 + return 0; 137 + /* If we can't get memory immediately, that's OK. Just 138 + * sleep a little. Even if we never get memory, the async 139 + * scans will finish eventually. 140 + */ 141 + data = kmalloc(sizeof(*data), GFP_KERNEL); 142 + if (!data) 143 + msleep(1); 144 + } while (!data); 145 + 146 + data->shost = NULL; 147 + init_completion(&data->prev_finished); 148 + 149 + spin_lock(&async_scan_lock); 150 + /* Check that there's still somebody else on the list */ 151 + if (list_empty(&scanning_hosts)) 152 + goto done; 153 + list_add_tail(&data->list, &scanning_hosts); 154 + spin_unlock(&async_scan_lock); 155 + 156 + printk(KERN_INFO "scsi: waiting for bus probes to complete ...\n"); 157 + wait_for_completion(&data->prev_finished); 158 + 159 + spin_lock(&async_scan_lock); 160 + list_del(&data->list); 161 + done: 162 + spin_unlock(&async_scan_lock); 163 + 164 + kfree(data); 165 + return 0; 166 + } 167 + 168 + #ifdef MODULE 169 + /* Only exported for the benefit of scsi_wait_scan */ 170 + EXPORT_SYMBOL_GPL(scsi_complete_async_scans); 171 + #endif 117 172 118 173 /** 119 174 * scsi_unlock_floptical - unlock device via a special MODE SENSE command ··· 688 619 * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized 689 620 **/ 690 621 static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, 691 - int *bflags) 622 + int *bflags, int async) 692 623 { 693 624 /* 694 625 * XXX do not save the inquiry, since it can change underneath us, ··· 864 795 * register it and tell the rest of the kernel 865 796 * about it. 866 797 */ 867 - if (scsi_sysfs_add_sdev(sdev) != 0) 798 + if (!async && scsi_sysfs_add_sdev(sdev) != 0) 868 799 return SCSI_SCAN_NO_RESPONSE; 869 800 870 801 return SCSI_SCAN_LUN_PRESENT; ··· 1033 964 goto out_free_result; 1034 965 } 1035 966 1036 - res = scsi_add_lun(sdev, result, &bflags); 967 + res = scsi_add_lun(sdev, result, &bflags, shost->async_scan); 1037 968 if (res == SCSI_SCAN_LUN_PRESENT) { 1038 969 if (bflags & BLIST_KEY) { 1039 970 sdev->lockable = 0; ··· 1533 1464 { 1534 1465 struct Scsi_Host *shost = dev_to_shost(parent); 1535 1466 1467 + if (!shost->async_scan) 1468 + scsi_complete_async_scans(); 1469 + 1536 1470 mutex_lock(&shost->scan_mutex); 1537 1471 if (scsi_host_scan_allowed(shost)) 1538 1472 __scsi_scan_target(parent, channel, id, lun, rescan); ··· 1581 1509 "%s: <%u:%u:%u>\n", 1582 1510 __FUNCTION__, channel, id, lun)); 1583 1511 1512 + if (!shost->async_scan) 1513 + scsi_complete_async_scans(); 1514 + 1584 1515 if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || 1585 1516 ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || 1586 1517 ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) ··· 1604 1529 return 0; 1605 1530 } 1606 1531 1532 + static void scsi_sysfs_add_devices(struct Scsi_Host *shost) 1533 + { 1534 + struct scsi_device *sdev; 1535 + shost_for_each_device(sdev, shost) { 1536 + if (scsi_sysfs_add_sdev(sdev) != 0) 1537 + scsi_destroy_sdev(sdev); 1538 + } 1539 + } 1540 + 1541 + /** 1542 + * scsi_prep_async_scan - prepare for an async scan 1543 + * @shost: the host which will be scanned 1544 + * Returns: a cookie to be passed to scsi_finish_async_scan() 1545 + * 1546 + * Tells the midlayer this host is going to do an asynchronous scan. 1547 + * It reserves the host's position in the scanning list and ensures 1548 + * that other asynchronous scans started after this one won't affect the 1549 + * ordering of the discovered devices. 1550 + */ 1551 + struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) 1552 + { 1553 + struct async_scan_data *data; 1554 + 1555 + if (strncmp(scsi_scan_type, "sync", 4) == 0) 1556 + return NULL; 1557 + 1558 + if (shost->async_scan) { 1559 + printk("%s called twice for host %d", __FUNCTION__, 1560 + shost->host_no); 1561 + dump_stack(); 1562 + return NULL; 1563 + } 1564 + 1565 + data = kmalloc(sizeof(*data), GFP_KERNEL); 1566 + if (!data) 1567 + goto err; 1568 + data->shost = scsi_host_get(shost); 1569 + if (!data->shost) 1570 + goto err; 1571 + init_completion(&data->prev_finished); 1572 + 1573 + spin_lock(&async_scan_lock); 1574 + shost->async_scan = 1; 1575 + if (list_empty(&scanning_hosts)) 1576 + complete(&data->prev_finished); 1577 + list_add_tail(&data->list, &scanning_hosts); 1578 + spin_unlock(&async_scan_lock); 1579 + 1580 + return data; 1581 + 1582 + err: 1583 + kfree(data); 1584 + return NULL; 1585 + } 1586 + 1587 + /** 1588 + * scsi_finish_async_scan - asynchronous scan has finished 1589 + * @data: cookie returned from earlier call to scsi_prep_async_scan() 1590 + * 1591 + * All the devices currently attached to this host have been found. 1592 + * This function announces all the devices it has found to the rest 1593 + * of the system. 1594 + */ 1595 + void scsi_finish_async_scan(struct async_scan_data *data) 1596 + { 1597 + struct Scsi_Host *shost; 1598 + 1599 + if (!data) 1600 + return; 1601 + 1602 + shost = data->shost; 1603 + if (!shost->async_scan) { 1604 + printk("%s called twice for host %d", __FUNCTION__, 1605 + shost->host_no); 1606 + dump_stack(); 1607 + return; 1608 + } 1609 + 1610 + wait_for_completion(&data->prev_finished); 1611 + 1612 + scsi_sysfs_add_devices(shost); 1613 + 1614 + spin_lock(&async_scan_lock); 1615 + shost->async_scan = 0; 1616 + list_del(&data->list); 1617 + if (!list_empty(&scanning_hosts)) { 1618 + struct async_scan_data *next = list_entry(scanning_hosts.next, 1619 + struct async_scan_data, list); 1620 + complete(&next->prev_finished); 1621 + } 1622 + spin_unlock(&async_scan_lock); 1623 + 1624 + scsi_host_put(shost); 1625 + kfree(data); 1626 + } 1627 + 1628 + static int do_scan_async(void *_data) 1629 + { 1630 + struct async_scan_data *data = _data; 1631 + scsi_scan_host_selected(data->shost, SCAN_WILD_CARD, SCAN_WILD_CARD, 1632 + SCAN_WILD_CARD, 0); 1633 + 1634 + scsi_finish_async_scan(data); 1635 + return 0; 1636 + } 1637 + 1607 1638 /** 1608 1639 * scsi_scan_host - scan the given adapter 1609 1640 * @shost: adapter to scan 1610 1641 **/ 1611 1642 void scsi_scan_host(struct Scsi_Host *shost) 1612 1643 { 1613 - scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, 1614 - SCAN_WILD_CARD, 0); 1644 + struct async_scan_data *data; 1645 + 1646 + if (strncmp(scsi_scan_type, "none", 4) == 0) 1647 + return; 1648 + 1649 + data = scsi_prep_async_scan(shost); 1650 + if (!data) { 1651 + scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, 1652 + SCAN_WILD_CARD, 0); 1653 + return; 1654 + } 1655 + kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); 1615 1656 } 1616 1657 EXPORT_SYMBOL(scsi_scan_host); 1617 1658
+31
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);
+15 -15
include/scsi/scsi_device.h
··· 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); \ ··· 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)
+3
include/scsi/scsi_host.h
··· 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 */