diff options
| author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2010-05-26 17:27:07 -0400 |
|---|---|---|
| committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-05-26 17:27:09 -0400 |
| commit | c560d105a197464603247bf55962fc7f23c8cb62 (patch) | |
| tree | 04f9738638aff5f4825fc2567540d288ffd4518a | |
| parent | a65a3e82b5b5f8f70cc0d51498441585d5b381f1 (diff) | |
[S390] ccwgroup: add locking around drvdata access
Several processes may concurrently try to create a group device
from the same ccw_device(s). Add locking arround the drvdata
access to prevent race conditions.
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
| -rw-r--r-- | drivers/s390/cio/ccwgroup.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 5f97ea2ee6b1..97b25d68e3e7 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
| @@ -123,8 +123,10 @@ ccwgroup_release (struct device *dev) | |||
| 123 | 123 | ||
| 124 | for (i = 0; i < gdev->count; i++) { | 124 | for (i = 0; i < gdev->count; i++) { |
| 125 | if (gdev->cdev[i]) { | 125 | if (gdev->cdev[i]) { |
| 126 | spin_lock_irq(gdev->cdev[i]->ccwlock); | ||
| 126 | if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) | 127 | if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) |
| 127 | dev_set_drvdata(&gdev->cdev[i]->dev, NULL); | 128 | dev_set_drvdata(&gdev->cdev[i]->dev, NULL); |
| 129 | spin_unlock_irq(gdev->cdev[i]->ccwlock); | ||
| 128 | put_device(&gdev->cdev[i]->dev); | 130 | put_device(&gdev->cdev[i]->dev); |
| 129 | } | 131 | } |
| 130 | } | 132 | } |
| @@ -262,11 +264,14 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | |||
| 262 | goto error; | 264 | goto error; |
| 263 | } | 265 | } |
| 264 | /* Don't allow a device to belong to more than one group. */ | 266 | /* Don't allow a device to belong to more than one group. */ |
| 267 | spin_lock_irq(gdev->cdev[i]->ccwlock); | ||
| 265 | if (dev_get_drvdata(&gdev->cdev[i]->dev)) { | 268 | if (dev_get_drvdata(&gdev->cdev[i]->dev)) { |
| 269 | spin_unlock_irq(gdev->cdev[i]->ccwlock); | ||
| 266 | rc = -EINVAL; | 270 | rc = -EINVAL; |
| 267 | goto error; | 271 | goto error; |
| 268 | } | 272 | } |
| 269 | dev_set_drvdata(&gdev->cdev[i]->dev, gdev); | 273 | dev_set_drvdata(&gdev->cdev[i]->dev, gdev); |
| 274 | spin_unlock_irq(gdev->cdev[i]->ccwlock); | ||
| 270 | } | 275 | } |
| 271 | /* Check for sufficient number of bus ids. */ | 276 | /* Check for sufficient number of bus ids. */ |
| 272 | if (i < num_devices && !curr_buf) { | 277 | if (i < num_devices && !curr_buf) { |
| @@ -303,8 +308,10 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | |||
| 303 | error: | 308 | error: |
| 304 | for (i = 0; i < num_devices; i++) | 309 | for (i = 0; i < num_devices; i++) |
| 305 | if (gdev->cdev[i]) { | 310 | if (gdev->cdev[i]) { |
| 311 | spin_lock_irq(gdev->cdev[i]->ccwlock); | ||
| 306 | if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) | 312 | if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) |
| 307 | dev_set_drvdata(&gdev->cdev[i]->dev, NULL); | 313 | dev_set_drvdata(&gdev->cdev[i]->dev, NULL); |
| 314 | spin_unlock_irq(gdev->cdev[i]->ccwlock); | ||
| 308 | put_device(&gdev->cdev[i]->dev); | 315 | put_device(&gdev->cdev[i]->dev); |
| 309 | gdev->cdev[i] = NULL; | 316 | gdev->cdev[i] = NULL; |
| 310 | } | 317 | } |
