summaryrefslogtreecommitdiff
path: root/drivers/s390/block/dasd_alias.c
diff options
context:
space:
mode:
authorStefan Haberland <stefan.haberland@de.ibm.com>2015-07-10 11:47:09 +0300
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2015-07-13 12:02:14 +0300
commitf81a49d13b3014c2b7c424628779a8af93f25c04 (patch)
tree5acd89ff363fcf1f1da4b082a798aed0709f5efe /drivers/s390/block/dasd_alias.c
parentf9c87a6f46d508eae0d9ae640be98d50f237f827 (diff)
downloadlinux-f81a49d13b3014c2b7c424628779a8af93f25c04.tar.xz
s390/dasd: fix kernel panic when alias is set offline
The dasd device driver selects which (alias or base) device is used for a given requests when the request is build. If the chosen alias device is set offline before the request gets queued to the device queue the starting function may use device structures that are already freed. This might lead to a hanging offline process or a kernel panic. Add a check to the starting function that returns the request to the upper layer if the device is already in offline processing. In addition to that prevent that an alias device that's already in offline processing gets chosen as start device. Reviewed-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Reviewed-by: Peter Oberparleiter <peter.oberparleiter@linux.vnet.ibm.com> Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/block/dasd_alias.c')
-rw-r--r--drivers/s390/block/dasd_alias.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index a2597e683e79..ee3a6faae22a 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -699,7 +699,8 @@ struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *base_device)
struct dasd_device, alias_list);
spin_unlock_irqrestore(&lcu->lock, flags);
alias_priv = (struct dasd_eckd_private *) alias_device->private;
- if ((alias_priv->count < private->count) && !alias_device->stopped)
+ if ((alias_priv->count < private->count) && !alias_device->stopped &&
+ !test_bit(DASD_FLAG_OFFLINE, &alias_device->flags))
return alias_device;
else
return NULL;