diff options
author | Stefan Haberland <stefan.haberland@de.ibm.com> | 2010-02-26 16:37:47 -0500 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-02-26 16:37:32 -0500 |
commit | 589c74d5076dd1bde13a5a36d97ca79be8bd72b2 (patch) | |
tree | 252349a17326853d7e026b357921da6192958d26 /drivers | |
parent | 9eb251225ab4dbea3119cfcf4c5194eed223a740 (diff) |
[S390] dasd: fix refcounting.
The function dasd_device_from_cdev returns a reference to the dasd
device and increases the refcount by one. If an exception occurs,
the refcount was not decreased in all cases
e.g. in dasd_discipline_show.
Prevent the offline processing from hang by correcting two functions
to decrease the refcount even if an error occured.
Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/s390/block/dasd.c | 24 | ||||
-rw-r--r-- | drivers/s390/block/dasd_devmap.c | 13 |
2 files changed, 25 insertions, 12 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 56df3c5ed385..302ca14a69e5 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -1003,12 +1003,20 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, | |||
1003 | return; | 1003 | return; |
1004 | } | 1004 | } |
1005 | 1005 | ||
1006 | device = (struct dasd_device *) cqr->startdev; | 1006 | device = dasd_device_from_cdev_locked(cdev); |
1007 | if (device == NULL || | 1007 | if (IS_ERR(device)) { |
1008 | device != dasd_device_from_cdev_locked(cdev) || | 1008 | DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s", |
1009 | strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { | 1009 | "unable to get device from cdev"); |
1010 | return; | ||
1011 | } | ||
1012 | |||
1013 | if (!cqr->startdev || | ||
1014 | device != cqr->startdev || | ||
1015 | strncmp(cqr->startdev->discipline->ebcname, | ||
1016 | (char *) &cqr->magic, 4)) { | ||
1010 | DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s", | 1017 | DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s", |
1011 | "invalid device in request"); | 1018 | "invalid device in request"); |
1019 | dasd_put_device(device); | ||
1012 | return; | 1020 | return; |
1013 | } | 1021 | } |
1014 | 1022 | ||
@@ -2291,11 +2299,6 @@ static void dasd_generic_auto_online(void *data, async_cookie_t cookie) | |||
2291 | if (ret) | 2299 | if (ret) |
2292 | pr_warning("%s: Setting the DASD online failed with rc=%d\n", | 2300 | pr_warning("%s: Setting the DASD online failed with rc=%d\n", |
2293 | dev_name(&cdev->dev), ret); | 2301 | dev_name(&cdev->dev), ret); |
2294 | else { | ||
2295 | struct dasd_device *device = dasd_device_from_cdev(cdev); | ||
2296 | wait_event(dasd_init_waitq, _wait_for_device(device)); | ||
2297 | dasd_put_device(device); | ||
2298 | } | ||
2299 | } | 2302 | } |
2300 | 2303 | ||
2301 | /* | 2304 | /* |
@@ -2430,6 +2433,9 @@ int dasd_generic_set_online(struct ccw_device *cdev, | |||
2430 | } else | 2433 | } else |
2431 | pr_debug("dasd_generic device %s found\n", | 2434 | pr_debug("dasd_generic device %s found\n", |
2432 | dev_name(&cdev->dev)); | 2435 | dev_name(&cdev->dev)); |
2436 | |||
2437 | wait_event(dasd_init_waitq, _wait_for_device(device)); | ||
2438 | |||
2433 | dasd_put_device(device); | 2439 | dasd_put_device(device); |
2434 | return rc; | 2440 | return rc; |
2435 | } | 2441 | } |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 4cac5b54f26a..d49766f3b940 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -874,12 +874,19 @@ dasd_discipline_show(struct device *dev, struct device_attribute *attr, | |||
874 | ssize_t len; | 874 | ssize_t len; |
875 | 875 | ||
876 | device = dasd_device_from_cdev(to_ccwdev(dev)); | 876 | device = dasd_device_from_cdev(to_ccwdev(dev)); |
877 | if (!IS_ERR(device) && device->discipline) { | 877 | if (IS_ERR(device)) |
878 | goto out; | ||
879 | else if (!device->discipline) { | ||
880 | dasd_put_device(device); | ||
881 | goto out; | ||
882 | } else { | ||
878 | len = snprintf(buf, PAGE_SIZE, "%s\n", | 883 | len = snprintf(buf, PAGE_SIZE, "%s\n", |
879 | device->discipline->name); | 884 | device->discipline->name); |
880 | dasd_put_device(device); | 885 | dasd_put_device(device); |
881 | } else | 886 | return len; |
882 | len = snprintf(buf, PAGE_SIZE, "none\n"); | 887 | } |
888 | out: | ||
889 | len = snprintf(buf, PAGE_SIZE, "none\n"); | ||
883 | return len; | 890 | return len; |
884 | } | 891 | } |
885 | 892 | ||