Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+15 −9
Original line number Diff line number Diff line
@@ -1003,12 +1003,20 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
		return;
	}

	device = (struct dasd_device *) cqr->startdev;
	if (device == NULL ||
	    device != dasd_device_from_cdev_locked(cdev) ||
	    strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
	device = dasd_device_from_cdev_locked(cdev);
	if (IS_ERR(device)) {
		DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s",
				"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",
				"invalid device in request");
		dasd_put_device(device);
		return;
	}

@@ -2291,11 +2299,6 @@ static void dasd_generic_auto_online(void *data, async_cookie_t cookie)
	if (ret)
		pr_warning("%s: Setting the DASD online failed with rc=%d\n",
			   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,
	} else
		pr_debug("dasd_generic device %s found\n",
				dev_name(&cdev->dev));

	wait_event(dasd_init_waitq, _wait_for_device(device));

	dasd_put_device(device);
	return rc;
}
+10 −3
Original line number Diff line number Diff line
@@ -874,11 +874,18 @@ dasd_discipline_show(struct device *dev, struct device_attribute *attr,
	ssize_t len;

	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",
			       device->discipline->name);
		dasd_put_device(device);
	} else
		return len;
	}
out:
	len = snprintf(buf, PAGE_SIZE, "none\n");
	return len;
}