aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStefan Haberland <stefan.haberland@de.ibm.com>2010-02-26 16:37:47 -0500
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-02-26 16:37:32 -0500
commit589c74d5076dd1bde13a5a36d97ca79be8bd72b2 (patch)
tree252349a17326853d7e026b357921da6192958d26 /drivers
parent9eb251225ab4dbea3119cfcf4c5194eed223a740 (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.c24
-rw-r--r--drivers/s390/block/dasd_devmap.c13
2 files changed, 25 insertions, 12 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 56df3c5ed38..302ca14a69e 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 4cac5b54f26..d49766f3b94 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 }
888out:
889 len = snprintf(buf, PAGE_SIZE, "none\n");
883 return len; 890 return len;
884} 891}
885 892