Commit 589c74d5 authored by Stefan Haberland's avatar Stefan Haberland Committed by Martin Schwidefsky

[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: default avatarStefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 9eb25122
...@@ -1003,12 +1003,20 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, ...@@ -1003,12 +1003,20 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
return; return;
} }
device = (struct dasd_device *) cqr->startdev; device = dasd_device_from_cdev_locked(cdev);
if (device == NULL || if (IS_ERR(device)) {
device != dasd_device_from_cdev_locked(cdev) || DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s",
strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { "unable to get device from cdev");
return;
}
if (!cqr->startdev ||
device != cqr->startdev ||
strncmp(cqr->startdev->discipline->ebcname,
(char *) &cqr->magic, 4)) {
DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s", DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s",
"invalid device in request"); "invalid device in request");
dasd_put_device(device);
return; return;
} }
...@@ -2291,11 +2299,6 @@ static void dasd_generic_auto_online(void *data, async_cookie_t cookie) ...@@ -2291,11 +2299,6 @@ static void dasd_generic_auto_online(void *data, async_cookie_t cookie)
if (ret) if (ret)
pr_warning("%s: Setting the DASD online failed with rc=%d\n", pr_warning("%s: Setting the DASD online failed with rc=%d\n",
dev_name(&cdev->dev), ret); dev_name(&cdev->dev), ret);
else {
struct dasd_device *device = dasd_device_from_cdev(cdev);
wait_event(dasd_init_waitq, _wait_for_device(device));
dasd_put_device(device);
}
} }
/* /*
...@@ -2430,6 +2433,9 @@ int dasd_generic_set_online(struct ccw_device *cdev, ...@@ -2430,6 +2433,9 @@ int dasd_generic_set_online(struct ccw_device *cdev,
} else } else
pr_debug("dasd_generic device %s found\n", pr_debug("dasd_generic device %s found\n",
dev_name(&cdev->dev)); dev_name(&cdev->dev));
wait_event(dasd_init_waitq, _wait_for_device(device));
dasd_put_device(device); dasd_put_device(device);
return rc; return rc;
} }
......
...@@ -874,12 +874,19 @@ dasd_discipline_show(struct device *dev, struct device_attribute *attr, ...@@ -874,12 +874,19 @@ dasd_discipline_show(struct device *dev, struct device_attribute *attr,
ssize_t len; ssize_t len;
device = dasd_device_from_cdev(to_ccwdev(dev)); device = dasd_device_from_cdev(to_ccwdev(dev));
if (!IS_ERR(device) && device->discipline) { if (IS_ERR(device))
goto out;
else if (!device->discipline) {
dasd_put_device(device);
goto out;
} else {
len = snprintf(buf, PAGE_SIZE, "%s\n", len = snprintf(buf, PAGE_SIZE, "%s\n",
device->discipline->name); device->discipline->name);
dasd_put_device(device); dasd_put_device(device);
} else return len;
len = snprintf(buf, PAGE_SIZE, "none\n"); }
out:
len = snprintf(buf, PAGE_SIZE, "none\n");
return len; return len;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment