s390/dasd: Fix locking issue when changing EER attribute

The reference to a device in question may get lost when the extended
error reporting (EER) attribute is being enabled/disabled while the
device is set offline at the same time. This is due to missing
refcounting and incorrect locking. Fix this by the following:

- In dasd_eer_store() get the device directly and handle the refcount
  accordingly.
- Move the lock in dasd_eer_enable() up so we can ensure safe
  processing.
- Check if the device is being set offline and return with -EBUSY if so.
- While at it, change the return code from -EPERM to -EMEDIUMTYPE as
  suggested by a FIXME, since that is what we're actually checking.

Reviewed-by: Stefan Haberland <sth@linux.vnet.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Jan Höppner
2016-10-12 12:51:04 +02:00
committed by Martin Schwidefsky
parent 0f57c97f24
commit 9de67725c8
2 changed files with 34 additions and 22 deletions

View File

@@ -1167,26 +1167,25 @@ static ssize_t
dasd_eer_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dasd_devmap *devmap;
struct dasd_device *device;
unsigned int val;
int rc;
int rc = 0;
devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
if (IS_ERR(devmap))
return PTR_ERR(devmap);
if (!devmap->device)
return -ENODEV;
device = dasd_device_from_cdev(to_ccwdev(dev));
if (IS_ERR(device))
return PTR_ERR(device);
if (kstrtouint(buf, 0, &val) || val > 1)
return -EINVAL;
if (val) {
rc = dasd_eer_enable(devmap->device);
if (rc)
return rc;
} else
dasd_eer_disable(devmap->device);
return count;
if (val)
rc = dasd_eer_enable(device);
else
dasd_eer_disable(device);
dasd_put_device(device);
return rc ? : count;
}
static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);