diff options
author | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-05-26 16:35:48 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-08 14:00:13 -0400 |
commit | 601e7638254c118fca135af9b1a9f35061420f62 (patch) | |
tree | 61b883be6901e4c994c5b472959e91ebdb267d6f | |
parent | 91bc31fb3bae4e55832c7c39d4f9c193285e6ab2 (diff) |
[SCSI] sd: fix bug in SCSI async probing
The async split up of probing in sd.c created a potential failure case where
something goes wrong with device_add(), but which we don't recover properly.
Since, in general, asynchronous error handling is hard, move the device_add()
into the asynchronous path (it should be fast) and make sure all the deferred
processing cannot fail.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | drivers/scsi/sd.c | 45 |
1 files changed, 21 insertions, 24 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 84044233b637..d8e1d15101b7 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -1902,24 +1902,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie) | |||
1902 | index = sdkp->index; | 1902 | index = sdkp->index; |
1903 | dev = &sdp->sdev_gendev; | 1903 | dev = &sdp->sdev_gendev; |
1904 | 1904 | ||
1905 | if (!sdp->request_queue->rq_timeout) { | ||
1906 | if (sdp->type != TYPE_MOD) | ||
1907 | blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT); | ||
1908 | else | ||
1909 | blk_queue_rq_timeout(sdp->request_queue, | ||
1910 | SD_MOD_TIMEOUT); | ||
1911 | } | ||
1912 | |||
1913 | device_initialize(&sdkp->dev); | ||
1914 | sdkp->dev.parent = &sdp->sdev_gendev; | ||
1915 | sdkp->dev.class = &sd_disk_class; | ||
1916 | dev_set_name(&sdkp->dev, dev_name(&sdp->sdev_gendev)); | ||
1917 | |||
1918 | if (device_add(&sdkp->dev)) | ||
1919 | goto out_free_index; | ||
1920 | |||
1921 | get_device(&sdp->sdev_gendev); | ||
1922 | |||
1923 | if (index < SD_MAX_DISKS) { | 1905 | if (index < SD_MAX_DISKS) { |
1924 | gd->major = sd_major((index & 0xf0) >> 4); | 1906 | gd->major = sd_major((index & 0xf0) >> 4); |
1925 | gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); | 1907 | gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); |
@@ -1954,11 +1936,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie) | |||
1954 | 1936 | ||
1955 | sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", | 1937 | sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", |
1956 | sdp->removable ? "removable " : ""); | 1938 | sdp->removable ? "removable " : ""); |
1957 | |||
1958 | return; | ||
1959 | |||
1960 | out_free_index: | ||
1961 | ida_remove(&sd_index_ida, index); | ||
1962 | } | 1939 | } |
1963 | 1940 | ||
1964 | /** | 1941 | /** |
@@ -2026,6 +2003,24 @@ static int sd_probe(struct device *dev) | |||
2026 | sdkp->openers = 0; | 2003 | sdkp->openers = 0; |
2027 | sdkp->previous_state = 1; | 2004 | sdkp->previous_state = 1; |
2028 | 2005 | ||
2006 | if (!sdp->request_queue->rq_timeout) { | ||
2007 | if (sdp->type != TYPE_MOD) | ||
2008 | blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT); | ||
2009 | else | ||
2010 | blk_queue_rq_timeout(sdp->request_queue, | ||
2011 | SD_MOD_TIMEOUT); | ||
2012 | } | ||
2013 | |||
2014 | device_initialize(&sdkp->dev); | ||
2015 | sdkp->dev.parent = &sdp->sdev_gendev; | ||
2016 | sdkp->dev.class = &sd_disk_class; | ||
2017 | dev_set_name(&sdkp->dev, dev_name(&sdp->sdev_gendev)); | ||
2018 | |||
2019 | if (device_add(&sdkp->dev)) | ||
2020 | goto out_free_index; | ||
2021 | |||
2022 | get_device(&sdp->sdev_gendev); | ||
2023 | |||
2029 | async_schedule(sd_probe_async, sdkp); | 2024 | async_schedule(sd_probe_async, sdkp); |
2030 | 2025 | ||
2031 | return 0; | 2026 | return 0; |
@@ -2055,8 +2050,10 @@ static int sd_probe(struct device *dev) | |||
2055 | **/ | 2050 | **/ |
2056 | static int sd_remove(struct device *dev) | 2051 | static int sd_remove(struct device *dev) |
2057 | { | 2052 | { |
2058 | struct scsi_disk *sdkp = dev_get_drvdata(dev); | 2053 | struct scsi_disk *sdkp; |
2059 | 2054 | ||
2055 | async_synchronize_full(); | ||
2056 | sdkp = dev_get_drvdata(dev); | ||
2060 | device_del(&sdkp->dev); | 2057 | device_del(&sdkp->dev); |
2061 | del_gendisk(sdkp->disk); | 2058 | del_gendisk(sdkp->disk); |
2062 | sd_shutdown(dev); | 2059 | sd_shutdown(dev); |